diff --git a/deploy/installer/LANDIS-II-V7 NECN Succession 6.6-setup.exe b/deploy/installer/LANDIS-II-V7 NECN Succession 6.6-setup.exe index 26e2e92..d7accb6 100644 Binary files a/deploy/installer/LANDIS-II-V7 NECN Succession 6.6-setup.exe and b/deploy/installer/LANDIS-II-V7 NECN Succession 6.6-setup.exe differ diff --git a/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.docx b/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.docx index 50df4b4..56d0137 100644 Binary files a/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.docx and b/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.docx differ diff --git a/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.pdf b/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.pdf index f86e837..0e1e05d 100644 Binary files a/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.pdf and b/docs/LANDIS-II Net Ecosystem CN Succession v6.6 User Guide.pdf differ diff --git a/docs/index.md b/docs/index.md index 7754d55..9f530a7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ # What is the NECN Succession Extension? -The Net Ecosystem Carbon & Nitrogen (NECN) Succession extension implements succession with full accounting of above and below ground carbon and nitrogen. Aboveground biomass is represented with cohorts that have biomass (g m-2). In addition, below ground processing of Carbon and Nitrogen is simulated following the core logic of the Century nutrient cycling model (v4.0). +The NECN Succession extension was designed to provide total ecosystem accounting of Carbon and Nitrogen and to allow species to respond dynamically to a changing climate via establishment and growth. NECN calculates how cohorts grow, reproduce, age, and die. Dead biomass is tracked over time, divided into four pools: surface wood, soil wood (dead coarse roots), surface litter (dead leaves), and soil litter (dead fine roots). In addition, three principle soil pools: fast (soil organic matter (SOM) 1), slow (SOM2), and passive (SOM3) are simulated, following the Century soil model. # Features @@ -12,9 +12,9 @@ The Net Ecosystem Carbon & Nitrogen (NECN) Succession extension implements succe # Release Notes -- Latest official release: Version 6.4.1 — May 2020 +- Latest official release: Version 6.6 — February 2021 - This extension was formerly named Century Succession. -- [NECN User Guide](https://github.com/LANDIS-II-Foundation/Extension-NECN-Succession/blob/master/docs/LANDIS-II%20Net%20Ecosystem%20CN%20Succession%20v6.4%20User%20Guide.pdf). +- [NECN User Guide](https://github.com/LANDIS-II-Foundation/Extension-NECN-Succession/blob/master/docs/LANDIS-II%20Net%20Ecosystem%20CN%20Succession%20v6.6%20User%20Guide.pdf). - [User Guide for Climate Library](https://github.com/LANDIS-II-Foundation/Library-Climate/blob/master/docs/LANDIS-II%20Climate%20Library%20v4.1%20User%20Guide.pdf) - Full release details found in the NECN User Guide and on GitHub. @@ -27,7 +27,7 @@ To use NECN, you need: # Download -Version 6.4.1 can be downloaded [here](https://github.com/LANDIS-II-Foundation/Extension-NECN-Succession/blob/master/deploy/past-releases/LANDIS-II-V7%20NECN%20Succession%206.4.1-setup.exe). To install it on your computer, just launch the installer. +Version 6.6 can be downloaded [here](https://github.com/LANDIS-II-Foundation/Extension-NECN-Succession/blob/master/deploy/installer/LANDIS-II-V7%20NECN%20Succession%206.6-setup.exe). To install it on your computer, just launch the installer. # Citation diff --git a/src/AvailableN.cs b/src/AvailableN.cs index 551bcc5..2936a4b 100644 --- a/src/AvailableN.cs +++ b/src/AvailableN.cs @@ -333,7 +333,7 @@ public static void AdjustAvailableN(ICohort cohort, ActiveSite site, double[] ac CalibrateLog.resorbedNused = resorbedNused; CalibrateLog.mineralNused = Nuptake; CalibrateLog.demand_N = totalNdemand; - Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},{2:0.00},", resorbedNused, Nuptake, totalNdemand); + //Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},{2:0.00},", resorbedNused, Nuptake, totalNdemand); } } diff --git a/src/CohortBiomass.cs b/src/CohortBiomass.cs index 5f42817..67eb7f6 100644 --- a/src/CohortBiomass.cs +++ b/src/CohortBiomass.cs @@ -55,7 +55,7 @@ public float[] ComputeChange(ICohort cohort, ActiveSite site) CalibrateLog.cohortAge = cohort.Age; CalibrateLog.cohortWoodB = cohort.WoodBiomass; CalibrateLog.cohortLeafB = cohort.LeafBiomass; - Outputs.CalibrateLog.Write("{0},{1},{2},{3},{4},{5:0.0},{6:0.0},", PlugIn.ModelCore.CurrentTime, Main.Month + 1, ecoregion.Index, cohort.Species.Name, cohort.Age, cohort.WoodBiomass, cohort.LeafBiomass); + //Outputs.CalibrateLog.Write("{0},{1},{2},{3},{4},{5:0.0},{6:0.0},", PlugIn.ModelCore.CurrentTime, Main.Month + 1, ecoregion.Index, cohort.Species.Name, cohort.Age, cohort.WoodBiomass, cohort.LeafBiomass); } @@ -155,8 +155,10 @@ public float[] ComputeChange(ICohort cohort, ActiveSite site) if (OtherData.CalibrateMode && PlugIn.ModelCore.CurrentTime > 0) { + CalibrateLog.deltaLeaf = deltaLeaf; + CalibrateLog.deltaWood = deltaWood; CalibrateLog.WriteLogFile(); - Outputs.CalibrateLog.WriteLine("{0:0.00},{1:0.00},{2:0.00},{3:0.00},", deltaWood, deltaLeaf, totalMortality[0], totalMortality[1]); + //Outputs.CalibrateLog.WriteLine("{0:0.00},{1:0.00},{2:0.00},{3:0.00},", deltaWood, deltaLeaf, totalMortality[0], totalMortality[1]); } return deltas; @@ -185,7 +187,7 @@ private double[] ComputeActualANPP(ICohort cohort, // 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 competition_limit = calculate_LAI_Competition(cohort, site); double potentialNPP = maxNPP * limitLAI * limitH20 * limitT * competition_limit; @@ -243,9 +245,9 @@ private double[] ComputeActualANPP(ICohort cohort, CalibrateLog.actualWoodNPP = woodNPP; CalibrateLog.actualLeafNPP = leafNPP; - 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); + //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}; @@ -295,7 +297,7 @@ private double[] ComputeAgeMortality(ICohort cohort, ActiveSite site) { CalibrateLog.mortalityAGEleaf = M_AGE_leaf; CalibrateLog.mortalityAGEwood = M_AGE_wood; - Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", M_AGE_wood, M_AGE_leaf); + //Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", M_AGE_wood, M_AGE_leaf); } return M_AGE; @@ -359,7 +361,7 @@ private double[] ComputeGrowthMortality(ICohort cohort, ActiveSite site, double { CalibrateLog.mortalityBIOwood = M_wood; CalibrateLog.mortalityBIOleaf = M_leaf; - Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", M_wood, M_leaf); + //Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", M_wood, M_leaf); } SiteVars.WoodMortality[site] += (M_wood); @@ -512,7 +514,7 @@ private double calculateN_Limit(ActiveSite site, ICohort cohort, double NPP, dou { CalibrateLog.mineralNalloc = mineralNallocation; CalibrateLog.resorbedNalloc = resorbedNallocation; - Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", mineralNallocation, resorbedNallocation); + //Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},", mineralNallocation, resorbedNallocation); } return Math.Max(limitN, 0.0); @@ -617,18 +619,15 @@ private static double calculateLAI_Limit(ICohort cohort, ActiveSite site) CalibrateLog.actual_LAI = lai; CalibrateLog.base_lai = base_lai; CalibrateLog.seasonal_adjustment = seasonal_adjustment; - Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},{2:0.00},", lai, base_lai, seasonal_adjustment); + //Outputs.CalibrateLog.Write("{0:0.00},{1:0.00},{2:0.00},", lai, base_lai, seasonal_adjustment); } - //PlugIn.ModelCore.UI.WriteLine("Yr={0},Mo={1}. Spp={2}, leafC={3:0.0}, woodC={4:0.00}.", PlugIn.ModelCore.CurrentTime, month + 1, species.Name, leafC, largeWoodC); - //PlugIn.ModelCore.UI.WriteLine("Yr={0},Mo={1}. Spp={2}, lai={3:0.0}, woodC={4:0.00}.", PlugIn.ModelCore.CurrentTime, month + 1, species.Name, lai, largeWoodC); - //PlugIn.ModelCore.UI.WriteLine("Yr={0},Mo={1}. LAI Limits: lai={2:0.0}, woodLAI={3:0.0}, leafLAI={4:0.0}, LAIlimit={5:0.00}.", PlugIn.ModelCore.CurrentTime, month + 1, lai, woodLAI, leafLAI, LAI_limit); return LAI_Growth_limit; } - private static double calculateCompetition_Limit(ICohort cohort, ActiveSite site) + private static double calculate_LAI_Competition(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]; @@ -709,7 +708,7 @@ private static double calculateWater_Limit(ActiveSite site, IEcoregion ecoregion if (PlugIn.ModelCore.CurrentTime > 0 && OtherData.CalibrateMode) { CalibrateLog.availableWater = SiteVars.AvailableWater[site]; - Outputs.CalibrateLog.Write("{0:0.00},", SiteVars.AvailableWater[site]); + //Outputs.CalibrateLog.Write("{0:0.00},", SiteVars.AvailableWater[site]); } return WaterLimit; diff --git a/src/Outputs.cs b/src/Outputs.cs index 6d79a3e..4dfdc1c 100644 --- a/src/Outputs.cs +++ b/src/Outputs.cs @@ -17,7 +17,7 @@ namespace Landis.Extension.Succession.NECN { public class Outputs { - public static StreamWriter CalibrateLog; + //public static StreamWriter CalibrateLog; public static MetadataTable monthlyLog; public static MetadataTable primaryLog; public static MetadataTable primaryLogShort; @@ -467,44 +467,44 @@ public static void WriteMonthlyLogFile(int month) } //Write log file for growth and limits - public static void CreateCalibrateLogFile() - { - string logFileName = "NECN-calibrate-OLD-log.csv"; - PlugIn.ModelCore.UI.WriteLine("******************WARNING************************", logFileName); - PlugIn.ModelCore.UI.WriteLine("******YOU ARE CURRENTLY IN CALIBRATE MODE********", logFileName); - PlugIn.ModelCore.UI.WriteLine("*************************************************", logFileName); - PlugIn.ModelCore.UI.WriteLine(" Opening NECN calibrate log file \"{0}\" ...", logFileName); - try - { - CalibrateLog = new StreamWriter(logFileName); - } - catch (Exception err) - { - string mesg = string.Format("{0}", err.Message); - throw new System.ApplicationException(mesg); - } - - CalibrateLog.AutoFlush = true; - - CalibrateLog.Write("Year, Month, ClimateRegionIndex, SpeciesName, CohortAge, CohortWoodB, CohortLeafB, "); // from ComputeChange - CalibrateLog.Write("MortalityAGEwood, MortalityAGEleaf, "); // from ComputeAgeMortality - CalibrateLog.Write("availableWater,"); //from Water_limit - CalibrateLog.Write("LAI, tlai, rlai,"); // from ComputeChange - CalibrateLog.Write("mineralNalloc, resorbedNalloc, "); // from calculateN_Limit - - // These three together: - CalibrateLog.Write("limitLAI, limitH20, limitT, limitN, "); //from ComputeActualANPP - CalibrateLog.Write("maxNPP, Bmax, Bsite, Bcohort, soilTemp, "); //from ComputeActualANPP - CalibrateLog.Write("actualWoodNPP, actualLeafNPP, "); //from ComputeActualANPP - - CalibrateLog.Write("MortalityBIOwood, MortalityBIOleaf, "); // from ComputeGrowthMortality - CalibrateLog.Write("NPPwood_C, NPPleaf_C, "); //from ComputeNPPcarbon - CalibrateLog.Write("resorbedNused, mineralNused, Ndemand,"); // from AdjustAvailableN - CalibrateLog.WriteLine("deltaWood, deltaLeaf, totalMortalityWood, totalMortalityLeaf"); // from ComputeChange + //public static void CreateCalibrateLogFile() + //{ + // string logFileName = "NECN-calibrate-OLD-log.csv"; + // PlugIn.ModelCore.UI.WriteLine("******************WARNING************************", logFileName); + // PlugIn.ModelCore.UI.WriteLine("******YOU ARE CURRENTLY IN CALIBRATE MODE********", logFileName); + // PlugIn.ModelCore.UI.WriteLine("*************************************************", logFileName); + // PlugIn.ModelCore.UI.WriteLine(" Opening NECN calibrate log file \"{0}\" ...", logFileName); + // try + // { + // CalibrateLog = new StreamWriter(logFileName); + // } + // catch (Exception err) + // { + // string mesg = string.Format("{0}", err.Message); + // throw new System.ApplicationException(mesg); + // } + + // CalibrateLog.AutoFlush = true; + + // CalibrateLog.Write("Year, Month, ClimateRegionIndex, SpeciesName, CohortAge, CohortWoodB, CohortLeafB, "); // from ComputeChange + // CalibrateLog.Write("MortalityAGEwood, MortalityAGEleaf, "); // from ComputeAgeMortality + // CalibrateLog.Write("availableWater,"); //from Water_limit + // CalibrateLog.Write("LAI, tlai, rlai,"); // from ComputeChange + // CalibrateLog.Write("mineralNalloc, resorbedNalloc, "); // from calculateN_Limit + + // // These three together: + // CalibrateLog.Write("limitLAI, limitH20, limitT, limitN, "); //from ComputeActualANPP + // CalibrateLog.Write("maxNPP, Bmax, Bsite, Bcohort, soilTemp, "); //from ComputeActualANPP + // CalibrateLog.Write("actualWoodNPP, actualLeafNPP, "); //from ComputeActualANPP + + // CalibrateLog.Write("MortalityBIOwood, MortalityBIOleaf, "); // from ComputeGrowthMortality + // CalibrateLog.Write("NPPwood_C, NPPleaf_C, "); //from ComputeNPPcarbon + // CalibrateLog.Write("resorbedNused, mineralNused, Ndemand,"); // from AdjustAvailableN + // CalibrateLog.WriteLine("deltaWood, deltaLeaf, totalMortalityWood, totalMortalityLeaf"); // from ComputeChange - } + //} public static void WriteMaps() { diff --git a/src/PlugIn.cs b/src/PlugIn.cs index 7fea68c..633b455 100644 --- a/src/PlugIn.cs +++ b/src/PlugIn.cs @@ -139,9 +139,8 @@ public override void Initialize() InitializeSites(Parameters.InitialCommunities, Parameters.InitialCommunitiesMap, modelCore); - if (Parameters.CalibrateMode) - Outputs.CreateCalibrateLogFile(); - //Establishment.InitializeLogFile(); + //if (Parameters.CalibrateMode) + // Outputs.CreateCalibrateLogFile(); B_MAX = 0; foreach (ISpecies species in ModelCore.Species) diff --git a/src/metadata/CalibrateLog.cs b/src/metadata/CalibrateLog.cs index 5be710f..0573e73 100644 --- a/src/metadata/CalibrateLog.cs +++ b/src/metadata/CalibrateLog.cs @@ -19,6 +19,7 @@ public class CalibrateLog public static double limitLAI, limitH20, limitT, limitN; public static double maxNPP, maxB, siteB, cohortB, soilTemp; public static double actualWoodNPP, actualLeafNPP; + public static double deltaWood, deltaLeaf; public static double mortalityBIOwood, mortalityBIOleaf; // CalibrateLog.Write("NPPwood_C, NPPleaf_C, "); //from ComputeNPPcarbon public static double resorbedNused, mineralNused, demand_N; @@ -58,6 +59,8 @@ public static void WriteLogFile() clog.SoilTemperature = soilTemp; clog.ActualWoodANPP = actualWoodNPP; clog.ActualLeafANPP = actualLeafNPP; + clog.DeltaWood = deltaWood; + clog.DeltaLeaf = deltaLeaf; clog.TotalNDemand = demand_N; @@ -134,6 +137,12 @@ public static void WriteLogFile() [DataFieldAttribute(Unit = "g_B_m2_month1", Desc = "Actual Leaf ANPP", Format = "0.0000")] public double ActualLeafANPP { set; get; } // ******************************************************************** + [DataFieldAttribute(Unit = "g_B_m2_month1", Desc = "Change in Wood Biomass", Format = "0.000")] + public double DeltaWood { set; get; } + // ******************************************************************** + [DataFieldAttribute(Unit = "g_B_m2_month1", Desc = "Change in Leaf Biomass", Format = "0.0000")] + public double DeltaLeaf { set; get; } + // ******************************************************************** [DataFieldAttribute(Unit = FieldUnits.g_B_m2, Desc = "Cohort Maximum Biomass")] public double CohortMaximumBiomass { set; get; } // ********************************************************************