コード例 #1
0
        private double IntergrateElevationsForAccumulation(double lowerElevation, double upperElevation, LinearPerPartFunction accumulationLookup)
        {
            var lowerLoad = accumulationLookup.f(lowerElevation);
            var upperLoad = accumulationLookup.f(upperElevation);

            var elevationPoints = accumulationLookup.Select(p => p.Key).Where(p => p > lowerElevation && p < upperElevation).ToArray();

            var loads = elevationPoints.Select(p => accumulationLookup.f(p)).ToList();               //change here, get all loads, not sum
            var areas = elevationPoints.Select(p => Areal.AreaForHeightLookup(p) * 0.0001).ToList(); // get areas as well

            loads.Insert(0, lowerLoad);
            loads.Add(upperLoad);

            areas.Insert(0, Areal.AreaForHeightLookup(lowerElevation) * 0.0001);
            areas.Add(Areal.AreaForHeightLookup(upperElevation) * 0.0001);

            var lowerElevationPoints   = accumulationLookup.Where(p => p.Key < lowerElevation);
            var previousElevationPoint = lowerElevationPoints.Any() ? lowerElevationPoints.Last().Key : lowerElevation;
            var previousLoad           = accumulationLookup.f(previousElevationPoint);
            var previousArea           = Areal.AreaForHeightLookup(previousElevationPoint) * 0.0001;


            var totalLoad        = 0d;
            var totalAreaBetween = 0d;

            // start at the second element
            for (var i = 0; i < loads.Count; i++)
            {
                double pArea;
                double pLoad;
                if (i == 0)
                {
                    pArea = previousArea;
                    pLoad = previousLoad;
                }
                else
                {
                    pArea = areas[i - 1];
                    pLoad = loads[i - 1];
                }
                var areaBetween = areas[i] - pArea;
                totalLoad        += areaBetween * (loads[i] + pLoad) / 2;
                totalAreaBetween += areaBetween;
            }

            // if we're accumulating across no area then our rate is 0
            if (totalAreaBetween <= 0)
            {
                return(0);
            }

            return(totalLoad / totalAreaBetween);
        }
コード例 #2
0
        /// <summary>
        /// Initialises the Zones using the "InitialLeafDryMatter" lookup tables
        ///
        /// The precise logic used here depends on the nature of the <see cref="Zones"/> collection
        /// </summary>
        private void InitialiseMultipleZones()
        {
            // Get the min and max heights of the storage
            var minHeight = FloodplainElevation;
            var maxHeight = Areal.MaxElevation;

            // Build a collection of all the unique points when the leaf matter changes
            // Include the Min and Max elevations as valid points
            var uniqueHeights = new List <double>
            {
                minHeight,
                maxHeight
            };

            foreach (var height in InitialLeafDryMatterReadilyDegradable.ToUnsortedArray().Select(p => p.Key))
            {
                if (height > minHeight)
                {
                    uniqueHeights.Add(height);
                }
            }

            foreach (var height in InitialLeafDryMatterNonReadilyDegradable.ToUnsortedArray().Select(p => p.Key))
            {
                if (height > minHeight)
                {
                    uniqueHeights.Add(height);
                }
            }

            // Add the current elevation
            uniqueHeights.Add(Elevation);

            // Process in increasing order
            var increasingHeights = uniqueHeights.OrderBy(h => h).ToArray();


            // Due to the odd nature of the Zones collection, we shall sort the Zones into Dry and Wet
            var increasingWetZoneArray = new List <FloodplainData>();
            var tempDryZoneArray       = new List <FloodplainData>();

            var previousCumulativeArea = 0.0;

            // Create the first zone from the lowest height to the next lowest height
            var previousHeight = increasingHeights[0];

            for (var i = 1; i < increasingHeights.Length; i++)
            {
                var height = increasingHeights[i];
                // Avoid duplicates
                if (height.EqualWithTolerance(previousHeight))
                {
                    continue;
                }

                // Anything at or below the current storage level is considered Wet
                var isWet = height <= Elevation;

                var area = Fac * Areal.AreaForHeightLookup(height);

                // Get the initial leaf matter settings
                var leafDryMatterNonReadilyDegradable =
                    IntergrateElevationsForAccumulation(
                        previousHeight,
                        height,
                        InitialLeafDryMatterNonReadilyDegradable);

                var leafDryMatterReadilyDegradable =
                    IntergrateElevationsForAccumulation(
                        previousHeight,
                        height,
                        InitialLeafDryMatterReadilyDegradable);

                // Create the zone
                var newZone = new FloodplainData(isWet)
                {
                    CumulativeAreaM2 = area,

                    // Set the area this zone covers
                    ZoneAreaM2 = area - previousCumulativeArea,
                    ElevationM = height,
                    LeafDryMatterNonReadilyDegradable = leafDryMatterNonReadilyDegradable,
                    LeafDryMatterReadilyDegradable    = leafDryMatterReadilyDegradable,
                };

                // Keep track of the last area
                previousCumulativeArea = area;
                previousHeight         = height;

                // Sort the zone into wet and dry
                if (newZone.Dry)
                {
                    tempDryZoneArray.Add(newZone);
                }
                else
                {
                    increasingWetZoneArray.Add(newZone);
                }
            }

            // The Zones collection has a very specific state.
            // This state has been carried over (presumably) from the FORTRAN implemenation.
            // The rules are...
            // 1. Dry zones are grouped together and come first in the collection
            // 2. Dry zones are ordered by DECREASING area
            // 3. Wet zones are grouped together and come last in the collection
            // 4. Wet zones are ordered by INCREASING area

            tempDryZoneArray.Reverse();
            Zones.AddRange(tempDryZoneArray);
            Zones.AddRange(increasingWetZoneArray);

            // Also set the PreviousArea to the current Area so the Zones arenconsidered "stable" on the first timestep
            PreviousArea = Areal.Area;
        }