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); }
public void RS39() { string plotFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "OSU", "Organon", "RS39 lower half.xlsx"); PspStand rs39 = new PspStand(plotFilePath, "RS39 lower half", 0.154441F); OrganonVariant variant = new OrganonVariantNwo(); OrganonConfiguration configuration = new OrganonConfiguration(variant); TestStand stand = rs39.ToStand(configuration, 105.0F); int startYear = 1992; stand.WriteCompetitionAsCsv("RS39 lower half initial competition.csv", variant, startYear); OrganonTest.GrowPspStand(rs39, stand, variant, startYear, 2019, Path.GetFileNameWithoutExtension(plotFilePath)); TreeQuantiles measuredQuantiles = new TreeQuantiles(stand, rs39, startYear); using StreamWriter quantileWriter = measuredQuantiles.WriteToCsv("RS39 lower half measured quantiles.csv", variant, startYear); foreach (int measurementYear in rs39.MeasurementYears) { if (measurementYear != startYear) { measuredQuantiles = new TreeQuantiles(stand, rs39, measurementYear); measuredQuantiles.WriteToCsv(quantileWriter, variant, measurementYear); } } }
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; } }