예제 #1
0
        /// <summary>
        /// The objective of this procedure is to reorder the Zone list so that all Dry zones come before Wet zones
        ///
        /// Note: this method seems to be
        /// </summary>
        private void GroupDryZones()
        {
            if (Zones.Count <= 1)
            {
                return;
            }

            for (int i = 0; i < (Zones.Count - 1); i++)
            {
                // Find the first spot where a where a Wet zone comes after a Dry zone
                if (Zones[i].Dry && Zones[i + 1].Wet)
                {
                    for (int j = i; j < (Zones.Count - 1); j++)
                    {
                        // Find the first Dry zone to the follow the wet zone and put it back at index 'i+1'
                        // This should be in front of all Wet zones
                        if (Zones[j].Wet && Zones[j + 1].Dry)
                        {
                            FloodplainData tmp = Zones[j + 1];
                            Zones.RemoveAt(j + 1);
                            Zones.Insert(i + 1, tmp);

                            // Only move one Dry zone then break back to the outer loop
                            break;
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Initialises the Floodplain
        ///
        /// TODO - This method is due to be removed once the <see cref="InitialiseMultipleZones"/> method has been tested
        /// </summary>
        private void InitialiseSingleZone()
        {
            var newZone = new FloodplainData(false);

            newZone.CumulativeAreaM2 = Fac * EffectiveMaximumArea;
            newZone.ZoneAreaM2       = newZone.CumulativeAreaM2;
            newZone.ElevationM       = Areal.MaxElevation;

            newZone.LeafDryMatterNonReadilyDegradable = IntergrateElevationsForAccumulation(Elevation, newZone.ElevationM,
                                                                                            InitialLeafDryMatterNonReadilyDegradable);
            newZone.LeafDryMatterReadilyDegradable =
                IntergrateElevationsForAccumulation(Elevation, newZone.ElevationM, InitialLeafDryMatterReadilyDegradable);

            Zones.Add(newZone);
        }
예제 #3
0
        private void GroupDryZones()
        {
            if (Zones.Count <= 1)
            {
                return;
            }

            for (int i = 0; i < (Zones.Count - 1); i++)
            {
                if (Zones[i].Dry && Zones[i + 1].Wet)
                {
                    for (int j = i; j < (Zones.Count - 1); j++)
                    {
                        if (Zones[j].Wet && Zones[j + 1].Dry)
                        {
                            FloodplainData tmp = Zones[j + 1];
                            Zones.RemoveAt(j + 1);
                            Zones.Insert(i + 1, tmp);
                            break;
                        }
                    }
                }
            }
        }
예제 #4
0
        protected override void ProcessDoc()
        {
            if (Zones.Count == 0)
            {
                var newZone = new FloodplainData(false);
                newZone.AreaM2 = Fac * EffectiveMaximumArea;
                newZone.LeafDryMatterNonReadilyDegradable = InitialLeafDryMatterNonReadilyDegradable;
                newZone.LeafDryMatterReadilyDegradable    = InitialLeafDryMatterReadilyDegradable;
                newZone.NewAreaM2 = newZone.AreaM2;
                Zones.Add(newZone);
            }

            UpdateFloodedAreas();

            double existingDOCMassKg = ConcentrationDoc * WorkingVolume; // kg/m^3 * m^3 = kg

            var docMilligrams = existingDOCMassKg * KG_TO_MG;

            if (Areal.Area.LessOrEqual(0.0))
            {
                FloodCounter = 0;
            }

            //!the DOC dissolution rate constant is temp dependent
            Leach1 = AbstractLumpedFlowRouting.Lintrpl(tempX.ToList(), DOC_k.ToList(), TemperatureEst,
                                                       DOC_k.Length);
            DocMax = AbstractLumpedFlowRouting.Lintrpl(tempX.ToList(), DOC_max.ToList(), TemperatureEst,
                                                       DOC_max.Length); // presumably a concentration?

            DOCEnteringWater = 0;
            TotalWetLeaf     = 0;
            LeachingRate     = 1 - Math.Exp(-Leach1 * Sigma);
            foreach (var zone in Zones)
            {
                if (Areal.Area.Less(zone.AreaM2))
                {
                    continue;
                }

                double wetleafKg = zone.NewAreaM2 * M2_TO_HA *
                                   ((zone.LeafDryMatterReadilyDegradable + zone.LeafDryMatterNonReadilyDegradable) +
                                    LeafAccumulationConstant);

                TotalWetLeaf += wetleafKg;
                double leafDOC = wetleafKg * 1000 * DocMax * (LeachingRate); // ??? How is this converting kg->mg (*1e-6)
                DOCEnteringWater += leafDOC;

                /*
                 * zone(floodrch,isub,ii,2) = max(0.,zone(floodrch,isub,ii,2)-(zone(floodrch,isub,ii,2) * (1 - Exp(-decomp1 * sigma *  86400))))
                 * zone(floodrch,isub,ii,3) = max(0.,zone(floodrch,isub,ii,3)-(zone(floodrch,isub,ii,3) * (1 - Exp(-decomp1 * sigma *  86400))))
                 */
                zone.LeafDryMatterReadilyDegradable    = Math.Max(0, zone.LeafDryMatterReadilyDegradable * (1 - LeachingRate));
                zone.LeafDryMatterNonReadilyDegradable = Math.Max(0, zone.LeafDryMatterNonReadilyDegradable * (1 - LeachingRate));
            }

            docMilligrams += DOCEnteringWater;

            foreach (var zone in Zones)
            {
                if (Areal.Area.Less(zone.AreaM2) && zone.Dry)
                {
                    zone.LeafDryMatterReadilyDegradable = zone.LeafDryMatterReadilyDegradable * Math.Exp(-LeafK1) +
                                                          (LeafAccumulationConstant * LeafA);
                    double MaxmimumNonReadilyDegradable = 2850d;
                    zone.LeafDryMatterNonReadilyDegradable = Math.Min(MaxmimumNonReadilyDegradable,
                                                                      zone.LeafDryMatterNonReadilyDegradable * Math.Exp(-LeafK2) +
                                                                      (LeafAccumulationConstant * (1 - LeafA)));
                }
            }

            //ConsumedDoc = (existingDOCMassKg * KG_TO_MG) * DocConsumptionCoefficient*Sigma;
            ConsumedDocMilligrams = docMilligrams * DocConsumptionCoefficient * Sigma;

            docMilligrams = Math.Max(docMilligrams - ConsumedDocMilligrams, 0.0);

            DissolvedOrganicCarbonLoad = docMilligrams * MG_TO_KG;


/*
 *                                              ! consumption of DOC by microbial activity (temp dependent)
 *
 *                                              Rchlod(Irch,2)=1.
 *                                          Valcon(Ircvld(Irch,WQno))=subloadDOC/fac
 *                                          DOCcalc(irch,isub,1)=1.
 *                                          if ( subrchdata(irch,isub,4).le.zerost ) then
 *                                              Valcon(Ircvld(Irch,WQno))=0.
 *                                          endif
 *                                          continue
 *
 */
        }
예제 #5
0
        private void IncreaseFloodedZones(double newarea)
        {
            FloodCounter++;
            int    minDryZone = -1;
            double shortleaf1, shortleaf2;

            if (Zones.Count == 1)
            {
                shortleaf1 = Zones[0].LeafDryMatterReadilyDegradable;
                shortleaf2 = Zones[0].LeafDryMatterNonReadilyDegradable;
                minDryZone = 0; // Departure from Fortran. To override NewAreaM2
            }
            else
            {
                minDryZone = Zones.Count - 1;
                for (int i = (Zones.Count - 1); i >= 0; i--)
                {
                    if (Areal.Area.Less(Zones[i].AreaM2) && Zones[i].Dry)
                    {
                        minDryZone = i;
                        break;
                    }
                }

                if (minDryZone == (Zones.Count - 1))
                {
                    shortleaf1 = Zones.Last().LeafDryMatterReadilyDegradable;
                    shortleaf2 = Zones.Last().LeafDryMatterNonReadilyDegradable;
                }
                else if (Zones[minDryZone + 1].Wet)
                {
                    shortleaf1 = Zones[minDryZone].LeafDryMatterReadilyDegradable;
                    shortleaf2 = Zones[minDryZone].LeafDryMatterNonReadilyDegradable;
                }
                else
                {
                    shortleaf1 = 0d;
                    shortleaf2 = 0d;
                    for (int i = (Zones.Count - 1); i >= minDryZone; i--)
                    {
                        if (Zones[i].Wet)
                        {
                            continue;
                        }

                        double ratioNewArea = (Zones[i].AreaM2 - (Areal.Area - newarea)) / newarea;
                        shortleaf1 = shortleaf1 +
                                     Zones[i].LeafDryMatterReadilyDegradable * ratioNewArea; // !use ratio;
                        shortleaf2 = shortleaf2 +
                                     Zones[i].LeafDryMatterNonReadilyDegradable * ratioNewArea;
                        for (int j = (i - 1); j >= (minDryZone + 1); j--)
                        {
                            if (Zones[j].Dry)
                            {
                                double ratio2 = Zones[j].NewAreaM2 / newarea;
                                shortleaf1 = shortleaf1 +
                                             (Zones[j].LeafDryMatterReadilyDegradable * ratio2);
                                shortleaf2 = shortleaf2 +
                                             (Zones[j].LeafDryMatterNonReadilyDegradable * ratio2);
                            }
                        }
                        double anotherRatio = (Areal.Area - Zones[minDryZone + 1].AreaM2) / newarea;
                        shortleaf1 = shortleaf1 + Zones[minDryZone].LeafDryMatterReadilyDegradable * anotherRatio; //  !use ratio
                        shortleaf2 = shortleaf2 + Zones[minDryZone].LeafDryMatterNonReadilyDegradable * anotherRatio;
                        break;
                    }
                }
            }

            var newZone = new FloodplainData(true);

            newZone.AreaM2 = Areal.Area;
            newZone.LeafDryMatterReadilyDegradable    = shortleaf1;
            newZone.LeafDryMatterNonReadilyDegradable = shortleaf2;
            newZone.NewAreaM2 = newarea;
            Zones.Add(newZone);

            if (minDryZone >= 0)
            {
                Zones[minDryZone].NewAreaM2 = Zones[minDryZone].AreaM2 - Areal.Area;
            }

            int removedDryZones = 0;
            int minZone         = Zones.Count;

            for (int i = (Zones.Count - 1); i >= 0; i--)
            {
                if (Areal.Area.GreaterOrEqual(Zones[i].AreaM2) && Zones[i].Dry)
                {
                    minZone = i;
                    removedDryZones++;
                }
            }

            if (removedDryZones > 0)
            {
                Zones.RemoveRange(minZone, removedDryZones);
            }
        }
예제 #6
0
        private void ContractFloodedZones(double reducedArea)
        {
            FloodCounter++;

            for (int i = 0; i < Zones.Count; i++)
            {
                var zone = Zones[i];
                if (Areal.Area.GreaterOrEqual(zone.AreaM2) || zone.Dry)
                {
                    continue;
                }

                int removeWetZones = 0;
                int lastFloodZone  = i;

                if (Areal.Area.EqualWithTolerance(0.0))
                {
                    lastFloodZone  = i;
                    removeWetZones = 1;
                }
                else
                {
                    for (int j = (i + 1); j < Zones.Count; j++)
                    {
                        if (Zones[j].Wet)
                        {
                            removeWetZones++;
                            lastFloodZone = j;
                        }
                    }
                }

                var shortleaf1 = 0d;
                var shortleaf2 = 0d;
                for (int j = (Zones.Count - 1); j >= (i + 1); j--)
                {
                    var zoneJ = Zones[j];
                    if (zoneJ.Wet)
                    {
                        double ratio = zoneJ.NewAreaM2 / reducedArea;
                        shortleaf1 += (zoneJ.LeafDryMatterReadilyDegradable * ratio);
                        shortleaf2 += (zoneJ.LeafDryMatterNonReadilyDegradable * ratio);
                    }
                }
                double ratioReducedArea = (zone.AreaM2 - Areal.Area) / reducedArea;
                shortleaf1 += (zone.LeafDryMatterReadilyDegradable * ratioReducedArea);
                // !use remaining area
                shortleaf2 += (zone.LeafDryMatterNonReadilyDegradable * ratioReducedArea);

                var newZone = new FloodplainData(false);
                newZone.AreaM2 = Zones[lastFloodZone].AreaM2;
                newZone.LeafDryMatterReadilyDegradable    = shortleaf1;
                newZone.LeafDryMatterNonReadilyDegradable = shortleaf2;
                newZone.NewAreaM2 = reducedArea;
                Zones.Add(newZone);

                zone.NewAreaM2 -= zone.AreaM2 - Areal.Area;
                zone.AreaM2     = Areal.Area;
                if (zone.NewAreaM2.Less(0.0))
                {
                    zone.NewAreaM2 = Areal.Area;
                }

                if (Areal.Area.EqualWithTolerance(0.0))
                {
                    Zones.RemoveRange(i, removeWetZones);
                }
                else
                {
                    Zones.RemoveRange(i + 1, removeWetZones);
                }
                return;
            }

            if (Areal.Area.Less(Zones.Last().AreaM2) && Zones.Last().Wet)
            {
                var last = Zones.Last();

                var newZone = new FloodplainData(false);
                newZone.AreaM2 = last.AreaM2;
                newZone.LeafDryMatterReadilyDegradable    = last.LeafDryMatterReadilyDegradable;
                newZone.LeafDryMatterNonReadilyDegradable = last.LeafDryMatterNonReadilyDegradable;
                newZone.NewAreaM2 = reducedArea;
                Zones.Add(newZone);

                last.NewAreaM2 -= last.AreaM2 - Areal.Area;
                last.AreaM2     = Areal.Area;
                if (last.NewAreaM2.Less(0.0))
                {
                    last.NewAreaM2 = Areal.Area;
                } // TODO ++ Common code...
            }
        }
예제 #7
0
        private void EndOfFlood()
        {
            if (FloodCounter == 0)
            {
                return;
            }

            for (int i = 0; i < Zones.Count; i++)
            {
                var zone = Zones[i];
                if (Areal.Area < zone.AreaM2 && zone.Wet)
                {
                    if (i == (Zones.Count - 1))
                    {
                        var newDryZone = new FloodplainData(false);
                        newDryZone.AreaM2 = zone.AreaM2;
                        newDryZone.LeafDryMatterReadilyDegradable    = zone.LeafDryMatterReadilyDegradable;
                        newDryZone.LeafDryMatterNonReadilyDegradable = zone.LeafDryMatterNonReadilyDegradable;
                        newDryZone.NewAreaM2 = zone.AreaM2;
                        Zones.Add(newDryZone);
                        break;
                    }
                    else
                    {
                        int removeWetZones = 1;
                        int lastFloodZone  = i;
                        for (int j = (i + 1); j < Zones.Count; j++)
                        {
                            if (Zones[j].Wet)
                            {
                                removeWetZones++;
                                lastFloodZone = j;
                            }
                        }

                        var shortleaf1 = 0d;
                        var shortleaf2 = 0d;
                        for (int j = (Zones.Count - 1); j >= (i + 1); j--)
                        {
                            var floodZone = Zones[j];
                            if (floodZone.Wet)
                            {
                                shortleaf1 += floodZone.LeafDryMatterReadilyDegradable * (floodZone.AreaM2 - Areal.Area) /
                                              Zones[lastFloodZone].AreaM2;
                                shortleaf2 += floodZone.LeafDryMatterNonReadilyDegradable * (floodZone.AreaM2 - Areal.Area) /
                                              Zones[lastFloodZone].AreaM2;
                            }
                        }
                        shortleaf1 += zone.LeafDryMatterReadilyDegradable * (zone.AreaM2 - Areal.Area) /
                                      Zones[lastFloodZone].AreaM2;
                        shortleaf2 += zone.LeafDryMatterNonReadilyDegradable * (zone.AreaM2 - Areal.Area) /
                                      Zones[lastFloodZone].AreaM2;

                        var newDryZone = new FloodplainData(false);
                        newDryZone.AreaM2 = Zones[lastFloodZone].AreaM2;
                        newDryZone.LeafDryMatterReadilyDegradable    = shortleaf1;
                        newDryZone.LeafDryMatterNonReadilyDegradable = shortleaf2;
                        newDryZone.NewAreaM2 = newDryZone.AreaM2;
                        break;
                    }
                }
            }

            /* Marker 150 */
            if (Zones.Count > 1)
            {
                for (int i = 0; i < Zones.Count; i++)
                {
                    if (Zones[i].Wet || Zones[i].AreaM2 < 1)
                    {
                        Zones.RemoveAt(i);
                        i--;
                    }
                }
            }

            for (int i = 0; i < (Zones.Count - 1); i++)
            {
                if (!(Zones[i].AreaM2 - Zones[i + 1].AreaM2).EqualWithTolerance(Zones[i].NewAreaM2))
                { // Why the if?
                    Zones[i].NewAreaM2 = Zones[i].AreaM2 - Zones[i + 1].AreaM2;
                }
            }

            if (!Zones.Last().AreaM2.EqualWithTolerance(Zones.Last().NewAreaM2))
            { // Why the if?
                Zones.Last().NewAreaM2 = Zones.Last().AreaM2;
            }

            FloodCounter = 0;
        }
예제 #8
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;
        }
예제 #9
0
        /// <summary>
        /// The area has increased.
        /// A Dry zone will be reduced in size as the water level encroaches on it
        /// Possible several Dry zones will be removed entirely as they are covered.
        /// A new Wet zone will cover the area that is now wet
        /// </summary>
        private void IncreaseFloodedZones(double newarea)
        {
            FloodCounter++;
            int    minDryZone = -1;
            double shortleaf1, shortleaf2;

            if (Zones.Count == 1)
            {
                shortleaf1 = Zones[0].LeafDryMatterReadilyDegradable;
                shortleaf2 = Zones[0].LeafDryMatterNonReadilyDegradable;
                minDryZone = 0; // Departure from Fortran. To override ZoneAreaM2
            }
            else
            {
                minDryZone = Zones.Count - 1;

                // We are looking for the Dry zone covers the current elevation
                // This is the zone that will be split into separate Wet and Dry zones

                // Since Dry zones are ordered by DECREASING area,
                // we search through the collection in REVERSE,
                // looking for the zone with area GREATER than the current floodplain area
                // Any Dry zone with an area Less than the current floodplain area will be removed
                for (int i = (Zones.Count - 1); i >= 0; i--)
                {
                    if (Areal.Area.Less(Zones[i].CumulativeAreaM2) && Zones[i].Dry)
                    {
                        minDryZone = i;
                        break;
                    }
                }

                if (minDryZone == (Zones.Count - 1))
                {
                    shortleaf1 = Zones.Last().LeafDryMatterReadilyDegradable;
                    shortleaf2 = Zones.Last().LeafDryMatterNonReadilyDegradable;
                }
                else if (Zones[minDryZone + 1].Wet)
                {
                    shortleaf1 = Zones[minDryZone].LeafDryMatterReadilyDegradable;
                    shortleaf2 = Zones[minDryZone].LeafDryMatterNonReadilyDegradable;
                }
                else
                {
                    shortleaf1 = 0d;
                    shortleaf2 = 0d;

                    for (int i = (Zones.Count - 1); i >= minDryZone; i--)
                    {
                        if (Zones[i].Wet)
                        {
                            continue;
                        }

                        double ratioNewArea = (Zones[i].CumulativeAreaM2 - (Areal.Area - newarea)) / newarea;
                        shortleaf1 = shortleaf1 +
                                     Zones[i].LeafDryMatterReadilyDegradable * ratioNewArea; // !use ratio;
                        shortleaf2 = shortleaf2 +
                                     Zones[i].LeafDryMatterNonReadilyDegradable * ratioNewArea;
                        for (int j = (i - 1); j >= (minDryZone + 1); j--)
                        {
                            if (Zones[j].Dry)
                            {
                                double ratio2 = Zones[j].ZoneAreaM2 / newarea;
                                shortleaf1 = shortleaf1 +
                                             (Zones[j].LeafDryMatterReadilyDegradable * ratio2);
                                shortleaf2 = shortleaf2 +
                                             (Zones[j].LeafDryMatterNonReadilyDegradable * ratio2);
                            }
                        }
                        double anotherRatio = (Areal.Area - Zones[minDryZone + 1].CumulativeAreaM2) / newarea;
                        shortleaf1 = shortleaf1 + Zones[minDryZone].LeafDryMatterReadilyDegradable * anotherRatio; //  !use ratio
                        shortleaf2 = shortleaf2 + Zones[minDryZone].LeafDryMatterNonReadilyDegradable * anotherRatio;
                        break;
                    }
                }
            }

            var newZone = new FloodplainData(true);

            newZone.CumulativeAreaM2 = Areal.Area;
            newZone.ElevationM       = Areal.Elevation;

            newZone.LeafDryMatterReadilyDegradable    = shortleaf1;
            newZone.LeafDryMatterNonReadilyDegradable = shortleaf2;
            newZone.ZoneAreaM2 = newarea;
            Zones.Add(newZone);

            // Adjust the area of the dry zone that will be split by the new water level
            if (minDryZone >= 0)
            {
                Zones[minDryZone].ZoneAreaM2 = Zones[minDryZone].CumulativeAreaM2 - Areal.Area;
            }

            int removedDryZones = 0;
            int minZone         = Zones.Count;

            // Find the range of Dry zones that will be covered by the new Wet zone and remove them
            for (int i = (Zones.Count - 1); i >= 0; i--)
            {
                if (Areal.Area.GreaterOrEqual(Zones[i].CumulativeAreaM2) && Zones[i].Dry)
                {
                    minZone = i;
                    removedDryZones++;
                }
            }

            if (removedDryZones > 0)
            {
                Zones.RemoveRange(minZone, removedDryZones);
            }
        }
예제 #10
0
        /// <summary>
        /// The area has reduced.
        /// One of the Wet zones will now be reduced to cover the new resulting area.
        /// Possibly some of the Wet zones will be removed entirely.
        /// A new Dry Zone will be created to cover the area that is now dry.
        /// </summary>
        private void ContractFloodedZones(double reducedArea)
        {
            FloodCounter++;

            for (int i = 0; i < Zones.Count; i++)
            {
                var zone = Zones[i];

                // Skip past all the Dry zones
                // We are looking for the Wet zone covers the current elevation
                // This is the zone that will be split into separate Wet and Dry zones

                // Since Wet zones are ordered by INCREASING area,
                // we search through the collection looking for the FIRST to have an area GREATER than the current floodplain area
                if (Areal.Area.GreaterOrEqual(zone.CumulativeAreaM2) || zone.Dry)
                {
                    continue;
                }

                int removeWetZones = 0;
                int lastFloodZone  = i;

                if (Areal.Area.EqualWithTolerance(0.0))
                {
                    lastFloodZone  = i;
                    removeWetZones = 1;
                }
                else
                {
                    // We want to find the range of Wet zones that need to be removed as they will be replaced by a Dry zone
                    for (int j = (i + 1); j < Zones.Count; j++)
                    {
                        if (Zones[j].Wet)
                        {
                            removeWetZones++;
                            lastFloodZone = j;
                        }
                    }
                }

                var shortleaf1 = 0d;
                var shortleaf2 = 0d;
                for (int j = (Zones.Count - 1); j >= (i + 1); j--)
                {
                    var zoneJ = Zones[j];
                    if (zoneJ.Wet)
                    {
                        double ratio = zoneJ.ZoneAreaM2 / reducedArea;
                        shortleaf1 += (zoneJ.LeafDryMatterReadilyDegradable * ratio);
                        shortleaf2 += (zoneJ.LeafDryMatterNonReadilyDegradable * ratio);
                    }
                }
                double ratioReducedArea = (zone.CumulativeAreaM2 - Areal.Area) / reducedArea;
                shortleaf1 += (zone.LeafDryMatterReadilyDegradable * ratioReducedArea);
                // !use remaining area
                shortleaf2 += (zone.LeafDryMatterNonReadilyDegradable * ratioReducedArea);

                // Create a new Dry zone to cover the area of all Wet zones that have been removed or resized.
                var newZone = new FloodplainData(false);
                newZone.CumulativeAreaM2 = Zones[lastFloodZone].CumulativeAreaM2;
                newZone.ElevationM       = Zones[lastFloodZone].ElevationM;

                newZone.LeafDryMatterReadilyDegradable    = shortleaf1;
                newZone.LeafDryMatterNonReadilyDegradable = shortleaf2;
                newZone.ZoneAreaM2 = reducedArea;
                Zones.Add(newZone);

                // Resize the Wet zone that will be split
                zone.ZoneAreaM2      -= zone.CumulativeAreaM2 - Areal.Area;
                zone.CumulativeAreaM2 = Areal.Area;
                zone.ElevationM       = Areal.Elevation;

                if (zone.ZoneAreaM2.Less(0.0))
                {
                    zone.ZoneAreaM2 = Areal.Area;
                }

                // Remove the Wet zones that have been replaced
                if (Areal.Area.EqualWithTolerance(0.0))
                {
                    Zones.RemoveRange(i, removeWetZones);
                }
                else
                {
                    Zones.RemoveRange(i + 1, removeWetZones);
                }
                return;
            }


            // TODO - I don't know how this code is reached
            // TODO - It seems to me that to pass the IF statement below, it would also not have gotten out of the prior loop...
            if (Areal.Area.Less(Zones.Last().CumulativeAreaM2) && Zones.Last().Wet)
            {
                var last = Zones.Last();

                var newZone = new FloodplainData(false);
                newZone.CumulativeAreaM2 = last.CumulativeAreaM2;
                newZone.ElevationM       = last.ElevationM;

                newZone.LeafDryMatterReadilyDegradable    = last.LeafDryMatterReadilyDegradable;
                newZone.LeafDryMatterNonReadilyDegradable = last.LeafDryMatterNonReadilyDegradable;
                newZone.ZoneAreaM2 = reducedArea;
                Zones.Add(newZone);

                last.ZoneAreaM2      -= last.CumulativeAreaM2 - Areal.Area;
                last.CumulativeAreaM2 = Areal.Area;
                last.ElevationM       = Areal.Elevation;

                if (last.ZoneAreaM2.Less(0.0))
                {
                    last.ZoneAreaM2 = Areal.Area;
                } // TODO ++ Common code...
            }
        }