private void DoUnderstoryWaterBalance() { UnderstoryCoverGreen = UnderstoryCoverMax * (1 - cover_green); UnderstoryPEP = eo * UnderstoryCoverGreen * (1 - cover_green); MyPaddock.Get("Soil Water.sw_dep", out sw_dep); //need to get latest copy of swdep because OP will have taken water up. for (int j = 0; j < ll15_dep.Length; j++) { UnderstoryPotSWUptake[j] = Math.Max(0.0, RootProportion(j, UnderstoryRootDepth) * UnderstoryKLmax * UnderstoryCoverGreen * (sw_dep[j] - ll15_dep[j])); } double TotUnderstoryPotSWUptake = MathUtility.Sum(UnderstoryPotSWUptake); UnderstoryEP = 0.0; for (int j = 0; j < ll15_dep.Length; j++) { UnderstorySWUptake[j] = UnderstoryPotSWUptake[j] * Math.Min(1.0, UnderstoryPEP / TotUnderstoryPotSWUptake); UnderstoryEP += UnderstorySWUptake[j]; sw_dep[j] = sw_dep[j] - UnderstorySWUptake[j]; } if (!MyPaddock.Set("Soil Water.sw_dep", sw_dep)) { throw new Exception("Unable to set sw_dep"); } if (UnderstoryPEP > 0.0) { UnderstoryFW = UnderstoryEP / UnderstoryPEP; } else { UnderstoryFW = 1.0; } }
private void DoGrowth() { double OPCover = 0; if (!MyPaddock.Get("OilPalm.cover_green", out OPCover)) { OPCover = 0.0; } double RUE = 1.3; DltDM = RUE * Radn * cover_green * (1 - OPCover) * FW; }
private bool empty = true; // tracks if the header has been printed for the interval value data [EventHandler] public void Ondodcaps() { int DOY = 0; double latitude = 0; double maxT = 0; double minT = 0; double radn = 0; double RootShootRatio = 0; double SLN = 0; double SWAvailable = 0; double lai = 0; MyPaddock.Get("DOY", out DOY); MyPaddock.Get("latitude", out latitude); MyPaddock.Get("maxT", out maxT); MyPaddock.Get("minT", out minT); MyPaddock.Get("radn", out radn); MyPaddock.Get("RootShootRatio", out RootShootRatio); MyPaddock.Get("SLN", out SLN); MyPaddock.Get("SWAvailable", out SWAvailable); MyPaddock.Get("lai", out lai); // Model the photosynthesis DCAPSTModel DM = Classic.SetUpModel(CP, PP, DOY, latitude, maxT, minT, radn); // Optional values DM.PrintIntervalValues = false; // Switch to print extra data (default = false) DM.Biolimit = 0; // Biological transpiration limit of the crop (0 disables mechanism) DM.Reduction = 0; // Excess water reduction fraction for bio-limited transpiration (0 disables mechanism) // Run the simulation DM.DailyRun(lai, SLN, SWAvailable, RootShootRatio); if (DM.PrintIntervalValues) { if (empty) { writer.WriteLine(DM.PrintResultHeader()); empty = false; } writer.WriteLine(DM.IntervalResults); } // Outputs RootShoot = RootShootRatio; BIOshootDAY = dcaps[0] = DM.ActualBiomass; BIOtotalDAY = BIOshootDAY * (1 + RootShoot); EcanDemand = dcaps[1] = DM.WaterDemanded; EcanSupply = dcaps[2] = DM.WaterSupplied; RadIntDcapst = dcaps[3] = DM.InterceptedRadiation; RUE = (RadIntDcapst == 0 ? 0 : BIOshootDAY / RadIntDcapst); TE = (EcanSupply == 0 ? 0 : BIOshootDAY / EcanSupply); BIOshootDAYPot = dcaps[4] = DM.PotentialBiomass; }
public override void DoWaterUptake(double Amount) { Uptake = Amount; if (TalkDirectlyToRoot) { MyPaddock.Set(OurName + "Root.SWUptake", Amount); } else { List <string> ModelNames = new List <string>(); List <double> Supply = new List <double>(); foreach (Paddock SubPaddock in MyPaddock.ChildPaddocks) { double[] SWSupply; string ModelName = SubPaddock.FullName + "." + Plant.Name + "Root"; MyPaddock.Get(ModelName + ".SWSupply", out SWSupply); Supply.Add(MathUtility.Sum(SWSupply)); ModelNames.Add(ModelName); } double fraction = Amount / MathUtility.Sum(Supply); if (fraction > 1) { throw new Exception("Requested SW uptake > Available supplies."); } int i = 0; foreach (string ModelName in ModelNames) { MyPaddock.Set(ModelName + ".SWUptake", Supply[i] * fraction); i++; } } }
public override void DoSWUptake(double SWDemand) { // Firstly grow roots. // the layer with root front int layer = FindLayerNo(RootDepth); dltRootDepth = RootDepthRate.Value * RootAdvanceFactorTemp.Value * Math.Min(RootAdvanceFactorWaterStress.Value, SWFactorRootDepth.Value) * xf[layer]; // prevent roots partially entering layers where xf == 0 int deepest_layer; for (deepest_layer = xf.Length - 1; deepest_layer >= 0 && (xf[deepest_layer] <= 0.0 || getModifiedKL(deepest_layer) <= 0.0); deepest_layer--) { ; /* nothing */ } int RootLayerMax = deepest_layer + 1; double RootDepthMax = MathUtility.Sum(dlayer, 0, deepest_layer + 1, 0.0); dltRootDepth = MathUtility.Constrain(dltRootDepth, double.MinValue, RootDepthMax - RootDepth); if (dltRootDepth < 0.0) { throw new Exception("negative root growth??"); } Util.Debug("Root.dltRootDepth=%f", dltRootDepth); Util.Debug("Root.root_layer_max=%i", RootLayerMax); Util.Debug("Root.root_depth_max=%f", RootDepthMax); // potential extractable sw DoPotentialExtractableSW(); // actual extractable sw (sw-ll) DoSWAvailable(); DoSWSupply(); if (SwimIsPresent) { MyPaddock.Get("uptake_water_" + Plant.CropType, out dlt_sw_dep); dlt_sw_dep = MathUtility.Multiply_Value(dlt_sw_dep, -1); // make them negative numbers. } else { DoWaterUptakeInternal(SWDemand); } Util.Debug("Root.dlt_sw_dep=%f", MathUtility.Sum(dlt_sw_dep)); }
public void OnInitialised() { /* IMPORTANT - Do NOT change the order of these values */ CP = Classic.SetUpCanopy( CanopyType.C3, // Canopy type 370, // CO2 partial pressure 0.7, // Empirical curvature factor 0.047, // Diffusivity-solubility ratio 210000, // O2 partial pressure 0.78, // PAR diffuse extinction coefficient 0.8, // NIR diffuse extinction coefficient 0.036, // PAR diffuse reflection coefficient 0.389, // NIR diffuse reflection coefficient 60, // Leaf angle 0.15, // PAR leaf scattering coefficient 0.8, // NIR leaf scattering coefficient 0.05, // Leaf width 1.3, // SLN ratio at canopy top 14, // Minimum structural nitrogen 1.5, // Wind speed 1.5); // Wind speed profile distribution coefficient PP = Classic.SetUpPathway( 0, // Electron transport minimum temperature 30.0, // Electron transport optimum temperature 45.0, // Electron transport maximum temperature 0.911017958600129, // Electron transport scaling constant 1, // Electron transport Beta value 6048.95289, //mesophyll conductance factor 273.422964228666, // Kc25 - Michaelis Menten constant of Rubisco carboxylation at 25 degrees C 93720, // KcFactor 165824.064155384, // Ko25 - Michaelis Menten constant of Rubisco oxygenation at 25 degrees C 33600, // KoFactor 4.59217066521612, // VcVo25 - Rubisco carboxylation to oxygenation at 25 degrees C 35713.19871277176, // VcVoFactor 0.0, // Kp25 - Michaelis Menten constant of PEPc activity at 25 degrees C (Unused in C3) 0.0, // KpFactor (Unused in C3) 65330, // VcFactor 46390, // RdFactor 57043.2677590512, // VpFactor 0.0, // PEPc regeneration (Unused in C3) 0.15, // Spectral correction factor 0.1, // Photosystem II activity fraction 0.003, // Bundle sheath CO2 conductance 1.1 * PsiFactor, // Max Rubisco activity to SLN ratio 1.85 * PsiFactor, // Max electron transport to SLN ratio 0.0 * PsiFactor, // Respiration to SLN ratio 1.0 * PsiFactor, // Max PEPc activity to SLN ratio 0.00412 * PsiFactor, // Mesophyll CO2 conductance to SLN ratio 0.75, // Extra ATP cost 0.7); // Intercellular CO2 to air CO2 ratio //Set the LAI trigger MyPaddock.Set("DCaPSTTriggerLAI", LAITrigger); MyPaddock.Get("PsModelName1", out PsModelName1); }
public void Ondodcaps() { int DOY = 0; double latitude = 0; double maxT = 0; double minT = 0; double radn = 0; double RootShootRatio = 0; double SLN = 0; double SWAvailable = 0; double lai = 0; MyPaddock.Get("DOY", out DOY); MyPaddock.Get("latitude", out latitude); MyPaddock.Get("maxT", out maxT); MyPaddock.Get("minT", out minT); MyPaddock.Get("radn", out radn); MyPaddock.Get("RootShootRatio", out RootShootRatio); MyPaddock.Get("SLN", out SLN); MyPaddock.Get("SWAvailable", out SWAvailable); MyPaddock.Get("lai", out lai); // Model the photosynthesis double rpar = 0.5; DCAPSTModel DM = Classic.SetUpModel(CP, PP, DOY, latitude, maxT, minT, radn, rpar); // Optional values DM.PrintIntervalValues = false; // Switch to print extra data (default = false) DM.Biolimit = 0; // Biological transpiration limit of the crop (0 disables mechanism) DM.Reduction = 0; // Excess water reduction fraction for bio-limited transpiration (0 disables mechanism) // Run the simulation DM.DailyRun(lai, SLN, SWAvailable, RootShootRatio); // Daily Outputs RootShoot = RootShootRatio; BIOshootDAY = dcaps[0] = DM.ActualBiomass; BIOtotalDAY = BIOshootDAY * (1 + RootShoot); EcanDemand = dcaps[1] = DM.WaterDemanded; EcanSupply = dcaps[2] = DM.WaterSupplied; RadIntDcapst = dcaps[3] = DM.InterceptedRadiation; RUE = (RadIntDcapst == 0 ? 0 : BIOshootDAY / RadIntDcapst); TE = (EcanSupply == 0 ? 0 : BIOshootDAY / EcanSupply); BIOshootDAYPot = dcaps[4] = DM.PotentialBiomass; SoilWater = SWAvailable; // Interval outputs foreach (var interval in DM.Intervals) { Hour = interval.Time; SunlitTemperature = interval.Sunlit.Temperature; ShadedTemperature = interval.Shaded.Temperature; SunlitAc1 = interval.Sunlit.Ac1.Assimilation; SunlitAc2 = interval.Sunlit.Ac2.Assimilation; SunlitAj = interval.Sunlit.Aj.Assimilation; ShadedAc1 = interval.Shaded.Ac1.Assimilation; ShadedAc2 = interval.Shaded.Ac2.Assimilation; ShadedAj = interval.Shaded.Aj.Assimilation; if (IntervalStep != null) { IntervalStep.Invoke(); } } }
// The following event handler will be called once at the beginning of the simulation [EventHandler] public void OnInitialised() { string path = "IntervalValues.csv"; stream = new FileStream(path, FileMode.Create); writer = new StreamWriter(stream); /* Do NOT change the order of these values */ CP = Classic.SetUpCanopy( CanopyType.CCM, // Canopy type 370, // CO2 partial pressure 0.7, // Empirical curvature factor 0.047, // Diffusivity-solubility ratio (Used in CCM) 210000, // O2 partial pressure 0.78, // PAR diffuse extinction coefficient 0.8, // NIR diffuse extinction coefficient 0.036, // PAR diffuse reflection coefficient 0.389, // NIR diffuse reflection coefficient 60, // Leaf angle 0.15, // PAR leaf scattering coefficient 0.8, // NIR leaf scattering coefficient 0.05, // Leaf width 1.3, // SLN ratio at canopy top 14, // Minimum structural nitrogen 1.5, // Wind speed 1.5); // Wind speed profile distribution coefficient PP = Classic.SetUpPathway( 0, // Electron transport minimum temperature 30.0, // Electron transport optimum temperature 45.0, // Electron transport maximum temperature 0.911017958600129, // Electron transport scaling constant 1, // Electron transport Beta value 0, // Mesophyll conductance minimum temperature 29.2338417788683, // Mesophyll conductance optimum temperature 45, // Mesophyll conductance maximum temperature 0.875790608584141, // Mesophyll conductance scaling constant 1, // Mesophyll conductance Beta value 17.52 * 273.422964228666, // Kc25 - Michaelis Menten constant of Rubisco carboxylation at 25 degrees C (Changed in CCM)********************* 93720, // KcFactor 1.34 * 165824.064155384, // Ko25 - Michaelis Menten constant of Rubisco oxygenation at 25 degrees C (Changed in CCM)********************* 33600, // KoFactor 13.07 * 4.59217066521612, // VcVo25 - Rubisco carboxylation to oxygenation at 25 degrees C (Changed in CCM)********************* 35713.19871277176, // VcVoFactor 75, // Kp25 - Michaelis Menten constant of PEPc activity at 25 degrees C (Used in CCM) 36300, // KpFactor (Used in CCM) 65330, // VcFactor 46390, // RdFactor 57043.2677590512, // VpFactor (Used in CCM) 400.0, // PEPc regeneration (Used in CCM) 0.15, // Spectral correction factor 0.1, // Photosystem II activity fraction (used in CCM) 0.003, // Bundle sheath CO2 conductance (Used in CCM)******************** 1.1 * PsiFactor, // Max Rubisco activity to SLN ratio 1.9484 * PsiFactor, // Max electron transport to SLN ratio (Changed in CCM)******************** 0.0 * PsiFactor, // Respiration to SLN ratio 1 * PsiFactor, // Max PEPc activity to SLN ratio (Changed in CCM)*********************0.373684157583268 0.00412 * PsiFactor, // Mesophyll CO2 conductance to SLN ratio 0.75, // Extra ATP cost (Changed in CCM)********************* 0.7); // Intercellular CO2 to air CO2 ratio //Set the LAI trigger MyPaddock.Set("DCaPSTTriggerLAI", LAITrigger); MyPaddock.Get("PsModelName1", out PsModelName1); }
//Called each daily timestep [EventHandler] void OnProcess() { //Delta arrays for each variable rainAmt += rain; double[] dlt_ks = new double[oc.Length]; double[] dlt_dul = new double[oc.Length]; double[] dlt_ll = new double[oc.Length]; double[] dlt_bd = new double[oc.Length]; double[] dlt_swcon = new double[oc.Length]; double[] dlt_sat = new double[oc.Length]; double[] dlt_hum = new double[oc.Length]; double[] dlt_biom = new double[oc.Length]; double[] dlt_ph = new double[oc.Length]; double[] dlt_n_avail = new double[oc.Length]; double[] dlt_biochar_c = new double[oc.Length]; double[] bc_nh4_dlt = new double[oc.Length]; double[] dlt_kl = new double[oc.Length]; for (int i = 0; i < oc.Length; i++)//Since kl's effect is multiplicative, its default needs to be 1 { dlt_kl[i] = 1.0; } //computeDULandBD(out saxon_dul, out saxon_bd, 0); //saxon_ll = computeLL(0); //saxon_sat = giveSAT(0); if (Today < date) { for (int i = 0; i < dlayer.Length; i++) { saxon_bd[i] = bd[i]; } } if (Today == date) { //Step 1 applyBiochar(); } if (Today > date) { for (int i = 0; i < oc.Length; i++) //try looping through all layers { MyPaddock.Get(soil_name + " Nitrogen.tf", out tf); //This si why soil name needs to be an input parameter MassComparison[i] = (BiocharC[i] / frac_c_biochar) / (LayerMass[i]); double n_demand, dlt_n_min_tot_bc; //double rd_hum_fac = 0.0, rd_biom_fac = 0.0, rd_carb_fac = 0.0, rd_cell_fac = 0.0, rd_lign_fac = 0.0, rd_ef_fac = 0.0, rd_fr_fac = 0.0; double nh4_change; double new_ph; //Local variables for this specific soil layer double new_layer_ll, new_layer_bd, new_layer_dul, new_layer_ks, new_layer_sat, new_layer_swcon = 0.0; //step 2 //When biochar functionality is expanded, every instance of a '0' method argument or array index will be changed to a layer index, and layers that biochar //alters will be iterated over in a for loop, but for now biochar only changes the first layer dlt_c_min_biochar[i] = computeDailyBCCarbDecomp(i); //step 3 computeDLTs(out dlt_c_biochar_biom[i], out dlt_c_biochar_hum[i], out dlt_c_biochar_co2[i], dlt_c_min_biochar[i]); //step 4 -inactive n_demand = getNDemand(dlt_c_biochar_biom[i], dlt_c_biochar_hum[i]); dlt_n_min_tot_bc = computeNFromDecomp(dlt_c_min_biochar[i]); n_demand_bc[i] = n_demand; n_avail_bc[i] = dlt_n_min_tot_bc; dlt_n_min_biochar[i] = dlt_n_min_tot_bc - n_demand; //This will get added to dlt_n_min_tot I think //Step 5 happens in model //Step 6 get_rd_factors(out rd_hum_fac, out rd_biom_fac, out rd_carb_fac, out rd_cell_fac, out rd_lign_fac, out rd_ef_fac, out rd_fr_fac, out rd_ef_fom_fac, out rd_fr_fom_fac, i); //Step 7 nh4_change = get_NH4_changes(i); //Step 8 soil_cec[i] = get_new_cec(i); new_ph = get_new_ph(i); //For computing delta locally. getCurrentSoilWatValues(); //Step 9 new_layer_ll = computeLL(i); computeDULandBD(out new_layer_dul, out new_layer_bd, i); //new_layer_sat = giveSAT(i); //Active but not being used /** * new_layer_swcon = computeSWCON(0, new_layer_sat, new_layer_bd); * new_layer_ks = computeKS(0, new_layer_sat, new_layer_dul, new_layer_ll); **/ //End of steps /** * The biochar decomposed event requires that changes be in terms of delta. * However, our equations give the total value, not the change, so we must compute * the change within this script. **/ //dlt_ks[0] = new_layer_ks - ks[0]; dlt_dul[i] = new_layer_dul; // -dul[i]; dlt_ll[i] = new_layer_ll; // -ll15[i]; //not actually a delta, model stops working if it is. Instead, is the next wanted value of bd if (BiocharC[i] != 0.0) { dlt_bd[i] = new_layer_bd + saxon_bd[i]; } else { dlt_bd[i] = initialBD[i]; } dlt_hum[i] = dlt_c_biochar_hum[i]; dlt_biom[i] = dlt_c_biochar_biom[i]; dlt_biochar_c[i] = dlt_c_min_biochar[i]; dlt_ph[i] = new_ph - ph[i]; dlt_n_avail[i] = dlt_n_min_biochar[i]; bc_nh4_dlt[i] = nh4_change; if (kl_switch.Equals("on")) //So that kl does not go to 0 { dlt_kl[i] = 1; //what became of step 10 } } //End of loop //The data structure for our decomposition event BiocharDecomposedType BiocharDecomp = new BiocharDecomposedType(); getCurrentSoilWatValues(); //region for andales saxon mergeing - to later integrate with double[] andales_bd = AndalesBD(); double[] bd_new = biggest_bd_dlt(dlt_bd, andales_bd); double[] sat_dlt_new = sat_in_terms_of_dlt(bd_new); for (int i = 0; i < oc.Length; i++) { double temp; saxon_sat[i] = (-(dlt_bd[i] - saxon_bd[i]) / 2.65) * 0.9 + sat[i]; saxon_bd[i] = dlt_bd[i]; till_bd[i] = andales_bd[i]; till_sat[i] = (-(andales_bd[i] - biochar_bd[i]) / 2.65) * 0.9 + sat[i]; temp = 100 / (bd_new[i] * init_soil_fac[i]); dlt_dlayer[i] = temp - dlayer[i]; } biochar_bd = bd_new; //Script control area if (dul_switch.Equals("on")) { BiocharDecomp.dlt_dul = dlt_dul; } if (ll_switch.Equals("on")) { BiocharDecomp.dlt_ll = dlt_ll; } if (sat_switch.Equals("on")) { BiocharDecomp.dlt_sat = sat_dlt_new; } //Since errors occur if bd is in terms of delta, we need to ensure that if bd is off, we still get what we want if (bd_switch.Equals("on")) { BiocharDecomp.dlt_bd = bd; //BiocharDecomp.dlt_bd = bd_new; //MyPaddock.Set("dlt_dlayer", dlt_dlayer); } else { BiocharDecomp.dlt_bd = bd; } if (swcon_switch.Equals("on")) { BiocharDecomp.dlt_swcon = dlt_swcon; } if (ks_switch.Equals("on")) { BiocharDecomp.dlt_ks = dlt_ks; } if (biochar_c_switch.Equals("on")) { BiocharDecomp.hum_c = dlt_hum; BiocharDecomp.biom_c = dlt_biom; BiocharDecomp.dlt_biochar_c = dlt_biochar_c; } if (nitrification_switch.Equals("on")) { BiocharDecomp.bc_nh4_change = bc_nh4_dlt; } if (decomp_switch.Equals("on")) { BiocharDecomp.dlt_rd_hum = rd_hum_fac; BiocharDecomp.dlt_rd_biom = rd_biom_fac; BiocharDecomp.dlt_rd_carb = rd_carb_fac; BiocharDecomp.dlt_rd_cell = rd_cell_fac; BiocharDecomp.dlt_rd_lign = rd_lign_fac; BiocharDecomp.dlt_rd_ef = rd_ef_fac; BiocharDecomp.dlt_rd_fr = rd_fr_fac; BiocharDecomp.dlt_rd_ef_fom = rd_ef_fom_fac; BiocharDecomp.dlt_rd_fr_fom = rd_fr_fom_fac; } BiocharDecomp.dlt_n_biochar = dlt_n_avail; if (ph_switch.Equals("on")) { BiocharDecomp.dlt_ph = dlt_ph; } BiocharDecomp.bc_wfps_factor = 1.0 - this.bc_wfps_factor; BiocharDecomp.dlt_kl = dlt_kl; //Since KL is a multiplicative effect, if we do not always assign this KL will go to 0 //If uninitialized, it is 0 by default BiocharDecomposed.Invoke(BiocharDecomp); Console.WriteLine("Biochar bd: " + biochar_bd[0]); } for (int i = 0; i < oc.Length; i++) { yesterday_oc[i] = oc[i]; //Make a deep copy } }