public void OrganonStandGrowthApi() { TestStand.WriteTreeHeader(this.TestContext !); foreach (OrganonVariant variant in TestConstant.Variants) { OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); // check crown competition API TestStand stand = OrganonTest.CreateDefaultStand(configuration); float crownCompetitionFactor = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand)[0]; Assert.IsTrue(crownCompetitionFactor >= 0.0F); Assert.IsTrue(crownCompetitionFactor <= TestConstant.Maximum.CrownCompetitionFactor); OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth | ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant); // recalculate heights and crown ratios for all trees Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration(); foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values) { OrganonGrowth.SetIngrowthHeightAndCrownRatio(variant, stand, treesOfSpecies, treesOfSpecies.Count, calibrationBySpecies); } OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth | ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant); // run Organon growth simulation stand = OrganonTest.CreateDefaultStand(configuration); if (configuration.IsEvenAge) { // stand error if less than one year to grow to breast height stand.AgeInYears = stand.BreastHeightAgeInYears + 2; } stand.SetQuantiles(); stand.WriteTreesAsCsv(this.TestContext !, variant, 0, false); TestStand initialStand = new TestStand(stand); TreeLifeAndDeath treeGrowth = new TreeLifeAndDeath(); for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep) { OrganonGrowth.Grow(simulationStep, configuration, stand, calibrationBySpecies); treeGrowth.AccumulateGrowthAndMortality(stand); OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth | ExpectedTreeChanges.HeightGrowth, OrganonWarnings.LessThan50TreeRecords, stand, variant); stand.WriteTreesAsCsv(this.TestContext !, variant, variant.GetEndYear(simulationStep), false); } OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth | ExpectedTreeChanges.HeightGrowth, treeGrowth, initialStand, stand); OrganonTest.Verify(calibrationBySpecies); } }
public void DiameterGrowthApi() { foreach (OrganonVariant variant in TestConstant.Variants) { OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); TestStand stand = OrganonTest.CreateDefaultStand(configuration); Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration(); Dictionary <FiaCode, float[]> previousTreeDiametersBySpecies = new Dictionary <FiaCode, float[]>(); foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values) { previousTreeDiametersBySpecies.Add(treesOfSpecies.Species, new float[treesOfSpecies.Capacity]); } for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep) { OrganonStandDensity treeCompetition = new OrganonStandDensity(stand, variant); foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values) { float[] previousTreeDiameters = previousTreeDiametersBySpecies[treesOfSpecies.Species]; OrganonGrowth.GrowDiameter(configuration, simulationStep, stand, treesOfSpecies, treeCompetition, calibrationBySpecies[treesOfSpecies.Species].Diameter); stand.SetSdiMax(configuration); for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex) { float dbhInInches = treesOfSpecies.Dbh[treeIndex]; float previousDbhInInches = previousTreeDiameters[treeIndex]; Assert.IsTrue(dbhInInches >= previousDbhInInches); Assert.IsTrue(dbhInInches <= TestConstant.Maximum.DiameterInInches); } } OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth, stand, variant); OrganonTest.Verify(calibrationBySpecies); } OrganonStandDensity densityForLookup = new OrganonStandDensity(stand, variant); for (float dbhInInches = 0.5F; dbhInInches <= 101.0F; ++dbhInInches) { float basalAreaLarger = densityForLookup.GetBasalAreaLarger(dbhInInches); Assert.IsTrue(basalAreaLarger >= 0.0F); Assert.IsTrue(basalAreaLarger <= densityForLookup.BasalAreaPerAcre); float crownCompetitionLarger = densityForLookup.GetCrownCompetitionFactorLarger(dbhInInches); Assert.IsTrue(crownCompetitionLarger >= 0.0F); Assert.IsTrue(crownCompetitionLarger <= densityForLookup.CrownCompetitionFactor); } } }
protected static void GrowPspStand(PspStand huffmanPeak, TestStand stand, OrganonVariant variant, int startYear, int endYear, string baseFileName) { OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); TestStand initialTreeData = new TestStand(stand); TreeLifeAndDeath treeGrowth = new TreeLifeAndDeath(); Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration(); if (configuration.IsEvenAge) { // stand error if less than one year to grow to breast height stand.AgeInYears = stand.BreastHeightAgeInYears + 2; } TestStandDensity density = new TestStandDensity(stand, variant); using StreamWriter densityWriter = density.WriteToCsv(baseFileName + " density.csv", variant, startYear); TreeQuantiles quantiles = new TreeQuantiles(stand); using StreamWriter quantileWriter = quantiles.WriteToCsv(baseFileName + " quantiles.csv", variant, startYear); using StreamWriter treeGrowthWriter = stand.WriteTreesToCsv(baseFileName + " tree growth.csv", variant, startYear); for (int simulationStep = 0, year = startYear + variant.TimeStepInYears; year <= endYear; year += variant.TimeStepInYears, ++simulationStep) { OrganonGrowth.Grow(simulationStep, configuration, stand, calibrationBySpecies); treeGrowth.AccumulateGrowthAndMortality(stand); huffmanPeak.AddIngrowth(year, stand, density); OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowthOrNoChange | ExpectedTreeChanges.HeightGrowthOrNoChange, stand, variant); density = new TestStandDensity(stand, variant); density.WriteToCsv(densityWriter, variant, year); quantiles = new TreeQuantiles(stand); quantiles.WriteToCsv(quantileWriter, variant, year); stand.WriteTreesToCsv(treeGrowthWriter, variant, year); } OrganonTest.Verify(ExpectedTreeChanges.ExpansionFactorConservedOrIncreased | ExpectedTreeChanges.DiameterGrowthOrNoChange | ExpectedTreeChanges.HeightGrowthOrNoChange, treeGrowth, initialTreeData, stand); OrganonTest.Verify(calibrationBySpecies); }
public void GrowApi() { foreach (OrganonVariant variant in TestConstant.Variants) { OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); TestStand stand = OrganonTest.CreateDefaultStand(configuration); Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration(); OrganonStandDensity densityStartOfStep = new OrganonStandDensity(stand, variant); for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep) { float[] crownCompetitionByHeight = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand); OrganonGrowth.Grow(simulationStep, configuration, stand, densityStartOfStep, calibrationBySpecies, ref crownCompetitionByHeight, out OrganonStandDensity densityEndOfStep, out int _); stand.SetSdiMax(configuration); OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth | ExpectedTreeChanges.HeightGrowth, stand, variant); OrganonTest.Verify(calibrationBySpecies); densityStartOfStep = densityEndOfStep; } } }
public void CrownGrowthApi() { foreach (OrganonVariant variant in TestConstant.Variants) { OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); TestStand stand = OrganonTest.CreateDefaultStand(configuration); Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration(); for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep) { OrganonStandDensity densityStartOfStep = new OrganonStandDensity(stand, variant); Assert.IsTrue(densityStartOfStep.BasalAreaPerAcre > 0.0F); Assert.IsTrue(densityStartOfStep.CrownCompetitionFactor > 0.0F); Assert.IsTrue(densityStartOfStep.TreesPerAcre > 0.0F); float[] crownCompetitionByHeight = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand); OrganonTest.Verify(crownCompetitionByHeight, variant); foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values) { variant.AddCrownCompetitionByHeight(treesOfSpecies, crownCompetitionByHeight); OrganonTest.Verify(crownCompetitionByHeight, variant); } OrganonStandDensity densityEndOfStep = new OrganonStandDensity(stand, variant); Assert.IsTrue(densityEndOfStep.BasalAreaPerAcre > 0.0F); Assert.IsTrue(densityEndOfStep.CrownCompetitionFactor > 0.0F); Assert.IsTrue(densityEndOfStep.TreesPerAcre > 0.0F); #pragma warning disable IDE0059 // Unnecessary assignment of a value crownCompetitionByHeight = OrganonGrowth.GrowCrown(variant, stand, densityEndOfStep, calibrationBySpecies); #pragma warning restore IDE0059 // Unnecessary assignment of a value OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant); OrganonTest.Verify(calibrationBySpecies); } } }
public void HeightGrowthApi() { foreach (OrganonVariant variant in TestConstant.Variants) { OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration(); TestStand stand = OrganonTest.CreateDefaultStand(configuration); float[] crownCompetitionByHeight = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand); DouglasFir.SiteConstants psmeSite = new DouglasFir.SiteConstants(stand.SiteIndex); WesternHemlock.SiteConstants tsheSite = new WesternHemlock.SiteConstants(stand.HemlockSiteIndex); foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values) { variant.GetHeightPredictionCoefficients(treesOfSpecies.Species, out float B0, out float B1, out float B2); for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex) { // predicted heights float dbhInInches = treesOfSpecies.Dbh[treeIndex]; float heightInFeet = treesOfSpecies.Height[treeIndex]; float predictedHeightInFeet = 4.5F + MathV.Exp(B0 + B1 * MathV.Pow(dbhInInches, B2)); Assert.IsTrue(predictedHeightInFeet >= 0.0F); // TODO: make upper limit of height species specific Assert.IsTrue(predictedHeightInFeet < TestConstant.Maximum.HeightInFeet); // growth effective age and potential height growth bool verifyAgeAndHeight = false; float growthEffectiveAgeInYears = -1.0F; float potentialHeightGrowth = -1.0F; if ((variant.TreeModel == TreeModel.OrganonNwo) || (variant.TreeModel == TreeModel.OrganonSmc)) { if (treesOfSpecies.Species == FiaCode.TsugaHeterophylla) { growthEffectiveAgeInYears = WesternHemlock.GetFlewellingGrowthEffectiveAge(tsheSite, variant.TimeStepInYears, heightInFeet, out potentialHeightGrowth); } else { growthEffectiveAgeInYears = DouglasFir.GetBrucePsmeAbgrGrowthEffectiveAge(psmeSite, variant.TimeStepInYears, heightInFeet, out potentialHeightGrowth); } verifyAgeAndHeight = true; } else if (variant.TreeModel == TreeModel.OrganonSwo) { if ((treesOfSpecies.Species == FiaCode.PinusPonderosa) || (treesOfSpecies.Species == FiaCode.PseudotsugaMenziesii)) { DouglasFir.GetDouglasFirPonderosaHeightGrowth(treesOfSpecies.Species == FiaCode.PseudotsugaMenziesii, stand.SiteIndex, heightInFeet, out growthEffectiveAgeInYears, out potentialHeightGrowth); verifyAgeAndHeight = true; } } if (verifyAgeAndHeight) { Assert.IsTrue(growthEffectiveAgeInYears >= -2.0F); Assert.IsTrue(growthEffectiveAgeInYears <= 500.0F); Assert.IsTrue(potentialHeightGrowth >= 0.0F); Assert.IsTrue(potentialHeightGrowth < 20.0F); } } } for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep) { foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values) { if (variant.IsBigSixSpecies(treesOfSpecies.Species)) { // TODO: why no height calibration in Organon API? OrganonGrowth.GrowHeightBigSixSpecies(configuration, simulationStep, stand, treesOfSpecies, 1.0F, crownCompetitionByHeight, out _); } else { OrganonGrowth.GrowHeightMinorSpecies(configuration, stand, treesOfSpecies, calibrationBySpecies[treesOfSpecies.Species].Height); } stand.SetSdiMax(configuration); for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex) { float heightInFeet = treesOfSpecies.Height[treeIndex]; // TODO: make upper limit of height species specific Assert.IsTrue(heightInFeet < TestConstant.Maximum.HeightInFeet); } } // since diameter growth is zero in this test any tree which is above its anticipated height for its current diameter // should have zero growth // This is expected behavior the height growth functions and, potentially, height growth limiting. OrganonTest.Verify(ExpectedTreeChanges.HeightGrowthOrNoChange, stand, variant); OrganonTest.Verify(calibrationBySpecies); } } }
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); }
public override void GrowDiameter(Trees trees, float growthMultiplier, float siteIndexFromDbh, OrganonStandDensity densityBeforeGrowth) { float B0; float B1; float B2; float B3; float B4; float B5; float B6; float K1; float K2; float K3; float K4; float speciesMultiplier = 0.8F; switch (trees.Species) { // Hann, Marshall, and Hanus(2006) FRL Research Contribution 49 case FiaCode.PseudotsugaMenziesii: B0 = -5.34253119F; B1 = 1.098406840F; B2 = -0.05218621F; B3 = 1.01380810F; B4 = 0.91202025F; B5 = -0.01756220F; B6 = -0.05168923F; K1 = 6.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; speciesMultiplier = 1.0F; break; // Zumrawi and Hann(1993) FRL Research Contribution 4 case FiaCode.AbiesGrandis: B0 = -2.34619F; B1 = 0.594640F; B2 = -0.000976092F; B3 = 1.12712F; B4 = 0.555333F; B5 = -0.0000290672F; B6 = -0.0470848F; K1 = 1.0F; K2 = 2.0F; K3 = 2.0F; K4 = 5.0F; speciesMultiplier = 0.8722F; break; // Unpublished Equation on File at OSU Dept.Forest Resources case FiaCode.TsugaHeterophylla: B0 = -4.87447412F; B1 = 0.4150723209F; B2 = -0.023744997F; B3 = 0.907837299F; B4 = 1.1346766989F; B5 = -0.015333503F; B6 = -0.03309787F; K1 = 5.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; speciesMultiplier = 1.0F; break; // Hann and Hanus(2002) OSU Department of Forest Management Internal Report #2 case FiaCode.ThujaPlicata: B0 = -11.45456097F; B1 = 0.784133664F; B2 = -0.0261377888F; B3 = 0.70174783F; B4 = 2.057236260F; B5 = -0.00415440257F; B6 = 0.0F; K1 = 5.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; break; // Hann and Hanus(2002) FRL Research Contribution 39 case FiaCode.TaxusBrevifolia: B0 = -9.15835863F; B1 = 1.0F; B2 = -0.00000035F; B3 = 1.16688474F; B4 = 0.0F; B5 = 0.0F; B6 = -0.02F; K1 = 4000.0F; K2 = 4.0F; K3 = 1.0F; K4 = 2.7F; break; // Hann and Hanus(2002) FRL Research Contribution 39 case FiaCode.ArbutusMenziesii: B0 = -8.84531757F; B1 = 1.5F; B2 = -0.0006F; B3 = 0.51225596F; B4 = 0.418129153F; B5 = -0.00355254593F; B6 = -0.0321315389F; K1 = 110.0F; K2 = 2.0F; K3 = 1.0F; K4 = 2.7F; speciesMultiplier = 0.7928F; break; // Hann and Hanus(2002) FRL Research Contribution 39 case FiaCode.AcerMacrophyllum: B0 = -3.41449922F; B1 = 1.0F; B2 = -0.05F; B3 = 0.0F; B4 = 0.324349277F; B5 = 0.0F; B6 = -0.0989519477F; K1 = 10.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; break; // Gould, Marshall, and Harrington(2008) West.J.Appl.For. 23: 26-33 case FiaCode.QuercusGarryana: B0 = -7.81267986F; B1 = 1.405616529F; B2 = -0.0603105850F; B3 = 0.64286007F; B4 = 1.037687142F; B5 = 0.0F; B6 = -0.0787012218F; K1 = 5.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; speciesMultiplier = 1.0F; break; // Hann and Hanus(2002) OSU Department of Forest Management Internal Report #1 case FiaCode.AlnusRubra: B0 = -4.39082007F; B1 = 1.0F; B2 = -0.0945057147F; B3 = 1.06867026F; B4 = 0.685908029F; B5 = -0.00586331028F; B6 = 0.0F; K1 = 5.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; break; // Hann and Hanus(2002) FRL Research Contribution 39 case FiaCode.CornusNuttallii: case FiaCode.Salix: B0 = -8.08352683F; B1 = 1.0F; B2 = -0.00000035F; B3 = 0.31176647F; B4 = 0.0F; B5 = 0.0F; B6 = -0.0730788052F; K1 = 4000.0F; K2 = 4.0F; K3 = 1.0F; K4 = 2.7F; break; default: throw Trees.CreateUnhandledSpeciesException(trees.Species); } speciesMultiplier *= growthMultiplier; for (int treeIndex = 0; treeIndex < trees.Count; ++treeIndex) { if (trees.LiveExpansionFactor[treeIndex] <= 0.0F) { trees.DbhGrowth[treeIndex] = 0.0F; continue; } float dbhInInches = trees.Dbh[treeIndex]; float basalAreaLarger = densityBeforeGrowth.GetBasalAreaLarger(dbhInInches); float crownRatio = trees.CrownRatio[treeIndex]; float LNDG = B0 + B1 * MathV.Ln(dbhInInches + K1) + B2 * MathV.Pow(dbhInInches, K2) + B3 * MathV.Ln((crownRatio + 0.2F) / 1.2F) + B4 * MathV.Ln(siteIndexFromDbh) + B5 * (MathV.Pow(basalAreaLarger, K3) / MathV.Ln(dbhInInches + K4)) + B6 * MathF.Sqrt(basalAreaLarger); float crownRatioAdjustment = OrganonGrowth.GetCrownRatioAdjustment(crownRatio); trees.DbhGrowth[treeIndex] = speciesMultiplier * MathV.Exp(LNDG) * crownRatioAdjustment; Debug.Assert(trees.DbhGrowth[treeIndex] > 0.0F); Debug.Assert(trees.DbhGrowth[treeIndex] < Constant.Maximum.DiameterIncrementInInches); } }
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; } }
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); }
public override void GrowDiameter(Trees trees, float growthMultiplier, float siteIndexFromDbh, OrganonStandDensity densityBeforeGrowth) { // These species were annualized by adding ln(0.2) to the intercept terms: DF, WH, RC, ACMA3, Cornus, Salix float B0; float B1; float B2; float B3; float B4; float B5; float B6; float K1; float K2; float K3; float K4; float speciesMultiplier = 0.8F; switch (trees.Species) { // Hann, Bluhm, and Hibbs Red Alder Plantation Analysis case FiaCode.AlnusRubra: B0 = -4.622849554F; B1 = 0.5112200516F; B2 = -0.1040194568F; B3 = 0.9536538143F; B4 = 1.0659344724F; B5 = -0.0193047405F; B6 = -0.0773539455F; K1 = 1.0F; K2 = 1.0F; K3 = 1.0F; K4 = 1.0F; speciesMultiplier = 1.0F; break; // Hann, Marshall, and Hanus(2006) FRL Research Contribution ?? case FiaCode.PseudotsugaMenziesii: B0 = -6.95196910F; B1 = 1.098406840F; B2 = -0.05218621F; B3 = 1.01380810F; B4 = 0.91202025F; B5 = -0.01756220F; B6 = -0.05168923F; K1 = 6.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; speciesMultiplier = 1.0F; break; // Unpublished equation on file at OSU Deptartment of Forest Resources case FiaCode.TsugaHeterophylla: B0 = -6.48391203F; B1 = 0.4150723209F; B2 = -0.023744997F; B3 = 0.907837299F; B4 = 1.1346766989F; B5 = -0.015333503F; B6 = -0.03309787F; K1 = 5.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; speciesMultiplier = 1.0F; break; // Hann and Hanus(2002) OSU Department of Forest Management Internal Report #2 case FiaCode.ThujaPlicata: B0 = -13.06399888F; B1 = 0.784133664F; B2 = -0.0261377888F; B3 = 0.70174783F; B4 = 2.057236260F; B5 = -0.00415440257F; B6 = 0.0F; K1 = 5.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; break; // Hann and Hanus(2002) FRL Research Contribution 39 case FiaCode.AcerMacrophyllum: B0 = -5.02393713F; B1 = 1.0F; B2 = -0.05F; B3 = 0.0F; B4 = 0.324349277F; B5 = 0.0F; B6 = -0.0989519477F; K1 = 10.0F; K2 = 1.0F; K3 = 1.0F; K4 = 2.7F; break; // Hann and Hanus(2002) FRL Research Contribution 39 case FiaCode.CornusNuttallii: case FiaCode.Salix: B0 = -9.69296474F; B1 = 1.0F; B2 = -0.00000035F; B3 = 0.31176647F; B4 = 0.0F; B5 = 0.0F; B6 = -0.0730788052F; K1 = 4000.0F; K2 = 4.0F; K3 = 1.0F; K4 = 2.7F; break; default: throw Trees.CreateUnhandledSpeciesException(trees.Species); } speciesMultiplier *= growthMultiplier; for (int treeIndex = 0; treeIndex < trees.Count; ++treeIndex) { if (trees.LiveExpansionFactor[treeIndex] <= 0.0F) { trees.DbhGrowth[treeIndex] = 0.0F; continue; } float dbhInInches = trees.Dbh[treeIndex]; float basalAreaLarger = densityBeforeGrowth.GetBasalAreaLarger(dbhInInches); float crownRatio = trees.CrownRatio[treeIndex]; float LNDG = B0 + B1 * MathV.Ln(dbhInInches + K1) + B2 * MathV.Pow(dbhInInches, K2) + B3 * MathV.Ln((crownRatio + 0.2F) / 1.2F) + B4 * MathV.Ln(siteIndexFromDbh) + B5 * (MathV.Pow(basalAreaLarger, K3) / MathV.Ln(dbhInInches + K4)) + B6 * MathF.Sqrt(basalAreaLarger); float crownRatioAdjustment = OrganonGrowth.GetCrownRatioAdjustment(crownRatio); trees.DbhGrowth[treeIndex] = speciesMultiplier * MathV.Exp(LNDG) * crownRatioAdjustment; Debug.Assert(trees.DbhGrowth[treeIndex] > 0.0F); Debug.Assert(trees.DbhGrowth[treeIndex] < Constant.Maximum.DiameterIncrementInInches); } }