public void SingleCohort_ZeroBiomass() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 100; cohorts.AddNewCohort(poputrem, initialBiomass); mockCalculator.CountCalled = 0; mockCalculator.Change = -2; expectedSite = activeSite; deadCohorts.Clear(); for (int time = 1; time <= 60; time++) { if (time % successionTimestep == 0) { cohorts.Grow(successionTimestep, activeSite, true); } } expectedCohorts.Clear(); Util.CheckCohorts(expectedCohorts, cohorts); Assert.AreEqual(1, deadCohorts.Count); ICohort deadCohort = deadCohorts[0]; Assert.AreEqual(poputrem, deadCohort.Species); Assert.AreEqual(initialBiomass / -mockCalculator.Change, deadCohort.Age); Assert.AreEqual(0, deadCohort.Biomass); }
public void NoCohorts_Grow() { SiteCohorts cohorts = new SiteCohorts(); mockCalculator.CountCalled = 0; cohorts.Grow(5, activeSite, false); Assert.AreEqual(0, mockCalculator.CountCalled); }
//--------------------------------------------------------------------- /// <summary> /// Grows all cohorts at a site for a number of years. /// </summary> public static void Grow(SiteCohorts cohorts, int years, ActiveSite site, bool isSuccessionTimestep) { for (int y = 1; y <= years; ++y) cohorts.Grow(site, (y == years && isSuccessionTimestep)); }
//--------------------------------------------------------------------- /// <summary> /// Grows all cohorts at a site for a number of years. /// </summary> public static void Grow(SiteCohorts cohorts, int years, ActiveSite site, bool isSuccessionTimestep) { for (int y = 1; y <= years; ++y) { cohorts.Grow(site, (y == years && isSuccessionTimestep)); } }
/// <summary> /// Grows all cohorts at a site for a specified number of years. The /// dead pools at the site also decompose for the given time period. /// </summary> public static void GrowCohorts(SiteCohorts cohorts, ActiveSite site, int years, bool isSuccessionTimestep) { for (int y = 1; y <= years; ++y) { cohorts.Grow(site, (y == years && isSuccessionTimestep)); Dead.Pools.Woody[site].Decompose(); Dead.Pools.NonWoody[site].Decompose(); } }
public void CombineYoungCohorts() { SiteCohorts cohorts = new SiteCohorts(); ushort[] initialBiomass = new ushort[] { 300, 700 }; cohorts.AddNewCohort(abiebals, initialBiomass[0]); // Grow 1st cohort for 4 years, adding 10 to its biomass per year mockCalculator.CountCalled = 0; mockCalculator.Change = 10; cohorts.Grow(4, activeSite, false); Assert.AreEqual(4, mockCalculator.CountCalled); expectedCohorts.Clear(); expectedCohorts[abiebals] = new ushort[] { 5, (ushort)(300 + 4 * mockCalculator.Change) }; Util.CheckCohorts(expectedCohorts, cohorts); // Add 2nd cohort and then grow both cohorts 6 more years up to // a succession timestep cohorts.AddNewCohort(abiebals, initialBiomass[1]); mockCalculator.CountCalled = 0; cohorts.Grow(6, activeSite, true); // ComputeChange for both cohorts for 5 years, then combine them, // and then one time for the combined cohort Assert.AreEqual(5 * 2 + 1, mockCalculator.CountCalled); expectedCohorts.Clear(); expectedCohorts[abiebals] = new ushort[] { successionTimestep, (ushort) (300 + (4 + 5) * mockCalculator.Change // first cohort before combining + 700 + 5 * mockCalculator.Change // 2nd cohort before combining + mockCalculator.Change) // growth after combining }; Util.CheckCohorts(expectedCohorts, cohorts); }
public void CombineYoungCohorts() { SiteCohorts cohorts = new SiteCohorts(); ushort[] initialBiomass = new ushort[] { 300, 700 }; cohorts.AddNewCohort(abiebals, initialBiomass[0]); // Grow 1st cohort for 4 years, adding 10 to its biomass per year mockCalculator.CountCalled = 0; mockCalculator.Change = 10; cohorts.Grow(4, activeSite, false); Assert.AreEqual(4, mockCalculator.CountCalled); expectedCohorts.Clear(); expectedCohorts[abiebals] = new ushort[] { 5, (ushort) (300 + 4 * mockCalculator.Change) }; Util.CheckCohorts(expectedCohorts, cohorts); // Add 2nd cohort and then grow both cohorts 6 more years up to // a succession timestep cohorts.AddNewCohort(abiebals, initialBiomass[1]); mockCalculator.CountCalled = 0; cohorts.Grow(6, activeSite, true); // ComputeChange for both cohorts for 5 years, then combine them, // and then one time for the combined cohort Assert.AreEqual(5 * 2 + 1, mockCalculator.CountCalled); expectedCohorts.Clear(); expectedCohorts[abiebals] = new ushort[] { successionTimestep, (ushort) (300 + (4 + 5) * mockCalculator.Change // first cohort before combining + 700 + 5 * mockCalculator.Change // 2nd cohort before combining + mockCalculator.Change) // growth after combining }; Util.CheckCohorts(expectedCohorts, cohorts); }
public void SingleCohort_LongevityReached() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 300; cohorts.AddNewCohort(poputrem, initialBiomass); mockCalculator.CountCalled = 0; mockCalculator.Change = 1; expectedSite = activeSite; deadCohorts.Clear(); // Repeatedly grow for succession timesteps until longevity // reached. int time = 0; do { time += successionTimestep; cohorts.Grow(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); }
//--------------------------------------------------------------------- /// <summary> /// Grows all cohorts at a site for a specified number of years. The /// dead pools at the site also decompose for the given time period. /// </summary> public static void GrowCohorts(SiteCohorts cohorts, ActiveSite site, int years, bool isSuccessionTimestep) { for (int y = 1; y <= years; ++y) { // Calculate competition for each cohort CohortBiomass.CalculateCompetition(cohorts); CohortBiomass.SubYear = y; cohorts.Grow(site, (y == years && isSuccessionTimestep)); SiteVars.WoodyDebris[site].Decompose(); SiteVars.Litter[site].Decompose(); } }
public void Grow() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 35; cohorts.AddNewCohort(abiebals, initialBiomass); mockCalculator.CountCalled = 0; mockCalculator.Change = 8; cohorts.Grow(activeSite, true); expectedCohorts.Clear(); expectedCohorts[abiebals] = new ushort[] { // age biomass 2, (ushort) (initialBiomass + mockCalculator.Change) }; Util.CheckCohorts(expectedCohorts, cohorts); }
public void Grow() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 35; cohorts.AddNewCohort(abiebals, initialBiomass); mockCalculator.CountCalled = 0; mockCalculator.Change = 8; cohorts.Grow(activeSite, true); expectedCohorts.Clear(); expectedCohorts[abiebals] = new ushort[] { // age biomass 2, (ushort)(initialBiomass + mockCalculator.Change) }; Util.CheckCohorts(expectedCohorts, cohorts); }
public void CohortsRemoved() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 40; mockCalculator.CountCalled = 0; mockCalculator.Change = 1; int timeOfLastSucc = 0; for (int time = 1; time <= 50; time++) { // Simulate the site being disturbed every 8 years which // results in a new cohort being added. bool siteDisturbed = (time % 8 == 0); bool isSuccTimestep = (time % successionTimestep == 0); if (siteDisturbed || isSuccTimestep) { cohorts.Grow((ushort)(time - timeOfLastSucc), activeSite, isSuccTimestep); timeOfLastSucc = time; } if (siteDisturbed) { cohorts.AddNewCohort(poputrem, initialBiomass); } } // Expected sequence of cohort changes: // // Time Grow_________ // Last Cohorts New // Time Succ years afterwards Cohort // ---- ---- ----- --------------- ------ // 8 0 8 1(40) // 16 8 8 9(48) 1(40) // 20 16 4 20(95*) * = 48+3 + 40+3 + 1 // 24 20 4 24(99) 1(40) // 32 24 8 32(107),9(48) 1(40) // 40 32 8 40(115),20(103*) 1(40) * = 48+7 + 40+7 + 1 // 48 40 8 48(123),28(111),9(48) 1(40) expectedCohorts.Clear(); expectedCohorts[poputrem] = new ushort[] { // age biomass 48, 123, 28, 111, 9, 48, 1, 40 }; Util.CheckCohorts(expectedCohorts, cohorts); // Remove cohorts whose ages are between 10 and 30 expectedSite = null; deadCohorts.Clear(); cohorts.Remove(AgeBetween5And30); expectedCohorts.Clear(); expectedCohorts[poputrem] = new ushort[] { // age biomass 48, 123, 1, 40 }; Util.CheckCohorts(expectedCohorts, cohorts); Assert.AreEqual(2, deadCohorts.Count); ushort[] cohortData = new ushort[] { // age biomass (in young to old order because Remove goes // from back to front) 9, 48, 28, 111 }; for (int i = 0; i < deadCohorts.Count; i++) { ICohort deadCohort = deadCohorts[i]; Assert.AreEqual(poputrem, deadCohort.Species); Assert.AreEqual(cohortData[i * 2], deadCohort.Age); Assert.AreEqual(cohortData[i * 2 + 1], deadCohort.Biomass); } }
/// <summary> /// Grows all cohorts at a site for a specified number of years. /// Litter is decomposed following the Century model. /// </summary> public static SiteCohorts Run( SiteCohorts siteCohorts, Location location, int years, bool isSuccessionTimeStep) { ActiveSite site = (ActiveSite) PlugIn.ModelCore.Landscape.GetSite(location); IEcoregion ecoregion = PlugIn.ModelCore.Ecoregion[site]; for (int y = 0; y < years; ++y) { SiteVars.ResetAnnualValues(site); if(y == 0 && SiteVars.FireSeverity != null && SiteVars.FireSeverity[site] > 0) FireEffects.ReduceLayers(SiteVars.FireSeverity[site], site); // Do not reset annual climate if it has already happend for this year. if(!EcoregionData.ClimateUpdates[ecoregion][y + PlugIn.ModelCore.CurrentTime]) { EcoregionData.SetAnnualClimate(PlugIn.ModelCore.Ecoregion[site], y); EcoregionData.ClimateUpdates[ecoregion][y + PlugIn.ModelCore.CurrentTime] = true; } // if spin-up phase, allow each initial community to have a unique climate if(PlugIn.ModelCore.CurrentTime == 0) { EcoregionData.SetAnnualClimate(PlugIn.ModelCore.Ecoregion[site], y); } // Next, Grow and Decompose each month int[] months = new int[12]{6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5}; if(OtherData.CalibrateMode) months = new int[12]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; for (int i = 0; i < 12; i++) { int month = months[i]; SiteVars.MonthlyAGNPPcarbon[site][month] = 0.0; SiteVars.MonthlyBGNPPcarbon[site][month] = 0.0; SiteVars.MonthlyNEE[site][month] = 0.0; SiteVars.MonthlyResp[site][month] = 0.0; SiteVars.SourceSink[site].Carbon = 0.0; SiteVars.TotalWoodBiomass[site] = Century.ComputeWoodBiomass((ActiveSite) site); double monthlyNdeposition = EcoregionData.AnnualWeather[PlugIn.ModelCore.Ecoregion[site]].MonthlyNdeposition[month]; SiteVars.MineralN[site] += monthlyNdeposition; //PlugIn.ModelCore.Log.WriteLine("Month={0}, Ndeposition={1}.", i+1, monthlyNdeposition); double liveBiomass = (double) ComputeLivingBiomass(siteCohorts); SoilWater.Run(y, month, liveBiomass, site); //SpeciesData.CalculateNGrowthLimits(site); // Calculate N limitations for each cohort AvailableN.CohortNlimits = new Dictionary<int, Dictionary<int,double>>(); AvailableN.CalculateNLimits(site); CohortBiomass.month = month; if(month==11) siteCohorts.Grow(site, (y == years && isSuccessionTimeStep), true); else siteCohorts.Grow(site, (y == years && isSuccessionTimeStep), false); WoodLayer.Decompose(site); LitterLayer.Decompose(site); SoilLayer.Decompose(site); //...Volatilization loss as a function of the mineral n which // remains after uptake by plants double volatilize = SiteVars.MineralN[site] * 0.02 * OtherData.MonthAdjust; // value from ffix.100 SiteVars.MineralN[site] -= volatilize; SiteVars.SourceSink[site].Nitrogen += volatilize; //SoilWater.Leach(site); SiteVars.MonthlyNEE[site][month] -= SiteVars.MonthlyAGNPPcarbon[site][month]; SiteVars.MonthlyNEE[site][month] -= SiteVars.MonthlyBGNPPcarbon[site][month]; SiteVars.MonthlyNEE[site][month] += SiteVars.SourceSink[site].Carbon; } } ComputeTotalCohortCN(site, siteCohorts); return siteCohorts; }
/// <summary> /// Grows all cohorts (including productivity and mortality) at a site /// for a specified number of years. The dead pools at the site also /// decompose for the given time period and fires occur. /// </summary> public static void GrowCohorts(SiteCohorts cohorts, ActiveSite site, int years, bool isSuccessionTimestep) { IEcoregion ecoregion = Model.Core.Ecoregion[site]; for (int y = 1; y <= years; ++y) { //Account for any preceding fires. if (SiteVars.FireSeverity != null) { FireEffects.ComputeFireEffects(site); } //Decompose litter cohorts (each member of list is 1 annual cohort). foreach (PoolD litter in SiteVars.Litter[site]) { ForestFloor.DecomposeLitter(litter, site); } //Remove litter cohorts past the limit value. foreach (PoolD removeLitter in SiteVars.RemoveLitter[site]) { SiteVars.Litter[site].Remove(removeLitter); SiteVars.Litter[site].TrimExcess(); } SiteVars.RemoveLitter[site].Clear(); SiteVars.RemoveLitter[site].TrimExcess(); //Decompose dead fine roots cohorts (each member // of list is 1 annual cohort). foreach (PoolD deadFRoots in SiteVars.DeadFineRoots[site]) { Roots.DecomposeDeadFineRoots(deadFRoots, site); } //Remove dead fine roots cohorts past the limit value. foreach (PoolD removeDeadFRoots in SiteVars.RemoveDeadFineRoots[site]) { SiteVars.DeadFineRoots[site].Remove(removeDeadFRoots); SiteVars.DeadFineRoots[site].TrimExcess(); } SiteVars.RemoveDeadFineRoots[site].Clear(); SiteVars.RemoveDeadFineRoots[site].TrimExcess(); //Decompose coarse woody debris (includes coarse roots). ForestFloor.DecomposeWood(site); //Decompose soil organic matter. SoilOrganicMatter.Decompose(ecoregion, site); //Weather charcoal to release N and P to mineral soil pools. Charcoal.Weathering(SiteVars.Charcoal[site], SiteVars.MineralSoil[site]); //Weather rock to release P to mineral pool. Rock.Weathering(ecoregion, SiteVars.Rock[site], SiteVars.MineralSoil[site]); //N and P deposition. MineralSoil.Deposition(ecoregion, SiteVars.MineralSoil[site]); //Grow all cohorts at once, including above-/belowground growth, mortality, // and litterfall. N and P are taken up with growth and N limits ANPP. cohorts.Grow(site, (y == years && isSuccessionTimestep), true); //Add yearly cohorts to litter and dead fine roots lists. ForestFloor.AddYearLitter(site); Roots.AddYearDeadFineRoots(site); //Leach excess mineral N. MineralSoil.Leaching(site); } }
//--------------------------------------------------------------------- /// <summary> /// Grows all cohorts at a site to reach the specified initial communities. /// Includes resets for soil organic matter and soil mineral contents to /// user-specified initial values. /// </summary> public static void InitGrowCohorts(SiteCohorts cohorts, ActiveSite site, int years, bool isSuccessionTimestep) { for (int y = 1; y <= years; ++y) { //Used to reset soil minerals to user-specified parameters // during run-up to initial communities. double minN = SiteVars.MineralSoil[site].ContentN; double minP = SiteVars.MineralSoil[site].ContentP; double somMass = SiteVars.SoilOrganicMatter[site].Mass; double somC = SiteVars.SoilOrganicMatter[site].ContentC; double somN = SiteVars.SoilOrganicMatter[site].ContentN; double somP = SiteVars.SoilOrganicMatter[site].ContentP; // Make sure mineral N and P are sufficient for initial growth // (initial mineral N/P values represent a static point, not integrated // over history when values may have been higher). SiteVars.MineralSoil[site].ContentN = 1000; SiteVars.MineralSoil[site].ContentP = 1000; SiteVars.PrevYearMortality[site] = SiteVars.CurrentYearMortality[site]; SiteVars.CurrentYearMortality[site] = 0.0; //Grow cohorts. cohorts.Grow(site, (y == years && isSuccessionTimestep), true); //Add yearly cohorts to litter and dead fine roots lists. ForestFloor.AddYearLitter(site); Roots.AddYearDeadFineRoots(site); //Decompose coarse woody debris (includes coarse roots). ForestFloor.DecomposeWood(site); //Decompose litter cohorts (each member of list is 1 // annual cohort). foreach (PoolD litter in SiteVars.Litter[site]) { ForestFloor.DecomposeLitter(litter, site); } //Remove litter cohorts past the limit value. foreach (PoolD removeLitter in SiteVars.RemoveLitter[site]) { SiteVars.Litter[site].Remove(removeLitter); SiteVars.Litter[site].TrimExcess(); } SiteVars.RemoveLitter[site].Clear(); SiteVars.RemoveLitter[site].TrimExcess(); //Decompose dead fine roots cohorts (each member // of list is 1 annual cohort). foreach(PoolD deadFRoots in SiteVars.DeadFineRoots[site]) { Roots.DecomposeDeadFineRoots(deadFRoots, site); } //Remove dead fine roots cohorts past the limit value. foreach (PoolD removeDeadFRoots in SiteVars.RemoveDeadFineRoots[site]) { SiteVars.DeadFineRoots[site].Remove(removeDeadFRoots); SiteVars.DeadFineRoots[site].TrimExcess(); } SiteVars.RemoveDeadFineRoots[site].Clear(); SiteVars.RemoveDeadFineRoots[site].TrimExcess(); //Reset soil organic and mineral values to user-specified parameters. SiteVars.MineralSoil[site].ContentN = minN; SiteVars.MineralSoil[site].ContentP = minP; SiteVars.SoilOrganicMatter[site].Mass = somMass; SiteVars.SoilOrganicMatter[site].ContentC = somC; SiteVars.SoilOrganicMatter[site].ContentN = somN; SiteVars.SoilOrganicMatter[site].ContentP = somP; } }
public void SingleCohort_ZeroBiomass() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 100; cohorts.AddNewCohort(poputrem, initialBiomass); mockCalculator.CountCalled = 0; mockCalculator.Change = -2; expectedSite = activeSite; deadCohorts.Clear(); for (int time = 1; time <= 60; time++) { if (time % successionTimestep == 0) cohorts.Grow(successionTimestep, activeSite, true); } expectedCohorts.Clear(); Util.CheckCohorts(expectedCohorts, cohorts); Assert.AreEqual(1, deadCohorts.Count); ICohort deadCohort = deadCohorts[0]; Assert.AreEqual(poputrem, deadCohort.Species); Assert.AreEqual(initialBiomass / -mockCalculator.Change, deadCohort.Age); Assert.AreEqual(0, deadCohort.Biomass); }
public void CohortsRemoved() { SiteCohorts cohorts = new SiteCohorts(); const ushort initialBiomass = 40; mockCalculator.CountCalled = 0; mockCalculator.Change = 1; int timeOfLastSucc = 0; for (int time = 1; time <= 50; time++) { // Simulate the site being disturbed every 8 years which // results in a new cohort being added. bool siteDisturbed = (time % 8 == 0); bool isSuccTimestep = (time % successionTimestep == 0); if (siteDisturbed || isSuccTimestep) { cohorts.Grow((ushort) (time - timeOfLastSucc), activeSite, isSuccTimestep); timeOfLastSucc = time; } if (siteDisturbed) cohorts.AddNewCohort(poputrem, initialBiomass); } // Expected sequence of cohort changes: // // Time Grow_________ // Last Cohorts New // Time Succ years afterwards Cohort // ---- ---- ----- --------------- ------ // 8 0 8 1(40) // 16 8 8 9(48) 1(40) // 20 16 4 20(95*) * = 48+3 + 40+3 + 1 // 24 20 4 24(99) 1(40) // 32 24 8 32(107),9(48) 1(40) // 40 32 8 40(115),20(103*) 1(40) * = 48+7 + 40+7 + 1 // 48 40 8 48(123),28(111),9(48) 1(40) expectedCohorts.Clear(); expectedCohorts[poputrem] = new ushort[] { // age biomass 48, 123, 28, 111, 9, 48, 1, 40 }; Util.CheckCohorts(expectedCohorts, cohorts); // Remove cohorts whose ages are between 10 and 30 expectedSite = null; deadCohorts.Clear(); cohorts.Remove(AgeBetween5And30); expectedCohorts.Clear(); expectedCohorts[poputrem] = new ushort[] { // age biomass 48, 123, 1, 40 }; Util.CheckCohorts(expectedCohorts, cohorts); Assert.AreEqual(2, deadCohorts.Count); ushort[] cohortData = new ushort[] { // age biomass (in young to old order because Remove goes // from back to front) 9, 48, 28, 111 }; for (int i = 0; i < deadCohorts.Count; i++) { ICohort deadCohort = deadCohorts[i]; Assert.AreEqual(poputrem, deadCohort.Species); Assert.AreEqual(cohortData[i*2], deadCohort.Age); Assert.AreEqual(cohortData[i*2+1], deadCohort.Biomass); } }