Esempio n. 1
0
        internal NormalRunoff runoff; //let derived PondSurface see this but not outside world.

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="NormalSurface"/> class.
        /// </summary>
        /// <param name="SoilObject">The soil object.</param>
        /// <param name="Clock">The clock.</param>
        public NormalSurface(SoilWaterSoil SoilObject, Clock Clock)
        {
            SurfaceType = Surfaces.NormalSurface;
            base.constants = SoilObject.Constants;
            runoff = new NormalRunoff(SoilObject);     //Soil is needed to initialise the cn2bare, etc.
            evap = new NormalEvaporation(SoilObject, Clock);
        }
Esempio n. 2
0
        //Constructor
        public NormalEvaporation(SoilWaterSoil SoilObject, Clock Clock)
        {
            cons = SoilObject.Constants;

            salb = SoilObject.Salb;

            summerCona = SoilObject.SummerCona;
            summerU = SoilObject.SummerU;
            summerDate = SoilObject.SummerDate;

            winterCona = SoilObject.WinterCona;
            winterU = SoilObject.WinterU;
            winterDate = SoilObject.WinterDate;

            // soilwat2_soil_property_param()

            //u - can either use (one value for summer and winter) or two different values.
            //    (must also take into consideration where they enter two values [one for summer and one for winter] but they make them both the same)

            if ((Double.IsNaN(summerU) || (Double.IsNaN(winterU))))
                {
                throw new Exception("A single value for u OR BOTH values for summeru and winteru must be specified");
                }
            //if they entered two values but they made them the same
            if (summerU == winterU)
                {
                u = summerU;      //u is now no longer null. As if the user had entered a value for u.
                }

            //cona - can either use (one value for summer and winter) or two different values.
            //       (must also take into consideration where they enter two values [one for summer and one for winter] but they make them both the same)

            if ((Double.IsNaN(summerCona)) || (Double.IsNaN(winterCona)))
                {
                throw new Exception("A single value for cona OR BOTH values for summercona and wintercona must be specified");
                }
            //if they entered two values but they made them the same.
            if (summerCona == winterCona)
                {
                cona = summerCona;   //cona is now no longer null. As if the user had entered a value for cona.
                }

            //summer and winter default dates.
            if (summerDate == "not_read")
                {
                summerDate = "1-oct";
                }

            if (winterDate == "not_read")
                {
                winterDate = "1-apr";
                }

            InitialiseAccumulatingVars(SoilObject, Clock);
        }
Esempio n. 3
0
        //Constructor
        public NormalRunoff(SoilWaterSoil SoilObject)
        {
            cons = SoilObject.Constants;

            _cn2_bare = SoilObject.cn2_bare;
            coverCnRed = SoilObject.cn_red;
            coverCnCov = SoilObject.cn_cov;

            //soilwat2_soil_property_param()

            if (coverCnRed >= _cn2_bare)
                {
                coverCnRed = _cn2_bare - 0.00009;
                }
        }
Esempio n. 4
0
        private void soilwat2_runoff_depth_factor(SoilWaterSoil SoilObject, ref double[] runoff_wf)
        {
            //runoff_wf -> ! (OUTPUT) weighting factor for runoff

            //*+  Purpose
            //*      Calculate the weighting factor hydraulic effectiveness used
            //*      to weight the effect of soil moisture on runoff.

            //*+  Mission Statement
            //*      Calculate soil moisture effect on runoff

            double cum_depth;                 //! cumulative depth (mm)
            double hydrol_effective_depth_local;    //! hydrologically effective depth for runoff (mm) - for when erosion turned on
            int hydrol_effective_layer;    //! layer number that the effective depth occurs in ()

            double scale_fact;                //! scaling factor for wf function to sum to 1
            double wf_tot;                    //! total of wf ()
            double wx;                        //! depth weighting factor for current total depth. intermediate variable for deriving wf (total wfs to current layer)
            double xx;                        //! intermediate variable for deriving wf total wfs to previous layer

            xx = 0.0;
            cum_depth = 0.0;
            wf_tot = 0.0;

            //! check if hydro_effective_depth applies for eroded profile.
            hydrol_effective_depth_local = Math.Min(cons.hydrol_effective_depth, SoilObject.DepthTotal);

            scale_fact = 1.0 / (1.0 - Math.Exp(-4.16));
            hydrol_effective_layer = SoilObject.FindLayerNo(hydrol_effective_depth_local);

            foreach (Layer lyr in SoilObject.TopToX(hydrol_effective_layer))
                {
                cum_depth = cum_depth + lyr.dlayer;
                cum_depth = Math.Min(cum_depth, hydrol_effective_depth_local);

                //! assume water content to c%hydrol_effective_depth affects runoff
                //! sum of wf should = 1 - may need to be bounded? <dms 7-7-95>
                wx = scale_fact * (1.0 - Math.Exp(-4.16 * MathUtilities.Divide(cum_depth, hydrol_effective_depth_local, 0.0)));
                runoff_wf[lyr.number-1] = wx - xx;  //zero based array
                xx = wx;

                wf_tot = wf_tot + runoff_wf[lyr.number-1]; //zero based array.
                }

            cons.bound_check_real_var(wf_tot, 0.9999, 1.0001, "wf_tot");
        }
Esempio n. 5
0
        private void CalcRunoff_USDA_SoilConservationService(double WaterForRunoff, SoilWaterSoil SoilObject)
        {
            //private void soilwat2_scs_runoff(double Rain, double Runon, double TotalInterception, ref double Runoff)
            //    {
            //cn2_new (output)
            //Runoff  (output)

            double cn;                                 //! scs curve number
            double cn1;                                //! curve no. for dry soil (antecedant) moisture
            double cn3;                                //! curve no. for wet soil (antecedant) moisture
            double cnpd;                               //! cn proportional in dry range (dul to ll15)

            double s;                                  //! potential max retention (surface ponding + infiltration)
            double xpb;                                //! intermedite variable for deriving runof
            double[] runoff_wf;                        //! weighting factor for depth for each layer
            double dul_fraction;                       // if between (0-1) not above dul, if (1-infinity) above dul

            double cover_fract;                        //! proportion of maximum cover effect on runoff (0-1)
            double cover_reduction = 0.0;

            double tillage_fract;
            double tillage_reduction = 0.0;            //! reduction in cn due to tillage

            runoff_wf = new double[SoilObject.num_layers];

            soilwat2_runoff_depth_factor(SoilObject, ref runoff_wf);

            cnpd = 0.0;
            foreach (Layer lyr in SoilObject)
                {
                dul_fraction = MathUtilities.Divide((lyr.sw_dep - lyr.ll15_dep), (lyr.dul_dep - lyr.ll15_dep), 0.0);
                cnpd = cnpd + dul_fraction * runoff_wf[lyr.number-1]; //zero based array.
                }
            cnpd = cons.bound(cnpd, 0.0, 1.0);

            //reduce cn2 for the day due to the cover effect
            //nb. cover_surface_runoff should really be a parameter to this function
            cover_fract = MathUtilities.Divide(cover_surface_runoff, coverCnCov, 0.0);
            cover_fract = cons.bound(cover_fract, 0.0, 1.0);
            cover_reduction = coverCnRed * cover_fract;
            cn2_new = _cn2_bare - cover_reduction;

            //tillage reduction on cn
            //nb. tillage_cn_red, tillage_cn_rain, and tillage_rain_sum, should really be parameters to this function
            if (tillageCnCumWater > 0.0)
                {
                //We minus 1 because we want the opposite fraction.
                //Tillage Reduction is biggest (CnRed value) straight after Tillage and gets smaller and becomes 0 when reaches CumWater.
                //unlike the Cover Reduction, where the reduction starts out smallest (0) and gets bigger and becomes (CnRed value) when you hit CnCover.
                tillage_fract = MathUtilities.Divide(cumWaterSinceTillage, tillageCnCumWater, 0.0) - 1.0;
                tillage_reduction = tillageCnRed * tillage_fract;
                cn2_new = cn2_new + tillage_reduction;
                }
            else
                {
                //nothing
                }

            //! cut off response to cover at high covers if p%cn_red < 100.
            cn2_new = cons.bound(cn2_new, 0.0, 100.0);

            cn1 = MathUtilities.Divide(cn2_new, (2.334 - 0.01334 * cn2_new), 0.0);
            cn3 = MathUtilities.Divide(cn2_new, (0.4036 + 0.005964 * cn2_new), 0.0);
            cn = cn1 + (cn3 - cn1) * cnpd;

            // ! curve number will be decided from scs curve number table ??dms
            s = 254.0 * (MathUtilities.Divide(100.0, cn, 1000000.0) - 1.0);
            xpb = WaterForRunoff - 0.2 * s;
            xpb = Math.Max(xpb, 0.0);

            //assign the output variable
            Runoff = MathUtilities.Divide(xpb * xpb, (WaterForRunoff + 0.8 * s), 0.0);

            //sv- I added these output variables
            cn_red_cov = cover_reduction;
            cn_red_till = tillage_reduction;

            //bound check the ouput variable
            cons.bound_check_real_var(Runoff, 0.0, WaterForRunoff, "runoff");
        }
Esempio n. 6
0
        public void CalcRunoff(double WaterForRunoff, SoilWaterSoil SoilObject)
        {
            //private void soilwat2_runoff(double Rain, double Runon, double TotalInterception, ref double Runoff)
            //{

            Runoff = 0.0;  //zero the return parameter

            if (WaterForRunoff > 0.0)
                {

                CalcRunoff_USDA_SoilConservationService(WaterForRunoff, SoilObject);

                cumWaterSinceTillage = cumWaterSinceTillage + WaterForRunoff;
                ShouldIStopTillageCNReduction();  //! NB. this needs to be done _after_ cn calculation.
                }
        }
Esempio n. 7
0
        //Initialise the Accumulating Variables
        public void InitialiseAccumulatingVars(SoilWaterSoil SoilObject, Clock Clock)
        {
            //reset the accumulated Evap variables (sumes1, sumes2, t)
            //nb. sumes1 -> is sum of es during stage1
            //used in the SoilWater Init, Reset event

            // soilwat2_soil_property_param()

            //assign u and cona to either sumer or winter values
            // Need to add 12 hours to move from "midnight" to "noon", or this won't work as expected
            if (DateUtilities.WithinDates(winterDate, Clock.Today, summerDate))
                {
                cona = winterCona;
                u = winterU;
                }
            else
                {
                cona = summerCona;
                u = summerU;
                }

            //private void soilwat2_evap_init()
            //    {

            //##################
            //Evap Init   --> soilwat2_evap_init (), soilwat2_ritchie_init()
            //##################

            //soilwat2_ritchie_init();
            //*+  Mission Statement
            //*       Initialise ritchie evaporation model

            double swr_top;       //! stage 2 evaporation occurs ratio available sw potentially available sw in top layer

            Layer top = SoilObject.GetTopLayer();

            //! set up evaporation stage
            swr_top = MathUtilities.Divide((top.sw_dep - top.ll15_dep), (top.dul_dep - top.ll15_dep), 0.0);
            swr_top = cons.bound(swr_top, 0.0, 1.0);

            //! are we in stage1 or stage2 evap?
            if (swr_top < cons.sw_top_crit)
                {
                //! stage 2 evap
                sumes2 = cons.sumes2_max - (cons.sumes2_max * MathUtilities.Divide(swr_top, cons.sw_top_crit, 0.0));
                sumes1 = u;
                t = MathUtilities.Sqr(MathUtilities.Divide(sumes2, cona, 0.0));
                }
            else
                {
                //! stage 1 evap
                sumes2 = 0.0;
                sumes1 = cons.sumes1_max - (cons.sumes1_max * swr_top);
                t = 0.0;
                }
        }
Esempio n. 8
0
        public void CalcEs_RitchieEq_LimitedBySW(SoilWaterSoil SoilObject, Clock Clock, double Infiltration)
        {
            //private void soilwat2_ritchie_evaporation()
            //    {
            //es          -> ! (output) actual evaporation (mm)
            //eos         -> ! (input) potential rate of evaporation (mm/day)
            //avail_sw_top -> ! (input) upper limit of soil evaporation (mm/day)  !sv- now calculated in here, not passed in as a argument.

            //*+  Purpose
            //*          ****** calculate actual evaporation from soil surface (es) ******
            //*          most es takes place in two stages: the constant rate stage
            //*          and the falling rate stage (philip, 1957).  in the constant
            //*          rate stage (stage 1), the soil is sufficiently wet for water
            //*          be transported to the surface at a rate at least equal to the
            //*          evaporation potential (eos).
            //*          in the falling rate stage (stage 2), the surface soil water
            //*          content has decreased below a threshold value, so that es
            //*          depends on the flux of water through the upper layer of soil
            //*          to the evaporating site near the surface.

            //*+  Notes
            //*       This changes globals - sumes1/2 and t.

            Es = 0.0;  //Zero the return value.

            double avail_sw_top;    //! available soil water in top layer for actual soil evaporation (mm)

            //2. get available soil water for evaporation

            Layer top = SoilObject.GetTopLayer();
            avail_sw_top = top.sw_dep - top.air_dry_dep;
            avail_sw_top = cons.bound(avail_sw_top, 0.0, Eo);

            //3. get actual soil water evaporation

            double esoil1;     //! actual soil evap in stage 1
            double esoil2;     //! actual soil evap in stage 2
            double sumes1_max; //! upper limit of sumes1
            double w_inf;      //! infiltration into top layer (mm)

            // Need to add 12 hours to move from "midnight" to "noon", or this won't work as expected
            if (DateUtilities.WithinDates(winterDate, Clock.Today, summerDate))
                {
                cona = winterCona;
                u = winterU;
                }
            else
                {
                cona = summerCona;
                u = summerU;
                }

            sumes1_max = u;
            w_inf = Infiltration;

            //! if infiltration, reset sumes1
            //! reset sumes2 if infil exceeds sumes1
            if (w_inf > 0.0)
                {
                sumes2 = Math.Max(0.0, (sumes2 - Math.Max(0.0, w_inf - sumes1)));
                sumes1 = Math.Max(0.0, sumes1 - w_inf);

                //! update t (incase sumes2 changed)
                t = MathUtilities.Sqr(MathUtilities.Divide(sumes2, cona, 0.0));
                }
            else
                {
                //! no infiltration, no re-set.
                }

            //! are we in stage1 ?
            if (sumes1 < sumes1_max)
                {
                //! we are in stage1
                //! set esoil1 = potential, or limited by u.
                esoil1 = Math.Min(Eos, sumes1_max - sumes1);

                if ((Eos > esoil1) && (esoil1 < avail_sw_top))
                    {
                    //*           !  eos not satisfied by 1st stage drying,
                    //*           !  & there is evaporative sw excess to air_dry, allowing for esoil1.
                    //*           !  need to calc. some stage 2 drying(esoil2).

                    //*  if g%sumes2.gt.0.0 then esoil2 =f(sqrt(time),p%cona,g%sumes2,g%eos-esoil1).
                    //*  if g%sumes2 is zero, then use ritchie's empirical transition constant (0.6).

                    if (sumes2 > 0.0)
                        {
                        t = t + 1.0;
                        esoil2 = Math.Min((Eos - esoil1), (cona * Math.Pow(t, 0.5) - sumes2));
                        }
                    else
                        {
                        esoil2 = 0.6 * (Eos - esoil1);
                        }
                    }
                else
                    {
                    //! no deficit (or esoil1.eq.eos_max,) no esoil2 on this day
                    esoil2 = 0.0;
                    }

                //! check any esoil2 with lower limit of evaporative sw.
                esoil2 = Math.Min(esoil2, avail_sw_top - esoil1);

                //!  update 1st and 2nd stage soil evaporation.
                sumes1 = sumes1 + esoil1;
                sumes2 = sumes2 + esoil2;
                t = MathUtilities.Sqr(MathUtilities.Divide(sumes2, cona, 0.0));
                }
            else
                {
                //! no 1st stage drying. calc. 2nd stage
                esoil1 = 0.0;

                t = t + 1.0;
                esoil2 = Math.Min(Eos, (cona * Math.Pow(t, 0.5) - sumes2));

                //! check with lower limit of evaporative sw.
                esoil2 = Math.Min(esoil2, avail_sw_top);

                //!   update 2nd stage soil evaporation.
                sumes2 = sumes2 + esoil2;
                }

            Es = esoil1 + esoil2;

            //! make sure we are within bounds
            Es = cons.bound(Es, 0.0, Eos);
            Es = cons.bound(Es, 0.0, avail_sw_top);
        }
Esempio n. 9
0
 /// <summary>
 /// Removes the evaporation from soil.
 /// </summary>
 /// <param name="SoilObject">The soil object.</param>
 public override void RemoveEvaporationFromSoil(ref SoilWaterSoil SoilObject)
 {
     Layer top = SoilObject.GetTopLayer();
     top.sw_dep = top.sw_dep - Es;
 }
Esempio n. 10
0
        /// <summary>
        /// Gets the surface.
        /// </summary>
        /// <param name="SoilObject">The soil object.</param>
        /// <param name="Clock">The clock.</param>
        /// <returns></returns>
        public Surface GetSurface(SoilWaterSoil SoilObject, Clock Clock)
        {
            Surface surface;

            if (SoilObject.max_pond <= 0.0)
                surface = new NormalSurface(SoilObject, Clock);
            else
                surface = new PondSurface(SoilObject, Clock);

            return surface;
        }
Esempio n. 11
0
 /// <summary>
 /// Removes the evaporation from soil.
 /// </summary>
 /// <param name="SoilObject">The soil object.</param>
 public virtual void RemoveEvaporationFromSoil(ref SoilWaterSoil SoilObject)
 {
 }
Esempio n. 12
0
 //nb. Use the methods below rather then just using a SoilObject method to add infiltration or remove water,
 //    because we might want to create Surfaces such as cracking clays that adds infiltration to not just
 //    the top layer but multiple layers. Also these surfaces might want to remove evaporation from
 //    multiple layers and not just the top layer. They will need logic to decide what fractions of
 //    infiltration or evaporation that they want to remove from which layers.
 /// <summary>
 /// Adds the infiltration to soil.
 /// </summary>
 /// <param name="SoilOject">The soil oject.</param>
 public virtual void AddInfiltrationToSoil(ref SoilWaterSoil SoilOject)
 {
 }
Esempio n. 13
0
 /// <summary>
 /// Adds the backed up water to surface.
 /// </summary>
 /// <param name="BackedUp">The backed up.</param>
 /// <param name="SoilObject">The soil object.</param>
 public virtual void AddBackedUpWaterToSurface(double BackedUp, ref SoilWaterSoil SoilObject)
 {
 }
Esempio n. 14
0
        /// <summary>
        /// Adds the backed up water to surface.
        /// </summary>
        /// <param name="BackedUp">The backed up.</param>
        /// <param name="SoilObject">The soil object.</param>
        public override void AddBackedUpWaterToSurface(double BackedUp, ref SoilWaterSoil SoilObject)
        {
            //do normal surface add backup to surface
            base.AddBackedUpWaterToSurface(BackedUp, ref SoilObject);

            //Any extra_runoff then it becomes a pond.
            pond = Math.Min(base.Runoff, SoilObject.max_pond);

            //If there is too much for the pond handle then add the excess to normal runoff.
            base.Runoff = base.Runoff - pond;
        }
Esempio n. 15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PondSurface"/> class.
 /// </summary>
 /// <param name="SoilObject">The soil object.</param>
 /// <param name="Clock">The clock.</param>
 public PondSurface(SoilWaterSoil SoilObject, Clock Clock)
     : base(SoilObject, Clock)
 {
     base.SurfaceType = Surfaces.PondSurface;
     pond = 0.0;
     pond_evap = 0.0;
 }
Esempio n. 16
0
        /// <summary>
        /// Adds the backed up water to surface.
        /// </summary>
        /// <param name="BackedUp">The backed up.</param>
        /// <param name="SoilObject">The soil object.</param>
        public override void AddBackedUpWaterToSurface(double BackedUp, ref SoilWaterSoil SoilObject)
        {
            //If Infiltration was more water that the top layer of soil had empty then the extra water had no choice but to back up.
            //In this case turn the backed up water into runoff and reduce the infiltration to only what the top layer could take before backing up.
            //The amount the top layer can take must be equal to the infiltration - backedup amount.

            //nb. What if lateral inflow caused it to back up? We are assuming only source of water into top layer is infiltration from surface.

            //remove backed up amount from the top layer of the soil. (All of the infiltration did not infiltrate)
            Layer top = SoilObject.GetTopLayer();
            top.sw_dep = top.sw_dep - BackedUp;

            //now reduce the infiltration amount by what backed up.
            base.Infiltration = base.Infiltration - BackedUp;

            //turn the proportion of the infiltration that backed up into runoff.
            base.Runoff = base.Runoff + BackedUp;
        }
Esempio n. 17
0
        private void OnSimulationCommencing(object sender, EventArgs e)
        {
            SaveModuleConstants();

            //daily inputs
            met = new MetData();
            irrig = new IrrigData();
            canopy = new CanopyData();
            surfaceCover = new SurfaceCoverData();

            //optional daily inputs
            runon = 0.0;
            interception = 0.0;
            residueinterception = 0.0;

            if (Soil.Thickness != null)
                {
                try
                    {
                    SoilObject = new SoilWaterSoil(constants, Soil);  //constructor can throw an Exception
                    surfaceFactory = new SurfaceFactory();
                    surface = surfaceFactory.GetSurface(SoilObject, Clock);  //constructor can throw an Exception (Evap class constructor too)

                //optional inputs (array)
                inflow_lat = null;
                }
                catch (Exception Ex)
                    {
                    throw new ApsimXException(this, Ex.Message);  //catch any constructor Exceptions and rethrow as an ApsimXException.
                    }
                }
            else
                {
                throw new ApsimXException(this, "SoilWater module has detected that the Soil has no layers.");
                }
        }
Esempio n. 18
0
 /// <summary>
 /// Adds the infiltration to soil.
 /// </summary>
 /// <param name="SoilObject">The soil object.</param>
 public override void AddInfiltrationToSoil(ref SoilWaterSoil SoilObject)
 {
     Layer top = SoilObject.GetTopLayer();
     top.sw_dep = top.sw_dep + Infiltration;
 }