//--------------------------------------------------------------------- public ushort Damage(ICohort cohort) { if (ageCohortDisturbance.Damage(cohort)) return cohort.Biomass; else return 0; }
//--------------------------------------------------------------------- float[] IDisturbance.ReduceOrKillMarkedCohort(ICohort cohort) { float reduction; float[] leafWoodReduction = new float[2]{0F, 0F}; if (reductions[cohort.Species.Index].TryGetValue(cohort.Age, out reduction)) { leafWoodReduction[0] = cohort.WoodBiomass / (cohort.LeafBiomass + cohort.WoodBiomass) * (float) reduction; leafWoodReduction[1] = cohort.LeafBiomass / (cohort.LeafBiomass + cohort.WoodBiomass) * (float) reduction; SiteVars.BiomassRemoved[currentSite] += (int) reduction; SiteVars.CohortsPartiallyDamaged[currentSite]++; if (originalStand.LastPrescription.PreventEstablishment) { numberCohortsReduced++; capacityReduction += (double)reduction / (double)cohort.Biomass; } // Record any cohort touched, not just killed: BaseHarvest.SiteVars.Stand[currentSite].UpdateDamageTable(cohort.Species.Name); return leafWoodReduction; } else return leafWoodReduction; }
//--------------------------------------------------------------------- int IDisturbance.ReduceOrKillMarkedCohort(ICohort cohort) { int reduction; if (reductions[cohort.Species.Index].TryGetValue(cohort.Age, out reduction)) { int litter = cohort.ComputeNonWoodyBiomass(currentSite); int woody = reduction - litter; SiteVars.BiomassRemoved[currentSite] += reduction; SiteVars.WoodyDebris[currentSite].Mass += woody; SiteVars.Litter[currentSite].Mass += litter; SiteVars.CohortsPartiallyDamaged[currentSite]++; if (originalStand.LastPrescription.PreventEstablishment) { numberCohortsReduced++; capacityReduction += (double) reduction / (double) cohort.Biomass; } // Record any cohort touched, not just killed: BaseHarvest.SiteVars.Stand[currentSite].UpdateDamageTable(cohort.Species.Name); BaseHarvest.SiteVars.Stand[currentSite].RecordBiomassRemoved(cohort.Species, reduction); return reduction; } else return 0; }
//--------------------------------------------------------------------- // Method for setting the available resorbed N for each cohort. // Amount of resorbed N must be in units of g N m-2. public static void SetResorbedNallocation(ICohort cohort, double resorbedNallocation, ActiveSite site) { int cohortAddYear = GetAddYear(cohort); //PlugIn.ModelCore.UI.WriteLine("SETResorbedNallocation: year={0}, mo={1}, species={2}, cohortAge={3}, cohortAddYear={4}.", PlugIn.ModelCore.CurrentTime, Century.Month, cohort.Species.Name, cohort.Age, cohortAddYear); Dictionary<int, double> cohortDict; double oldResorbedNallocation; // If the dictionary entry exists for the cohort, overwrite it: if (SiteVars.CohortResorbedNallocation[site].TryGetValue(cohort.Species.Index, out cohortDict)) if (cohortDict.TryGetValue(cohortAddYear, out oldResorbedNallocation)) { SiteVars.CohortResorbedNallocation[site][cohort.Species.Index][cohortAddYear] = resorbedNallocation; return; } // If the dictionary does not exist for the cohort, create it: Dictionary<int, double> newEntry = new Dictionary<int, double>(); newEntry.Add(cohortAddYear, resorbedNallocation); if (SiteVars.CohortResorbedNallocation[site].ContainsKey(cohort.Species.Index)) { SiteVars.CohortResorbedNallocation[site][cohort.Species.Index].Add(cohortAddYear, resorbedNallocation); } else { SiteVars.CohortResorbedNallocation[site].Add(cohort.Species.Index, newEntry); } //PlugIn.ModelCore.UI.WriteLine("SET ResorbedNallocation: ResorbedNallocation={0:0.00000}.", resorbedNallocation); return; }
//--------------------------------------------------------------------- int IDisturbance.Damage(ICohort cohort) { int reduction; if (reductions[cohort.Species.Index].TryGetValue(cohort.Age, out reduction)) { //UI.WriteLine("Removing: {0:0.0}/{1:0.0}.", reduction, cohort.Biomass); SiteVars.BiomassRemoved[currentSite] += reduction; SiteVars.CohortsPartiallyDamaged[currentSite]++; if (originalStand.LastPrescription.PreventEstablishment) { numberCohortsReduced++; capacityReduction += (double) reduction / (double) cohort.Biomass; } // Record any cohort touched, not just killed: BaseHarvest.SiteVars.Stand[currentSite].UpdateDamageTable(cohort.Species.Name); return reduction; } else return 0; }
public CohortBiomass(ActiveSite Site, ICohort Cohort, int Index) { this.cohort = Cohort; fRad = 0; site = Site; spc = Cohort.Species; }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ushort IDisturbance.Damage(ICohort cohort) { if (5 <= cohort.Age && cohort.Age <= 30) return cohort.Biomass; else return 0; }
//--------------------------------------------------------------------- // This method replaces the delegate method. It is called every year when // ACT_ANPP is calculated, for each cohort. Therefore, this method is operating at // an ANNUAL time step and separate from the normal extension time step. public static double ReduceCohortGrowth(ICohort cohort, ActiveSite site)//, int siteBiomass) { // PlugIn.ModelCore.UI.WriteLine(" Calculating cohort growth reduction due to insect defoliation..."); double summaryGrowthReduction = 0.0; int sppIndex = cohort.Species.Index; foreach(IInsect insect in PlugIn.ManyInsect) { if(!insect.ActiveOutbreak) continue; int suscIndex = insect.SppTable[sppIndex].Susceptibility - 1; //if (suscIndex < 0) suscIndex = 0; int yearBack = 0; double annualDefoliation = 0.0; if(insect.HostDefoliationByYear[site].ContainsKey(PlugIn.ModelCore.CurrentTime - yearBack)) { // PlugIn.ModelCore.UI.WriteLine("Host Defoliation By Year: Time={0}, suscIndex={1}, spp={2}.", (PlugIn.ModelCore.CurrentTime - yearBack), suscIndex+1, cohort.Species.Name); annualDefoliation += insect.HostDefoliationByYear[site][PlugIn.ModelCore.CurrentTime - yearBack][suscIndex]; } double cumulativeDefoliation = annualDefoliation; while(annualDefoliation > 0) { yearBack++; annualDefoliation = 0.0; if(insect.HostDefoliationByYear[site].ContainsKey(PlugIn.ModelCore.CurrentTime - yearBack)) { // PlugIn.ModelCore.UI.WriteLine("Host Defoliation By Year: Time={0}, suscIndex={1}, spp={2}.", (PlugIn.ModelCore.CurrentTime - yearBack), suscIndex+1, cohort.Species.Name); annualDefoliation = insect.HostDefoliationByYear[site][PlugIn.ModelCore.CurrentTime - yearBack][suscIndex]; cumulativeDefoliation += annualDefoliation; } } double slope = insect.SppTable[sppIndex].GrowthReduceSlope; double intercept = insect.SppTable[sppIndex].GrowthReduceIntercept; double growthReduction = 1.0 - (cumulativeDefoliation * slope + intercept); summaryGrowthReduction += growthReduction; // PlugIn.ModelCore.UI.WriteLine("Time={0}, Spp={1}, SummaryGrowthReduction={2:0.00}.", PlugIn.ModelCore.CurrentTime,cohort.Species.Name, summaryGrowthReduction); } if (summaryGrowthReduction > 1.0) // Cannot exceed 100% summaryGrowthReduction = 1.0; if(summaryGrowthReduction > 1.0 || summaryGrowthReduction < 0) { PlugIn.ModelCore.UI.WriteLine("Cohort Total Growth Reduction = {0:0.00}. Site R/C={1}/{2}.", summaryGrowthReduction, site.Location.Row, site.Location.Column); throw new ApplicationException("Error: Total Growth Reduction is not between 1.0 and 0.0"); } return summaryGrowthReduction; }
//--------------------------------------------------------------------- /// <summary> /// Initializes a new instance. /// </summary> public DeathEventArgs(ICohort cohort, ActiveSite site, ExtensionType disturbanceType) { this.cohort = cohort; this.site = site; this.disturbanceType = disturbanceType; }
//--------------------------------------------------------------------- /// <summary> /// Raises a Cohort.Died event. /// </summary> public static void Died(ICohort cohort, ActiveSite site) { if (DiedEvent != null) { DiedEvent(cohort, site); } }
//--------------------------------------------------------------------- /// <summary> /// Raises a Cohort.DeathEvent. /// </summary> public static void Died(object sender, ICohort cohort, ActiveSite site, ExtensionType disturbanceType) { if (DeathEvent != null) DeathEvent(sender, new DeathEventArgs(cohort, site, disturbanceType)); }
//--------------------------------------------------------------------- public double ComputeCohortBasalArea(ICohort cohort) { double local_const = 3.1415926 / (4 * 10000.00); double cohortBA = Math.Pow(cohort.Diameter, 2) * local_const * cohort.Treenumber; return(cohortBA); }
//--------------------------------------------------------------------- public void RemoveCohort(int index, ICohort cohort, ActiveSite site, ExtensionType disturbanceType) { cohorts.RemoveAt(index); Cohort.Died(this, cohort, site, disturbanceType); }
//--------------------------------------------------------------------- public int ComputeChange(ICohort cohort, ActiveSite site, int siteBiomass, int prevYearSiteMortality) { CountCalled++; return(Change); }
//--------------------------------------------------------------------- // This method replaces the delegate method. It is called every year when // ACT_ANPP is calculated, for each cohort. Therefore, this method is operating at // an ANNUAL time step and separate from the normal extension time step. public static double DefoliateCohort(ICohort cohort, ActiveSite site, int siteBiomass) { // This maintains backwards compatibility with succession versions that don't use Biomass Library // but the functions must be sure to provide siteBiomass not cohortBiomass double defoliation = Landis.Extension.Insects.Defoliate.DefoliateCohort(site, cohort.Species, cohort.Biomass, siteBiomass); return defoliation; }
private void ReduceCohort(int index, ICohort cohort, ActiveSite site, ExtensionType disturbanceType, float reduction) { //cohortData.RemoveAt(index); Cohort.PartialMortality(this, cohort, site, disturbanceType, reduction); }
//--------------------------------------------------------------------- /// <summary> /// Computes the percentage of a cohort's standing biomass that is non-woody. /// April 2010: changed to be a constant percentage of foliage, so that the /// calculations of turnover give reasonable numbers. /// </summary> public Percentage ComputeNonWoodyPercentage(ICohort cohort, ActiveSite site) { double leaf = 0.1; Percentage temp = new Percentage(leaf); return(temp); }
//--------------------------------------------------------------------- private void RemoveCohort(int index, ICohort cohort, ActiveSite site, PlugInType disturbanceType) { cohortData.RemoveAt(index); Cohort.Died(this, cohort, site, disturbanceType); }
//--------------------------------------------------------------------- public int ComputeChange(ICohort cohort, ActiveSite site, int siteBiomass, int prevYearSiteMortality) { CountCalled++; return Change; }
//--------------------------------------------------------------------- // DamageCohort is a filter to determine which cohorts are removed. // Each cohort is passed into the function and tested whether it should // be killed. bool ICohortDisturbance.MarkCohortForDeath(ICohort cohort) { //PlugIn.ModelCore.Log.WriteLine("Cohort={0}, {1}, {2}.", cohort.Species.Name, cohort.Age, cohort.Species.Index); bool killCohort = false; bool BF = false; ISppParameters sppParms = epidemicParms.SppParameters[cohort.Species.Index]; string mySpecies = cohort.Species.Name; if (mySpecies == "abiebals") { BF = true; } if (BF && cohort.Age > this.bfAgeCutoff) { killCohort = true; } else { if (cohort.Age >= sppParms.ResistantHostAge) { if (this.random <= this.siteVulnerability * sppParms.ResistantHostVuln) { killCohort = true; } } if (cohort.Age >= sppParms.TolerantHostAge) { if (this.random <= this.siteVulnerability * sppParms.TolerantHostVuln) { killCohort = true; } } if (cohort.Age >= sppParms.VulnerableHostAge) { if (this.random <= this.siteVulnerability * sppParms.VulnerableHostVuln) { killCohort = true; } } } if (killCohort) { this.siteCohortsKilled++; if (sppParms.CFSConifer) { this.siteCFSconifersKilled++; } } return(killCohort); }
//--------------------------------------------------------------------- // A filter to determine which cohorts are removed. // Use species level variables for bark thickness accumulation with age to calculate cohort level mortality. // the cohort level mortality is a binomial distribution int IDisturbance.ReduceOrKillMarkedCohort(ICohort cohort) { this.AvailableCohorts++; bool killCohort = false; // User Inputs double Beta_naught_m = PlugIn.Parameters.CohortMortalityB0; // Intercept parameter for mortality curve double Beta_Bark = PlugIn.Parameters.CohortMortalityB1; // The parameter fit for the relationship between bark thickness and mortality. double Beta_Site_Mortality = PlugIn.Parameters.CohortMortalityB2; // The parameter fit for the relationship between site level and individual level mortality. // From the input file each species will need // AgeDBH _Parameter is a parameter to scale Age and DBH estimated from a function in the form of // It is essentially the half-life of the MaxBarkThickness *Age relationship. // This is a logistic survival code with the MaxBarkThickness being asymptote. // As age increase DBH approaches MaxBarkThickness double AgeDBH = SpeciesData.AgeDBH[cohort.Species]; // The maximum measured Bark thickness. The asymptote of the logistic survival curve. // This was calculated by using a species-specific bark DBH Coefficient described in Cansler 2020 and the maximum measured DBH form FIA. // Cansler, C. A., Hood, S. M., Varner, J. M., van Mantgem, P. J., Agne, M. C., Andrus, R. A., ... & // Bentz, B. J. (2020). The Fire and Tree Mortality Database, for empirical modeling of individual tree // mortality after fire. Scientific data, 7(1), 1-14. double MaxBarkThickness = SpeciesData.MaximumBarkThickness[cohort.Species]; //// CohortAge The age of the cohort double BarkThickness = (MaxBarkThickness * cohort.Age) / (cohort.Age + AgeDBH); double Pm = Math.Exp(Beta_naught_m + (Beta_Bark * BarkThickness) + (Beta_Site_Mortality * SiteMortality)); double probabilityMortality = Pm / (1.0 + Pm); double random = PlugIn.ModelCore.GenerateUniform(); if (probabilityMortality > random) { //PlugIn.ModelCore.UI.WriteLine("damage prob={0}, Random#={1}", ProbablityMortality, random); killCohort = true; this.TotalBiomassMortality += cohort.Biomass; foreach (IDeadWood deadwood in PlugIn.Parameters.DeadWoodList) { if (cohort.Species == deadwood.Species && cohort.Age >= deadwood.MinAge) { SiteVars.SpecialDeadWood[this.currentSite] += cohort.Biomass; //PlugIn.ModelCore.UI.WriteLine("special dead = {0}, site={1}.", SiteVars.SpecialDeadWood[this.Current_damage_site], this.Current_damage_site); } } } if (killCohort) { this.CohortsKilled++; return(cohort.Biomass); } return(0); }
//--------------------------------------------------------------------- private double UpdateDeadBiomass(ICohort cohort, double actualANPP, double totalMortality, ActiveSite site, double newBiomass) { ISpecies species = cohort.Species; double leafLongevity = SpeciesData.LeafLongevity[species]; double cohortBiomass = newBiomass; // Mortality is for the current year's biomass. double leafFraction = ComputeFractionANPPleaf(species); // First, deposit the a portion of the leaf mass directly onto the forest floor. // In this way, the actual amount of leaf biomass is added for the year. double annualLeafANPP = actualANPP * leafFraction; ForestFloor.AddLitter(annualLeafANPP, species, site); // -------------------------------------------------------------------------------- // The next section allocates mortality from standing (wood and leaf) biomass, i.e., // biomass that has accrued from previous years' growth. // Subtract annual leaf growth as that was taken care of above. totalMortality -= annualLeafANPP; // Assume that standing foliage is equal to this years annualLeafANPP * leaf longevity // minus this years leaf ANPP. This assumes that actual ANPP has been relatively constant // over the past 2 or 3 years (if coniferous). double standing_nonwood = (annualLeafANPP * leafLongevity) - annualLeafANPP; double standing_wood = Math.Max(0, cohortBiomass - standing_nonwood); double fractionStandingNonwood = standing_nonwood / cohortBiomass; // Assume that the remaining mortality is divided proportionally // between the woody mass and non-woody mass (Niklaus & Enquist, // 2002). Do not include current years growth. double mortality_nonwood = Math.Max(0.0, totalMortality * fractionStandingNonwood); double mortality_wood = Math.Max(0.0, totalMortality - mortality_nonwood); if (mortality_wood < 0 || mortality_nonwood < 0) { throw new ApplicationException("Error: Woody input is < 0"); } // Add mortality to dead biomass pools. if (mortality_wood > 0) { ForestFloor.AddWoody((ushort)mortality_wood, species, site); } if (mortality_nonwood > 0) { ForestFloor.AddLitter(mortality_nonwood, species, site); } // Total mortality not including annual leaf litter M_noLeafLitter = (int)mortality_wood; return(annualLeafANPP + mortality_nonwood + mortality_wood); }
//--------------------------------------------------------------------- /// <summary> /// Records a species that should be checked for resprouting during /// reproduction. /// </summary> /// <param name="cohort"> /// The cohort whose death triggered the current call to this method. /// </param> /// <param name="site"> /// The site where the cohort died. /// </param> /// <remarks> /// If the cohort's age is within the species' age range for /// resprouting, then the species will be have additional resprouting /// criteria (light, probability) checked during reproduction. /// </remarks> public static void CheckForResprouting(ICohort cohort, ActiveSite site) { ISpecies species = cohort.Species; if (species.MinSproutAge <= cohort.Age && cohort.Age <= species.MaxSproutAge) { resprout[site].Set(species.Index, true); } }
public int ReduceOrKillMarkedCohort(ICohort cohort) { if (_siteHarvestingRule.SpeciesName.Equals(cohort.Species.Name) == false) { return(0); } return((int)(cohort.Biomass * (double)_siteHarvestingRule.Percentage)); }
//--------------------------------------------------------------------- /// <summary> /// Initializes a new instance. /// </summary> public PartialDeathEventArgs(ICohort cohort, ActiveSite site, ExtensionType disturbanceType, float reduction) { this.cohort = cohort; this.site = site; this.disturbanceType = disturbanceType; this.reduction = reduction; }
//--------------------------------------------------------------------- /// <summary> /// Monthly mortality as a function of standing leaf and wood biomass. /// </summary> //private double[] ComputeGrowthMortality(ICohort cohort, ActiveSite site) private double[] ComputeGrowthMortality(ICohort cohort, ActiveSite site, double siteBiomass, double[] AGNPP) { double maxBiomass = SpeciesData.Max_Biomass[cohort.Species]; double NPPwood = (double)AGNPP[0]; //if(cohort.WoodBiomass <= 0 || cohort.LeafBiomass <= 0) // return (new double[2]{0.0, 0.0}); double M_wood = cohort.WoodBiomass * FunctionalType.Table[SpeciesData.FuncType[cohort.Species]].MonthlyWoodMortality; double M_leaf = 0.0; double relativeBiomass = siteBiomass / maxBiomass; double M_constant = 5.0; //This constant controls the rate of change of mortality with NPP //Functon which calculates an adjustment factor for mortality that ranges from 0 to 1 and exponentially increases with relative biomass. double M_wood_relative = Math.Max(0.0, (Math.Exp(M_constant * relativeBiomass) - 1) / (Math.Exp(M_constant) - 1)); //This function calculates mortality as a function of NPP M_wood = NPPwood * M_wood_relative; // Leaves and Needles dropped. if (SpeciesData.LeafLongevity[cohort.Species] > 1.0) { M_leaf = cohort.LeafBiomass / (double)SpeciesData.LeafLongevity[cohort.Species] / 12.0; //Needle deposit spread across the year. } else { if (Main.Month + 1 == FunctionalType.Table[SpeciesData.FuncType[cohort.Species]].LeafNeedleDrop) { M_leaf = cohort.LeafBiomass / 2.0; //spread across 2 months } if (Main.Month + 2 > FunctionalType.Table[SpeciesData.FuncType[cohort.Species]].LeafNeedleDrop) { M_leaf = cohort.LeafBiomass; //drop the remainder } } double[] M_BIO = new double[2] { M_wood, M_leaf }; if (M_wood < 0.0 || M_leaf < 0.0) { PlugIn.ModelCore.UI.WriteLine("Mwood={0}, Mleaf={1}.", M_wood, M_leaf); throw new ApplicationException("Error: Wood or Leaf Growth Mortality is < 0"); } if (PlugIn.ModelCore.CurrentTime > 0 && OtherData.CalibrateMode) { Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", M_wood, M_leaf); } SiteVars.WoodMortality[site] += (M_wood); return(M_BIO); }
//--------------------------------------------------------------------- /// <summary> /// Raises a Cohort.DeathEvent. /// </summary> public static void Died(object sender, ICohort cohort, ActiveSite site, PlugInType disturbanceType) { if (DeathEvent != null) { DeathEvent(sender, new DeathEventArgs(cohort, site, disturbanceType)); } }
//--------------------------------------------------------------------- /// <summary> /// Occurs when a cohort is killed by an age-only disturbance. /// </summary> //public static event DeathEventHandler<DeathEventArgs> AgeOnlyDeathEvent; //--------------------------------------------------------------------- /// <summary> /// Raises a Cohort.AgeOnlyDeathEvent. /// </summary> public static void KilledByAgeOnlyDisturbance(object sender, ICohort cohort, ActiveSite site, ExtensionType disturbanceType) { if (AgeOnlyDeathEvent != null) { AgeOnlyDeathEvent(sender, new Landis.Library.BiomassCohorts.DeathEventArgs(cohort, site, disturbanceType)); } }
//--------------------------------------------------------------------- /// <summary> /// Raises a Cohort.AgeOnlyDeathEvent. /// </summary> public static void KilledByAgeOnlyDisturbance(object sender, ICohort cohort, ActiveSite site, PlugInType disturbanceType) { if (AgeOnlyDeathEvent != null) { AgeOnlyDeathEvent(sender, new DeathEventArgs(cohort, site, disturbanceType)); } }
//--------------------------------------------------------------------- public double MyCompute(ICohort cohort, ActiveSite site, int siteBiomass) { Assert.AreEqual(myCohort, cohort); Assert.AreEqual(myActiveSite, site); Assert.AreEqual(mySiteBiomass, siteBiomass); myComputeCalled = true; return myComputeResult; }
//--------------------------------------------------------------------- public double MyCompute(ICohort cohort, ActiveSite site, int siteBiomass) { Assert.AreEqual(myCohort, cohort); Assert.AreEqual(myActiveSite, site); Assert.AreEqual(mySiteBiomass, siteBiomass); myComputeCalled = true; return(myComputeResult); }
//--------------------------------------------------------------------- public ushort Damage(ICohort cohort) { if (ageCohortDisturbance.Damage(cohort)) { Cohort.KilledByAgeOnlyDisturbance(this, cohort, ageCohortDisturbance.CurrentSite, ageCohortDisturbance.Type); return cohort.Biomass; } else return 0; }
//, int month) //--------------------------------------------------------------------- public static void AddResorbedN(ICohort cohort, double leafBiomass, ActiveSite site) { // Resorbed N: We are assuming that any leaves dropped as a function of normal // growth and maintenance (e.g., fall senescence) will involve resorption of leaf N. double resorbedN = AvailableN.CalculateResorbedN(site, cohort.Species, leafBiomass); //, month); double previouslyResorbedN = GetResorbedNallocation(cohort); AvailableN.SetResorbedNallocation(cohort, resorbedN + previouslyResorbedN); return; }
private static double calculateCompetition_Limit(ICohort cohort, ActiveSite site) { double k = -0.14; // This is the value given for all temperature ecosystems. I started with 0.1 double monthly_cumulative_LAI = SiteVars.MonthlyLAI[site][Main.Month]; double competition_limit = Math.Max(0.0, Math.Exp(k * monthly_cumulative_LAI)); //if (PlugIn.ModelCore.CurrentTime > 0 && OtherData.CalibrateMode) // Outputs.CalibrateLog.Write("{0:0.00},", monthly_cumulative_LAI); return(competition_limit); }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ushort IDisturbance.Damage(ICohort cohort) { if (5 <= cohort.Age && cohort.Age <= 30) { return(cohort.Biomass); } else { return(0); } }
public static bool CohortIsDead(ICohort cohort) { //System.Console.WriteLine("COHORT AGE\t" + cohort.Age); if (cohort.NSC <= 1) { //System.Console.WriteLine("DEAD COHORT\t" + cohort.Age); return(true); } return(false); }
//--------------------------------------------------------------------- // This is the SIMULATION year that a cohort was born (not its age). // The number can be negative if the cohort was added with the initial community. //--------------------------------------------------------------------- private static int GetAddYear(ICohort cohort) { int currentYear = PlugIn.ModelCore.CurrentTime; int cohortAddYear = currentYear - (cohort.Age - Century.Year); if (Century.MonthCnt == 11) { cohortAddYear++; } return(cohortAddYear); }
//--------------------------------------------------------------------- public ushort Damage(ICohort cohort) { if (ageCohortDisturbance.Damage(cohort)) { return(cohort.Biomass); } else { return(0); } }
public int ReduceOrKillMarkedCohort(ICohort cohort) { if (ageCohortDisturbance.MarkCohortForDeath(cohort)) { Cohort.KilledByAgeOnlyDisturbance(this, cohort, ageCohortDisturbance.CurrentSite, ageCohortDisturbance.Type); return (int)cohort.Wood; } else return 0; }
//--------------------------------------------------------------------- /// <summary> /// Scheller TESTING 12/2016 /// Raises a Cohort.DeathEvent if partial mortality. /// </summary> public static void PartialMortality(object sender, ICohort cohort, ActiveSite site, ExtensionType disturbanceType, float reduction) { if (PartialDeathEvent != null) { PartialDeathEvent(sender, new Landis.Library.BiomassCohorts.PartialDeathEventArgs(cohort, site, disturbanceType, reduction)); } }
/// <summary> /// Passed anonymously to succession modules to compute defoliation /// In succession modules defoliation is computed per-cohort, hence cohortBiomass parameter /// </summary> /// <param name="active"></param> /// <param name="species"></param> /// <param name="cohortBiomass"></param> /// <param name="siteBiomass"></param> /// <returns></returns> //public static double InsectDefoliate(ActiveSite active, ISpecies species, int cohortBiomass, int siteBiomass) public static double InsectDefoliate(ICohort cohort, ActiveSite active, int siteBiomass) { double totalDefoliation = 0.0; InsectDefoliation id = null; foreach (IChange lcc in SiteVars.LandUse[active].LandCoverChanges) { if (lcc.GetType() == typeof(InsectDefoliation)) { id = (lcc as InsectDefoliation); if (id.repeat) { CohortDefoliation.Compute = InsectDefoliate; } else if (Model.Core.CurrentTime > id.harvestTime) { //Model.Core.UI.WriteLine("Disabling defoliation after harvest time: " + Model.Core.CurrentTime); CohortDefoliation.Compute = DontCompute; id = null; break; } break; } } if (id != null) { //Landis.Extension.Succession.BiomassPnET.Cohort defolCohort = (cohort as Landis.Extension.Succession.BiomassPnET.Cohort); ICohort defolCohort = cohort; if (id.landCoverSelectors.ContainsKey(defolCohort.Species.Name)) { Percentage percentage = null; id.landCoverSelectors[defolCohort.Species.Name].Selects(defolCohort, out percentage); if (percentage == null) { //Model.Core.UI.WriteLine("Null percent"); } else { totalDefoliation = percentage.Value; } if (totalDefoliation > 1.0) // Cannot exceed 100% defoliation { totalDefoliation = 1.0; } } } return(totalDefoliation); }
private static string OutputCohortFileName(ActiveSite site, ICohort cohort) { string dir = Landis.Extension.Succession.BiomassPnET.InputParametersParser.Names.PNEToutputsites; if (System.IO.Directory.Exists("output/" + dir) == false) { System.IO.Directory.CreateDirectory("output/" + dir); } string FileName = "output/" + dir + "/CohortData_" + site + "_" + cohort.YearOfBirth + "_" + cohort.Species.Name + Constants.ext; return(FileName); }
//--------------------------------------------------------------------- public static void AddResorbedN(ICohort cohort, double deadLeafRootsBiomass, ActiveSite site)//, int month) { // Resorbed N: We are assuming that any leaves dropped as a function of normal // growth and maintenance (e.g., fall senescence) will involve resorption of leaf N. double resorbedN = AvailableN.CalculateResorbedN(site, cohort.Species, deadLeafRootsBiomass); //, month); //double resorbedN = AvailableN.CalculateResorbedN(site, cohort.Species, cohort.LeafBiomass); //, month); double previouslyResorbedN = GetResorbedNallocation(cohort, site); AvailableN.SetResorbedNallocation(cohort, resorbedN + previouslyResorbedN, site); return; }
//--------------------------------------------------------------------- /// <summary> /// Computes the percentage of a cohort's standing biomass that is non-woody. /// This method is designed for external calls that need to /// estimate the amount of non-wood biomass. /// </summary> public Percentage ComputeNonWoodyPercentage(ICohort cohort, ActiveSite site) { double mortalityAge = ComputeAgeMortality(cohort); double actualANPP = ComputeActualANPP(cohort, site); // Age mortality is discounted from ANPP to prevent the over- // estimation of mortality. ANPP cannot be negative. actualANPP = Math.Max(0, actualANPP - mortalityAge); return(new Percentage(ComputeStandingLeafBiomass(actualANPP, cohort) / cohort.Biomass)); }
public void SingleCohort_LongevityReached() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 300; cohorts.AddNewCohort(poputrem, initialBiomass); mockCalculator.CountCalled = 0; mockCalculator.Change = 1; expectedSender = cohorts[poputrem]; expectedDistType = null; // death during growth phase expectedSite = activeSite; deadCohorts.Clear(); // Repeatedly grow for succession timesteps until longevity // reached. int time = 0; do { time += successionTimestep; Util.Grow(cohorts, successionTimestep, activeSite, true); } while (time <= poputrem.Longevity); expectedCohorts.Clear(); Util.CheckCohorts(expectedCohorts, cohorts); // Calculator called L times where L is longevity. Inituitively, // one would think since initial cohort's age is 1, it'd only take // L-1 times to get to the max age (= L). So the calculator // should be called L-1 times. But the combining of young cohorts // at the first succession timestep (t_succ = 20) results in the // calculator being called twice with cohort age = t_succ-1 (19). // At the end of year 19, the cohort's age is 20 and the // calculator has been called 19 times. But at the start of year // 20, the combine-young-cohorts operation is done because it's a // succession timestep. The combine operation takes all the young // cohorts (age <= t_succ = 20) and replaces them with one cohort // with age = t_succ-1 (= 19). This ensures that after the growth // phase, the cohort's age will be t_succ (20). So the growth // phase of year 20 calls the calculator for the 20th time with // cohort age 19. Assert.AreEqual(poputrem.Longevity, mockCalculator.CountCalled); Assert.AreEqual(1, deadCohorts.Count); ICohort deadCohort = deadCohorts[0]; Assert.AreEqual(poputrem, deadCohort.Species); Assert.AreEqual(poputrem.Longevity, deadCohort.Age); Assert.AreEqual(initialBiomass + (poputrem.Longevity * mockCalculator.Change), deadCohort.Biomass); }
//--------------------------------------------------------------------- // Interface method for biomass disturbances int IDisturbance.ReduceOrKillMarkedCohort(ICohort cohort) { int reduction = 0; SpecificAgesCohortSelector specificAgeCohortSelector; if (partialCohortSelectors.TryGetValue(cohort.Species, out specificAgeCohortSelector)) { Percentage percentage; if (specificAgeCohortSelector.Selects(cohort, out percentage)) reduction = (int)(percentage * cohort.Biomass); } Record(reduction, cohort); return reduction; }
//--------------------------------------------------------------------- protected override void Record(int reduction, ICohort cohort) { if (SiteLog.Enabled) { SiteLog.RecordHarvest(cohort.Species, reduction); if (isDebugEnabled) log.DebugFormat(" {0}, age {1}, biomass {2} : reduction = {3}", cohort.Species.Name, cohort.Age, cohort.Biomass, reduction); } }
public static Dictionary<int, Dictionary<int, double>> CohortMineralNallocation; //calculated monthly //public static Dictionary<int, Dictionary<int, double>> CohortResorbedNallocation; //--------------------------------------------------------------------- // Method for retrieving the available resorbed N for each cohort. // Return amount of resorbed N in g N m-2. public static double GetResorbedNallocation(ICohort cohort, ActiveSite site) { int cohortAddYear = GetAddYear(cohort); //PlugIn.ModelCore.UI.WriteLine("GETResorbedNallocation: year={0}, mo={1}, species={2}, cohortAge={3}, cohortAddYear={4}.", PlugIn.ModelCore.CurrentTime, Century.Month, cohort.Species.Name, cohort.Age, cohortAddYear); double resorbedNallocation = 0.0; Dictionary<int, double> cohortDict; if (SiteVars.CohortResorbedNallocation[site].TryGetValue(cohort.Species.Index, out cohortDict)) cohortDict.TryGetValue(cohortAddYear, out resorbedNallocation); //PlugIn.ModelCore.UI.WriteLine("GETResorbedNallocation: year={0}, mo={1}, species={2}, cohortAge={3}, cohortAddYear={4}.", PlugIn.ModelCore.CurrentTime, Century.Month, cohort.Species.Name, cohort.Age, cohortAddYear); return resorbedNallocation; }
//--------------------------------------------------------------------- int IDisturbance.ReduceOrKillMarkedCohort(ICohort cohort) { int reduction; if (reductions[cohort.Species.Index].TryGetValue(cohort.Age, out reduction)) { //SiteVars.BiomassRemoved[currentSite] += reduction; //SiteVars.CohortsPartiallyDamaged[currentSite]++; return reduction; } else return 0; }
public void Init() { betualle = Data.Species["betualle"]; const ushort age = 100; const int biomass = 500; CohortData data = new CohortData(age, biomass); myCohort = new Cohort(betualle, data); bool[,] grid = new bool[,]{ {true} }; DataGrid<bool> dataGrid = new DataGrid<bool>(grid); ILandscape landscape = new Landscape.Landscape(dataGrid); myActiveSite = landscape[1,1]; }
//--------------------------------------------------------------------- /// <summary> /// Kills coarse roots and add the biomass to the Wood Debris pool. /// </summary> public static void AddCoarseRootLitter(double abovegroundWoodBiomass,ICohort cohort, ISpecies species, ActiveSite site) { double coarseRootBiomass = CalculateCoarseRoot(cohort, abovegroundWoodBiomass); // Ratio above to below if(coarseRootBiomass > 0) WoodLayer.PartitionResidue(coarseRootBiomass, FunctionalType.Table[SpeciesData.FuncType[species]].WoodDecayRate, SpeciesData.CoarseRootCN[species], SpeciesData.CoarseRootLignin[species], LayerName.CoarseRoot, LayerType.Soil, site); }
//--------------------------------------------------------------------- /// <summary> /// Computes the cohort's biomass that is leaf litter /// or other non-woody components. Assumption is that remainder is woody. /// </summary> public static double ComputeStandingLeafBiomass(double ANPPactual, ICohort cohort) { double annualLeafFraction = ComputeFractionANPPleaf(cohort.Species); double annualFoliar = ANPPactual * annualLeafFraction; double B_nonwoody = annualFoliar * SpeciesData.LeafLongevity[cohort.Species]; // Non-woody cannot be less than 2.5% or greater than leaf fraction of total // biomass for a cohort. B_nonwoody = Math.Max(B_nonwoody, cohort.Biomass * 0.025); B_nonwoody = Math.Min(B_nonwoody, cohort.Biomass * annualLeafFraction); return B_nonwoody; }
public static void AdjustAvailableN(ICohort cohort, ActiveSite site, double[] actualANPP) { // Because Growth used some Nitrogen, it must be subtracted from the appropriate pools, either resorbed or mineral. //PlugIn.ModelCore.UI.WriteLine("AdjustAvailableN"); double totalNdemand = AvailableN.CalculateCohortNDemand(cohort.Species, site, actualANPP); double adjNdemand = totalNdemand; double resorbedNused = 0.0; double mineralNused = 0.0; // Use resorbed N first and only if it is spring time unless you are evergreen. double leafLongevity = SpeciesData.LeafLongevity[cohort.Species]; if ((leafLongevity <= 1.0 && Century.Month > 2 && Century.Month < 6) || leafLongevity > 1.0) { double resorbedNallocation = Math.Max(0.0, AvailableN.GetResorbedNallocation(cohort)); resorbedNused = resorbedNallocation - Math.Max(0.0, resorbedNallocation - totalNdemand); AvailableN.SetResorbedNallocation(cohort, Math.Max(0.0, resorbedNallocation - totalNdemand)); adjNdemand = Math.Max(0.0, totalNdemand - resorbedNallocation); } // Reduce available N after taking into account that some N may have been provided // via resorption (above). double Nuptake = 0.0; if (SiteVars.MineralN[site] >= adjNdemand) { SiteVars.MineralN[site] -= adjNdemand; mineralNused = adjNdemand; Nuptake = adjNdemand; } else { double NdemandAdjusted = SiteVars.MineralN[site]; mineralNused = SiteVars.MineralN[site]; SiteVars.MineralN[site] = 0.0; Nuptake = SiteVars.MineralN[site]; } //PlugIn.ModelCore.UI.WriteLine("totalNdemand={0:0.00}, Nuptake={1:0.00}, mineralN={2:0.0}, mineralNused={3:0.0}, resorbedNused={4:0.0},", totalNdemand, Nuptake, SiteVars.MineralN[site], mineralNused, resorbedNused); SiteVars.TotalNuptake[site] += Nuptake; if (OtherData.CalibrateMode && PlugIn.ModelCore.CurrentTime > 0) { //Outputs.CalibrateLog.Write("{0:0.00}, {1:0.00}, {2:0.00}, {3:0.00},", deltaWood, deltaLeaf, totalMortality[0], totalMortality[1]); Outputs.CalibrateLog.Write("{0:0.00}, {1:0.00}, {2:0.00},", resorbedNused, mineralNused, totalNdemand); } }
//--------------------------------------------------------------------- float[] IDisturbance.Damage(ICohort cohort) { float reduction; float[] leafWoodReduction = new float[2]{0F, 0F}; if (reductions[cohort.Species.Index].TryGetValue(cohort.Age, out reduction)) { leafWoodReduction[0] = cohort.WoodBiomass / (cohort.LeafBiomass + cohort.WoodBiomass) * (float) reduction; leafWoodReduction[1] = cohort.LeafBiomass / (cohort.LeafBiomass + cohort.WoodBiomass) * (float) reduction; SiteVars.BiomassRemoved[currentSite] += (int) reduction; return leafWoodReduction; } else return leafWoodReduction; }
//--------------------------------------------------------------------- public float[] ReduceOrKillMarkedCohort(ICohort cohort) { float[] damage = new float[]{0,0}; if (ageCohortDisturbance.MarkCohortForDeath(cohort)) { Cohort.KilledByAgeOnlyDisturbance(this, cohort, ageCohortDisturbance.CurrentSite, ageCohortDisturbance.Type); damage[0] = cohort.WoodBiomass; damage[1] = cohort.LeafBiomass; return damage; } //else return damage; }
public static void WriteHeader(ActiveSite site, ICohort cohort) { if (HasSiteOutput[site] == false) return; FileName = "output/CohortData_" + site + "_" + cohort.YearOfBirth + "_" + cohort.Species.Name + Constants.ext; if (System.IO.File.Exists(FileName)) System.IO.File.Delete(FileName); string hdr=""; hdr = "Year" + delim + "Month" + delim + "Date" + delim + "CanopyLayer" + delim + "PAR0(W_m2)" + delim + "LeafOn" + delim + "LAI(m2)" + delim + "GDD(C|base=PsnTMin)" + delim + "GrossPsn(g_m2_mo)" + delim + "FolResp(g_m2_mo)" + delim + "MaintResp(g_m2_mo)" + delim + "NetPsn(g_m2_mo)" + delim + "ReleasedNSC" + delim + "Folalloc" + delim + "RootAlloc" + delim + "WoodAlloc" + delim + "VPD" + delim + "WUE(g_mm)" + delim + "DelAmax(-)" + delim + "Transpiration(mm_mo)" + delim + "Fol(gDW_m2)" + delim + //"FolShed(gDW_m2)" + delim + "Root(gDW_m2)" + delim + "Wood(gDW_m2)" + delim + "NSC(gC_m2)" + delim + "Water(mm)" + delim + "wfps" + delim + "dWater(-)" + delim + "DTemp_psn" + delim + "DTemp_resp" + delim + "fage" + delim + "fRad(-)"; System.IO.StreamWriter sw = System.IO.File.AppendText(FileName); sw.WriteLine(hdr); sw.Close(); }
//--------------------------------------------------------------------- // Crown scorching is when a cohort loses its foliage but is not killed. public static double CrownScorching(ICohort cohort, byte siteSeverity) { int difference = (int) siteSeverity - cohort.Species.FireTolerance; double ageFraction = 1.0 - ((double) cohort.Age / (double) cohort.Species.Longevity); if(SpeciesData.Epicormic[cohort.Species]) { if(difference < 0) return 0.5 * ageFraction; if(difference == 0) return 0.75 * ageFraction; if(difference > 0) return 1.0 * ageFraction; } return 0.0; }
public static void WriteHeader(ActiveSite site, ICohort cohort) { string FileName = OutputCohortFileName(site, cohort); if (System.IO.File.Exists(FileName)) System.IO.File.Delete(FileName); string hdr=""; hdr = "Year" + delim + "Month" + delim + "Date" + delim + "Age" + delim + "CanopyLayer" + delim + "PAR0(W_m2)" + delim + //"LeafOn" + delim + "LAI(m2)" + delim + "GDD(C|base=PsnTMin)" + delim + "HDD(C|base=PsnTMin)" + delim + "GrossPsn(g_m2_mo)" + delim + "FolResp(g_m2_mo)" + delim + "MaintResp(g_m2_mo)" + delim + "NetPsn(g_m2_mo)" + delim + "ReleasedNSC(g_m2_mo)" + delim + "Folalloc(g_m2_mo)" + delim + "RootAlloc(g_m2_mo)" + delim + "WoodAlloc(g_m2_mo)" + delim + "VPD(kPa)" + delim + "WUE(g_mm)" + delim + "Transpiration(mm_mo)" + delim + "Fol(gDW_m2)" + delim + //"FolShed(gDW_m2)" + delim + "Root(gDW_m2)" + delim + "Wood(gDW_m2)" + delim + "NSC(gC_m2)" + delim + "fWater(-)" + delim + "fTemp_psn" + delim + "fTemp_resp" + delim + "fage" + delim + "fRad(-)"; System.IO.StreamWriter sw = System.IO.File.AppendText(FileName); sw.WriteLine(hdr); sw.Close(); }
//--------------------------------------------------------------------- /// <summary> /// Selects which cohorts are harvested. /// </summary> /// <returns> /// true if the given cohort is to be harvested. The cohort's biomass /// should be reduced by the percentage returned in the second /// parameter. /// </returns> public bool Selects(ICohort cohort, out Percentage percentage) { ushort ageToLookUp = 0; AgeRange? containingRange; if (agesAndRanges.Contains(cohort.Age, out containingRange)) { if (! containingRange.HasValue) ageToLookUp = cohort.Age; else { ageToLookUp = containingRange.Value.Start; } if (! percentages.TryGetValue(ageToLookUp, out percentage)) percentage = defaultPercentage; return true; } percentage = null; return false; }