Example #1
0
            /*!
             * \brief   adjust drainage according to changed root depth.
             *
             * \param   lastConditions  The last soil conditions.
             * \param   tawRz           The totally available water in root zone.
             * \param   tawDz           The totally available water in the zone under root up to 2m or maxDepth.
             * \param   zr              The rooting depth.
             * \param   maxDepth        The maximum depth of the soil profile.
             *
             * \return  The fixed SoilConditions.
             */

            internal static SoilConditions AdjustSoilConditionsZr(SoilConditions lastConditions, double tawRz, double tawDz, double zr, double maxDepth)
            {
                if (lastConditions.tawRz == null)
                {
                    lastConditions.tawRz = tawRz;
                }
                if (lastConditions.tawDz == null)
                {
                    lastConditions.tawDz = tawDz;
                }

                if (zr == lastConditions.zr)
                {
                    return(lastConditions);
                }

                var drSum = lastConditions.drRz + lastConditions.drDz;

                //catch special case root zone from max to 0
                if (lastConditions.zr == maxDepth && zr == 0)
                {
                    lastConditions.drRz = 0;
                    lastConditions.drDz = lastConditions.drRz;
                }
                //catch special case root zone from 0 to max
                else if (lastConditions.zr == 0 && zr == maxDepth)
                {
                    lastConditions.drRz = lastConditions.drDz;
                    lastConditions.drDz = 0;
                }
                //root zone shrinks -> add root drainage to deep zone
                else if (zr < lastConditions.zr)
                {
                    var tawRzRatio = ((double)lastConditions.tawRz / lastConditions.zr) / (tawRz / zr);
                    var zrFactor   = zr / lastConditions.zr;
                    lastConditions.drRz = lastConditions.drRz * zrFactor / tawRzRatio;
                    lastConditions.drDz = drSum - lastConditions.drRz;
                }
                //root zone grows -> add deep drainage to root zone
                else
                {
                    var tawDzRatio = ((double)lastConditions.tawDz / (maxDepth - lastConditions.zr)) / (tawDz / (maxDepth - zr));
                    var zrFactor   = (maxDepth - zr) / (maxDepth - lastConditions.zr);
                    lastConditions.drDz = lastConditions.drDz * zrFactor / tawDzRatio;
                    lastConditions.drRz = drSum - lastConditions.drDz;
                }
                lastConditions.tawRz = tawRz;
                lastConditions.tawDz = tawDz;

                return(lastConditions);
            }
Example #2
0
            /*!
             * \brief   Clone constructor.
             *
             * \param   soilConditions  The soil conditions to clone.
             */

            public SoilConditions(SoilConditions soilConditions)
            {
                //use this for .net 4.0
                //foreach (PropertyInfo pi in this.GetType().GetProperties())
                //use this for .net 4.5
                foreach (PropertyInfo pi in this.GetType().GetRuntimeProperties())
                {
                    if (soilConditions.GetType().GetRuntimeProperty(pi.Name) == null)
                    {
                        continue;
                    }
                    pi.SetValue(this, soilConditions.GetType().GetRuntimeProperty(pi.Name).GetValue(soilConditions, null), null);
                }
            }
Example #3
0
            /*!
             * \brief   adjust soil conditions if drainage is exceeded and the water content is negative.
             *
             * \param   lastConditions  The last soil conditions.
             * \param   tawRz           The totally available water in root zone.
             * \param   tawDz           The totally available water in the zone under root up to 2m or maxDepth.
             * \param   zrNew           The new rooting depth.
             * \param   maxDepth        The maximum depth of the soil profile.
             * \param [in,out]  e       The actual evaporation, may be adjusted.
             * \param [in,out]  t       The actual transpiration, may be adjusted.
             *
             * \return  The fixed SoilConditions.
             */

            internal static SoilConditions AdjustSoilConditionsExceeded(SoilConditions lastConditions, double tawRz, double tawDz, double zrNew, double maxDepth, ref double e, ref double t)
            {
                if (zrNew != lastConditions.zr)
                {
                    lastConditions = AdjustSoilConditionsZr(lastConditions, tawRz, tawDz, zrNew, maxDepth);
                }

                var balanceSum = e + t;
                //calculate soil water balance
                var dpRz = Math.Max(0, balanceSum - lastConditions.drRz);
                var drRz = lastConditions.drRz - balanceSum + dpRz;

                if (drRz < 0)
                {
                    //negative drainage should not happen -> percolate excess water to deep zone
                    dpRz -= drRz;
                    drRz  = 0;
                }
                else if (drRz > lastConditions.tawRz)
                {
                    //drainage exceeds taw -> adjust this day values to stay beyond this limit
                    var drRzExceeded = drRz - (double)lastConditions.tawRz;

                    var eFactor  = e / balanceSum;
                    var etFactor = t / balanceSum;
                    t    = Math.Min(0, t - drRzExceeded * etFactor);
                    e    = Math.Min(0, e - drRzExceeded * eFactor);
                    drRz = lastConditions.drRz - balanceSum - drRzExceeded + dpRz;
                }

                var dpDz = Math.Max(0, dpRz - lastConditions.drDz);
                var drDz = lastConditions.drDz - dpRz + dpDz;

                if (drDz < 0)
                {
                    //negative drainage should not happen -> deep percolate excess water
                    dpDz -= drDz;
                    drDz  = 0;
                }
                if (drDz > tawDz)
                {
                    //drainage exceeds taw should not happen in deep zone -> write exceed value to result table
                    drDz = tawDz;
                }

                return(lastConditions);
            }
Example #4
0
        /*!
         * \brief   calculate evaporation.
         *
         * \param [in,out]  lastConditions  The last soil conditions.
         * \param   plantSet                Set the plant values.
         * \param   climateSet              Set the climate values.
         * \param   irrigationType          Type of the irrigation.
         * \param   et0                     The reference evapotranspiration.
         * \param   eFactor                 The factor e is reduced by. May be used to consider mulching etc.
         * \param   tew                     The totally evaporable water.
         * \param   irrigationFw            The fraction of wetted surface depending on irrigation type.
         * \param   autoIrrigationFw        The fraction of wetted surface depending on automatic irrigation type.
         * \param   netIrrigation           The netto irrigation.
         * \param   autoNetIrrigation       The automatic netto irrigation.
         * \param   interception            The interception.
         * \param   interceptionIrr         The interception of the irrigated water.
         * \param   interceptionAutoIrr     The interception of the automatic irrigated water.
         * \param [in,out]  eResult         The result of the calculation.
         *
         * \return  true if it succeeds, false if it fails.
         */

        public static bool ECalculation(
            ref SoilConditions lastConditions,
            PlantValues plantSet,
            ClimateValues climateSet,
            String irrigationType,
            double et0,
            double eFactor,
            double tew,
            double irrigationFw,
            double autoIrrigationFw,
            double netIrrigation,
            double autoNetIrrigation,
            double interception,
            double interceptionIrr,
            double interceptionAutoIrr,
            ref EvaporationResult eResult
            )
        {
            if (eResult == null)
            {
                eResult = new EvaporationResult();
            }
            var rewFactor = 2.2926;
            var kcMax     = 1.2;
            var kcMin     = 0.0;
            var kcb       = 0.0;
            var fc        = 0.0;

            if (!(plantSet.isFallow == true))
            {
                kcb   = (double)plantSet.Kcb;
                kcMax = 1.2 + (0.04 * ((double)climateSet.windspeed - 2) - 0.004 * ((double)climateSet.humidity - 45)) * Math.Pow(((double)plantSet.height / 3), 0.3);
                kcMax = Math.Max(kcMax, kcb + 0.05);
                kcMax = Math.Min(kcMax, 1.3);
                kcMax = Math.Max(kcMax, 1.05);
                kcMin = 0.175;
                fc    = Math.Pow(Math.Max((kcb - kcMin), 0.01) / (kcMax - kcMin), 1 + 0.5 * (double)plantSet.height);
                fc    = Math.Min(0.99, fc);
            }
            eResult.kcMin = kcMin;
            eResult.kcMax = kcMax;
            eResult.kcb   = kcb;
            eResult.fc    = fc;

            var few = Math.Min(1 - fc, Math.Min(irrigationFw, autoIrrigationFw));

            if ((netIrrigation > 0 || autoNetIrrigation > 0) && (irrigationType == "drip"))
            {
                few = Math.Min(1 - fc, (1 - (2 / 3) * fc) * Math.Min(irrigationFw, autoIrrigationFw));
            }

            eResult.few = few;
            eResult.tew = tew;
            var rew = tew / rewFactor;

            eResult.rew = rew;
            var kr = 1.0;

            if (lastConditions.de > rew)
            {
                kr = (tew - lastConditions.de) / (tew - rew);
                kr = Math.Max(0, kr);
            }
            if (rew == 0)
            {
                kr = 0;
            }
            eResult.kr = kr;
            var ke = Math.Min(kr * (kcMax - kcb), few * kcMax);

            eResult.ke = ke;
            var e = ke * et0;

            e         = e * eFactor;
            eResult.e = e;
            var rpPrecipitation    = climateSet.rpPrecipitation != null ? (double)climateSet.rpPrecipitation : (double)climateSet.precipitation;
            var netPrecititationTc = rpPrecipitation - interception + netIrrigation - interceptionIrr + autoNetIrrigation - interceptionAutoIrr;
            var dpe = netPrecititationTc - lastConditions.de;

            dpe = Math.Max(0, dpe);
            var de = lastConditions.de - netPrecititationTc + e / few + dpe;

            de = Math.Max(0, de);
            de = Math.Min(tew, de);
            lastConditions.de  = de;
            lastConditions.dpe = dpe;
            eResult.de         = de;
            eResult.dpe        = dpe;
            return(true);
        }