Example #1
0
        public override int GrowHeightBigSix(OrganonConfiguration configuration, OrganonStand stand, Trees trees, float[] crownCompetitionByHeight)
        {
            float P1;
            float P2;
            float P3;
            float P4;
            float P5;
            float P6;
            float P7;
            float P8;

            switch (trees.Species)
            {
            // Ritchie and Hann(1990) FRL Research Paper 54
            case FiaCode.AbiesGrandis:
                P1 = 1.0F;
                P2 = -0.0328142F;
                P3 = -0.0127851F;
                P4 = 1.0F;
                P5 = 6.19784F;
                P6 = 2.0F;
                P7 = 0.0F;
                P8 = 1.01F;
                break;

            case FiaCode.PseudotsugaMenziesii:
                P1 = 0.655258886F;
                P2 = -0.006322913F;
                P3 = -0.039409636F;
                P4 = 0.5F;
                P5 = 0.597617316F;
                P6 = 2.0F;
                P7 = 0.631643636F;
                P8 = 1.010018427F;
                break;

            case FiaCode.TsugaHeterophylla:
                P1 = 1.0F;
                P2 = -0.0384415F;
                P3 = -0.0144139F;
                P4 = 0.5F;
                P5 = 1.04409F;
                P6 = 2.0F;
                P7 = 0.0F;
                P8 = 1.03F;
                break;

            default:
                throw Trees.CreateUnhandledSpeciesException(trees.Species);
            }

            int oldTreeRecordCount = 0;

            for (int treeIndex = 0; treeIndex < trees.Count; ++treeIndex)
            {
                if (trees.LiveExpansionFactor[treeIndex] <= 0.0F)
                {
                    trees.HeightGrowth[treeIndex] = 0.0F;
                    continue;
                }

                float growthEffectiveAge        = configuration.Variant.GetGrowthEffectiveAge(configuration, stand, trees, treeIndex, out float potentialHeightGrowth);
                float crownCompetitionIncrement = OrganonVariant.GetCrownCompetitionFactorByHeight(trees.Height[treeIndex], crownCompetitionByHeight);

                float crownRatio = trees.CrownRatio[treeIndex];
                float FCR        = -P5 *MathV.Pow(1.0F - crownRatio, P6) * MathV.Exp(P7 * MathF.Sqrt(crownCompetitionIncrement));

                float B0           = P1 * MathV.Exp(P2 * crownCompetitionIncrement);
                float B1           = MathV.Exp(P3 * MathV.Pow(crownCompetitionIncrement, P4));
                float MODIFER      = P8 * (B0 + (B1 - B0) * MathF.Exp(FCR)); // changed from MathV due to FCR of -91 being observed
                float CRADJ        = OrganonGrowth.GetCrownRatioAdjustment(crownRatio);
                float heightGrowth = potentialHeightGrowth * MODIFER * CRADJ;
                Debug.Assert(heightGrowth > 0.0F);
                trees.HeightGrowth[treeIndex] = heightGrowth;

                if (growthEffectiveAge > configuration.Variant.OldTreeAgeThreshold)
                {
                    ++oldTreeRecordCount;
                }
            }
            return(oldTreeRecordCount);
        }
Example #2
0
        public override void ReduceExpansionFactors(OrganonStand stand, OrganonStandDensity densityBeforeGrowth, Trees trees, float fertilizationExponent)
        {
            // SMC MORTALITY
            float B0;
            float B1;
            float B2;
            float B3;
            float B4;
            float B5;
            float siteIndex = stand.SiteIndex;

            switch (trees.Species)
            {
            // Hann, Marshall, and Hanus(2006) FRL Research Contribution 49
            case FiaCode.PseudotsugaMenziesii:
                B0 = -3.12161659F;
                B1 = -0.44724396F;
                B2 = 0.0F;
                B3 = -2.48387172F;
                B4 = 0.01843137F;
                B5 = 0.01353918F;
                break;

            // Unpublished Equation on File at OSU Dept.Forest Resources
            case FiaCode.AbiesGrandis:
                B0 = -7.60159F;
                B1 = -0.200523F;
                B2 = 0.0F;
                B3 = 0.0F;
                B4 = 0.0441333F;
                B5 = 0.00063849F;
                break;

            // Hann, Marshall, Hanus(2003) FRL Research Contribution 40
            case FiaCode.TsugaHeterophylla:
            case FiaCode.ThujaPlicata:
                B0        = -0.761609F;
                B1        = -0.529366F;
                B2        = 0.0F;
                B3        = -4.74019F;
                B4        = 0.0119587F;
                B5        = 0.00756365F;
                siteIndex = stand.HemlockSiteIndex;     // BUGBUG: why does redcedar get hemlock site index only here?
                break;

            // Hann and Hanus(2001) FRL Research Contribution 34
            case FiaCode.TaxusBrevifolia:
                B0 = -4.072781265F;
                B1 = -0.176433475F;
                B2 = 0.0F;
                B3 = -1.729453975F;
                B4 = 0.0F;
                B5 = 0.012525642F;
                break;

            // Hann and Hanus(2001) FRL Research Contribution 34
            case FiaCode.ArbutusMenziesii:
                B0 = -6.089598985F;
                B1 = -0.245615070F;
                B2 = 0.0F;
                B3 = -3.208265570F;
                B4 = 0.033348079F;
                B5 = 0.013571319F;
                break;

            // Hann and Hanus(2001) FRL Research Contribution 34
            case FiaCode.AcerMacrophyllum:
                B0 = -2.976822456F;
                B1 = 0.0F;
                B2 = 0.0F;
                B3 = -6.223250962F;
                B4 = 0.0F;
                B5 = 0.0F;
                break;

            // Gould, Marshall, and Harrington(2008) West.J.Appl.For. 23: 26-33
            case FiaCode.QuercusGarryana:
                B0 = -6.00031085F;
                B1 = -0.10490823F;
                B2 = 0.0F;
                B3 = -0.99541909F;
                B4 = 0.00912739F;
                B5 = 0.87115652F;
                break;

            // best guess
            case FiaCode.AlnusRubra:
                B0 = -2.0F;
                B1 = -0.5F;
                B2 = 0.015F;
                B3 = -3.0F;
                B4 = 0.015F;
                B5 = 0.01F;
                break;

            // Hann and Hanus(2001) FRL Research Contribution 34
            case FiaCode.CornusNuttallii:
                B0 = -3.020345211F;
                B1 = 0.0F;
                B2 = 0.0F;
                B3 = -8.467882343F;
                B4 = 0.013966388F;
                B5 = 0.009461545F;
                break;

            // buest guess
            case FiaCode.Salix:
                B0 = -1.386294361F;
                B1 = 0.0F;
                B2 = 0.0F;
                B3 = 0.0F;
                B4 = 0.0F;
                B5 = 0.0F;
                break;

            default:
                throw Trees.CreateUnhandledSpeciesException(trees.Species);
            }

            float[]? mortalityKforRedAlder = null;
            if (trees.Species == FiaCode.AlnusRubra)
            {
                mortalityKforRedAlder = new float[trees.Capacity];
            }

            for (int treeIndex = 0; treeIndex < trees.Count; ++treeIndex)
            {
                if (trees.LiveExpansionFactor[treeIndex] <= 0.0F)
                {
                    continue;
                }
                float dbhInInches     = trees.Dbh[treeIndex];
                float basalAreaLarger = densityBeforeGrowth.GetBasalAreaLarger(dbhInInches);
                if (trees.Species == FiaCode.AbiesGrandis)
                {
                    basalAreaLarger /= dbhInInches;
                }
                else if (trees.Species == FiaCode.QuercusGarryana)
                {
                    basalAreaLarger = MathV.Ln(basalAreaLarger + 5.0F);
                }
                float crownRatio = trees.CrownRatio[treeIndex];
                float PMK        = B0 + B1 * dbhInInches + B2 * dbhInInches * dbhInInches + B3 * crownRatio + B4 * siteIndex + B5 * basalAreaLarger + fertilizationExponent;
                if (trees.Species == FiaCode.AlnusRubra)
                {
                    mortalityKforRedAlder ![treeIndex] = PMK;
Example #3
0
        public override void ReduceExpansionFactors(OrganonStand stand, OrganonStandDensity densityBeforeGrowth, Trees trees, float fertilizationExponent)
        {
            // RAP MORTALITY
            float B0;
            float B1;
            float B2;
            float B3;
            float B4;
            float B5;
            float POW = 0.2F;

            switch (trees.Species)
            {
            // RA Coefficients from Hann, Bluhm, and Hibbs New Red Alder Equation
            case FiaCode.AlnusRubra:
                B0  = -4.333150734F;
                B1  = -0.9856713799F;
                B2  = 0.0F;
                B3  = -2.583317081F;
                B4  = 0.0369852164F;
                B5  = 0.0394546978F;
                POW = 1.0F;
                break;

            // Hann, Marshall, and Hanus(2006) FRL Research Contribution 49
            case FiaCode.PseudotsugaMenziesii:
                B0 = -3.12161659F;
                B1 = -0.44724396F;
                B2 = 0.0F;
                B3 = -2.48387172F;
                B4 = 0.01843137F;
                B5 = 0.01353918F;
                break;

            // Hann, Marshall, Hanus(2003) FRL Research Contribution 40
            case FiaCode.TsugaHeterophylla:
                B0 = -0.761609F;
                B1 = -0.529366F;
                B2 = 0.0F;
                B3 = -4.74019F;
                B4 = 0.0119587F;
                B5 = 0.00756365F;
                break;

            // WH of Hann, Marshall, Hanus(2003) FRL Research Contribution 40
            case FiaCode.ThujaPlicata:
                B0 = -0.761609F;
                B1 = -0.529366F;
                B2 = 0.0F;
                B3 = -4.74019F;
                B4 = 0.0119587F;
                B5 = 0.00756365F;
                break;

            // Hann and Hanus(2001) FRL Research Contribution 34
            case FiaCode.AcerMacrophyllum:
                B0 = -2.976822456F;
                B1 = 0.0F;
                B2 = 0.0F;
                B3 = -6.223250962F;
                B4 = 0.0F;
                B5 = 0.0F;
                break;

            // Hann and Hanus(2001) FRL Research Contribution 34
            case FiaCode.CornusNuttallii:
                B0 = -3.020345211F;
                B1 = 0.0F;
                B2 = 0.0F;
                B3 = -8.467882343F;
                B4 = 0.013966388F;
                B5 = 0.009461545F;
                break;

            // best guess
            case FiaCode.Salix:
                B0 = -1.386294361F;
                B1 = 0.0F;
                B2 = 0.0F;
                B3 = 0.0F;
                B4 = 0.0F;
                B5 = 0.0F;
                break;

            default:
                throw Trees.CreateUnhandledSpeciesException(trees.Species);
            }

            // BUGBUG: Fortran code didn't use red alder site index for red alder and used hemlock site index for all conifers, not just hemlock and redcedar
            float siteIndex = stand.HemlockSiteIndex; // interpreted as Douglas-fir site index

            if (trees.Species == FiaCode.AlnusRubra)
            {
                siteIndex = stand.SiteIndex;
            }
            else if ((trees.Species == FiaCode.TsugaHeterophylla) || (trees.Species == FiaCode.ThujaPlicata))
            {
                siteIndex = OrganonVariantNwo.ToHemlockSiteIndexStatic(siteIndex); // convert from Douglas-fir site index to actual hemlock site inde
            }

            for (int treeIndex = 0; treeIndex < trees.Count; ++treeIndex)
            {
                if (trees.LiveExpansionFactor[treeIndex] <= 0.0F)
                {
                    continue;
                }
                float dbhInInches     = trees.Dbh[treeIndex];
                float basalAreaLarger = densityBeforeGrowth.GetBasalAreaLarger(dbhInInches);
                float crownRatio      = trees.CrownRatio[treeIndex];
                float PMK             = B0 + B1 * dbhInInches + B2 * dbhInInches * dbhInInches + B3 * crownRatio + B4 * siteIndex + B5 * basalAreaLarger + fertilizationExponent;

                float XPM = 1.0F / (1.0F + MathV.Exp(-PMK));
                float survivalProbability = POW == 1.0 ? 1.0F - XPM : MathV.Pow(1.0F - XPM, POW); // RAP is the only variant using unfertlized POW != 1
                survivalProbability *= OrganonGrowth.GetCrownRatioAdjustment(crownRatio);
                Debug.Assert(survivalProbability >= 0.0F);
                Debug.Assert(survivalProbability <= 1.0F);

                float newLiveExpansionFactor = survivalProbability * trees.LiveExpansionFactor[treeIndex];
                if (newLiveExpansionFactor < 0.00001F)
                {
                    newLiveExpansionFactor = 0.0F;
                }
                float mortalityExpansionFactor = trees.LiveExpansionFactor[treeIndex] - newLiveExpansionFactor;

                trees.DeadExpansionFactor[treeIndex] = mortalityExpansionFactor;
                trees.LiveExpansionFactor[treeIndex] = newLiveExpansionFactor;
            }
        }
Example #4
0
        public override float GetGrowthEffectiveAge(OrganonConfiguration configuration, OrganonStand stand, Trees trees, int treeIndex, out float potentialHeightGrowth)
        {
            float growthEffectiveAge;

            if (trees.Species == FiaCode.AlnusRubra)
            {
                // GROWTH EFFECTIVE AGE AND POTENTIAL HEIGHT GROWTH FROM WEISKITTEL, HANN, HIBBS, LAM, AND BLUHM (2009) RED ALDER TOP HEIGHT GROWTH
                float siteIndexFromGround = stand.SiteIndex + 4.5F;
                RedAlder.WHHLB_HG(siteIndexFromGround, configuration.PDEN, trees.Height[treeIndex], 1.0F, out growthEffectiveAge, out potentialHeightGrowth);
            }
            else if (trees.Species == FiaCode.TsugaHeterophylla)
            {
                // POTENTIAL HEIGHT GROWTH FROM FLEWELLING'S WESTERN HEMLOCK DOMINANT HEIGHT GROWTH
                // BUGBUG: why isn't redcedar also on this code path?
                float siteIndexFromGround             = OrganonVariantNwo.ToHemlockSiteIndexStatic(stand.HemlockSiteIndex); // stand.HemlockSiteIndex is interpreted as PSME site index
                WesternHemlock.SiteConstants tsheSite = new WesternHemlock.SiteConstants(siteIndexFromGround);
                growthEffectiveAge = WesternHemlock.GetFlewellingGrowthEffectiveAge(tsheSite, this.TimeStepInYears, trees.Height[treeIndex], out potentialHeightGrowth);
            }
            else
            {
                // POTENTIAL HEIGHT GROWTH FROM BRUCE'S (1981) DOMINANT HEIGHT GROWTH FOR DOUGLAS-FIR AND GRAND FIR
                DouglasFir.SiteConstants psmeSite = new DouglasFir.SiteConstants(stand.HemlockSiteIndex); // stand.HemlockSiteIndex is interpreted as PSME site index
                growthEffectiveAge = DouglasFir.GetBrucePsmeAbgrGrowthEffectiveAge(psmeSite, this.TimeStepInYears, trees.Height[treeIndex], out potentialHeightGrowth);
            }
            return(growthEffectiveAge);
        }
Example #5
0
        public override int GrowHeightBigSix(OrganonConfiguration configuration, OrganonStand stand, Trees trees, float[] crownCompetitionByHeight)
        {
            // WEIGHTED CENTRAL PAI PROCEDURE PARAMETERS FOR RED ALDER
            float P1;
            float P2;
            float P3;
            float P4;
            float P5;
            float P6;
            float P7;
            float P8;

            switch (trees.Species)
            {
            // Hann, Bluhm, and Hibbs Red Alder Plantation Analysis
            case FiaCode.AlnusRubra:
                P1 = 0.809837005F;
                P2 = -0.0134163653F;
                P3 = -0.0609398629F;
                P4 = 0.5F;
                P5 = 1.0F;
                P6 = 2.0F;
                P7 = 0.1469442410F;
                P8 = 1.0476380753F;
                break;

            // Hann, Marshall, and Hanus(2006) FRL Research Contribution ??
            case FiaCode.PseudotsugaMenziesii:
                P1 = 0.655258886F;
                P2 = -0.006322913F;
                P3 = -0.039409636F;
                P4 = 0.5F;
                P5 = 0.597617316F;
                P6 = 2.0F;
                P7 = 0.631643636F;
                P8 = 1.010018427F;
                break;

            // Johnson(2002) Willamette Industries Report
            case FiaCode.TsugaHeterophylla:
                P1 = 1.0F;
                P2 = -0.0384415F;
                P3 = -0.0144139F;
                P4 = 0.5F;
                P5 = 1.04409F;
                P6 = 2.0F;
                P7 = 0.0F;
                P8 = 1.03F;
                break;

            default:
                throw Trees.CreateUnhandledSpeciesException(trees.Species);
            }

            int oldTreeRecordCount = 0;

            for (int treeIndex = 0; treeIndex < trees.Count; ++treeIndex)
            {
                if (trees.LiveExpansionFactor[treeIndex] <= 0.0F)
                {
                    trees.HeightGrowth[treeIndex] = 0.0F;
                    continue;
                }

                float growthEffectiveAge        = configuration.Variant.GetGrowthEffectiveAge(configuration, stand, trees, treeIndex, out float potentialHeightGrowth);
                float crownCompetitionIncrement = OrganonVariant.GetCrownCompetitionFactorByHeight(trees.Height[treeIndex], crownCompetitionByHeight);

                float crownRatio = trees.CrownRatio[treeIndex];
                float FCR        = -P5 *MathV.Pow(1.0F - crownRatio, P6) * MathV.Exp(P7 * MathF.Sqrt(crownCompetitionIncrement));

                float B0           = P1 * MathV.Exp(P2 * crownCompetitionIncrement);
                float B1           = MathV.Exp(P3 * MathV.Pow(crownCompetitionIncrement, P4));
                float MODIFER      = P8 * (B0 + (B1 - B0) * MathV.Exp(FCR));
                float CRADJ        = OrganonGrowth.GetCrownRatioAdjustment(crownRatio);
                float heightGrowth = potentialHeightGrowth * MODIFER * CRADJ;
                Debug.Assert(heightGrowth > 0.0F);
                trees.HeightGrowth[treeIndex] = heightGrowth;

                if (growthEffectiveAge > configuration.Variant.OldTreeAgeThreshold)
                {
                    ++oldTreeRecordCount;
                }
            }
            return(oldTreeRecordCount);
        }
Example #6
0
        /// <summary>
        /// Computes old growth index?
        /// </summary>
        /// <param name="stand">Stand data.</param>
        /// <param name="incrementMultiplier">Zero or minus one, usually zero.</param>
        /// <param name="OG">Old growth indicator.</param>
        /// <remarks>
        /// Supports only to 99 inch DBH.
        /// </remarks>
        public static float GetOldGrowthIndicator(OrganonVariant variant, OrganonStand stand)
        {
            // TODO: move diameter class and stand density information into stand for simplified state management and reduced compute
            int diameterClasses = 100;

            float[] treesPerAcreByDiameterClass   = new float[diameterClasses];
            float[] weightedDbhByDiameterClass    = new float[diameterClasses];
            float[] weightedHeightByDiameterClass = new float[diameterClasses];
            foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
            {
                if (variant.IsBigSixSpecies(treesOfSpecies.Species) == false)
                {
                    continue;
                }
                for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex)
                {
                    float dbhInInches = treesOfSpecies.Dbh[treeIndex];
                    int   dbhIndex    = (int)dbhInInches;
                    if (dbhIndex >= treesPerAcreByDiameterClass.Length)
                    {
                        dbhIndex = treesPerAcreByDiameterClass.Length - 1;
                    }

                    float expansionFactor = treesOfSpecies.LiveExpansionFactor[treeIndex];
                    Debug.Assert(expansionFactor >= 0.0F);
                    Debug.Assert(expansionFactor <= Constant.Maximum.ExpansionFactor);

                    treesPerAcreByDiameterClass[dbhIndex]   += expansionFactor;
                    weightedDbhByDiameterClass[dbhIndex]    += expansionFactor * dbhInInches;
                    weightedHeightByDiameterClass[dbhIndex] += expansionFactor * treesOfSpecies.Height[treeIndex];
                }
            }

            float largestFiveTpaWeightedHeight = 0.0F;
            float largestFiveTpaWeightedDbh    = 0.0F;
            float largeTreeTpa = 0.0F;

            for (int dbhIndex = weightedHeightByDiameterClass.Length - 1; dbhIndex >= 0; --dbhIndex)
            {
                largestFiveTpaWeightedHeight += weightedHeightByDiameterClass[dbhIndex];
                largestFiveTpaWeightedDbh    += weightedDbhByDiameterClass[dbhIndex];
                largeTreeTpa += treesPerAcreByDiameterClass[dbhIndex];
                if (largeTreeTpa > 5.0F)
                {
                    float TRDIFF = treesPerAcreByDiameterClass[dbhIndex] - (largeTreeTpa - 5.0F);
                    largestFiveTpaWeightedHeight = largestFiveTpaWeightedHeight - weightedHeightByDiameterClass[dbhIndex] + ((weightedHeightByDiameterClass[dbhIndex] / treesPerAcreByDiameterClass[dbhIndex]) * TRDIFF);
                    largestFiveTpaWeightedDbh    = largestFiveTpaWeightedDbh - weightedDbhByDiameterClass[dbhIndex] + ((weightedDbhByDiameterClass[dbhIndex] / treesPerAcreByDiameterClass[dbhIndex]) * TRDIFF);
                    largeTreeTpa = 5.0F;
                    break;
                }
            }

            float oldGrowthIndicator = 0.0F;

            if (largeTreeTpa > 0.0F)
            {
                float HT5  = largestFiveTpaWeightedHeight / largeTreeTpa;
                float DBH5 = largestFiveTpaWeightedDbh / largeTreeTpa;
                oldGrowthIndicator = DBH5 * HT5 / 10000.0F;
                Debug.Assert(oldGrowthIndicator >= 0.0F);
                Debug.Assert(oldGrowthIndicator <= 1000.0F);
            }
            return(oldGrowthIndicator);
        }
Example #7
0
 public static void ReduceExpansionFactors(OrganonConfiguration configuration, int simulationStep, OrganonStand stand, OrganonStandDensity densityBeforeGrowth)
 {
     foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
     {
         FiaCode species = treesOfSpecies.Species;
         float   fertilizationExponent = OrganonMortality.GetMortalityFertilizationAdjustment(species, configuration.Variant.TreeModel, simulationStep, configuration.Treatments);
         configuration.Variant.ReduceExpansionFactors(stand, densityBeforeGrowth, treesOfSpecies, fertilizationExponent);
     }
 }