private static void EnsureCategoryExists(HierarchyCategory category) { if (!categoryTransforms.ContainsKey(category)) { GameObject categoryGameObject = new GameObject(category.ToString()); categoryTransforms.Add(category, categoryGameObject.transform); } }
public static GameObject Instantiate <T>(GameObject prefab, HierarchyCategory category) { GameObject instance = GameObject.Instantiate(prefab); Add(instance, category); return(instance); }
public static T Instantiate <T>(T prefab, HierarchyCategory category) where T : MonoBehaviour { T instance = Object.Instantiate(prefab); Add(instance.gameObject, category); return(instance); }
public static GameObject CreateGameObject(HierarchyCategory category) { GameObject gameObject = new GameObject(); Add(gameObject, category); return(gameObject); }
public static void Add(GameObject gameObject, HierarchyCategory category) { if (category == HierarchyCategory.None) { return; } EnsureCategoryExists(category); gameObject.transform.SetParent(categoryTransforms[category]); }
/// <summary> /// Contains algorithims implementing the sizing calculations for various facility configurations /// </summary> /// <param name="facility"></param> /// <param name="category"></param> /// <param name="catchment"></param> /// <param name="inflowHydrograph"></param> /// <returns></returns> public static StormEventResults PerformCalculations(Facility facility, HierarchyCategory category, Catchment catchment, Hydrograph inflowHydrograph) { string message; Facility.Validate(facility, Convert.ToInt32(category), out message); if (!facility.IsValid) { throw new ArgumentException("Unable to perform calculations: failed validation with message '" + message + "'"); } double dt = inflowHydrograph.TimeStepMinutes; int timeSteps = inflowHydrograph.AsArray().Count(); double inflowFromRain; double inflowVolume; double inflowVolumeCummulative = 0; double[] surfaceInfiltrationCapacity = new double[timeSteps]; //Column E, aka Percolation Capacity double initialInfiltrationToAmendedSoil; double[] storedToBeInfiltrated = new double[timeSteps]; double graphLocator = 0; double potentialExtraInfiltration; double cumulativeInfiltrationVolume = 0; //Column J double additionalInfiltrationFromStorage; //Column K double[] totalInfiltrationCapacityToBelowGrade = new double[timeSteps]; //Column L double inflowToSurfaceStorageAfterInfiltration; //Column M double[] inflowMinusInfiltration = new double[timeSteps]; //Column N double surfaceStorageCumulativeVolume = 0; //Column O,P,Q,R combined. double[] flowOvertoppingToUnderdrain = new double[timeSteps]; //Column T (or Column W for type E) double[] infiltrationToBelowGrade = new double[timeSteps]; //Column Z double[] totalFlowToBelowGrade = new double[timeSteps]; //Column AA double[] inflowToRockStorage = new double[timeSteps]; //column AB double[] totalInfiltrationCapacityToNative = new double[timeSteps]; //Column AE double totalInfiltratedToNative = 0; double rockStorageCumulativeVolume = 0; //Column AJ double[] rockPercentCapacity = new double[timeSteps]; //Column AK/AL for A,B&E facilities; Column AR/AS for C&F; double excessRockCumulativeVolume = 0; //Column AM double underdrainStorageAreaCumulativeVolume = 0; //Column AR double[] aboveGradeStoragePercentCapacity = new double[timeSteps]; //Column AO for A,B facilities; Column S for C,D&F double[] aboveGradeSecondaryStoragePercentCapacity = new double[timeSteps]; //Column AO for E facilities double[] rockOverflowToEscapeRoute = new double[timeSteps]; //Column AP double[] overflowToEscapeRoute = new double[timeSteps]; //Column AQ for A,B,D,E,F facilities; Column AT for C&F double nativeInfiltrationRate = facility.NativeSoilInfiltrationCapacityCfs(); double growingMediumInfiltrationRate = facility.ImportedMediumInfiltrationCapacityCfs(); //The Lag Index is a property of the growing medium depth and infiltration rate that //corresponds to the number of time steps it will take for water to percolate through the //growing medium. The infiltration hydrograph to the rock medium is delayed by the lag index. //For facility configurations A, B, and E, no lag is applied when the native infiltration rate is less //than the growing medium infilration rate. double lagFactor = (facility.Configuration == FacilityConfiguration.A || facility.Configuration == FacilityConfiguration.B || facility.Configuration == FacilityConfiguration.E) && nativeInfiltrationRate < growingMediumInfiltrationRate ? 0 : facility.GrowingMediumPorespace; double lagTime = facility.GrowingMediumDepthIn / catchment.ImportedMediumInfiltrationInchesPerHour * 60 * lagFactor; int lag = (int)Math.Ceiling(lagTime / inflowHydrograph.TimeStepMinutes); // Rounding up is perfored in the current calculator. This may be unnecessary. for (int i = 0; i < timeSteps; i++) { inflowFromRain = inflowHydrograph.AsArray()[i]; inflowVolume = inflowFromRain * 600; inflowVolumeCummulative += inflowVolume; //Facility configurations A,B, and D have rock-influenced surface storage demand. When //the rock storage is full, infiltration rates in the growing medium can be limited by //infiltration rates of the native soil. if (facility.HasRockInfluencedSurfaceStorage && rockPercentCapacity[Math.Max(1, i - 1)] >= 1) { surfaceInfiltrationCapacity[i] = Math.Min(growingMediumInfiltrationRate, nativeInfiltrationRate); } else { surfaceInfiltrationCapacity[i] = growingMediumInfiltrationRate; } initialInfiltrationToAmendedSoil = Math.Min(inflowFromRain, surfaceInfiltrationCapacity[i]); storedToBeInfiltrated[i] = Math.Max(inflowFromRain - initialInfiltrationToAmendedSoil, 0) * 600; graphLocator = storedToBeInfiltrated[i] - storedToBeInfiltrated[Math.Max(1, i - 1)] < 0 ? 1 : graphLocator; potentialExtraInfiltration = (surfaceInfiltrationCapacity[i] - initialInfiltrationToAmendedSoil) * graphLocator; cumulativeInfiltrationVolume += (potentialExtraInfiltration * 600); // Existing spreadsheet rounds up storageToBeInfiltrated to nearest ten, // allowing more potentialExtraInfiltration to fill rock storage. This may be unnecessary... double storedToBeInfiltratedRoundedUp = Math.Ceiling(storedToBeInfiltrated.Sum() / 10) * 10; double cumulativeInfiltrationVolumeRounded = Math.Round(cumulativeInfiltrationVolume, 10); // Added 6/24/2015 to deal with binary storage of floating point numbers without changing to decimal data type additionalInfiltrationFromStorage = cumulativeInfiltrationVolumeRounded > storedToBeInfiltratedRoundedUp || cumulativeInfiltrationVolumeRounded > facility.SurfaceCapacityAtDepth1CuFt ? 0 : potentialExtraInfiltration; totalInfiltrationCapacityToBelowGrade[i] = initialInfiltrationToAmendedSoil + additionalInfiltrationFromStorage; inflowToSurfaceStorageAfterInfiltration = Math.Max(inflowFromRain - totalInfiltrationCapacityToBelowGrade[i], 0); inflowMinusInfiltration[i] = inflowFromRain - surfaceInfiltrationCapacity[i]; surfaceStorageCumulativeVolume += (inflowMinusInfiltration[i] * 600); surfaceStorageCumulativeVolume = Math.Max(surfaceStorageCumulativeVolume, 0); surfaceStorageCumulativeVolume = Math.Min(surfaceStorageCumulativeVolume, facility.SurfaceCapacityAtDepth1CuFt); flowOvertoppingToUnderdrain[i] = surfaceStorageCumulativeVolume < facility.SurfaceCapacityAtDepth1CuFt ? 0 : inflowToSurfaceStorageAfterInfiltration; if (i - lag < 0) { infiltrationToBelowGrade[i] = totalInfiltrationCapacityToBelowGrade[0]; } else { infiltrationToBelowGrade[i] = totalInfiltrationCapacityToBelowGrade[i - lag]; } totalFlowToBelowGrade[i] = infiltrationToBelowGrade[i] + flowOvertoppingToUnderdrain[i]; if (facility.Configuration == FacilityConfiguration.E || facility.Configuration == FacilityConfiguration.F) { inflowToRockStorage[i] = totalFlowToBelowGrade[i]; } else { inflowToRockStorage[i] = infiltrationToBelowGrade[i]; } totalInfiltrationCapacityToNative[i] = nativeInfiltrationRate; if (rockStorageCumulativeVolume + inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i] < 0) { totalInfiltratedToNative += rockStorageCumulativeVolume + inflowToRockStorage[i]; } else { totalInfiltratedToNative += totalInfiltrationCapacityToNative[i]; } rockStorageCumulativeVolume += ((inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]) * 600); excessRockCumulativeVolume = rockStorageCumulativeVolume < facility.RockStorageCapacityCuFt ? 0 : rockStorageCumulativeVolume - facility.RockStorageCapacityCuFt; rockStorageCumulativeVolume = Math.Max(rockStorageCumulativeVolume, 0); if (facility.HasRockInfluencedSurfaceStorage) { aboveGradeStoragePercentCapacity[i] = (surfaceStorageCumulativeVolume + excessRockCumulativeVolume) / facility.SurfaceCapacityAtDepth1CuFt; //E facilities have a secondary storage volume if (facility.HasSecondaryOverflow) { aboveGradeSecondaryStoragePercentCapacity[i] = (surfaceStorageCumulativeVolume + excessRockCumulativeVolume) / facility.SurfaceCapacityAtDepth2CuFt; aboveGradeSecondaryStoragePercentCapacity[i] = Math.Min(aboveGradeSecondaryStoragePercentCapacity[i], 1); } } //C, D, and F facilities have a direct connection from the rock gallery to an overflow, //and therefore above grade storage capacity is independent of rock gallery volume else { aboveGradeStoragePercentCapacity[i] = surfaceStorageCumulativeVolume / facility.SurfaceCapacityAtDepth1CuFt; } aboveGradeStoragePercentCapacity[i] = Math.Min(aboveGradeStoragePercentCapacity[i], 1); if (facility.HasRockInfluencedSurfaceStorage && !facility.HasSecondaryOverflow) // A, B { // Added 6/22/2015 to handle case where surface is full, but should overflow more due to limited rock gallery. // This will occur only once during a storm, as the next cycle will limit above grade infiltration to the rock gallery // and overflow the correct amount. double belowGradeInflowMinusInfiltration = inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]; if (aboveGradeStoragePercentCapacity[i] == 1 && belowGradeInflowMinusInfiltration > 0) { rockOverflowToEscapeRoute[i] = belowGradeInflowMinusInfiltration; } else { rockOverflowToEscapeRoute[i] = 0; } rockPercentCapacity[i] = facility.HasRockStorage ? rockStorageCumulativeVolume / facility.RockStorageCapacityCuFt : 1; rockPercentCapacity[i] = Math.Min(rockPercentCapacity[i], 1); } else if (facility.HasSecondaryOverflow) // E { rockOverflowToEscapeRoute[i] = aboveGradeSecondaryStoragePercentCapacity[i] < 1 ? 0 : Math.Max(totalFlowToBelowGrade[i] - facility.NativeSoilInfiltrationCapacityCfs(), 0); rockPercentCapacity[i] = facility.HasRockStorage ? rockStorageCumulativeVolume / facility.RockStorageCapacityCuFt : 1; rockPercentCapacity[i] = Math.Min(rockPercentCapacity[i], 1); } else if (!facility.HasRockInfluencedSurfaceStorage) // C, D & F { underdrainStorageAreaCumulativeVolume += ((inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]) * 600); underdrainStorageAreaCumulativeVolume = Math.Max(underdrainStorageAreaCumulativeVolume, 0); underdrainStorageAreaCumulativeVolume = Math.Min(underdrainStorageAreaCumulativeVolume, facility.RockStorageCapacityCuFt); if ((underdrainStorageAreaCumulativeVolume / facility.RockStorageCapacityCuFt >= 1) || facility.RockStorageCapacityCuFt == 0) // Added facility.RockStorageCapacityCuFt for 0/0 case { rockOverflowToEscapeRoute[i] = inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]; } rockPercentCapacity[i] = facility.HasRockStorage ? underdrainStorageAreaCumulativeVolume / facility.RockStorageCapacityCuFt : 1; rockPercentCapacity[i] = Math.Min(rockPercentCapacity[i], 1); } if (facility.Configuration == FacilityConfiguration.F || // Facility F is different, in that overflow from the surface goes to the subsurface facility.Configuration == FacilityConfiguration.E) // Facility E is strange also, in that the flow overtopping to the underdrain doesn't also go to the escape route. { overflowToEscapeRoute[i] = excessRockCumulativeVolume > 0 ? rockOverflowToEscapeRoute[i] : 0; } else { overflowToEscapeRoute[i] = excessRockCumulativeVolume > 0 ? flowOvertoppingToUnderdrain[i] + rockOverflowToEscapeRoute[i] : flowOvertoppingToUnderdrain[i]; } } StormEventResults results = new StormEventResults(); results.PeakSurfaceOverflow = flowOvertoppingToUnderdrain.Max(); results.PeakOverflow = overflowToEscapeRoute.Max(); results.OverflowVolume = overflowToEscapeRoute.Sum() * 600; results.PercentSurfaceCapacityUsed = aboveGradeStoragePercentCapacity.Max(); results.PercentRockCapacityUsed = rockPercentCapacity.Max(); results.InflowVolume = inflowHydrograph.AsArray().Sum() * 600; results.PeakInflowRate = inflowHydrograph.AsArray().Max(); results.AboveGradePrimaryResults.Add(new Hydrograph("Inflow from rain", "cfs", inflowHydrograph.AsArray(), dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", surfaceInfiltrationCapacity, dt)); switch (facility.Configuration) { case FacilityConfiguration.A: results.AboveGradePrimaryResults.Add(new Hydrograph("Infiltration to native soil", "cfs", infiltrationToBelowGrade, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", overflowToEscapeRoute, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.PercentRockCapacityUsed = -1; // There is no rock gallery. break; case FacilityConfiguration.B: results.AboveGradePrimaryResults.Add(new Hydrograph("Percolation to below grade storage", "cfs", infiltrationToBelowGrade, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", overflowToEscapeRoute, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", infiltrationToBelowGrade, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); break; case FacilityConfiguration.C: results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Flow bypassing growing medium", "cfs", flowOvertoppingToUnderdrain, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", inflowToRockStorage, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", rockOverflowToEscapeRoute, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); break; case FacilityConfiguration.D: results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Flow bypassing growing medium", "cfs", flowOvertoppingToUnderdrain, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); break; case FacilityConfiguration.E: results.AboveGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", rockOverflowToEscapeRoute, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeSecondaryStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", inflowToRockStorage, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); results.PercentSurfaceCapacityUsed = aboveGradeSecondaryStoragePercentCapacity.Max(); break; case FacilityConfiguration.F: results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Flow bypassing growing medium", "cfs", flowOvertoppingToUnderdrain, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", inflowToRockStorage, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", rockOverflowToEscapeRoute, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); break; } return(results); }
private Facility ValidateFacility(string hierarchy, string facilityType, string configuration) { try { //Read catchment parameters to local variables double imperviousArea = Convert.ToDouble(txtImperviousArea.Text); double curveNumber = Convert.ToDouble(txtCurveNumber.Text); double preCurveNumber = Convert.ToDouble(txtPreCurveNumber.Text); double timeOfConcentration = Convert.ToDouble(txtTimeOfConcentration.Text); double nativeInfiltrationRate = Convert.ToDouble(txtNativeSoilInfiltrationRate.Text); InfiltrationTestType infiltrationTestType; switch (cmbInfiltrationProcedure.SelectedIndex) { case (0): infiltrationTestType = InfiltrationTestType.OpenPitFallingHead; break; case (1): infiltrationTestType = InfiltrationTestType.EncasedFallingHead; break; case (2): infiltrationTestType = InfiltrationTestType.DoubleRingInfiltometer; break; default: infiltrationTestType = InfiltrationTestType.OpenPitFallingHead; break; } //Create catchment object local variables Catchment catchment = new Catchment("Catchment A") { ImperviousAreaSquareFeet = imperviousArea, AcceptableSeparationFromGroundwater = chkMeetsGroundwaterRequirements.Checked, CurveNumber = curveNumber, TimeOfConcentrationMinutes = timeOfConcentration, TestedInfiltrationRateInchesPerHour = nativeInfiltrationRate, InfiltrationTestType = infiltrationTestType }; //Read facility parameters to local variables double bottomArea = Convert.ToDouble(txtBottomArea.Text); double bottomWidth = Convert.ToDouble(txtBottomWidth.Text); double sideSlope = Convert.ToDouble(txtSideSlope.Text); double storageDepth1 = Convert.ToDouble(txtStorageDepth1.Text); double storageDepth2 = Convert.ToDouble(txtStorageDepth2.Text); double storageDepth3 = Convert.ToDouble(txtStorageDepth3.Text); double growingMediumDepth = Convert.ToDouble(txtGrowingMediumDepth.Text); double freeboardDepth = Convert.ToDouble(txtFreeboardDepth.Text); double rockStorageDepth = Convert.ToDouble(txtRockStorageDepth.Text); double rockStorageVoidRatio = Convert.ToDouble(txtRockVoidRatio.Text); double rockStorageBottomArea = Convert.ToDouble(txtRockStorageBottomArea.Text); double surfaceAreaAtStorageDepth1 = Convert.ToDouble(txtSurfaceAreaAtDepth1.Text); double bottomPerimiterLength = Convert.ToDouble(txtBottomPerimeterLength.Text); double surfaceAreaAtStorageDepth2 = Convert.ToDouble(txtSurfaceAreaAtDepth2.Text); FacilityShape shape = GetFacilityShape(cmbFacilityShape.Text); FacilityConfiguration config; config = (FacilityConfiguration)cmbFacilityConfiguration.Text[0]; FacilityType type = GetFacilityType(cmbFacilityType.Text); Facility facility; if (type == FacilityType.Basin || type == FacilityType.PlanterFlat) { facility = new Facility(type, config, catchment) { BottomAreaSqFt = bottomArea, BottomWidthFt = bottomWidth, SideSlopeRatio = sideSlope, StorageDepth1In = storageDepth1, StorageDepth2In = storageDepth2, StorageDepth3In = storageDepth3, GrowingMediumDepthIn = growingMediumDepth, FreeboardIn = freeboardDepth, RockStorageDepthIn = rockStorageDepth, RockVoidRatio = rockStorageVoidRatio, RockStorageBottomAreaSqFt = rockStorageBottomArea, SurfaceAreaAtStorageDepth1SqFt = surfaceAreaAtStorageDepth1, BottomPerimeterLengthFt = bottomPerimiterLength, SurfaceAreaAtStorageDepth2SqFt = surfaceAreaAtStorageDepth2, Shape = shape }; } else //Write sloped facility parameters from UI to facility object and verify results { //ShowSlopedFacilityWS(); List <SlopedFacilitySegment> segments; if (_sfws != null) { if (_sfws.Segments != null) { segments = _sfws.Segments; } else { segments = new List <SlopedFacilitySegment>(); } } else { segments = new List <SlopedFacilitySegment>(); } facility = new SlopedFacility(type, config, catchment, segments) { BottomAreaSqFt = bottomArea, BottomWidthFt = bottomWidth, SideSlopeRatio = sideSlope, StorageDepth1In = storageDepth1, StorageDepth2In = storageDepth2, StorageDepth3In = storageDepth3, GrowingMediumDepthIn = growingMediumDepth, FreeboardIn = freeboardDepth, RockStorageDepthIn = rockStorageDepth, RockVoidRatio = rockStorageVoidRatio, RockStorageBottomAreaSqFt = rockStorageBottomArea, SurfaceAreaAtStorageDepth1SqFt = surfaceAreaAtStorageDepth1, Shape = shape }; } int hierarchyNumber = Convert.ToInt32(hierarchy); HierarchyCategory hierarchyCategory = (HierarchyCategory)hierarchyNumber; string message; _validFacility = Facility.Validate(facility, hierarchyNumber, out message); ToggleUIParameters(facility); if (!_validFacility) { DisableUI(message); } return(facility); } catch (Exception ex) { MessageBox.Show("Error with facility parameters: " + ex.Message); return(null); } }
/// <summary> /// Executes the calculator and returns a PacResults. /// </summary> /// <param name="catchment">A catchment object defining the hydrologic parameters of the post-developed catchment area to be evaluated.</param> /// <param name="preCatchment">A catchment object defining the hydrologic parameters of the pre-developed catchment area to be evaluated.</param> /// <param name="facility">A Facility object defining the stormwater management facility to be evaluated.</param> /// <param name="category">Identifies the HierarchyCategory the proposed facility will be evaluated against.</param> /// <param name="dischargePoint">Identifies the DischargePoint of the proposed facility.</param> /// <returns>A PacResults object containing the results of the calculation.</returns> internal static PacResults PerformCalculations(Catchment catchment, Catchment preCatchment, Facility facility, HierarchyCategory category, DischargePoint dischargePoint) { //Define design storms RainfallEvent pollutionReduction = RainfallEvent.GetScsOneAEvent("Pollution Reduction", 0.83); RainfallEvent twoYear = RainfallEvent.GetScsOneAEvent("Two-Year", 2.4); RainfallEvent fiveYear = RainfallEvent.GetScsOneAEvent("Five-Year", 2.9); RainfallEvent tenYear = RainfallEvent.GetScsOneAEvent("Ten-Year", 3.4); RainfallEvent twentyFiveYear = RainfallEvent.GetScsOneAEvent("Twentyfive-Year", 3.9); PacResults results = new PacResults(); //Calculate hydrographs for the most important design storms Hydrograph imperviousHydrographPR = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, pollutionReduction); Hydrograph imperviousHydrographTwoYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, twoYear); Hydrograph imperviousHydrographFiveYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, fiveYear); Hydrograph imperviousHydrographTenYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, tenYear); Hydrograph imperviousHydrographTwentyfiveYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, twentyFiveYear); results.PollutionReductionResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographPR); results.PollutionReductionPeakOverflow = results.PollutionReductionResults.PeakOverflow; results.PollutionReductionTotalOverflowVolume = results.PollutionReductionResults.OverflowVolume; results.PollutionReductionSurfaceCapacity = results.PollutionReductionResults.PercentSurfaceCapacityUsed; results.PollutionReductionPercentRockCapacity = results.PollutionReductionResults.PercentRockCapacityUsed; results.PollutionReductionInflowVolume = results.PollutionReductionResults.InflowVolume; results.PollutionReductionPeakInflow = results.PollutionReductionResults.PeakInflowRate; results.TwoYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographTwoYear); results.TwoYearPeakOverflow = results.TwoYearResults.PeakOverflow; results.TwoYearTotalOverflowVolume = results.TwoYearResults.OverflowVolume; results.TwoYearInflowVolume = results.TwoYearResults.InflowVolume; results.TwoYearPeakInflow = results.TwoYearResults.PeakInflowRate; results.FiveYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographFiveYear); results.FiveYearPeakOverflow = results.FiveYearResults.PeakOverflow; results.FiveYearTotalOverflowVolume = results.FiveYearResults.OverflowVolume; results.FiveYearInflowVolume = results.FiveYearResults.InflowVolume; results.FiveYearPeakInflow = results.FiveYearResults.PeakInflowRate; results.TenYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographTenYear); results.TenYearPeakOverflow = results.TenYearResults.PeakOverflow; results.TenYearTotalOverflowVolume = results.TenYearResults.OverflowVolume; results.TenYearSurfaceCapacity = results.TenYearResults.PercentSurfaceCapacityUsed; results.TenYearPercentRockCapacity = results.TenYearResults.PercentRockCapacityUsed; results.TenYearInflowVolume = results.TenYearResults.InflowVolume; results.TenYearPeakInflow = results.TenYearResults.PeakInflowRate; results.TwentyfiveYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographTwentyfiveYear); results.TwentyfiveYearPeakOverflow = results.TwentyfiveYearResults.PeakOverflow; results.TwentyfiveYearTotalOverflowVolume = results.TwentyfiveYearResults.OverflowVolume; results.TwentyfiveYearInflowVolume = results.TwentyfiveYearResults.InflowVolume; results.TwentyfiveYearPeakInflow = results.TwentyfiveYearResults.PeakInflowRate; results.TenYearScore = PacScore.NotUsed; // Defaults results.FlowControlScore = PacScore.NotUsed; results.TwoYearFlowControlScore = PacScore.NotUsed; results.FiveYearFlowControlScore = PacScore.NotUsed; results.TenYearFlowControlScore = PacScore.NotUsed; results.TwentyfiveYearFlowControlScore = PacScore.NotUsed; switch (category) { case HierarchyCategory.Category1: case HierarchyCategory.Category2: results.TenYearScore = results.TenYearPeakOverflow > 0 ? PacScore.Fail : PacScore.Pass; break; case HierarchyCategory.Category3: //Define preliminary catchment runoff results results.PreDevelopedTwoYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twoYear)).PeakInflowRate; results.PreDevelopedFiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, fiveYear)).PeakInflowRate; results.PreDevelopedTenYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, tenYear)).PeakInflowRate; results.PreDevelopedTwentyfiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twentyFiveYear)).PeakInflowRate; switch (dischargePoint) { case DischargePoint.A: results.FlowControlScore = PacScore.NotUsed; break; case DischargePoint.B: if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow / 2) { results.TwoYearFlowControlScore = PacScore.Pass; } else { results.TwoYearFlowControlScore = PacScore.Fail; } if (results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow) { results.FiveYearFlowControlScore = PacScore.Pass; } else { results.FiveYearFlowControlScore = PacScore.Fail; } if (results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) { results.TenYearFlowControlScore = PacScore.Pass; } else { results.TenYearFlowControlScore = PacScore.Fail; } if (results.TwentyfiveYearPeakOverflow <= results.PreDevelopedTwentyfiveYearPeakInflow) { results.TwentyfiveYearFlowControlScore = PacScore.Pass; } else { results.TwentyfiveYearFlowControlScore = PacScore.Fail; } if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow / 2 && results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow && results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow && results.TwentyfiveYearPeakOverflow <= results.PreDevelopedTwentyfiveYearPeakInflow) { results.FlowControlScore = PacScore.Pass; } else { results.FlowControlScore = PacScore.Fail; } break; case DischargePoint.C: if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow) { results.TwoYearFlowControlScore = PacScore.Pass; } else { results.TwoYearFlowControlScore = PacScore.Fail; } if (results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow) { results.FiveYearFlowControlScore = PacScore.Pass; } else { results.FiveYearFlowControlScore = PacScore.Fail; } if (results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) { results.TenYearFlowControlScore = PacScore.Pass; } else { results.TenYearFlowControlScore = PacScore.Fail; } if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow && results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow && results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) { results.FlowControlScore = PacScore.Pass; } else { results.FlowControlScore = PacScore.Fail; } break; default: break; } break; case HierarchyCategory.Category4: //Define preliminary catchment runoff results results.PreDevelopedTwoYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twoYear)).PeakInflowRate; results.PreDevelopedFiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, fiveYear)).PeakInflowRate; results.PreDevelopedTenYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, tenYear)).PeakInflowRate; results.PreDevelopedTwentyfiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twentyFiveYear)).PeakInflowRate; if (results.TwentyfiveYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) { results.FlowControlScore = PacScore.Pass; results.TwentyfiveYearFlowControlScore = PacScore.Pass; } else { results.FlowControlScore = PacScore.Fail; results.TwentyfiveYearFlowControlScore = PacScore.Fail; } break; default: break; } results.PollutionReductionScore = results.PollutionReductionResults.PeakSurfaceOverflow > 0 ? PacScore.Fail : PacScore.Pass; return(results); }
/// <summary> /// Contains algorithims implementing the sizing calculations for various facility configurations /// </summary> /// <param name="facility"></param> /// <param name="category"></param> /// <param name="catchment"></param> /// <param name="inflowHydrograph"></param> /// <returns></returns> public static StormEventResults PerformCalculations(Facility facility, HierarchyCategory category, Catchment catchment, Hydrograph inflowHydrograph) { string message; Facility.Validate(facility, Convert.ToInt32(category), out message); if (!facility.IsValid) throw new ArgumentException("Unable to perform calculations: failed validation with message '" + message + "'"); double dt = inflowHydrograph.TimeStepMinutes; int timeSteps = inflowHydrograph.AsArray().Count(); double inflowFromRain; double inflowVolume; double inflowVolumeCummulative = 0; double[] surfaceInfiltrationCapacity = new double[timeSteps]; //Column E, aka Percolation Capacity double initialInfiltrationToAmendedSoil; double[] storedToBeInfiltrated = new double[timeSteps]; double graphLocator = 0; double potentialExtraInfiltration; double cumulativeInfiltrationVolume = 0; //Column J double additionalInfiltrationFromStorage; //Column K double[] totalInfiltrationCapacityToBelowGrade = new double[timeSteps]; //Column L double inflowToSurfaceStorageAfterInfiltration; //Column M double[] inflowMinusInfiltration = new double[timeSteps]; //Column N double surfaceStorageCumulativeVolume = 0; //Column O,P,Q,R combined. double[] flowOvertoppingToUnderdrain = new double[timeSteps]; //Column T (or Column W for type E) double[] infiltrationToBelowGrade = new double[timeSteps]; //Column Z double[] totalFlowToBelowGrade = new double[timeSteps]; //Column AA double[] inflowToRockStorage = new double[timeSteps]; //column AB double[] totalInfiltrationCapacityToNative = new double[timeSteps]; //Column AE double totalInfiltratedToNative = 0; double rockStorageCumulativeVolume = 0; //Column AJ double[] rockPercentCapacity = new double[timeSteps]; //Column AK/AL for A,B&E facilities; Column AR/AS for C&F; double excessRockCumulativeVolume = 0; //Column AM double underdrainStorageAreaCumulativeVolume = 0; //Column AR double[] aboveGradeStoragePercentCapacity = new double[timeSteps]; //Column AO for A,B facilities; Column S for C,D&F double[] aboveGradeSecondaryStoragePercentCapacity = new double[timeSteps]; //Column AO for E facilities double[] rockOverflowToEscapeRoute = new double[timeSteps]; //Column AP double[] overflowToEscapeRoute = new double[timeSteps]; //Column AQ for A,B,D,E,F facilities; Column AT for C&F double nativeInfiltrationRate = facility.NativeSoilInfiltrationCapacityCfs(); double growingMediumInfiltrationRate = facility.ImportedMediumInfiltrationCapacityCfs(); //The Lag Index is a property of the growing medium depth and infiltration rate that //corresponds to the number of time steps it will take for water to percolate through the //growing medium. The infiltration hydrograph to the rock medium is delayed by the lag index. //For facility configurations A, B, and E, no lag is applied when the native infiltration rate is less //than the growing medium infilration rate. double lagFactor = (facility.Configuration == FacilityConfiguration.A || facility.Configuration == FacilityConfiguration.B || facility.Configuration == FacilityConfiguration.E) && nativeInfiltrationRate < growingMediumInfiltrationRate ? 0 : facility.GrowingMediumPorespace; double lagTime = facility.GrowingMediumDepthIn / catchment.ImportedMediumInfiltrationInchesPerHour * 60 * lagFactor; int lag = (int)Math.Ceiling(lagTime / inflowHydrograph.TimeStepMinutes); // Rounding up is perfored in the current calculator. This may be unnecessary. for (int i = 0; i < timeSteps; i++) { inflowFromRain = inflowHydrograph.AsArray()[i]; inflowVolume = inflowFromRain * 600; inflowVolumeCummulative += inflowVolume; //Facility configurations A,B, and D have rock-influenced surface storage demand. When //the rock storage is full, infiltration rates in the growing medium can be limited by //infiltration rates of the native soil. if (facility.HasRockInfluencedSurfaceStorage && rockPercentCapacity[Math.Max(1, i - 1)] >= 1) surfaceInfiltrationCapacity[i] = Math.Min(growingMediumInfiltrationRate, nativeInfiltrationRate); else surfaceInfiltrationCapacity[i] = growingMediumInfiltrationRate; initialInfiltrationToAmendedSoil = Math.Min(inflowFromRain, surfaceInfiltrationCapacity[i]); storedToBeInfiltrated[i] = Math.Max(inflowFromRain - initialInfiltrationToAmendedSoil, 0) * 600; graphLocator = storedToBeInfiltrated[i] - storedToBeInfiltrated[Math.Max(1, i - 1)] < 0 ? 1 : graphLocator; potentialExtraInfiltration = (surfaceInfiltrationCapacity[i] - initialInfiltrationToAmendedSoil) * graphLocator; cumulativeInfiltrationVolume += (potentialExtraInfiltration * 600); // Existing spreadsheet rounds up storageToBeInfiltrated to nearest ten, // allowing more potentialExtraInfiltration to fill rock storage. This may be unnecessary... double storedToBeInfiltratedRoundedUp = Math.Ceiling(storedToBeInfiltrated.Sum()/10)*10; double cumulativeInfiltrationVolumeRounded = Math.Round(cumulativeInfiltrationVolume, 10); // Added 6/24/2015 to deal with binary storage of floating point numbers without changing to decimal data type additionalInfiltrationFromStorage = cumulativeInfiltrationVolumeRounded > storedToBeInfiltratedRoundedUp || cumulativeInfiltrationVolumeRounded > facility.SurfaceCapacityAtDepth1CuFt ? 0 : potentialExtraInfiltration; totalInfiltrationCapacityToBelowGrade[i] = initialInfiltrationToAmendedSoil + additionalInfiltrationFromStorage; inflowToSurfaceStorageAfterInfiltration = Math.Max(inflowFromRain - totalInfiltrationCapacityToBelowGrade[i], 0); inflowMinusInfiltration[i] = inflowFromRain - surfaceInfiltrationCapacity[i]; surfaceStorageCumulativeVolume += (inflowMinusInfiltration[i] * 600); surfaceStorageCumulativeVolume = Math.Max(surfaceStorageCumulativeVolume, 0); surfaceStorageCumulativeVolume = Math.Min(surfaceStorageCumulativeVolume, facility.SurfaceCapacityAtDepth1CuFt); flowOvertoppingToUnderdrain[i] = surfaceStorageCumulativeVolume < facility.SurfaceCapacityAtDepth1CuFt ? 0 : inflowToSurfaceStorageAfterInfiltration; if (i - lag < 0) infiltrationToBelowGrade[i] = totalInfiltrationCapacityToBelowGrade[0]; else infiltrationToBelowGrade[i] = totalInfiltrationCapacityToBelowGrade[i - lag]; totalFlowToBelowGrade[i] = infiltrationToBelowGrade[i] + flowOvertoppingToUnderdrain[i]; if (facility.Configuration == FacilityConfiguration.E || facility.Configuration == FacilityConfiguration.F) inflowToRockStorage[i] = totalFlowToBelowGrade[i]; else inflowToRockStorage[i] = infiltrationToBelowGrade[i]; totalInfiltrationCapacityToNative[i] = nativeInfiltrationRate; if (rockStorageCumulativeVolume + inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i] < 0) totalInfiltratedToNative += rockStorageCumulativeVolume + inflowToRockStorage[i]; else totalInfiltratedToNative += totalInfiltrationCapacityToNative[i]; rockStorageCumulativeVolume += ((inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]) * 600); excessRockCumulativeVolume = rockStorageCumulativeVolume < facility.RockStorageCapacityCuFt ? 0 : rockStorageCumulativeVolume - facility.RockStorageCapacityCuFt; rockStorageCumulativeVolume = Math.Max(rockStorageCumulativeVolume, 0); if (facility.HasRockInfluencedSurfaceStorage) { aboveGradeStoragePercentCapacity[i] = (surfaceStorageCumulativeVolume + excessRockCumulativeVolume) / facility.SurfaceCapacityAtDepth1CuFt; //E facilities have a secondary storage volume if (facility.HasSecondaryOverflow) { aboveGradeSecondaryStoragePercentCapacity[i] = (surfaceStorageCumulativeVolume + excessRockCumulativeVolume) / facility.SurfaceCapacityAtDepth2CuFt; aboveGradeSecondaryStoragePercentCapacity[i] = Math.Min(aboveGradeSecondaryStoragePercentCapacity[i], 1); } } //C, D, and F facilities have a direct connection from the rock gallery to an overflow, //and therefore above grade storage capacity is independent of rock gallery volume else { aboveGradeStoragePercentCapacity[i] = surfaceStorageCumulativeVolume / facility.SurfaceCapacityAtDepth1CuFt; } aboveGradeStoragePercentCapacity[i] = Math.Min(aboveGradeStoragePercentCapacity[i], 1); if (facility.HasRockInfluencedSurfaceStorage && !facility.HasSecondaryOverflow) // A, B { // Added 6/22/2015 to handle case where surface is full, but should overflow more due to limited rock gallery. // This will occur only once during a storm, as the next cycle will limit above grade infiltration to the rock gallery // and overflow the correct amount. double belowGradeInflowMinusInfiltration = inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]; if (aboveGradeStoragePercentCapacity[i] == 1 && belowGradeInflowMinusInfiltration > 0 ) rockOverflowToEscapeRoute[i] = belowGradeInflowMinusInfiltration; else rockOverflowToEscapeRoute[i] = 0; rockPercentCapacity[i] = facility.HasRockStorage ? rockStorageCumulativeVolume / facility.RockStorageCapacityCuFt : 1; rockPercentCapacity[i] = Math.Min(rockPercentCapacity[i], 1); } else if (facility.HasSecondaryOverflow) // E { rockOverflowToEscapeRoute[i] = aboveGradeSecondaryStoragePercentCapacity[i] < 1 ? 0 : Math.Max(totalFlowToBelowGrade[i] - facility.NativeSoilInfiltrationCapacityCfs(), 0); rockPercentCapacity[i] = facility.HasRockStorage ? rockStorageCumulativeVolume / facility.RockStorageCapacityCuFt : 1; rockPercentCapacity[i] = Math.Min(rockPercentCapacity[i], 1); } else if (!facility.HasRockInfluencedSurfaceStorage) // C, D & F { underdrainStorageAreaCumulativeVolume += ((inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]) * 600); underdrainStorageAreaCumulativeVolume = Math.Max(underdrainStorageAreaCumulativeVolume, 0); underdrainStorageAreaCumulativeVolume = Math.Min(underdrainStorageAreaCumulativeVolume, facility.RockStorageCapacityCuFt); if ((underdrainStorageAreaCumulativeVolume / facility.RockStorageCapacityCuFt >= 1) || facility.RockStorageCapacityCuFt == 0) // Added facility.RockStorageCapacityCuFt for 0/0 case rockOverflowToEscapeRoute[i] = inflowToRockStorage[i] - totalInfiltrationCapacityToNative[i]; rockPercentCapacity[i] = facility.HasRockStorage ? underdrainStorageAreaCumulativeVolume / facility.RockStorageCapacityCuFt : 1; rockPercentCapacity[i] = Math.Min(rockPercentCapacity[i], 1); } if (facility.Configuration == FacilityConfiguration.F // Facility F is different, in that overflow from the surface goes to the subsurface || facility.Configuration == FacilityConfiguration.E) // Facility E is strange also, in that the flow overtopping to the underdrain doesn't also go to the escape route. overflowToEscapeRoute[i] = excessRockCumulativeVolume > 0 ? rockOverflowToEscapeRoute[i] : 0; else overflowToEscapeRoute[i] = excessRockCumulativeVolume > 0 ? flowOvertoppingToUnderdrain[i] + rockOverflowToEscapeRoute[i] : flowOvertoppingToUnderdrain[i]; } StormEventResults results = new StormEventResults(); results.PeakSurfaceOverflow = flowOvertoppingToUnderdrain.Max(); results.PeakOverflow = overflowToEscapeRoute.Max(); results.OverflowVolume = overflowToEscapeRoute.Sum() * 600; results.PercentSurfaceCapacityUsed = aboveGradeStoragePercentCapacity.Max(); results.PercentRockCapacityUsed = rockPercentCapacity.Max(); results.InflowVolume = inflowHydrograph.AsArray().Sum() * 600; results.PeakInflowRate = inflowHydrograph.AsArray().Max(); results.AboveGradePrimaryResults.Add(new Hydrograph("Inflow from rain", "cfs", inflowHydrograph.AsArray(), dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", surfaceInfiltrationCapacity, dt)); switch (facility.Configuration) { case FacilityConfiguration.A: results.AboveGradePrimaryResults.Add(new Hydrograph("Infiltration to native soil", "cfs", infiltrationToBelowGrade, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", overflowToEscapeRoute, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.PercentRockCapacityUsed = -1; // There is no rock gallery. break; case FacilityConfiguration.B: results.AboveGradePrimaryResults.Add(new Hydrograph("Percolation to below grade storage", "cfs", infiltrationToBelowGrade, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", overflowToEscapeRoute, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", infiltrationToBelowGrade, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); break; case FacilityConfiguration.C: results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Flow bypassing growing medium", "cfs", flowOvertoppingToUnderdrain, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", inflowToRockStorage, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", rockOverflowToEscapeRoute, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); break; case FacilityConfiguration.D: results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Flow bypassing growing medium", "cfs", flowOvertoppingToUnderdrain, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); break; case FacilityConfiguration.E: results.AboveGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", rockOverflowToEscapeRoute, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeSecondaryStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", inflowToRockStorage, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); results.PercentSurfaceCapacityUsed = aboveGradeSecondaryStoragePercentCapacity.Max(); break; case FacilityConfiguration.F: results.AboveGradePrimaryResults.Add(new Hydrograph("Total flow to below grade storage", "cfs", inflowToRockStorage, dt)); results.AboveGradePrimaryResults.Add(new Hydrograph("Flow bypassing growing medium", "cfs", flowOvertoppingToUnderdrain, dt)); results.AboveGradeSecondaryResults.Add(new Hydrograph("Percent surface capacity", "%", aboveGradeStoragePercentCapacity, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Inflow to rock storage", "cfs", inflowToRockStorage, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Infiltration capacity", "cfs", totalInfiltrationCapacityToNative, dt)); results.BelowGradePrimaryResults.Add(new Hydrograph("Overflow to approved discharge", "cfs", rockOverflowToEscapeRoute, dt)); results.BelowGradeSecondaryResults.Add(new Hydrograph("Percent rock capacity", "%", rockPercentCapacity, dt)); break; } return results; }
/// <summary> /// Executes the calculator and returns a PacResults. /// </summary> /// <param name="catchment">A catchment object defining the hydrologic parameters of the post-developed catchment area to be evaluated.</param> /// <param name="preCatchment">A catchment object defining the hydrologic parameters of the pre-developed catchment area to be evaluated.</param> /// <param name="facility">A Facility object defining the stormwater management facility to be evaluated.</param> /// <param name="category">Identifies the HierarchyCategory the proposed facility will be evaluated against.</param> /// <param name="dischargePoint">Identifies the DischargePoint of the proposed facility.</param> /// <returns>A PacResults object containing the results of the calculation.</returns> internal static PacResults PerformCalculations(Catchment catchment, Catchment preCatchment, Facility facility, HierarchyCategory category, DischargePoint dischargePoint) { //Define design storms RainfallEvent pollutionReduction = RainfallEvent.GetScsOneAEvent("Pollution Reduction", 0.83); RainfallEvent twoYear = RainfallEvent.GetScsOneAEvent("Two-Year", 2.4); RainfallEvent fiveYear = RainfallEvent.GetScsOneAEvent("Five-Year", 2.9); RainfallEvent tenYear = RainfallEvent.GetScsOneAEvent("Ten-Year", 3.4); RainfallEvent twentyFiveYear = RainfallEvent.GetScsOneAEvent("Twentyfive-Year", 3.9); PacResults results = new PacResults(); //Calculate hydrographs for the most important design storms Hydrograph imperviousHydrographPR = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, pollutionReduction); Hydrograph imperviousHydrographTwoYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, twoYear); Hydrograph imperviousHydrographFiveYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, fiveYear); Hydrograph imperviousHydrographTenYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, tenYear); Hydrograph imperviousHydrographTwentyfiveYear = SantaBarbaraUrbanHydrograph.CalculateHydrograph (catchment, twentyFiveYear); results.PollutionReductionResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographPR); results.PollutionReductionPeakOverflow = results.PollutionReductionResults.PeakOverflow; results.PollutionReductionTotalOverflowVolume = results.PollutionReductionResults.OverflowVolume; results.PollutionReductionSurfaceCapacity = results.PollutionReductionResults.PercentSurfaceCapacityUsed; results.PollutionReductionPercentRockCapacity = results.PollutionReductionResults.PercentRockCapacityUsed; results.PollutionReductionInflowVolume = results.PollutionReductionResults.InflowVolume; results.PollutionReductionPeakInflow = results.PollutionReductionResults.PeakInflowRate; results.TwoYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographTwoYear); results.TwoYearPeakOverflow = results.TwoYearResults.PeakOverflow; results.TwoYearTotalOverflowVolume = results.TwoYearResults.OverflowVolume; results.TwoYearInflowVolume = results.TwoYearResults.InflowVolume; results.TwoYearPeakInflow = results.TwoYearResults.PeakInflowRate; results.FiveYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographFiveYear); results.FiveYearPeakOverflow = results.FiveYearResults.PeakOverflow; results.FiveYearTotalOverflowVolume = results.FiveYearResults.OverflowVolume; results.FiveYearInflowVolume = results.FiveYearResults.InflowVolume; results.FiveYearPeakInflow = results.FiveYearResults.PeakInflowRate; results.TenYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographTenYear); results.TenYearPeakOverflow = results.TenYearResults.PeakOverflow; results.TenYearTotalOverflowVolume = results.TenYearResults.OverflowVolume; results.TenYearSurfaceCapacity = results.TenYearResults.PercentSurfaceCapacityUsed; results.TenYearPercentRockCapacity = results.TenYearResults.PercentRockCapacityUsed; results.TenYearInflowVolume = results.TenYearResults.InflowVolume; results.TenYearPeakInflow = results.TenYearResults.PeakInflowRate; results.TwentyfiveYearResults = ReservoirRouter.PerformCalculations(facility, category, catchment, imperviousHydrographTwentyfiveYear); results.TwentyfiveYearPeakOverflow = results.TwentyfiveYearResults.PeakOverflow; results.TwentyfiveYearTotalOverflowVolume = results.TwentyfiveYearResults.OverflowVolume; results.TwentyfiveYearInflowVolume = results.TwentyfiveYearResults.InflowVolume; results.TwentyfiveYearPeakInflow = results.TwentyfiveYearResults.PeakInflowRate; results.TenYearScore = PacScore.NotUsed; // Defaults results.FlowControlScore = PacScore.NotUsed; results.TwoYearFlowControlScore = PacScore.NotUsed; results.FiveYearFlowControlScore = PacScore.NotUsed; results.TenYearFlowControlScore = PacScore.NotUsed; results.TwentyfiveYearFlowControlScore = PacScore.NotUsed; switch (category) { case HierarchyCategory.Category1: case HierarchyCategory.Category2: results.TenYearScore = results.TenYearPeakOverflow > 0 ? PacScore.Fail : PacScore.Pass; break; case HierarchyCategory.Category3: //Define preliminary catchment runoff results results.PreDevelopedTwoYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twoYear)).PeakInflowRate; results.PreDevelopedFiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, fiveYear)).PeakInflowRate; results.PreDevelopedTenYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, tenYear)).PeakInflowRate; results.PreDevelopedTwentyfiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twentyFiveYear)).PeakInflowRate; switch (dischargePoint) { case DischargePoint.A: results.FlowControlScore = PacScore.NotUsed; break; case DischargePoint.B: if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow / 2) results.TwoYearFlowControlScore = PacScore.Pass; else results.TwoYearFlowControlScore = PacScore.Fail; if (results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow) results.FiveYearFlowControlScore = PacScore.Pass; else results.FiveYearFlowControlScore = PacScore.Fail; if (results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) results.TenYearFlowControlScore = PacScore.Pass; else results.TenYearFlowControlScore = PacScore.Fail; if (results.TwentyfiveYearPeakOverflow <= results.PreDevelopedTwentyfiveYearPeakInflow) results.TwentyfiveYearFlowControlScore = PacScore.Pass; else results.TwentyfiveYearFlowControlScore = PacScore.Fail; if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow / 2 && results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow && results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow && results.TwentyfiveYearPeakOverflow <= results.PreDevelopedTwentyfiveYearPeakInflow) results.FlowControlScore = PacScore.Pass; else results.FlowControlScore = PacScore.Fail; break; case DischargePoint.C: if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow) results.TwoYearFlowControlScore = PacScore.Pass; else results.TwoYearFlowControlScore = PacScore.Fail; if (results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow) results.FiveYearFlowControlScore = PacScore.Pass; else results.FiveYearFlowControlScore = PacScore.Fail; if (results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) results.TenYearFlowControlScore = PacScore.Pass; else results.TenYearFlowControlScore = PacScore.Fail; if (results.TwoYearPeakOverflow <= results.PreDevelopedTwoYearPeakInflow && results.FiveYearPeakOverflow <= results.PreDevelopedFiveYearPeakInflow && results.TenYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) results.FlowControlScore = PacScore.Pass; else results.FlowControlScore = PacScore.Fail; break; default: break; } break; case HierarchyCategory.Category4: //Define preliminary catchment runoff results results.PreDevelopedTwoYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twoYear)).PeakInflowRate; results.PreDevelopedFiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, fiveYear)).PeakInflowRate; results.PreDevelopedTenYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, tenYear)).PeakInflowRate; results.PreDevelopedTwentyfiveYearPeakInflow = ReservoirRouter.PerformCalculations(facility, category, preCatchment, SantaBarbaraUrbanHydrograph.CalculateHydrograph(preCatchment, twentyFiveYear)).PeakInflowRate; if (results.TwentyfiveYearPeakOverflow <= results.PreDevelopedTenYearPeakInflow) { results.FlowControlScore = PacScore.Pass; results.TwentyfiveYearFlowControlScore = PacScore.Pass; } else { results.FlowControlScore = PacScore.Fail; results.TwentyfiveYearFlowControlScore = PacScore.Fail; } break; default: break; } results.PollutionReductionScore = results.PollutionReductionResults.PeakSurfaceOverflow > 0 ? PacScore.Fail : PacScore.Pass; return results; }