Пример #1
0
        public void AddIngrowth(int year, OrganonStand stand, OrganonStandDensity standDensity)
        {
            List <int> remainingIngrowthYears = this.IngrowthByYear.Keys.Where(key => key > this.yearOfMostRecentIngrowthAdded).ToList();

            if ((remainingIngrowthYears.Count < 1) || (remainingIngrowthYears[0] > year))
            {
                // no ingrowth in this simulation step
                return;
            }
            int ingrowthYear = remainingIngrowthYears[0];

            Debug.Assert((remainingIngrowthYears.Count == 1) || (remainingIngrowthYears[1] > year)); // for now, assume only one ingrowth measurement per simulation timestep

            float fixedPlotExpansionFactor = this.GetTreesPerAcreExpansionFactor();

            foreach (PspTreeMeasurementSeries tree in this.IngrowthByYear[ingrowthYear])
            {
                Trees treesOfSpecies = stand.TreesBySpecies[tree.Species];
                Debug.Assert(treesOfSpecies.Capacity > treesOfSpecies.Count);

                float dbhInInches  = Constant.InchesPerCentimeter * tree.DbhInCentimetersByYear.Values[0];
                float heightInFeet = TestConstant.FeetPerMeter * TreeRecord.EstimateHeightInMeters(tree.Species, dbhInInches);
                treesOfSpecies.Add(tree.Tag, dbhInInches, heightInFeet, tree.EstimateInitialCrownRatio(standDensity), fixedPlotExpansionFactor);
            }

            this.yearOfMostRecentIngrowthAdded = ingrowthYear;
        }
Пример #2
0
        public void VolumeFia()
        {
            int treeCount = 42;

            // TODO: TSHE, THPL, ...
            Trees trees = new Trees(FiaCode.PseudotsugaMenziesii, treeCount, Units.English);

            float[] fiaMerchantableCubicFeetPerAcre      = new float[treeCount];
            float[] fiaScribnerBoardFeetPerAcre          = new float[treeCount];
            float   merchantableCubicFeetPerAcre         = 0.0F;
            float   merchantableCubicMetersPerHectare    = 0.0F;
            float   totalCylinderCubicMeterVolumePerAcre = 0.0F;
            float   totalScribnerBoardFeetPerAcre        = 0.0F;

            for (int treeIndex = 0; treeIndex < treeCount; ++treeIndex)
            {
                // create trees with a range of expansion factors to catch errors in expansion factor management
                float      treeRatio = (float)treeIndex / (float)treeCount;
                TreeRecord tree      = new TreeRecord(treeIndex, trees.Species, (float)treeIndex, 1.0F - 0.75F * treeRatio, 0.6F + treeIndex);
                trees.Add(tree.Tag, tree.DbhInInches, tree.HeightInFeet, tree.CrownRatio, tree.LiveExpansionFactor);

                float dbhInMeters    = TestConstant.MetersPerInch * tree.DbhInInches;
                float heightInMeters = Constant.MetersPerFoot * tree.HeightInFeet;
                float treeSizedCylinderCubicMeterVolumePerAcre = tree.LiveExpansionFactor * 0.25F * MathF.PI * dbhInMeters * dbhInMeters * heightInMeters;

                fiaMerchantableCubicFeetPerAcre[treeIndex] = tree.LiveExpansionFactor * FiaVolume.GetMerchantableCubicFeet(trees, treeIndex);
                merchantableCubicFeetPerAcre          += fiaMerchantableCubicFeetPerAcre[treeIndex];
                fiaScribnerBoardFeetPerAcre[treeIndex] = tree.LiveExpansionFactor * FiaVolume.GetScribnerBoardFeet(trees, treeIndex);
                totalScribnerBoardFeetPerAcre         += fiaScribnerBoardFeetPerAcre[treeIndex];

                merchantableCubicMetersPerHectare += OsuVolume.GetCubicVolume(trees, treeIndex);

                // taper coefficient should be in the vicinity of 0.3 for larger trees, but this is not well defined for small trees
                // Lower bound can be made more stringent if necessary.
                Assert.IsTrue(fiaMerchantableCubicFeetPerAcre[treeIndex] >= 0.0);
                Assert.IsTrue(fiaMerchantableCubicFeetPerAcre[treeIndex] <= 0.4 * Constant.CubicFeetPerCubicMeter * treeSizedCylinderCubicMeterVolumePerAcre);

                Assert.IsTrue(fiaScribnerBoardFeetPerAcre[treeIndex] >= 0.0);
                Assert.IsTrue(fiaScribnerBoardFeetPerAcre[treeIndex] <= 6.5 * 0.4 * Constant.CubicFeetPerCubicMeter * treeSizedCylinderCubicMeterVolumePerAcre);
                totalCylinderCubicMeterVolumePerAcre += treeSizedCylinderCubicMeterVolumePerAcre;
            }

            float totalCylinderCubicFeetVolumePerAcre = Constant.CubicFeetPerCubicMeter * totalCylinderCubicMeterVolumePerAcre;

            Assert.IsTrue(merchantableCubicFeetPerAcre >= 0.05 * totalCylinderCubicFeetVolumePerAcre);
            Assert.IsTrue(merchantableCubicFeetPerAcre <= 0.35 * totalCylinderCubicFeetVolumePerAcre);
            Assert.IsTrue(merchantableCubicFeetPerAcre >= 0.5 * Constant.HectaresPerAcre * Constant.CubicFeetPerCubicMeter * merchantableCubicMetersPerHectare);

            Assert.IsTrue(merchantableCubicMetersPerHectare <= 0.35 * Constant.AcresPerHectare * totalCylinderCubicMeterVolumePerAcre);

            Assert.IsTrue(totalScribnerBoardFeetPerAcre >= 1.75 * 0.35 * totalCylinderCubicFeetVolumePerAcre);
            Assert.IsTrue(totalScribnerBoardFeetPerAcre <= 6.5 * 0.40 * totalCylinderCubicFeetVolumePerAcre);

            // check SIMD 128 result against scalar
            float totalScribnerBoardFeetPerAcre128 = FiaVolume.GetScribnerBoardFeetPerAcre(trees);
            float simdScalarScribnerDifference     = totalScribnerBoardFeetPerAcre - totalScribnerBoardFeetPerAcre128;

            Assert.IsTrue(MathF.Abs(simdScalarScribnerDifference) < 0.004 * totalScribnerBoardFeetPerAcre);
        }
Пример #3
0
 public TreeRecord(int tag, FiaCode species, float dbhInInches, float crownRatio, float expansionFactor)
 {
     this.CrownRatio          = crownRatio;
     this.DbhInInches         = dbhInInches;
     this.HeightInFeet        = TreeRecord.EstimateHeightInFeet(species, dbhInInches);
     this.LiveExpansionFactor = expansionFactor;
     this.Species             = species;
     this.Tag = tag;
 }
Пример #4
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);
        }
Пример #5
0
 public static float EstimateHeightInFeet(FiaCode species, float dbhInInches)
 {
     return(TestConstant.FeetPerMeter * TreeRecord.EstimateHeightInMeters(species, dbhInInches));
 }