//--------------------------------------------------------------------------------------------------------- /// <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]; } } }
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(); } }
//--------------------------------------------------------------------------------------------------------- /// <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); }
/// <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)); }
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); }
/// <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));; }
/// <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));; }
//--------------------------------------------------------------------------------------------------------- /// <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); } }
/// <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)); }
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)); }
/// <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));; }
//--------------------------------------------------------------------------------------------------------- /// <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); }
/// <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)); }
//--------------------------------------------------------------------------- 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(); } }
// 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));; }