//--------------------------------------------------------------------- private double ComputeActualANPP(ICohort cohort, ActiveSite site, int siteBiomass, int prevYearSiteMortality) { growthReduction = CohortGrowthReduction.Compute(cohort, site); double cohortBiomass = cohort.Biomass; double capacityReduction = 1.0; double maxANPP = SpeciesData.ANPP_MAX_Spp[cohort.Species][ecoregion]; //double maxBiomass = SpeciesData.B_MAX_Spp[cohort.Species][ecoregion]; //CForCS double maxBiomass = SpeciesData.B_MAX_Spp[cohort.Species][ecoregion] * capacityReduction; double growthShape = SpeciesData.GrowthCurveShapeParm[cohort.Species]; if (SiteVars.CapacityReduction != null && SiteVars.CapacityReduction[site] > 0) { capacityReduction = 1.0 - SiteVars.CapacityReduction[site]; if (PlugIn.CalibrateMode) { PlugIn.ModelCore.UI.WriteLine("Yr={0}. Capacity Remaining={1:0.00}, Spp={2}, Age={3} B={4}.", (PlugIn.ModelCore.CurrentTime + SubYear), capacityReduction, cohort.Species.Name, cohort.Age, cohort.Biomass); } } double indexC = CalculateCompetition(site, cohort); //Biomass model //if ((indexC <= 0.0 && cohortBiomass > 0) || indexC > 1.0) //Biomass model // throw new ApplicationException("Application terminating."); // Potential biomass, equation 3 in Scheller and Mladenoff, 2004 //double potentialBiomass = Math.Max(1, maxBiomass - siteBiomass); //old CForCS double potentialBiomass = Math.Max(1, maxBiomass - siteBiomass + cohortBiomass); //Biomass model // Species can use new space immediately // but not in the case of capacity reduction due to harvesting. if (capacityReduction >= 1.0) { potentialBiomass = Math.Max(potentialBiomass, prevYearSiteMortality); } // Ratio of cohort's actual biomass to potential biomass B_AP = Math.Min(1.0, cohortBiomass / potentialBiomass); // Ratio of cohort's potential biomass to maximum biomass. The // ratio cannot be exceed 1. //B_PM = Math.Min(1.0, potentialBiomass / maxBiomass); //old CForCS B_PM = Math.Min(1.0, indexC); //Biomass model // Actual ANPP: equation (4) from Scheller & Mladenoff, 2004. // Constants k1 and k2 control whether growth rate declines with // age. Set to default = 1. //double actualANPP = maxANPP * Math.E * B_AP * Math.Exp(-1 * B_AP) * B_PM; //old CForCS double actualANPP = maxANPP * Math.E * Math.Pow(B_AP, growthShape) * Math.Exp(-1 * Math.Pow(B_AP, growthShape)) * B_PM; //Biomass model // Calculated actual ANPP can not exceed the limit set by the // maximum ANPP times the ratio of potential to maximum biomass. // This down regulates actual ANPP by the available growing space. actualANPP = Math.Min(maxANPP * B_PM, actualANPP); if (growthReduction > 0) { actualANPP *= (1.0 - growthReduction); } //if (site.Location.Row == 279 && site.Location.Column == 64 && cohort.Species.Name == "Pl") //{ // PlugIn.ModelCore.UI.WriteLine("Yr={0}, Age={1}, PotBio={2}, CohortBio={3}, maxBio={4}, siteBio={5}, ANPP={6}.", PlugIn.ModelCore.CurrentTime, cohort.Age, potentialBiomass, cohort.Biomass, maxBiomass, siteBiomass, actualANPP); //} return(actualANPP); }
//--------------------------------------------------------------------- private double[] ComputeActualANPP(ICohort cohort, ActiveSite site, double siteBiomass, double[] mortalityAge) { double leafFractionNPP = FunctionalType.Table[SpeciesData.FuncType[cohort.Species]].FCFRACleaf; double maxBiomass = SpeciesData.Max_Biomass[cohort.Species]; //.B_MAX_Spp[cohort.Species][ecoregion]; double sitelai = SiteVars.LAI[site]; double maxNPP = SpeciesData.Max_ANPP[cohort.Species]; //.ANPP_MAX_Spp[cohort.Species][ecoregion]; double limitT = calculateTemp_Limit(site, cohort.Species); double limitH20 = calculateWater_Limit(site, ecoregion, cohort.Species); double limitLAI = calculateLAI_Limit(cohort, site); // RMS 03/2016: Testing alternative more similar to how Biomass Succession operates: REMOVE FOR NEXT RELEASE //double limitCapacity = 1.0 - Math.Min(1.0, Math.Exp(siteBiomass / maxBiomass * 5.0) / Math.Exp(5.0)); double competition_limit = calculateCompetition_Limit(cohort, site); //double potentialNPP_NoN = maxNPP * limitLAI * limitH20 * limitT; // * limitCapacity; double potentialNPP = maxNPP * limitLAI * limitH20 * limitT * competition_limit; //double potentialNPP = maxNPP * limitLAI * limitH20 * limitT * limitCapacity; double limitN = calculateN_Limit(site, cohort, potentialNPP, leafFractionNPP); potentialNPP *= limitN; //if (Double.IsNaN(limitT) || Double.IsNaN(limitH20) || Double.IsNaN(limitLAI) || Double.IsNaN(limitCapacity) || Double.IsNaN(limitN)) //{ // PlugIn.ModelCore.UI.WriteLine(" A limit = NaN! Will set to zero."); // PlugIn.ModelCore.UI.WriteLine(" Yr={0},Mo={1}. GROWTH LIMITS: LAI={2:0.00}, H20={3:0.00}, N={4:0.00}, T={5:0.00}, Capacity={6:0.0}", PlugIn.ModelCore.CurrentTime, month + 1, limitLAI, limitH20, limitN, limitT, limitCapacity); // PlugIn.ModelCore.UI.WriteLine(" Yr={0},Mo={1}. Other Information: MaxB={2}, Bsite={3}, Bcohort={4:0.0}, SoilT={5:0.0}.", PlugIn.ModelCore.CurrentTime, month + 1, maxBiomass, (int)siteBiomass, (cohort.WoodBiomass + cohort.LeafBiomass), SiteVars.SoilTemperature[site]); //} // Age mortality is discounted from ANPP to prevent the over- // estimation of growth. ANPP cannot be negative. double actualANPP = Math.Max(0.0, potentialNPP - mortalityAge[0] - mortalityAge[1]); // Growth can be reduced by another extension via this method. // To date, no extension has been written to utilize this hook. double growthReduction = CohortGrowthReduction.Compute(cohort, site); if (growthReduction > 0.0) { actualANPP *= (1.0 - growthReduction); } double leafNPP = actualANPP * leafFractionNPP; double woodNPP = actualANPP * (1.0 - leafFractionNPP); if (Double.IsNaN(leafNPP) || Double.IsNaN(woodNPP)) { PlugIn.ModelCore.UI.WriteLine(" EITHER WOOD or LEAF NPP = NaN! Will set to zero."); //PlugIn.ModelCore.UI.WriteLine(" Yr={0},Mo={1}, SpeciesName={2}, CohortAge={3}. GROWTH LIMITS: LAI={4:0.00}, H20={5:0.00}, N={6:0.00}, T={7:0.00}, Capacity={8:0.0}.", PlugIn.ModelCore.CurrentTime, Main.Month + 1, cohort.Species.Name, cohort.Age, limitLAI, limitH20, limitN, limitT, limitCapacity); PlugIn.ModelCore.UI.WriteLine(" Yr={0},Mo={1}. Other Information: MaxB={2}, Bsite={3}, Bcohort={4:0.0}, SoilT={5:0.0}.", PlugIn.ModelCore.CurrentTime, Main.Month + 1, maxBiomass, (int)siteBiomass, (cohort.WoodBiomass + cohort.LeafBiomass), SiteVars.SoilTemperature[site]); PlugIn.ModelCore.UI.WriteLine(" Yr={0},Mo={1}. WoodNPP={2:0.00}, LeafNPP={3:0.00}.", PlugIn.ModelCore.CurrentTime, Main.Month + 1, woodNPP, leafNPP); if (Double.IsNaN(leafNPP)) { leafNPP = 0.0; } if (Double.IsNaN(woodNPP)) { woodNPP = 0.0; } } if (PlugIn.ModelCore.CurrentTime > 0 && OtherData.CalibrateMode) { //Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},{2:0.00},{3:0.00}, {4:0.00},", limitLAI, limitH20, limitT, limitCapacity, limitN); Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},{2:0.00},{3:0.00},", limitLAI, limitH20, limitT, limitN); Outputs.CalibrateLog.Write("{0},{1},{2},{3:0.0},{4:0.0},", maxNPP, maxBiomass, (int)siteBiomass, (cohort.WoodBiomass + cohort.LeafBiomass), SiteVars.SoilTemperature[site]); Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", woodNPP, leafNPP); } return(new double[2] { woodNPP, leafNPP }); }
//--------------------------------------------------------------------- private double ComputeActualANPP(ICohort cohort, ActiveSite site) { int siteBiomass = SiteVars.TotalBiomass[site]; // --------------------------------------------------------- // Growth reduction ranges from 1.0 (total) to none (0.0). // Growth reduction is calculated by an disturbance function, typically an extension // with a dedicated calculator. The method CohortGrowthReduction.Compute is a delegate method // and lives within the disturbance extension. growthReduction = CohortGrowthReduction.Compute(cohort, site); double growthShape = SpeciesData.GrowthCurveShapeParm[cohort.Species]; double cohortBiomass = cohort.Biomass; double capacityReduction = 1.0; if (SiteVars.CapacityReduction != null && SiteVars.CapacityReduction[site] > 0) { capacityReduction = 1.0 - SiteVars.CapacityReduction[site]; if (PlugIn.CalibrateMode) { PlugIn.ModelCore.UI.WriteLine("Yr={0}. Capacity Remaining={1:0.00}, Spp={2}, Age={3} B={4}.", (PlugIn.ModelCore.CurrentTime + SubYear), capacityReduction, cohort.Species.Name, cohort.Age, cohort.Biomass); } } double maxBiomass = SpeciesData.B_MAX_Spp[cohort.Species, ecoregion] * capacityReduction; double maxANPP = SpeciesData.ANPP_MAX_Spp[cohort.Species, ecoregion]; // Potential biomass, equation 3 in Scheller and Mladenoff, 2004 double potentialBiomass = Math.Max(1.0, maxBiomass - siteBiomass + cohortBiomass); // Species can use new space from mortality immediately // but not in the case of capacity reduction due to harvesting. if (capacityReduction >= 1.0) { potentialBiomass = Math.Max(potentialBiomass, SiteVars.PreviousYearMortality[site]); } // Ratio of cohort's actual biomass to potential biomass B_AP = cohortBiomass / potentialBiomass; double indexC = CalculateCompetition(site, cohort); if ((indexC <= 0.0 && cohortBiomass > 0) || indexC > 1.0) { PlugIn.ModelCore.UI.WriteLine("Error: Competition Index [{0:0.00}] is <= 0.0 or > 1.0", indexC); PlugIn.ModelCore.UI.WriteLine("Yr={0}. SPECIES={1}, AGE={2}, B={3}", (PlugIn.ModelCore.CurrentTime + SubYear), cohort.Species.Name, cohort.Age, cohortBiomass); throw new ApplicationException("Application terminating."); } B_PM = indexC; // PlugIn.ModelCore.Log.WriteLine("indexC={0:0.00}, lightIndexC={1:0.00}, OldSchool={2:0.00}.", indexC, indexLightC, indexOldSchool); // Actual ANPP: equation (4) from Scheller & Mladenoff, 2004. double actualANPP = maxANPP * Math.E * Math.Pow(B_AP, growthShape) * Math.Exp(-1 * Math.Pow(B_AP, growthShape)) * B_PM; // Calculated actual ANPP can not exceed the limit set by the // maximum ANPP times the ratio of potential to maximum biomass. // This down regulates actual ANPP by the available growing space. actualANPP = Math.Min(maxANPP * B_PM, actualANPP); if (growthReduction > 0) { actualANPP *= (1.0 - growthReduction); } if (PlugIn.CalibrateMode && PlugIn.ModelCore.CurrentTime > 0) { PlugIn.ModelCore.UI.WriteLine("Yr={0}. Calculate ANPPactual...", (PlugIn.ModelCore.CurrentTime + SubYear)); PlugIn.ModelCore.UI.WriteLine("Yr={0}. Spp={1}, Age={2}.", (PlugIn.ModelCore.CurrentTime + SubYear), cohort.Species.Name, cohort.Age); PlugIn.ModelCore.UI.WriteLine("Yr={0}. MaxANPP={1}, MaxB={2:0}, Bsite={3}, Bcohort={4:0.0}.", (PlugIn.ModelCore.CurrentTime + SubYear), maxANPP, maxBiomass, (int)siteBiomass, cohort.Biomass); PlugIn.ModelCore.UI.WriteLine("Yr={0}. B_PM={1:0.0}, B_AP={2:0.0}, actualANPP={3:0.0}, capacityReduction={4:0.0}.", (PlugIn.ModelCore.CurrentTime + SubYear), B_PM, B_AP, actualANPP, capacityReduction); } return(actualANPP); }