示例#1
0
        //---------------------------------------------------------------------------------------------------------
        /// <summary>
        ///
        /// </summary>
        /// <param name="PM"></param>
        /// <param name="canopy"></param>
        public virtual void DoWaterInteraction(PhotosynthesisModel PM, LeafCanopy canopy, TranspirationMode mode)
        {
            for (int i = 0; i < canopy.NLayers; i++)
            {
                Rn[i] = AbsorbedIrradiancePAR[i] + AbsorbedIrradianceNIR[i];

                double BnUp     = 8 * canopy.Sigma * Math.Pow((PM.EnvModel.GetTemp(PM.Time) + PM.EnvModel.AbsoluteTemperature), 3) * (LeafTemp__[i] - PM.EnvModel.GetTemp(PM.Time)); //This should be: HEnergyBalance - * (LeafTemp__[i]-PM.EnvModel.GetTemp(PM.Time));
                double VPTLeaf  = 0.61365 * Math.Exp(17.502 * LeafTemp__[i] / (240.97 + LeafTemp__[i]));
                double VPTAir   = 0.61365 * Math.Exp(17.502 * PM.EnvModel.GetTemp(PM.Time) / (240.97 + PM.EnvModel.GetTemp(PM.Time)));
                double VPTAir_1 = 0.61365 * Math.Exp(17.502 * (PM.EnvModel.GetTemp(PM.Time) + 1) / (240.97 + (PM.EnvModel.GetTemp(PM.Time) + 1)));
                double VPTMin   = 0.61365 * Math.Exp(17.502 * PM.EnvModel.MinT / (240.97 + PM.EnvModel.MinT));

                double s = VPTAir_1 - VPTAir;
                VPD_la[i] = VPTLeaf - VPTMin;

                double Wl = VPTLeaf / (PM.EnvModel.ATM * 100) * 1000;
                double Wa = VPTMin / (PM.EnvModel.ATM * 100) * 1000;

                if (mode == TranspirationMode.unlimited)
                {
                    double a_var_gsCO2  = 1 / GbCO2[i];
                    double d_var_gsCO2  = (Wl - Wa) / (1000 - (Wl + Wa) / 2) * (canopy.Ca + Ci[i]) / 2;
                    double e_var_gsCO2  = A[i];
                    double f_var_gsCO2  = canopy.Ca - Ci[i];
                    double m_var_gsCO2  = 1.37; //Constant
                    double n_var_gsCO2  = 1.6;  //Constant
                    double a_lump_gsCO2 = e_var_gsCO2 * a_var_gsCO2 * m_var_gsCO2 + e_var_gsCO2 * a_var_gsCO2 * n_var_gsCO2 + d_var_gsCO2 * m_var_gsCO2 * n_var_gsCO2 - f_var_gsCO2 * m_var_gsCO2;
                    double b_lump_gsCO2 = e_var_gsCO2 * m_var_gsCO2 * (e_var_gsCO2 * Math.Pow(a_var_gsCO2, 2) * n_var_gsCO2 + a_var_gsCO2 * d_var_gsCO2 * m_var_gsCO2 * n_var_gsCO2 - a_var_gsCO2 * f_var_gsCO2 * n_var_gsCO2);
                    double c_lump_gsCO2 = -a_lump_gsCO2;
                    double d_lump_gsCO2 = m_var_gsCO2 * A[i];

                    GsCO2[i] = 2 * d_lump_gsCO2 / (Math.Pow((Math.Pow(a_lump_gsCO2, 2) - 4 * b_lump_gsCO2), 0.5) - a_lump_gsCO2);
                    double Gtw   = 1 / (1 / (1.37 * GbCO2[i]) + 1 / (1.6 * GsCO2[i])); //Are these the same constansts shown above
                    double GtCO2 = 1 / (1 / GbCO2[i] + 1 / GsCO2[i]);

                    //DO NOT DELETE - FILLED ARE OF SPREADSHEET
                    //double EMolsPerSecond = Gtw * (Wl - Wa) / (1000 - (Wl + Wa) / 2);
                    //double EMmPerHour = EMolsPerSecond * 18 / 1000 * 3600;

                    //double LambdaEEnergyBalance = 44100 * EMolsPerSecond; //44100 should be a parameter..discuss with AW
                    //double HEnergyBalance = 8 * canopy.Sigma * Math.Pow((PM.EnvModel.GetTemp(PM.Time) + PM.EnvModel.AbsoluteTemperature), 3);

                    //TDelta[i] = (Rn[i] - LambdaEEnergyBalance) / (HEnergyBalance + canopy.Rcp / Rbh[i]);

                    double rtw = canopy.Rair / Gtw * PM.EnvModel.ATM;

                    double a_lump_lambdaE = s * (Rn[i] - BnUp) + VPD_la[i] * canopy.Rcp / Rbh[i];
                    double b_lump_lambdaE = s + canopy.G * (rtw) / Rbh[i];
                    double lambdaE        = a_lump_lambdaE / b_lump_lambdaE;
                    double EKgPerSecond   = lambdaE / canopy.Lambda;
                    WaterUseMolsSecond[i] = EKgPerSecond / 18 * 1000;
                    WaterUse[i]           = EKgPerSecond * 3600;

                    double a_lump_deltaT = canopy.G * (Rn[i] - BnUp) * rtw / canopy.Rcp - VPD_la[i];
                    double d_lump_deltaT = s + canopy.G * rtw / Rbh[i];
                    TDelta[i] = a_lump_deltaT / d_lump_deltaT;

                    VPD_la[i] = 0.61365 * Math.Exp(17.502 * LeafTemp__[i] / (240.97 + LeafTemp__[i])) - 0.61365 * Math.Exp(17.502 * PM.EnvModel.MinT / (240.97 + PM.EnvModel.MinT));

                    LeafTemp[i] = PM.EnvModel.GetTemp(PM.Time) + TDelta[i];
                }

                else
                {
                    WaterUseMolsSecond[i] = WaterUse[i] / 18 * 1000 / 3600;
                    double EKgPerSecond = WaterUseMolsSecond[i] * 18 / 1000;

                    double rtw = (s * (Rn[i] - BnUp) + VPD_la[i] * canopy.Rcp / Rbh[i] - canopy.Lambda * EKgPerSecond * s) * Rbh[i] / (canopy.Lambda * EKgPerSecond * canopy.G);
                    Rsw[i] = rtw - Rbw[i];

                    GsCO2[i] = canopy.Rair * PM.EnvModel.ATM / Rsw[i] / 1.6;

                    double GtCO2 = 1 / (1 / GbCO2[i] + 1 / GsCO2[i]);

                    double a_lump_deltaT = canopy.G * (Rn[i] - BnUp) * rtw / canopy.Rcp - VPD_la[i];
                    double d_lump_deltaT = s + canopy.G * rtw / Rbh[i];

                    TDelta[i] = a_lump_deltaT / d_lump_deltaT;

                    //DO NOT DELETE - FILLED ARE OF SPREADSHEET
                    //double LambdaEEnergyBalance = 44100 * EMolsPerSecond; //44100 should be a parameter..discuss with AW
                    //double HEnergyBalance = 8 * canopy.Sigma * Math.Pow((PM.EnvModel.GetTemp(PM.Time) + PM.EnvModel.AbsoluteTemperature), 3);

                    //double Tdelta = (Rn[i] - LambdaEEnergyBalance) / (HEnergyBalance + canopy.Rcp / Rbh[i]); //This is not used anywhere

                    //double Gtw = EMolsPerSecond * (1000 - (Wl + Wa) / 2) / (Wl - Wa);

                    //GsCO2[i] = 1 / ((1 / Gtw - 1 / (1.37 * GbCO2[i])) * 1.6);

                    //GtCO2 = 1 / (1 / GbCO2[i] + 1 / GsCO2[i]);

                    LeafTemp[i] = PM.EnvModel.GetTemp(PM.Time) + TDelta[i];
                }
            }
        }
示例#2
0
        public override void Run(bool sendNotification, double swAvail = 0, double maxHourlyT = -1, double sunlitFraction = 0, double shadedFraction = 0)
        {
            if (!Initialised)
            {
                return;
            }

            if (sendNotification && NotifyStart != null)
            {
                NotifyStart(false);
            }

            // Sets the environment
            EnvModel.Run(this.Time);
            Canopy.CalcCanopyStructure(this.EnvModel.SunAngle.Rad);

            // Sets the canopy status
            SunlitAc1 = new SunlitCanopy(Canopy.NLayers, SSType.Ac1);
            SunlitAj  = new SunlitCanopy(Canopy.NLayers, SSType.Aj);
            ShadedAc1 = new ShadedCanopy(Canopy.NLayers, SSType.Ac1);
            ShadedAj  = new ShadedCanopy(Canopy.NLayers, SSType.Aj);

            double temp = EnvModel.GetTemp(Time);

            // Don't perform photosynthesis beyond temperature boundaries
            if (temp > Canopy.CPath.JTMax || temp < Canopy.CPath.JTMin || temp > Canopy.CPath.GmTMax || temp < Canopy.CPath.GmTMin)
            {
                ZeroVariables();
                return;
            }

            // Don't perform photosynthesis if the sun isn't up
            if (EnvModel.Ios.Value(this.Time) <= (0 + double.Epsilon))
            {
                ZeroVariables();
                return;
            }

            // Calculate the leaf area index
            SunlitAc1.CalcLAI(this.Canopy, ShadedAc1);
            SunlitAj.CalcLAI(this.Canopy, ShadedAj);
            ShadedAc1.CalcLAI(this.Canopy, SunlitAc1);
            ShadedAj.CalcLAI(this.Canopy, SunlitAj);

            // Run the canopy model
            Canopy.Run(this, EnvModel);
            SunlitAc1.Run(Canopy.NLayers, this, ShadedAc1);
            SunlitAj.Run(Canopy.NLayers, this, ShadedAj);
            ShadedAc1.Run(Canopy.NLayers, this, SunlitAc1);
            ShadedAj.Run(Canopy.NLayers, this, SunlitAj);

            // Set the transpirtation mode
            TranspirationMode mode = TranspirationMode.unlimited;

            if (maxHourlyT != -1)
            {
                mode = TranspirationMode.limited;
            }

            // For the initial photosynthesis calculation each hour we use air temperature
            bool useAirTemp = true;

            var results = new bool[4];

            // Initial calculation
            results[0] = (SunlitAc1.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, sunlitFraction));
            results[1] = (SunlitAj.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, sunlitFraction));
            results[2] = (ShadedAc1.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, shadedFraction));
            results[3] = (ShadedAj.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, shadedFraction));

            // After initialisation we use new leaf temperature
            useAirTemp = false;

            // SUNLIT CALCULATIONS
            double defaultAC1A     = 0.0;
            double defaultAC1Water = 0.0;
            double defaultAJA      = 0.0;
            double defaultAJWater  = 0.0;

            // If the initial calculation fails, set values to 0
            if (results[0] || results[1])
            {
                SunlitAc1.A[0]        = 0.0;
                SunlitAc1.WaterUse[0] = 0.0;
                SunlitAj.A[0]         = 0.0;
                SunlitAj.WaterUse[0]  = 0.0;
            }
            else
            {
                defaultAC1A     = SunlitAc1.A[0];
                defaultAC1Water = SunlitAc1.WaterUse[0];
                defaultAJA      = SunlitAj.A[0];
                defaultAJWater  = SunlitAj.WaterUse[0];
            }

            // Ben Ababaei (2019.10.14): If NONE of the As is > 0.5, don't get inside the following loop.
            // If there is sufficient photosynthetic rate
            if (SunlitAc1.A[0] > 0.5 && SunlitAj.A[0] > 0.5)
            {
                for (int n = 0; n < 3; n++)
                {
                    results[0] = SunlitAc1.CalcPhotosynthesis(this, useAirTemp, 0, SunlitAc1.LeafTemp[0], mode, maxHourlyT, sunlitFraction);
                    results[1] = SunlitAj.CalcPhotosynthesis(this, useAirTemp, 0, SunlitAj.LeafTemp[0], mode, maxHourlyT, sunlitFraction);

                    // If any of the above is < 0, set both values zero (for each type of leaf separately).
                    if (results[0] || results[1])
                    {
                        SunlitAc1.A[0]        = defaultAC1A;
                        SunlitAc1.WaterUse[0] = defaultAC1Water;
                        SunlitAj.A[0]         = defaultAJA;
                        SunlitAj.WaterUse[0]  = defaultAC1Water;

                        break;
                    }
                }
            }

            // SHADED CALCULATIONS
            if (results[2] || results[3])
            {
                ShadedAc1.A[0]        = 0.0;
                ShadedAc1.WaterUse[0] = 0.0;
                ShadedAj.A[0]         = 0.0;
                ShadedAj.WaterUse[0]  = 0.0;
            }
            else
            {
                defaultAC1A     = ShadedAc1.A[0];
                defaultAC1Water = ShadedAc1.WaterUse[0];
                defaultAJA      = ShadedAj.A[0];
                defaultAJWater  = ShadedAj.WaterUse[0];
            }

            // If there is sufficient photosynthetic rate
            if (ShadedAc1.A[0] > 0.5 && ShadedAj.A[0] > 0.5)
            {
                for (int n = 0; n < 3; n++)
                {
                    results[2] = ShadedAc1.CalcPhotosynthesis(this, useAirTemp, 0, ShadedAc1.LeafTemp[0], mode, maxHourlyT, shadedFraction);
                    results[3] = ShadedAj.CalcPhotosynthesis(this, useAirTemp, 0, ShadedAj.LeafTemp[0], mode, maxHourlyT, shadedFraction);

                    // If any of the above is < 0, set both values zero (for each type of leaf separately).
                    if (results[2] || results[3])
                    {
                        ShadedAc1.A[0]        = defaultAC1A;
                        ShadedAc1.WaterUse[0] = defaultAC1Water;
                        ShadedAj.A[0]         = defaultAJA;
                        ShadedAj.WaterUse[0]  = defaultAJWater;
                    }
                }
            }

            if (sendNotification && NotifyFinish != null)
            {
                NotifyFinish();
            }
        }
示例#3
0
        //---------------------------------------------------------------------------------------------------------
        /// <summary>
        ///
        /// </summary>
        /// <param name="s"></param>
        /// <param name="PM"></param>
        /// <param name="useAirTemp"></param>
        /// <param name="layer"></param>
        /// <param name="leafTemperature"></param>
        /// <param name="mode"></param>
        /// <param name="maxHourlyT"></param>
        /// <param name="Tfraction"></param>
        /// <returns></returns>
        public static bool CalcPhotosynthesis(this SunlitShadedCanopy s, PhotosynthesisModel PM, bool useAirTemp, int layer, double leafTemperature,
                                              TranspirationMode mode, double maxHourlyT, double Tfraction)
        {
            double p, q;

            LeafCanopy canopy = PM.Canopy;

            s.Oi[layer] = canopy.OxygenPartialPressure;

            s.Om[layer] = canopy.OxygenPartialPressure;

            s.Oc[layer] = s.Oi[layer];

            s.LeafTemp__[layer] = leafTemperature;

            if (useAirTemp)
            {
                s.LeafTemp__[layer] = PM.EnvModel.GetTemp(PM.Time);
            }

            s.CalcConductanceResistance(PM, canopy);

            s.VcMaxT[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], s.VcMax25[layer], canopy.CPath.VcTMin);
            s.RdT[layer]    = TemperatureFunction.Val2(s.LeafTemp__[layer], s.Rd25[layer], canopy.CPath.RdTMin);
            s.JMaxT[layer]  = TemperatureFunction.Val(s.LeafTemp__[layer], s.JMax25[layer], canopy.CPath.JMaxC, canopy.CPath.JTMax, canopy.CPath.JTMin, canopy.CPath.JTOpt, canopy.CPath.JBeta);

            canopy.Ja = (1 - canopy.F) / 2;

            s.J[layer] = (canopy.Ja * s.AbsorbedIrradiance[layer] + s.JMaxT[layer] - Math.Pow(Math.Pow(canopy.Ja * s.AbsorbedIrradiance[layer] + s.JMaxT[layer], 2) -
                                                                                              4 * canopy.Theta * s.JMaxT[layer] * canopy.Ja * s.AbsorbedIrradiance[layer], 0.5)) / (2 * canopy.Theta);

            s.Kc[layer]   = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KcP25, canopy.CPath.KcTMin);
            s.Ko[layer]   = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KoP25, canopy.CPath.KoTMin);
            s.VcVo[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.VcMax_VoMaxP25, canopy.CPath.VcMax_VoMaxTMin);


            s.ScO[layer] = s.Ko[layer] / s.Kc[layer] * s.VcVo[layer];

            s.G_[layer] = 0.5 / s.ScO[layer];

            s.r_[layer] = s.G_[layer] * s.Oc[layer];

            canopy.Sco = s.ScO[layer];

            s.gm_CO2T[layer] = s.LAIS[layer] * TemperatureFunction.Val(s.LeafTemp__[layer], canopy.Gm25[layer], canopy.CPath.GmC, canopy.CPath.GmTMax, canopy.CPath.GmTMin, canopy.CPath.GmTOpt, canopy.CPath.GmBeta);

            if (mode == TranspirationMode.unlimited)
            {
                s.Ci[layer] = canopy.CPath.CiCaRatio * canopy.Ca;

                p = s.Ci[layer];

                q = 1 / s.gm_CO2T[layer];

                //Caculate A's
                if (s.type == SSType.AC1)
                {
                    s.A[layer] = CalcAc(s, canopy, layer, TranspirationMode.unlimited, p, q);
                }
                else if (s.type == SSType.AJ)
                {
                    s.A[layer] = CalcAj(s, canopy, layer, TranspirationMode.unlimited, p, q);
                }

                if (s.A[layer] < 0 || double.IsNaN(s.A[layer]))
                {
                    s.A[layer] = 0;
                }

                if (PM.conductanceModel == PhotosynthesisModel.ConductanceModel.DETAILED)
                {
                    s.Ci[layer] = canopy.Ca - s.A[layer] / s.Gb_CO2[layer] - s.A[layer] / s.gs_CO2[layer];
                }

                s.Cc[layer] = s.Ci[layer] - s.A[layer] / s.gm_CO2T[layer];

                if (s.Cc[layer] < 0 || double.IsNaN(s.Cc[layer]))
                {
                    s.Cc[layer] = 0;
                }

                s.CiCaRatio[layer] = s.Ci[layer] / canopy.Ca;

                s.DoWaterInteraction(PM, canopy, mode);
            }

            else if (mode == TranspirationMode.limited)
            {
                s.WaterUse[layer] = maxHourlyT * Tfraction;

                s.Elambda[layer] = s.WaterUse[layer] / (0.001 * 3600) * canopy.Lambda / 1000;

                s.DoWaterInteraction(PM, canopy, mode);

                s.gm_CO2T[layer] = s.LAIS[layer] * TemperatureFunction.Val(s.LeafTemp__[layer], canopy.Gm25[layer], canopy.CPath.GmC, canopy.CPath.GmTMax, canopy.CPath.GmTMin, canopy.CPath.GmTOpt, canopy.CPath.GmBeta);

                double Gt = 1 / (1 / s.GbCO2[layer] + 1 / s.GsCO2[layer]);

                p = canopy.Ca - s.WaterUseMolsSecond[layer] * canopy.Ca / (Gt + s.WaterUseMolsSecond[layer] / 2);
                q = 1 / (Gt + s.WaterUseMolsSecond[layer] / 2) + 1 / s.gm_CO2T[layer];

                //Caculate A's
                if (s.type == SSType.AC1)
                {
                    s.A[layer] = CalcAc(s, canopy, layer, TranspirationMode.limited, p, q);
                }
                else if (s.type == SSType.AJ)
                {
                    s.A[layer] = CalcAj(s, canopy, layer, TranspirationMode.limited, p, q);
                }

                s.Cb[layer] = canopy.Ca - s.A[layer] / s.GbCO2[layer];

                s.Ci[layer] = ((Gt - s.WaterUseMolsSecond[layer] / 2) * canopy.Ca - s.A[layer]) / (Gt + s.WaterUseMolsSecond[layer] / 2);
            }

            double airTemp = PM.EnvModel.GetTemp(PM.Time);

            if (useAirTemp)
            {
                s.LeafTemp[layer] = PM.EnvModel.GetTemp(PM.Time);
            }

            double diffTemp = s.LeafTemp__[layer] - s.LeafTemp[layer];


            s.LeafTemp[layer] = (s.LeafTemp[layer] + s.LeafTemp__[layer]) / 2;

            if ((Math.Abs(diffTemp) > s.leafTempTolerance) || double.IsNaN(s.LeafTemp[layer]))
            {
                return(false);
            }
            return(true);
        }
示例#4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="canopy"></param>
        /// <param name="layer"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static double CalcAc(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode, double p, double q)
        {
            double x_1, x_2, x_3, x_4, x_5, x_6, x_7;

            x_1 = s.VcMaxT[layer];
            x_2 = 0;
            x_3 = s.Kc[layer] * (1 + s.Oc[layer] / s.Ko[layer]);
            x_4 = 0;
            x_5 = 0;
            x_6 = 0;
            x_7 = 0;

            return(CalcAssimilation(s, x_1, x_2, x_3, x_4, x_5, x_6, x_7, p, q, layer, canopy));
        }
示例#5
0
        public override void Run(bool sendNotification, double swAvail = 0, double maxHourlyT = -1, double sunlitFraction = 0, double shadedFraction = 0)
        {
            if (!Initialised)
            {
                return;
            }

            if (sendNotification && NotifyStart != null)
            {
                NotifyStart(false);
            }

            EnvModel.Run(this.Time);
            Canopy.CalcCanopyStructure(this.EnvModel.SunAngle.Rad);

            SunlitAC1 = new SunlitCanopy(Canopy.NLayers, SSType.AC1);
            SunlitAJ  = new SunlitCanopy(Canopy.NLayers, SSType.AJ);
            ShadedAC1 = new ShadedCanopy(Canopy.NLayers, SSType.AC1);
            ShadedAJ  = new ShadedCanopy(Canopy.NLayers, SSType.AJ);

            double temp = EnvModel.GetTemp(Time);

            if (temp > Canopy.CPath.JTMax || temp < Canopy.CPath.JTMin || temp > Canopy.CPath.GmTMax || temp < Canopy.CPath.GmTMin)
            {
                ZeroVariables();
                return;
            }

            if (EnvModel.Ios.Value(this.Time) <= (0 + double.Epsilon))
            {
                ZeroVariables();
                return;
            }


            SunlitAC1.CalcLAI(this.Canopy, ShadedAC1);
            SunlitAJ.CalcLAI(this.Canopy, ShadedAJ);
            ShadedAC1.CalcLAI(this.Canopy, SunlitAC1);
            ShadedAJ.CalcLAI(this.Canopy, SunlitAJ);

            Canopy.Run(this, EnvModel);

            SunlitAC1.Run(Canopy.NLayers, this, ShadedAC1);
            SunlitAJ.Run(Canopy.NLayers, this, ShadedAJ);
            ShadedAC1.Run(Canopy.NLayers, this, SunlitAC1);
            ShadedAJ.Run(Canopy.NLayers, this, SunlitAJ);

            TranspirationMode mode = TranspirationMode.unlimited;

            if (maxHourlyT != -1)
            {
                mode = TranspirationMode.limited;
            }

            bool useAirTemp = false;

            List <bool> results = new List <bool>();

            results.Add(SunlitAC1.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, sunlitFraction));
            results.Add(SunlitAJ.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, sunlitFraction));
            results.Add(ShadedAC1.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, shadedFraction));
            results.Add(ShadedAJ.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), mode, maxHourlyT, shadedFraction));

            Count = 1;

            bool caughtError = false;

            while (results.Contains(false) && !caughtError)
            {
                results.Clear();
                results.Add(SunlitAC1.CalcPhotosynthesis(this, useAirTemp, 0, SunlitAC1.LeafTemp[0], mode, maxHourlyT, sunlitFraction));
                results.Add(SunlitAJ.CalcPhotosynthesis(this, useAirTemp, 0, SunlitAJ.LeafTemp[0], mode, maxHourlyT, sunlitFraction));
                results.Add(ShadedAC1.CalcPhotosynthesis(this, useAirTemp, 0, ShadedAC1.LeafTemp[0], mode, maxHourlyT, shadedFraction));
                results.Add(ShadedAJ.CalcPhotosynthesis(this, useAirTemp, 0, ShadedAJ.LeafTemp[0], mode, maxHourlyT, shadedFraction));

                Count++;

                if (Count > 50 && !caughtError)
                {
                    ZeroVariables();

                    //writeScenario(swAvail);
                    caughtError = true;

                    return;
                }
            }

            // canopy.calcCanopyBiomassAccumulation(this);

            if (sendNotification && NotifyFinish != null)
            {
                NotifyFinish();
            }
            // writeScenario(swAvail);
        }
示例#6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="canopy"></param>
        /// <param name="layer"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static double CalcAj(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode, double p, double q)
        {
            double x_1, x_2, x_3, x_4, x_5, x_6, x_7;

            x_1 = s.J[layer] / 4;
            x_2 = 2 * s.G_[layer];
            x_3 = 0;
            x_4 = 0;
            x_5 = 0;
            x_6 = 0;
            x_7 = 0;

            return(CalcAssimilation(s, x_1, x_2, x_3, x_4, x_5, x_6, x_7, p, q, layer, canopy));;
        }
示例#7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="canopy"></param>
        /// <param name="layer"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static double CalcAj(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode)
        {
            s.x_1 = (1 - canopy.CPath.X) * canopy.z * s.J[layer] / 3.0;
            s.x_2 = 7.0 / 3.0 * s.G_[layer];
            s.x_3 = 0;
            s.x_4 = 0;
            s.x_5 = canopy.CPath.X * canopy.z * s.J[layer] / canopy.CPath.Phi;
            s.x_6 = 0;
            s.x_7 = s.Cc[layer] * (1 - canopy.CPath.X) * canopy.z * s.J[layer] / (3 * s.Cc[layer] + 7 * s.G_[layer] * s.Oc[layer]);
            s.x_8 = 1;
            s.x_9 = 1;

            return(CalcAssimilation(s, layer, canopy));;
        }
示例#8
0
        //---------------------------------------------------------------------------------------------------------
        /// <summary>
        ///
        /// </summary>
        /// <param name="PM"></param>
        /// <param name="useAirTemp"></param>
        /// <param name="layer"></param>
        /// <param name="leafTemperature"></param>
        /// <param name="cm"></param>
        /// <param name="mode"></param>
        /// <param name="maxHourlyT"></param>
        /// <param name="Tfraction"></param>
        /// <returns></returns>
        public static bool CalcPhotosynthesis(this SunlitShadedCanopy s, PhotosynthesisModel PM, bool useAirTemp, int layer, double leafTemperature, double cm, double cc, double oc,
                                              TranspirationMode mode, double maxHourlyT, double Tfraction)
        {
            LeafCanopy canopy = PM.Canopy;

            s.LeafTemp__[layer] = leafTemperature;
            if (useAirTemp)
            {
                s.LeafTemp__[layer] = PM.EnvModel.GetTemp(PM.Time);
            }

            s.CalcConductanceResistance(PM, canopy);

            s.Cm__[layer] = cm;
            s.Cc[layer]   = cc;
            s.Oc[layer]   = oc;

            s.VcMaxT[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], s.VcMax25[layer], canopy.CPath.VcTEa);
            s.RdT[layer]    = TemperatureFunction.Val2(s.LeafTemp__[layer], s.Rd25[layer], canopy.CPath.RdTEa);
            s.JMaxT[layer]  = TemperatureFunction.Val(s.LeafTemp__[layer], s.JMax25[layer], canopy.CPath.JMaxC, canopy.CPath.JTMax, canopy.CPath.JTMin, canopy.CPath.JTOpt, canopy.CPath.JBeta);
            s.VpMaxT[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], s.VpMax25[layer], canopy.CPath.VpMaxTEa);
            s.GmT[layer]    = TemperatureFunction.Val(s.LeafTemp__[layer], s.Gm25[layer], canopy.CPath.GmC, canopy.CPath.GmTMax, canopy.CPath.GmTMin, canopy.CPath.GmTOpt, canopy.CPath.GmBeta);
            s.Vpr[layer]    = canopy.Vpr_l * s.LAIS[layer];

            canopy.Ja = (1 - canopy.F) / 2;

            s.J[layer] = (canopy.Ja * s.AbsorbedIrradiance[layer] + s.JMaxT[layer] - Math.Pow(Math.Pow(canopy.Ja * s.AbsorbedIrradiance[layer] + s.JMaxT[layer], 2) -
                                                                                              4 * canopy.Theta * s.JMaxT[layer] * canopy.Ja * s.AbsorbedIrradiance[layer], 0.5)) / (2 * canopy.Theta);

            s.Kc[layer]   = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KcP25, canopy.CPath.KcTEa);
            s.Ko[layer]   = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KoP25, canopy.CPath.KoTEa);
            s.VcVo[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.VcMax_VoMaxP25, canopy.CPath.VcMax_VoMaxTEa);

            s.Oi[layer] = canopy.OxygenPartialPressure;
            s.Om[layer] = canopy.OxygenPartialPressure;

            s.ScO[layer] = s.Ko[layer] / s.Kc[layer] * s.VcVo[layer];
            s.G_[layer]  = 0.5 / s.ScO[layer];
            canopy.Sco   = s.ScO[layer];

            s.K_[layer]  = s.Kc[layer] * (1 + canopy.OxygenPartialPressure / s.Ko[layer]);
            s.Kp[layer]  = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KpP25, canopy.CPath.KpTEa);
            s.Gbs[layer] = canopy.Gbs_CO2 * s.LAIS[layer];

            if (mode == TranspirationMode.unlimited)
            {
                s.Rm[layer]  = s.RdT[layer] * 0.5;
                s.Gbs[layer] = canopy.Gbs_CO2 * s.LAIS[layer];
                s.Ci[layer]  = canopy.CPath.CiCaRatio * canopy.Ca;

                s.p = s.Ci[layer];
                s.q = 1 / s.GmT[layer];

                //Caculate A's
                if (s.type == SSType.Ac1)
                {
                    s.A[layer] = CalcAc1(s, canopy, layer, TranspirationMode.unlimited);
                }
                else if (s.type == SSType.Ac2)
                {
                    s.A[layer] = CalcAc2(s, canopy, layer, TranspirationMode.unlimited);
                }
                else if (s.type == SSType.Aj)
                {
                    s.A[layer] = CalcAj(s, canopy, layer, TranspirationMode.unlimited);
                }

                s.DoWaterInteraction(PM, canopy, mode);
            }
            else if (mode == TranspirationMode.limited)
            {
                s.WaterUse[layer] = maxHourlyT * Tfraction;
                s.DoWaterInteraction(PM, canopy, mode);

                double Gt = 1 / (1 / s.GbCO2[layer] + 1 / s.GsCO2[layer]);

                s.p = canopy.Ca - s.WaterUseMolsSecond[layer] * canopy.Ca / (Gt + s.WaterUseMolsSecond[layer] / 2);
                s.q = 1 / (Gt + s.WaterUseMolsSecond[layer] / 2) + 1 / s.GmT[layer];

                //Caculate A's
                if (s.type == SSType.Ac1)
                {
                    s.A[layer] = CalcAc1(s, canopy, layer, TranspirationMode.limited);
                }
                else if (s.type == SSType.Ac2)
                {
                    s.A[layer] = CalcAc2(s, canopy, layer, TranspirationMode.limited);
                }
                else if (s.type == SSType.Aj)
                {
                    s.A[layer] = CalcAj(s, canopy, layer, TranspirationMode.limited);
                }

                s.Ci[layer] = ((Gt - s.WaterUseMolsSecond[0] / 2) * canopy.Ca - s.A[layer]) / (Gt + s.WaterUseMolsSecond[0] / 2);
            }

            s.Oc[layer]       = canopy.Alpha * s.A[layer] / (canopy.Constant * s.Gbs[layer]) + s.Om[layer];
            s.Cc[layer]       = (s.Ci[layer] - s.A[layer] / s.GmT[layer]) + (((s.Ci[layer] - s.A[layer] / s.GmT[layer]) * s.x_4 + s.x_5) - s.x_6 * s.A[layer] - s.m - s.x_7) * s.x_8 / s.Gbs[layer];
            s.Cm[layer]       = s.Ci[layer] - s.A[layer] / s.GmT[layer];
            s.LeafTemp[layer] = (s.LeafTemp[layer] + s.LeafTemp__[layer]) / 2;

            // Test if A is sensible
            if (double.IsNaN(s.A[layer]) || s.A[layer] <= 0.0)
            {
                return(true);
            }
            // Test if WaterUse is sensible
            else if (double.IsNaN(s.WaterUse[layer]) || s.WaterUse[layer] <= 0)
            {
                return(true);
            }
            // If both are sensible, return false (no errors fonud)
            else
            {
                return(false);
            }
        }
示例#9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="canopy"></param>
        /// <param name="layer"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static double CalcAc(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode, double p, double q)
        {
            double x_1, x_2, x_3, x_4, x_5, x_6, x_7;

            x_1 = s.VcMaxT[layer];
            x_2 = s.Kc[layer] / s.Ko[layer];
            x_3 = s.Kc[layer];
            x_4 = 0;
            x_5 = 0;
            x_6 = 1;
            x_7 = 1;

            if (s.type == SSType.AC1)
            {
                x_4 = s.VpMaxT[layer] / (s.Cm__[layer] + s.Kp[layer]); //Delta Eq (A56)
                                                                       //x_5 = 0;
            }
            else if (s.type == SSType.AC2)
            {
                x_5 = s.Vpr[layer];
            }

            s.X_4 = x_4;
            s.X_5 = x_5;

            return(CalcAssimilation(s, x_1, x_2, x_3, x_4, x_5, x_6, x_7, p, q, layer, canopy));
        }
示例#10
0
        public static double CalcAc2(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode)
        {
            s.x_1 = s.VcMaxT[layer];
            s.x_2 = s.Kc[layer] / s.Ko[layer];
            s.x_3 = s.Kc[layer];
            s.x_4 = 0;
            s.x_5 = s.Vpr[layer];
            s.x_6 = 0;
            s.x_7 = s.Cc[layer] * s.VcMaxT[layer] / (s.Cc[layer] + s.Kc[layer] * (1 + s.Oc[layer] / s.Ko[layer]));;
            s.x_8 = 1;
            s.x_9 = 1;

            return(CalcAssimilation(s, layer, canopy));
        }
示例#11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="canopy"></param>
        /// <param name="layer"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static double CalcAj(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode, double p, double q)
        {
            double x_1, x_2, x_3, x_4, x_5, x_6, x_7;

            x_1 = (1 - canopy.CPath.X) * s.J[layer] / 3.0;
            x_2 = 7.0 / 3.0 * s.G_[layer];
            x_3 = 0;
            x_4 = 0;
            x_5 = canopy.CPath.X * s.J[layer] / canopy.CPath.Phi;
            x_6 = 1;
            x_7 = 1;

            s.X_4 = x_4;
            s.X_5 = x_5;

            return(CalcAssimilation(s, x_1, x_2, x_3, x_4, x_5, x_6, x_7, p, q, layer, canopy));;
        }
示例#12
0
        //---------------------------------------------------------------------------------------------------------
        /// <summary>
        ///
        /// </summary>
        /// <param name="PM"></param>
        /// <param name="useAirTemp"></param>
        /// <param name="layer"></param>
        /// <param name="leafTemperature"></param>
        /// <param name="cm"></param>
        /// <param name="mode"></param>
        /// <param name="maxHourlyT"></param>
        /// <param name="Tfraction"></param>
        /// <returns></returns>
        public static bool CalcPhotosynthesis(this SunlitShadedCanopy s, PhotosynthesisModel PM, bool useAirTemp, int layer, double leafTemperature, double cm,
                                              TranspirationMode mode, double maxHourlyT, double Tfraction)
        {
            double p, q;

            LeafCanopy canopy = PM.Canopy;

            //leafTemp[layer] = PM.envModel.getTemp(PM.time);
            s.LeafTemp__[layer] = leafTemperature;

            if (useAirTemp)
            {
                s.LeafTemp__[layer] = PM.EnvModel.GetTemp(PM.Time);
            }

            s.Cm__[layer] = cm;

            double vpd = PM.EnvModel.GetVPD(PM.Time);

            s.VcMaxT[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], s.VcMax25[layer], canopy.CPath.VcTMin);
            s.RdT[layer]    = TemperatureFunction.Val2(s.LeafTemp__[layer], s.Rd25[layer], canopy.CPath.RdTMin);
            s.JMaxT[layer]  = TemperatureFunction.Val(s.LeafTemp__[layer], s.JMax25[layer], canopy.CPath.JMaxC, canopy.CPath.JTMax, canopy.CPath.JTMin, canopy.CPath.JTOpt, canopy.CPath.JBeta);
            s.VpMaxT[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], s.VpMax25[layer], canopy.CPath.VpMaxTMin);


            s.Vpr[layer] = canopy.Vpr_l * s.LAIS[layer];

            canopy.Ja = (1 - canopy.F) / 2;

            s.J[layer] = (canopy.Ja * s.AbsorbedIrradiance[layer] + s.JMaxT[layer] - Math.Pow(Math.Pow(canopy.Ja * s.AbsorbedIrradiance[layer] + s.JMaxT[layer], 2) -
                                                                                              4 * canopy.Theta * s.JMaxT[layer] * canopy.Ja * s.AbsorbedIrradiance[layer], 0.5)) / (2 * canopy.Theta);

            s.Kc[layer]   = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KcP25, canopy.CPath.KcTMin);
            s.Ko[layer]   = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KoP25, canopy.CPath.KoTMin);
            s.VcVo[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.VcMax_VoMaxP25, canopy.CPath.VcMax_VoMaxTMin);

            s.ScO[layer] = s.Ko[layer] / s.Kc[layer] * s.VcVo[layer];

            s.G_[layer] = 0.5 / s.ScO[layer];

            canopy.Sco = s.ScO[layer]; //For reporting ???

            s.K_[layer] = s.Kc[layer] * (1 + canopy.OxygenPartialPressure / s.Ko[layer]);

            s.Kp[layer] = TemperatureFunction.Val2(s.LeafTemp__[layer], canopy.CPath.KpP25, canopy.CPath.KpTMin);

            s.Gbs[layer] = canopy.Gbs_CO2 * s.LAIS[layer];

            s.Oi[layer] = canopy.OxygenPartialPressure;

            s.Om[layer] = canopy.OxygenPartialPressure;

            if (mode == TranspirationMode.unlimited)
            {
                s.VPD[layer] = PM.EnvModel.GetVPD(PM.Time);

                s.gm_CO2T[layer] = s.LAIS[layer] * TemperatureFunction.Val(s.LeafTemp__[layer], canopy.Gm25[layer], canopy.CPath.GmC, canopy.CPath.GmTMax, canopy.CPath.GmTMin, canopy.CPath.GmTOpt, canopy.CPath.GmBeta);

                s.Rm[layer] = s.RdT[layer] * 0.5;

                s.Gbs[layer] = canopy.Gbs_CO2 * s.LAIS[layer];

                s.Ci[layer] = canopy.CPath.CiCaRatio * canopy.Ca;

                p = s.Ci[layer];

                q = 1 / s.gm_CO2T[layer];

                //Caculate A's
                if (s.type == SSType.AJ)
                {
                    s.A[layer] = CalcAj(s, canopy, layer, TranspirationMode.unlimited, p, q);
                }
                else
                {
                    s.A[layer] = CalcAc(s, canopy, layer, TranspirationMode.unlimited, p, q);
                }

                s.CalcConductanceResistance(PM, canopy);

                s.Cm[layer] = s.Ci[layer] - s.A[layer] / s.gm_CO2T[layer];

                s.XX = s.Cm[layer] * s.X_4 + s.X_5;

                if (s.type == SSType.AC1 || s.type == SSType.AC2)
                {
                    s.Vp[layer] = Math.Min(s.Cm[layer] * s.VpMaxT[layer] / (s.Cm[layer] + s.Kp[layer]), s.Vpr[layer]);
                }
                else if (s.type == SSType.AJ)
                {
                    s.Vp[layer] = canopy.CPath.X * s.J[layer] / 2;
                }

                s.Oc[layer] = canopy.Alpha * s.A[layer] / (0.047 * s.Gbs[layer]) + s.Om[layer];

                s.r_[layer] = s.G_[layer] * s.Oc[layer];

                s.Cc[layer] = s.Cm[layer] + (s.XX - s.A[layer] - s.Rm[layer]) / s.Gbs[layer];

                if (s.Cc[layer] < 0 || double.IsNaN(s.Cc[layer]))
                {
                    s.Cc[layer] = 0;
                }

                s.F[layer] = s.Gbs[layer] * (s.Cc[layer] - s.Cm[layer]) / s.XX;

                s.DoWaterInteraction(PM, canopy, mode);
            }

            else if (mode == TranspirationMode.limited)
            {
                s.WaterUse[layer] = maxHourlyT * Tfraction;

                s.Elambda[layer] = s.WaterUse[layer] / (0.001 * 3600) * canopy.Lambda / 1000;

                double totalAbsorbed = s.AbsorbedIrradiancePAR[layer] + s.AbsorbedIrradianceNIR[layer];
                s.Rn[layer] = totalAbsorbed - 2 * (canopy.Sigma * Math.Pow(273 + s.LeafTemp__[layer], 4) - canopy.Sigma * Math.Pow(273 + PM.EnvModel.GetTemp(PM.Time), 4));

                s.CalcConductanceResistance(PM, canopy);

                s.DoWaterInteraction(PM, canopy, mode);

                s.gm_CO2T[layer] = s.LAIS[layer] * TemperatureFunction.Val(s.LeafTemp__[layer], canopy.Gm25[layer], canopy.CPath.GmC, canopy.CPath.GmTMax, canopy.CPath.GmTMin, canopy.CPath.GmTOpt, canopy.CPath.GmBeta);

                double Gt = 1 / (1 / s.GbCO2[layer] + 1 / s.GsCO2[layer]);

                p = canopy.Ca - s.WaterUseMolsSecond[layer] * canopy.Ca / (Gt + s.WaterUseMolsSecond[layer] / 2);
                q = 1 / (Gt + s.WaterUseMolsSecond[layer] / 2) + 1 / s.gm_CO2T[layer];

                //Caculate A's
                if (s.type == SSType.AJ)
                {
                    s.A[layer] = CalcAj(s, canopy, layer, TranspirationMode.limited, p, q);
                }
                else
                {
                    s.A[layer] = CalcAc(s, canopy, layer, TranspirationMode.limited, p, q);
                }

                s.Cb[layer] = canopy.Ca - s.A[layer] / s.GbCO2[layer];

                s.Ci[layer] = ((Gt - s.WaterUseMolsSecond[0] / 2) * canopy.Ca - s.A[layer]) / (Gt + s.WaterUseMolsSecond[0] / 2);

                s.Cm[layer] = s.Ci[layer] - s.A[layer] / s.gm_CO2T[layer];

                s.XX = s.Cm[layer] * s.X_4 + s.X_5;

                s.Oc[layer] = canopy.Alpha * s.A[layer] / (0.047 * s.Gbs[layer]) + s.Om[layer];

                s.r_[layer] = s.G_[layer] * s.Oc[layer];

                s.Cc[layer] = s.Cm[layer] + (s.XX - s.A[layer] - s.Rm[layer]) / s.Gbs[layer];

                if (s.Cc[layer] < 0 || double.IsNaN(s.Cc[layer]))
                {
                    s.Cc[layer] = 0;
                }

                s.F[layer] = s.Gbs[layer] * (s.Cc[layer] - s.Cm[layer]) / s.XX;
            }

            double airTemp = PM.EnvModel.GetTemp(PM.Time);

            if (useAirTemp)
            {
                s.LeafTemp[layer] = PM.EnvModel.GetTemp(PM.Time);
            }

            double diffCm   = (s.type == SSType.AC1 ? Math.Abs(s.Cm__[layer] - s.Cm[layer]) : 0);
            double diffTemp = s.LeafTemp__[layer] - s.LeafTemp[layer];


            s.LeafTemp[layer] = (s.LeafTemp[layer] + s.LeafTemp__[layer]) / 2;

            s.Cm[layer] = (s.Cm[layer] + s.Cm__[layer]) / 2;

            if ((Math.Abs(diffCm) > s.CmTolerance) ||
                (Math.Abs(diffTemp) > s.leafTempTolerance) ||
                double.IsNaN(s.Cm[layer]) || double.IsNaN(s.LeafTemp[layer]))
            {
                return(false);
            }
            return(true);
        }
示例#13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="canopy"></param>
        /// <param name="layer"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static double CalcAc1(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode)
        {
            s.x_1 = s.VcMaxT[layer];
            s.x_2 = s.Kc[layer] / s.Ko[layer];
            s.x_3 = s.Kc[layer];
            s.x_4 = s.VpMaxT[layer] / (s.Cm__[layer] + s.Kp[layer]);
            s.x_5 = 0;
            s.x_6 = 1;
            s.x_7 = 0;
            s.x_8 = 1;
            s.x_9 = 1;

            return(CalcAssimilation(s, layer, canopy));
        }
示例#14
0
        //---------------------------------------------------------------------------
        public override void Run(bool sendNotification, double swAvail = 0, double maxHourlyT = -1, double sunlitFraction = 0, double shadedFraction = 0)
        {
            if (!Initialised)
            {
                return;
            }

            if (sendNotification && NotifyStart != null)
            {
                NotifyStart(false);
            }

            EnvModel.Run(this.Time);
            Canopy.CalcCanopyStructure(this.EnvModel.SunAngle.Rad);

            SunlitAC1 = new SunlitCanopy(Canopy.NLayers, SSType.AC1);
            sunlitAC2 = new SunlitCanopy(Canopy.NLayers, SSType.AC2);
            SunlitAJ  = new SunlitCanopy(Canopy.NLayers, SSType.AJ);
            ShadedAC1 = new ShadedCanopy(Canopy.NLayers, SSType.AC1);
            shadedAC2 = new ShadedCanopy(Canopy.NLayers, SSType.AC2);
            ShadedAJ  = new ShadedCanopy(Canopy.NLayers, SSType.AJ);

            double temp = EnvModel.GetTemp(Time);

            if (temp > Canopy.CPath.JTMax || temp < Canopy.CPath.JTMin || temp > Canopy.CPath.GmTMax || temp < Canopy.CPath.GmTMin)
            {
                ZeroVariables();
                return;
            }

            if (EnvModel.Ios.Value(this.Time) <= (0 + double.Epsilon))
            {
                ZeroVariables();
                return;
            }

            SunlitAC1.CalcLAI(this.Canopy, ShadedAC1);
            sunlitAC2.CalcLAI(this.Canopy, shadedAC2);
            SunlitAJ.CalcLAI(this.Canopy, ShadedAJ);
            ShadedAC1.CalcLAI(this.Canopy, SunlitAC1);
            shadedAC2.CalcLAI(this.Canopy, sunlitAC2);
            ShadedAJ.CalcLAI(this.Canopy, SunlitAJ);

            Canopy.Run(this, EnvModel);

            SunlitAC1.Run(Canopy.NLayers, this, ShadedAC1);
            sunlitAC2.Run(Canopy.NLayers, this, shadedAC2);
            SunlitAJ.Run(Canopy.NLayers, this, ShadedAJ);
            ShadedAC1.Run(Canopy.NLayers, this, SunlitAC1);
            shadedAC2.Run(Canopy.NLayers, this, sunlitAC2);
            ShadedAJ.Run(Canopy.NLayers, this, SunlitAJ);

            TranspirationMode mode = TranspirationMode.unlimited;

            if (maxHourlyT != -1)
            {
                mode = TranspirationMode.limited;
            }

            bool useAirTemp = false;

            double defaultCm = 160;

            List <bool> results = new List <bool>();

            results.Add(SunlitAC1.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), defaultCm, mode, maxHourlyT, sunlitFraction));
            results.Add(sunlitAC2.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), defaultCm, mode, maxHourlyT, sunlitFraction));
            results.Add(SunlitAJ.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), defaultCm, mode, maxHourlyT, sunlitFraction));
            results.Add(ShadedAC1.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), defaultCm, mode, maxHourlyT, shadedFraction));
            results.Add(shadedAC2.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), defaultCm, mode, maxHourlyT, shadedFraction));
            results.Add(ShadedAJ.CalcPhotosynthesis(this, useAirTemp, 0, EnvModel.GetTemp(Time), defaultCm, mode, maxHourlyT, shadedFraction));

            Count = 1;

            bool caughtError = false;

            while (results.Contains(false) && !caughtError)
            {
                results.Clear();
                results.Add(SunlitAC1.CalcPhotosynthesis(this, useAirTemp, 0, SunlitAC1.LeafTemp[0], SunlitAC1.Cm[0], mode, maxHourlyT, sunlitFraction));
                results.Add(sunlitAC2.CalcPhotosynthesis(this, useAirTemp, 0, sunlitAC2.LeafTemp[0], sunlitAC2.Cm[0], mode, maxHourlyT, sunlitFraction));
                results.Add(SunlitAJ.CalcPhotosynthesis(this, useAirTemp, 0, SunlitAJ.LeafTemp[0], SunlitAJ.Cm[0], mode, maxHourlyT, sunlitFraction));
                results.Add(ShadedAC1.CalcPhotosynthesis(this, useAirTemp, 0, ShadedAC1.LeafTemp[0], ShadedAC1.Cm[0], mode, maxHourlyT, shadedFraction));
                results.Add(shadedAC2.CalcPhotosynthesis(this, useAirTemp, 0, shadedAC2.LeafTemp[0], shadedAC2.Cm[0], mode, maxHourlyT, shadedFraction));
                results.Add(ShadedAJ.CalcPhotosynthesis(this, useAirTemp, 0, ShadedAJ.LeafTemp[0], ShadedAJ.Cm[0], mode, maxHourlyT, shadedFraction));

                if (double.IsNaN(SunlitAC1.Cm[0]) ||
                    double.IsNaN(sunlitAC2.Cm[0]) ||
                    double.IsNaN(SunlitAJ.Cm[0]) ||
                    double.IsNaN(ShadedAC1.Cm[0]) ||
                    double.IsNaN(shadedAC2.Cm[0]) ||
                    double.IsNaN(ShadedAJ.Cm[0]) ||
                    Count == 30)
                {
                    SunlitAC1.Cm[0] = defaultCm;
                    sunlitAC2.Cm[0] = defaultCm;
                    SunlitAJ.Cm[0]  = defaultCm;
                    ShadedAC1.Cm[0] = defaultCm;
                    shadedAC2.Cm[0] = defaultCm;
                    ShadedAJ.Cm[0]  = defaultCm;

                    useAirTemp = true;
                }

                if (Count > 100)
                {
                    ZeroVariables();

                    return;
                }

                Count++;

                if (Count > 100 && !caughtError)
                {
                    StreamWriter sr = new StreamWriter("scenario.csv");

                    sr.WriteLine("Lat," + EnvModel.LatitudeD);
                    sr.WriteLine("DOY," + EnvModel.DOY);
                    sr.WriteLine("Maxt," + EnvModel.MaxT);
                    sr.WriteLine("AvailableWater," + swAvail);
                    sr.WriteLine("Mint," + EnvModel.MinT);
                    sr.WriteLine("Radn," + EnvModel.Radn);
                    sr.WriteLine("Ratio," + EnvModel.AtmTransmissionRatio);
                    sr.WriteLine("LAI," + Canopy.LAI);
                    sr.WriteLine("SLN," + Canopy.CPath.SLNAv);

                    List <double> temps = new List <double>();

                    for (int i = 0; i <= 12; i++)
                    {
                        temps.Add(EnvModel.GetTemp(i + 5));
                    }

                    sr.WriteLine("Temps," + String.Join(",", temps.ToArray()));

                    sr.Flush();

                    sr.Close();

                    caughtError = true;
                }
            }

            if (sendNotification && NotifyFinish != null)
            {
                NotifyFinish();
            }
        }
示例#15
0
        // No CalcAc2 in C3

        /// <summary>
        ///
        /// </summary>
        /// <param name="canopy"></param>
        /// <param name="layer"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static double CalcAj(SunlitShadedCanopy s, LeafCanopy canopy, int layer, TranspirationMode mode)
        {
            s.x_1 = s.J[layer] / 4;
            s.x_2 = 2 * s.G_[layer];
            s.x_3 = 0;
            s.x_4 = 0;
            s.x_5 = 0;
            s.x_6 = 0;
            s.x_7 = 0;
            s.x_8 = 0;
            s.x_9 = 0;

            return(CalcAssimilation(s, layer, canopy));;
        }