/// <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; } } } } }
/// <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); }
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; } } } } }
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 * */ }
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); } }
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... } }
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; }
/// <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; }
/// <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); } }
/// <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... } }