//---------------------------------------------------------------------
 public ushort Damage(ICohort cohort)
 {
     if (ageCohortDisturbance.Damage(cohort))
         return cohort.Biomass;
     else
         return 0;
 }
コード例 #2
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;
        }
コード例 #4
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;
        }
コード例 #5
0
        //---------------------------------------------------------------------

        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;
        }
コード例 #6
0
 public CohortBiomass(ActiveSite Site, ICohort Cohort, int Index)
 {
     this.cohort = Cohort;
     fRad = 0;
     site = Site;
     spc = Cohort.Species;
 }
コード例 #7
0
            //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

            ushort IDisturbance.Damage(ICohort cohort)
            {
                if (5 <= cohort.Age && cohort.Age <= 30)
                    return cohort.Biomass;
                else
                    return 0;
            }
コード例 #8
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;
        }
コード例 #9
0
        //---------------------------------------------------------------------

        /// <summary>
        /// Initializes a new instance.
        /// </summary>
        public DeathEventArgs(ICohort cohort,
                              ActiveSite site,
                              ExtensionType disturbanceType)
        {
            this.cohort          = cohort;
            this.site            = site;
            this.disturbanceType = disturbanceType;
        }
コード例 #10
0
        //---------------------------------------------------------------------

        /// <summary>
        /// Raises a Cohort.Died event.
        /// </summary>
        public static void Died(ICohort cohort,
                                ActiveSite site)
        {
            if (DiedEvent != null)
            {
                DiedEvent(cohort, site);
            }
        }
コード例 #11
0
        //---------------------------------------------------------------------

        /// <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));
        }
コード例 #12
0
        //---------------------------------------------------------------------

        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);
        }
コード例 #13
0
 //---------------------------------------------------------------------
 public void RemoveCohort(int index,
                          ICohort cohort,
                          ActiveSite site,
                          ExtensionType disturbanceType)
 {
     cohorts.RemoveAt(index);
     Cohort.Died(this, cohort, site, disturbanceType);
 }
コード例 #14
0
        //---------------------------------------------------------------------

        public int ComputeChange(ICohort cohort,
                                 ActiveSite site,
                                 int siteBiomass,
                                 int prevYearSiteMortality)
        {
            CountCalled++;
            return(Change);
        }
コード例 #15
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 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;
           
        }
コード例 #16
0
 private void ReduceCohort(int index,
                           ICohort cohort,
                           ActiveSite site,
                           ExtensionType disturbanceType, float reduction)
 {
     //cohortData.RemoveAt(index);
     Cohort.PartialMortality(this, cohort, site, disturbanceType, reduction);
 }
コード例 #17
0
        //---------------------------------------------------------------------

        /// <summary>
        /// Initializes a new instance.
        /// </summary>
        public DeathEventArgs(ICohort cohort,
                              ActiveSite site,
                              ExtensionType disturbanceType)
        {
            this.cohort = cohort;
            this.site = site;
            this.disturbanceType = disturbanceType;
        }
コード例 #18
0
        //---------------------------------------------------------------------

        /// <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);
        }
コード例 #19
0
        //---------------------------------------------------------------------

        private void RemoveCohort(int index,
                                  ICohort cohort,
                                  ActiveSite site,
                                  PlugInType disturbanceType)
        {
            cohortData.RemoveAt(index);
            Cohort.Died(this, cohort, site, disturbanceType);
        }
コード例 #20
0
        //---------------------------------------------------------------------

        public int ComputeChange(ICohort    cohort,
                                 ActiveSite site,
                                 int        siteBiomass,
                                 int        prevYearSiteMortality)
        {
            CountCalled++;
            return Change;
        }
コード例 #21
0
        //---------------------------------------------------------------------
        // 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);
        }
コード例 #22
0
        //---------------------------------------------------------------------
        //  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);
        }
コード例 #23
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);
        }
コード例 #24
0
        //---------------------------------------------------------------------

        /// <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);
            }
        }
コード例 #25
0
        public int ReduceOrKillMarkedCohort(ICohort cohort)
        {
            if (_siteHarvestingRule.SpeciesName.Equals(cohort.Species.Name) == false)
            {
                return(0);
            }

            return((int)(cohort.Biomass * (double)_siteHarvestingRule.Percentage));
        }
コード例 #26
0
        //---------------------------------------------------------------------

        /// <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;
        }
コード例 #27
0
        //---------------------------------------------------------------------

        /// <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);
        }
コード例 #28
0
        //---------------------------------------------------------------------

        /// <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));
            }
        }
コード例 #29
0
        //---------------------------------------------------------------------

        /// <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));
            }
        }
コード例 #30
0
        //---------------------------------------------------------------------

        /// <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));
            }
        }
コード例 #31
0
        //---------------------------------------------------------------------

        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;
        }
コード例 #32
0
        //---------------------------------------------------------------------

        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);
        }
コード例 #33
0
        //---------------------------------------------------------------------

        public ushort Damage(ICohort cohort)
        {
            if (ageCohortDisturbance.Damage(cohort)) {
                Cohort.KilledByAgeOnlyDisturbance(this, cohort,
                                                  ageCohortDisturbance.CurrentSite,
                                                  ageCohortDisturbance.Type);
                return cohort.Biomass;
            }
            else
                return 0;
        }
コード例 #34
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;
        }
コード例 #35
0
        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);
        }
コード例 #36
0
            //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

            ushort IDisturbance.Damage(ICohort cohort)
            {
                if (5 <= cohort.Age && cohort.Age <= 30)
                {
                    return(cohort.Biomass);
                }
                else
                {
                    return(0);
                }
            }
コード例 #37
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);
        }
コード例 #38
0
        //---------------------------------------------------------------------
        // 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);
        }
コード例 #39
0
        //---------------------------------------------------------------------

        public ushort Damage(ICohort cohort)
        {
            if (ageCohortDisturbance.Damage(cohort))
            {
                return(cohort.Biomass);
            }
            else
            {
                return(0);
            }
        }
コード例 #40
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;
 }
コード例 #41
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));
            }
        }
コード例 #42
0
        /// <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);
        }
コード例 #43
0
        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);
        }
コード例 #44
0
        //---------------------------------------------------------------------

        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;
        }
コード例 #45
0
        //---------------------------------------------------------------------

        /// <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));
        }
コード例 #46
0
        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);
        }
コード例 #47
0
        //---------------------------------------------------------------------

        // 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);
            }
        }
コード例 #49
0
        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;
        }
コード例 #50
0
        //---------------------------------------------------------------------
        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;
        }
コード例 #51
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];
        }
コード例 #52
0
        //---------------------------------------------------------------------
        /// <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);
        }
コード例 #53
0
        //---------------------------------------------------------------------
        /// <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;
        }
コード例 #54
0
        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);
            }
        }
コード例 #55
0
        //---------------------------------------------------------------------

        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;
        }
コード例 #56
0
        //---------------------------------------------------------------------

        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;
        }
コード例 #57
0
        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();
        }
コード例 #58
0
        //---------------------------------------------------------------------
        // 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;
        }
コード例 #59
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;
 }