Example #1
0
        public static TreatmentFacility ToTreatmentFacility(this TreatmentBMP treatmentBMP, bool isBaselineCondition)
        {
            var    treatmentBMPNodeID   = NereidUtilities.TreatmentBMPNodeID(treatmentBMP);
            var    lspcBasinKey         = treatmentBMP.LSPCBasin?.LSPCBasinKey.ToString();
            var    isFullyParameterized = treatmentBMP.IsFullyParameterized();
            double?treatmentRate        = null;
            var    modelingAttribute    = treatmentBMP.TreatmentBMPModelingAttribute;

            // in the baseline condition, anything built after 2003 is treated as if it doesn't exist.
            if (!isFullyParameterized ||
                (isBaselineCondition && treatmentBMP.YearBuilt.HasValue && treatmentBMP.YearBuilt.Value > NereidUtilities.BASELINE_CUTOFF_YEAR))
            {
                return(new TreatmentFacility
                {
                    NodeID = treatmentBMPNodeID,
                    FacilityType = "NoTreatment",
                    ReferenceDataKey = lspcBasinKey,
                    DesignStormwaterDepth = treatmentBMP.PrecipitationZone?.DesignStormwaterDepthInInches ?? .8,
                    EliminateAllDryWeatherFlowOverride = modelingAttribute?.DryWeatherFlowOverrideID == DryWeatherFlowOverride.Yes.DryWeatherFlowOverrideID
                });
            }

            // treatment rate is an alias for four different fields, so we need to pick the one that's not null
            if (modelingAttribute.InfiltrationDischargeRate != null)
            {
                treatmentRate = modelingAttribute.InfiltrationDischargeRate;
            }
            else if (modelingAttribute.TreatmentRate != null)
            {
                treatmentRate = modelingAttribute.TreatmentRate;
            }
            else if (modelingAttribute.AverageDivertedFlowrate != null)
            {
                // AverageDivertedFlowrate is collected in gallons per day instead of CFS, but we need to send CFS to Nereid.
                treatmentRate = modelingAttribute.AverageDivertedFlowrate * NereidUtilities.GPD_TO_CFS;
            }
            else if (modelingAttribute.AverageTreatmentFlowrate != null)
            {
                treatmentRate = modelingAttribute.AverageTreatmentFlowrate;
            }

            double?area = null;

            // area_sqft is an alias for four different fields, so we need to take the one that's not null
            if (modelingAttribute.EffectiveFootprint != null)
            {
                area = modelingAttribute.EffectiveFootprint;
            }
            else if (modelingAttribute.InfiltrationSurfaceArea != null)
            {
                area = modelingAttribute.InfiltrationSurfaceArea;
            }
            else if (modelingAttribute.MediaBedFootprint != null)
            {
                area = modelingAttribute.MediaBedFootprint;
            }
            else if (modelingAttribute.WettedFootprint != null)
            {
                area = modelingAttribute.WettedFootprint;
            }

            double?designCapacity = null;

            if (modelingAttribute.DesignDryWeatherTreatmentCapacity != null)
            {
                designCapacity = modelingAttribute.DesignDryWeatherTreatmentCapacity;
            }
            else if (modelingAttribute.DesignLowFlowDiversionCapacity != null)
            {
                // DesignLowFlowDiversionCapacity is collected in GPD, so convert to CFS
                designCapacity = modelingAttribute.DesignLowFlowDiversionCapacity * NereidUtilities.GPD_TO_CFS;
            }

            if (designCapacity == null)
            {
                designCapacity = treatmentRate;
            }
            else if (treatmentRate == null)
            {
                treatmentRate = designCapacity;
            }

            // null-coalescence here represents default values.
            // It's generally an anti-pattern for an API to require its clients to insert default values,
            // since the API should be written to replace nulls/absent values with defaults,
            // but it's so few that it's not worth a revision to the modeling engine at this time (4/16/2020)
            var treatmentFacility = new TreatmentFacility
            {
                NodeID                    = treatmentBMPNodeID,
                FacilityType              = treatmentBMP.TreatmentBMPType.TreatmentBMPModelingType.TreatmentBMPModelingTypeName,
                ReferenceDataKey          = lspcBasinKey,
                DesignStormwaterDepth     = treatmentBMP.PrecipitationZone.DesignStormwaterDepthInInches,
                DesignCapacity            = designCapacity,
                DesignMediaFiltrationRate = modelingAttribute.DesignMediaFiltrationRate,
                //convert Days to Hours for this field.
                DesignResidenceTimeforPermanentPool = modelingAttribute.DesignResidenceTimeforPermanentPool * 24 ?? double.PositiveInfinity,
                DiversionRate = modelingAttribute.DiversionRate,
                DrawdownTimeforWQDetentionVolume = modelingAttribute.DrawdownTimeforWQDetentionVolume,
                Area = area,
                EffectiveRetentionDepth                 = modelingAttribute.EffectiveRetentionDepth,
                MonthsOfOperation                       = modelingAttribute.MonthsOfOperation?.MonthsOfOperationNereidAlias ?? MonthsOfOperation.Both.MonthsOfOperationNereidAlias,
                PermanentPoolorWetlandVolume            = modelingAttribute.PermanentPoolorWetlandVolume,
                RoutingConfiguration                    = modelingAttribute.RoutingConfigurationID == RoutingConfiguration.Online.RoutingConfigurationID,
                StorageVolumeBelowLowestOutletElevation = modelingAttribute.StorageVolumeBelowLowestOutletElevation,
                // SummerHarvestedWaterDemand is collected in GPD, so convert to CFS
                SummerHarvestedWaterDemand = modelingAttribute.SummerHarvestedWaterDemand * NereidUtilities.GPD_TO_CFS,
                TimeOfConcentration        = modelingAttribute.TimeOfConcentration?.TimeOfConcentrationDisplayName ?? TimeOfConcentration.FiveMinutes.TimeOfConcentrationDisplayName,
                TotalDrawdownTime          = modelingAttribute.DrawdownTimeforWQDetentionVolume,
                TotalEffectiveBMPVolume    = modelingAttribute.TotalEffectiveBMPVolume,
                TreatmentRate = treatmentRate,
                UnderlyingHydrologicSoilGroup = modelingAttribute.UnderlyingHydrologicSoilGroup?.UnderlyingHydrologicSoilGroupDisplayName.ToLower() ?? UnderlyingHydrologicSoilGroup.D.UnderlyingHydrologicSoilGroupDisplayName.ToLower(),
                UnderlyingInfiltrationRate    = modelingAttribute.UnderlyingInfiltrationRate,
                UpstreamBMP = modelingAttribute.UpstreamTreatmentBMPID.HasValue ? NereidUtilities.TreatmentBMPNodeID(modelingAttribute.UpstreamTreatmentBMPID.Value) : null,
                WaterQualityDetentionVolume = modelingAttribute.WaterQualityDetentionVolume,
                // WinterHarvestedWaterDemand is collected in GPD, so convert to CFS
                WinterHarvestedWaterDemand         = modelingAttribute.WinterHarvestedWaterDemand * NereidUtilities.GPD_TO_CFS,
                EliminateAllDryWeatherFlowOverride = modelingAttribute.DryWeatherFlowOverrideID == DryWeatherFlowOverride.Yes.DryWeatherFlowOverrideID
            };

            return(treatmentFacility);
        }