Exemplo n.º 1
0
        /// <summary>Does the actual water uptake and send the deltas to soil module</summary>
        /// <exception cref="System.Exception">Error on computing water uptake</exception>
        /// <remarks>The amount of water taken up from each soil layer is set per mySpecies</remarks>
        private void DoSoilWaterUptake()
        {
            PMF.WaterChangedType WaterTakenUp = new PMF.WaterChangedType();
            WaterTakenUp.DeltaWater = new double[nLayers];

            double uptakeFraction = Math.Min(1.0, swardWaterDemand / soilAvailableWater.Sum());
            double speciesFraction = 0.0;

            swardWaterUptake = new double[nLayers];

            if (useAltWUptake == "no")
            {
                // calc the amount of water to be taken up
                for (int layer = 0; layer <= RootFrontier; layer++)
                {
                    swardWaterUptake[layer] += soilAvailableWater[layer] * uptakeFraction;
                    WaterTakenUp.DeltaWater[layer] -= swardWaterUptake[layer];
                }

                // partition uptake between species, as function of their demand only
                foreach (PastureSpecies mySpecies in mySward)
                {
                    mySpecies.mySoilWaterTakenUp = new double[nLayers];
                    speciesFraction = mySpecies.WaterDemand / swardWaterDemand;
                    for (int layer = 0; layer <= RootFrontier; layer++)
                        mySpecies.mySoilWaterTakenUp[layer] = swardWaterUptake[layer] * speciesFraction;
                }
            }
            else
            { // Method implemented by RCichota
                // Uptake is distributed over the profile according to water availability,
                //  this means that water status and root distribution have been taken into account

                double[] adjustedWAvailable;

                double[] sumWaterAvailable = new double[nLayers];
                for (int layer = 0; layer < RootFrontier; layer++)
                    sumWaterAvailable[layer] = mySward.Sum(mySpecies => mySpecies.SoilAvailableWater[layer]);

                foreach (PastureSpecies mySpecies in mySward)
                {
                    // get adjusted water available
                    adjustedWAvailable = new double[nLayers];
                    for (int layer = 0; layer < mySpecies.RootFrontier; layer++)
                        adjustedWAvailable[layer] = soilAvailableWater[layer] * mySpecies.SoilAvailableWater[layer] / sumWaterAvailable[layer];

                    // get fraction of demand supplied by the soil
                    uptakeFraction = Math.Min(1.0, mySpecies.WaterDemand / adjustedWAvailable.Sum());

                    // get the actual amounts taken up from each layer
                    mySpecies.mySoilWaterTakenUp = new double[nLayers];
                    for (int layer = 0; layer <= mySpecies.RootFrontier; layer++)
                    {
                        mySpecies.mySoilWaterTakenUp[layer] = adjustedWAvailable[layer] * uptakeFraction;
                        WaterTakenUp.DeltaWater[layer] -= mySpecies.mySoilWaterTakenUp[layer];
                    }
                }
                if (Math.Abs(WaterTakenUp.DeltaWater.Sum() + swardWaterDemand) > 0.0001)
                    throw new Exception("Error on computing water uptake");
            }

            // aggregate all water taken up
            foreach (PastureSpecies mySpecies in mySward)
                swardWaterUptake.Zip(mySpecies.WaterUptake, (x, y) => x + y);

            // send the delta water taken up
            WaterChanged.Invoke(WaterTakenUp);
        }
Exemplo n.º 2
0
        private void OnWaterChanged(WaterChangedType WaterChanged)
        {
            //This event is Only used by Plant2 and AgPasture.
            //This event was added so that the Plant2 module could extract water via its roots from the SoilWater module.
            //At the time Plant2 was not advanced enough to be able to do a "Set" on another modules variables.
            //Plant2 still uses this method to extract water using its roots.

            //*+  Purpose
            //*     Another module wants to change our water

            foreach (Layer lyr in SoilObject.TopToX(WaterChanged.DeltaWater.Length))
                {
                lyr.sw_dep = lyr.sw_dep + WaterChanged.DeltaWater[lyr.number-1];
                SoilObject.CheckLayerForErrors(lyr.number);
                }
        }
Exemplo n.º 3
0
        /// <summary>Sends the delta water to the soil module.</summary>
        private void DoSoilWaterUptake()
        {
            if (mySoilWaterUptake.Sum() > Epsilon)
            {
                WaterChangedType waterTakenUp = new WaterChangedType();
                waterTakenUp.DeltaWater = new double[nLayers];
                for (int layer = 0; layer <= roots.BottomLayer; layer++)
                    waterTakenUp.DeltaWater[layer] = -mySoilWaterUptake[layer];

                if (WaterChanged != null)
                    WaterChanged.Invoke(waterTakenUp);
            }
        }
Exemplo n.º 4
0
        /// <summary>Computes the actual water uptake and send the deltas to soil module</summary>
        /// <returns>The amount of water taken up for each soil layer</returns>
        /// <exception cref="System.Exception">Error on computing water uptake</exception>
        private double[] DoSoilWaterUptake()
        {
            PMF.WaterChangedType WaterTakenUp = new PMF.WaterChangedType();
            WaterTakenUp.DeltaWater = new double[nLayers];

            double uptakeFraction = Math.Min(1.0, MathUtilities.Divide(myWaterDemand, mySoilAvailableWater.Sum(), 0.0));
            double[] result = new double[nLayers];

            if (useAltWUptake == "no")
            {
                for (int layer = 0; layer <= myRootFrontier; layer++)
                {
                    result[layer] = mySoilAvailableWater[layer] * uptakeFraction;
                    WaterTakenUp.DeltaWater[layer] = -result[layer];
                }
            }
            else
            { // Method implemented by RCichota
                // Uptake is distributed over the profile according to water availability,
                //  this means that water status and root distribution have been taken into account

                for (int layer = 0; layer <= myRootFrontier; layer++)
                {
                    result[layer] = mySoilAvailableWater[layer] * uptakeFraction;
                    WaterTakenUp.DeltaWater[layer] = -result[layer];
                }
                if (Math.Abs(WaterTakenUp.DeltaWater.Sum() + myWaterDemand) > 0.0001)
                    throw new Exception("Error on computing water uptake");
            }

            // send the delta water taken up
            WaterChanged.Invoke(WaterTakenUp);

            return result;
        }
Exemplo n.º 5
0
        /// <summary>Sends the delta water to the soil module.</summary>
        private void DoSoilWaterUptake()
        {
            if (swardSoilWaterUptake.Sum() > Epsilon)
            {
                WaterChangedType WaterTakenUp = new WaterChangedType();
                WaterTakenUp.DeltaWater = new double[nLayers];
                for (int layer = 0; layer <= RootFrontier; layer++)
                    WaterTakenUp.DeltaWater[layer] -= swardSoilWaterUptake[layer];

                if (WaterChanged != null)
                    WaterChanged.Invoke(WaterTakenUp);
            }
        }
Exemplo n.º 6
0
        //called at end of OnProcess() Event Handler.
        /// <summary>
        /// Sugar_set_other_variableses the specified i_dlt_no3gsm.
        /// </summary>
        /// <param name="i_dlt_no3gsm">The i_dlt_no3gsm.</param>
        /// <param name="i_dlt_nh4gsm">The i_dlt_nh4gsm.</param>
        /// <param name="i_dlt_sw_dep">The i_dlt_sw_dep.</param>
        void sugar_set_other_variables(double[] i_dlt_no3gsm, double[] i_dlt_nh4gsm, double[] i_dlt_sw_dep)
        {
            //*+  Purpose
            //*      Set the value of a variable or array in other module/s.

            //*+  Mission Statement
            //*     Set value of variable or array in other module/s

            //*+  Notes
            //*      a flag is set if any of the totals is requested.  The totals are
            //*      reset during the next process phase when this happens.

            double[] l_dlt_NO3 = new double[max_layer];    //! soil NO3 change (kg/ha)
            double[] l_dlt_NH4 = new double[max_layer];    //! soil NO3 change (kg/ha)
            int num_layers;            //! number of layers

            if (uptake_source == "calc")
                {

                num_layers = count_of_real_vals(dlayer, max_layer);

                //sv- I added this resize, from max_layer to num_layer.
                //    Done so the NitrogenChanges.DeltaNO3 etc. gets an array of a sensible size.
                Array.Resize(ref l_dlt_NO3, num_layers);
                Array.Resize(ref l_dlt_NH4, num_layers);
                Array.Resize(ref i_dlt_sw_dep, num_layers);

                for (int layer = 0; layer < num_layers; layer++)
                    {
                    l_dlt_NO3[layer] = i_dlt_no3gsm[layer] * gm2kg / sm2ha;
                    l_dlt_NH4[layer] = i_dlt_nh4gsm[layer] * gm2kg / sm2ha;
                    }

                NitrogenChangedType NitrogenChanges = new NitrogenChangedType();
                NitrogenChanges.Sender = "Sugarcane";
                NitrogenChanges.DeltaNO3 = l_dlt_NO3;
                NitrogenChanges.DeltaNH4 = l_dlt_NH4;

                NitrogenChanged.Invoke(NitrogenChanges);  //trigger/invoke the Nitrogen Changed Event

                WaterChangedType WaterChanges = new WaterChangedType();
                WaterChanges.DeltaWater = i_dlt_sw_dep;

                WaterChanged.Invoke(WaterChanges);      //trigger/invoke the Water Changed Event

                }
            else if (uptake_source == "swim3")
                {
                num_layers = count_of_real_vals(dlayer, max_layer);

                //sv- I added this resize, from max_layer to num_layer
                //    Done so the NitrogenChanges.DeltaNO3 etc. gets an array of the sensible size.
                Array.Resize(ref l_dlt_NO3, num_layers);
                Array.Resize(ref l_dlt_NH4, num_layers);

                for (int layer = 0; layer < num_layers; layer++)
                    {
                    l_dlt_NO3[layer] = i_dlt_no3gsm[layer] * gm2kg / sm2ha;
                    l_dlt_NH4[layer] = i_dlt_nh4gsm[layer] * gm2kg / sm2ha;
                    }

                NitrogenChangedType NitrogenChanges = new NitrogenChangedType();
                NitrogenChanges.Sender = "Sugarcane";
                NitrogenChanges.DeltaNO3 = l_dlt_NO3;
                NitrogenChanges.DeltaNH4 = l_dlt_NH4;

                NitrogenChanged.Invoke(NitrogenChanges);  //trigger/invoke the Nitrogen Changed Event
                }
            else
                {
                //! assume that the module that calculated uptake has also updated these pools.
                }
        }
Exemplo n.º 7
0
        //===============================================
        /// <summary>
        /// water uptake processes ...
        /// Rainss Notes 20010707
        /// - Should this be done per species? Is using the root frontier an acceptable solution?
        /// - Plant2 breaks this into two parts: WaterSupply and DoWaterUptake
        /// </summary>
        /// <returns></returns>
        private double SWUptakeProcess()
        {
            SoilCrop soilCrop = this.Soil.Crop(Name) as SoilCrop;

            //find out soil available water
            p_waterSupply = 0;
            for (int layer = 0; layer < Soil.Thickness.Length; layer++)
            {
                SWSupply[layer] = Math.Max(0.0, soilCrop.KL[layer] * (Soil.Water[layer] - soilCrop.LL[layer] * (Soil.Thickness[layer])))
                                * LayerFractionForRoots(layer, p_rootFrontier);
                if (layer < p_bottomRootLayer)
                    p_waterSupply += SWSupply[layer];
            }

            //uptake in proportion
            PMF.WaterChangedType WaterUptake = new PMF.WaterChangedType();
            WaterUptake.DeltaWater = new double[Soil.Thickness.Length];
            //double[] SWUptake = new double[dlayer.Length];
            double Fraction = Math.Min(1.0, p_waterDemand / p_waterSupply);
            double actualUptake = 0.0;
            for (int layer = 0; layer < p_bottomRootLayer; layer++)
            {   //water are taken up only in top layers that root can reach.
                SWUptake[layer] = SWSupply[layer] * Fraction;
                actualUptake += SWUptake[layer];
                WaterUptake.DeltaWater[layer] = -SWUptake[layer];
            }

            if (WaterChanged != null)
                WaterChanged.Invoke(WaterUptake);

            return actualUptake;
        }