Esempio n. 1
0
        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);
                }
            }
        }
Esempio n. 2
0
 public void MortalityApi()
 {
     foreach (OrganonVariant variant in TestConstant.Variants)
     {
         OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
         TestStand            stand         = OrganonTest.CreateDefaultStand(configuration);
         OrganonStandDensity  density       = new OrganonStandDensity(stand, variant);
         for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep)
         {
             OrganonMortality.ReduceExpansionFactors(configuration, simulationStep, stand, density);
             stand.SetSdiMax(configuration);
             OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant);
             float oldGrowthIndicator = OrganonMortality.GetOldGrowthIndicator(variant, stand);
             Assert.IsTrue(oldGrowthIndicator >= 0.0F);
             Assert.IsTrue(oldGrowthIndicator <= 2.0F);
         }
     }
 }
Esempio n. 3
0
        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;
                }
            }
        }
Esempio n. 4
0
        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);
                }
            }
        }
Esempio n. 5
0
        public TestStand ToStand(OrganonConfiguration configuration, float siteIndex)
        {
            int firstPlotMeasurementYear = this.GetFirstMeasurementYear();

            // populate Organon version of stand
            // Currently, PSP stands are assumed to have IsEvenAge = false, which causes Organon to require a stand age of
            // zero years be passed.
            TestStand stand = new TestStand(configuration.Variant, 0, siteIndex)
            {
                NumberOfPlots = this.plotCount
            };

            foreach (KeyValuePair <FiaCode, int> speciesCount in this.CountTreesBySpecies())
            {
                // skip any unsupported species as they should be remapped in following loops
                if (configuration.Variant.IsSpeciesSupported(speciesCount.Key) == false)
                {
                    continue;
                }

                // metric PSP data is converted to English units for Organon below
                stand.TreesBySpecies.Add(speciesCount.Key, new Trees(speciesCount.Key, speciesCount.Value, Units.English));
            }

            float fixedPlotExpansionFactor = this.GetTreesPerAcreExpansionFactor();

            foreach (PspTreeMeasurementSeries tree in this.MeasurementsByTag.Values)
            {
                int firstTreeMeasurementYear = tree.GetFirstMeasurementYear();
                Debug.Assert(firstTreeMeasurementYear >= firstPlotMeasurementYear);
                if (firstTreeMeasurementYear != firstPlotMeasurementYear)
                {
                    // tree is ingrowth
                    List <PspTreeMeasurementSeries> ingrowthForYear = this.IngrowthByYear.GetOrAdd(firstTreeMeasurementYear);
                    ingrowthForYear.Add(tree);
                    continue;
                }

                FiaCode species        = PspStand.MaybeRemapToSupportedSpecies(tree.Species, configuration.Variant);
                Trees   treesOfSpecies = stand.TreesBySpecies[species];
                Debug.Assert(treesOfSpecies.Capacity > treesOfSpecies.Count);
                float dbhInInches  = TestConstant.InchesPerCm * tree.DbhInCentimetersByYear[firstPlotMeasurementYear];
                float heightInFeet = TreeRecord.EstimateHeightInFeet(species, dbhInInches);
                treesOfSpecies.Add(tree.Tag, dbhInInches, heightInFeet, TestConstant.Default.CrownRatio, fixedPlotExpansionFactor);
            }

            // estimate crown ratios
            OrganonStandDensity       standDensity   = new OrganonStandDensity(stand, configuration.Variant);
            Dictionary <FiaCode, int> indexBySpecies = new Dictionary <FiaCode, int>();

            foreach (PspTreeMeasurementSeries tree in this.MeasurementsByTag.Values)
            {
                int firstTreeMeasurementYear = tree.GetFirstMeasurementYear();
                if (firstTreeMeasurementYear != firstPlotMeasurementYear)
                {
                    continue;
                }

                if (indexBySpecies.TryGetValue(tree.Species, out int treeIndex) == false)
                {
                    treeIndex = 0;
                    indexBySpecies.Add(tree.Species, treeIndex);
                }

                FiaCode species        = PspStand.MaybeRemapToSupportedSpecies(tree.Species, configuration.Variant);
                Trees   treesOfSpecies = stand.TreesBySpecies[species];
                treesOfSpecies.CrownRatio[treeIndex] = tree.EstimateInitialCrownRatio(standDensity);
                indexBySpecies[tree.Species]         = ++treeIndex;
            }

            // complete stand initialization
            stand.EnsureSiteIndicesSet(configuration.Variant);
            stand.SetQuantiles();
            stand.SetRedAlderSiteIndexAndGrowthEffectiveAge();
            stand.SetSdiMax(configuration);

            return(stand);
        }
Esempio n. 6
0
        protected static TestStand CreateDefaultStand(OrganonConfiguration configuration)
        {
            // TODO: cover cases with more than one SIMD width per species
            TestStand stand = new TestStand(configuration.Variant, 0, TestConstant.Default.SiteIndex)
            {
                PlantingDensityInTreesPerHectare = 939.0F // 380 trees per acre
            };

            switch (configuration.Variant.TreeModel)
            {
            case TreeModel.OrganonNwo:
            case TreeModel.OrganonSmc:
                stand.Add(new TreeRecord(1, FiaCode.PseudotsugaMenziesii, 0.1F, 0.4F, 10.0F));
                stand.Add(new TreeRecord(2, FiaCode.PseudotsugaMenziesii, 0.2F, 0.5F, 20.0F));
                stand.Add(new TreeRecord(3, FiaCode.PseudotsugaMenziesii, 0.3F, 0.6F, 10.0F));
                stand.Add(new TreeRecord(4, FiaCode.PseudotsugaMenziesii, 10.0F, 0.5F, 10.0F));
                stand.Add(new TreeRecord(5, FiaCode.AbiesGrandis, 0.1F, 0.6F, 1.0F));
                stand.Add(new TreeRecord(6, FiaCode.AbiesGrandis, 1.0F, 0.7F, 2.0F));
                stand.Add(new TreeRecord(7, FiaCode.TsugaHeterophylla, 0.1F, 0.6F, 5.0F));
                stand.Add(new TreeRecord(8, FiaCode.TsugaHeterophylla, 0.5F, 0.7F, 10.0F));
                stand.Add(new TreeRecord(9, FiaCode.ThujaPlicata, 0.1F, 0.4F, 10.0F));
                stand.Add(new TreeRecord(10, FiaCode.ThujaPlicata, 1.0F, 0.5F, 15.0F));

                stand.Add(new TreeRecord(11, FiaCode.TaxusBrevifolia, 0.1F, 0.7F, 2.0F));
                stand.Add(new TreeRecord(12, FiaCode.ArbutusMenziesii, 1.0F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(13, FiaCode.AcerMacrophyllum, 0.1F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(14, FiaCode.QuercusGarryana, 10.0F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(15, FiaCode.AlnusRubra, 0.1F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(16, FiaCode.CornusNuttallii, 0.1F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(17, FiaCode.Salix, 0.1F, 0.5F, 2.0F));
                break;

            case TreeModel.OrganonRap:
                stand.Add(new TreeRecord(1, FiaCode.AlnusRubra, 0.1F, 0.3F, 30.0F));
                stand.Add(new TreeRecord(2, FiaCode.AlnusRubra, 0.2F, 0.4F, 40.0F));
                stand.Add(new TreeRecord(3, FiaCode.AlnusRubra, 0.3F, 0.5F, 30.0F));

                stand.Add(new TreeRecord(4, FiaCode.PseudotsugaMenziesii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(5, FiaCode.TsugaHeterophylla, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(6, FiaCode.ThujaPlicata, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(7, FiaCode.AcerMacrophyllum, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(8, FiaCode.CornusNuttallii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(9, FiaCode.Salix, 0.1F, 0.5F, 1.0F));
                break;

            case TreeModel.OrganonSwo:
                stand.Add(new TreeRecord(1, FiaCode.PseudotsugaMenziesii, 0.1F, 0.5F, 5.0F));
                stand.Add(new TreeRecord(2, FiaCode.AbiesConcolor, 0.1F, 0.5F, 5.0F));
                stand.Add(new TreeRecord(3, FiaCode.AbiesGrandis, 0.1F, 0.5F, 5.0F));
                stand.Add(new TreeRecord(4, FiaCode.PinusPonderosa, 0.1F, 0.5F, 10.0F));
                stand.Add(new TreeRecord(5, FiaCode.PinusLambertiana, 0.1F, 0.5F, 10.0F));
                stand.Add(new TreeRecord(6, FiaCode.CalocedrusDecurrens, 0.1F, 0.5F, 10.0F));

                stand.Add(new TreeRecord(7, FiaCode.TsugaHeterophylla, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(8, FiaCode.ThujaPlicata, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(9, FiaCode.TaxusBrevifolia, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(10, FiaCode.ArbutusMenziesii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(11, FiaCode.ChrysolepisChrysophyllaVarChrysophylla, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(12, FiaCode.NotholithocarpusDensiflorus, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(13, FiaCode.QuercusChrysolepis, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(14, FiaCode.AcerMacrophyllum, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(15, FiaCode.QuercusGarryana, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(16, FiaCode.QuercusKelloggii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(17, FiaCode.AlnusRubra, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(18, FiaCode.CornusNuttallii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(19, FiaCode.Salix, 0.1F, 0.5F, 1.0F));
                break;

            default:
                throw OrganonVariant.CreateUnhandledModelException(configuration.Variant.TreeModel);
            }

            stand.SetRedAlderSiteIndexAndGrowthEffectiveAge();
            stand.SetSdiMax(configuration);
            return(stand);
        }