Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

requirements for stage-damage removed #1181

Merged
merged 4 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions HEC.FDA.Model/compute/ImpactAreaScenarioSimulation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ internal ImpactAreaScenarioSimulation(int impactAreaID)
/// <summary>
/// This code path currently only used by tests.
/// </summary>
public ImpactAreaScenarioResults Compute(ConvergenceCriteria convergenceCriteria, bool computeIsDeterministic =false)
public ImpactAreaScenarioResults Compute(ConvergenceCriteria convergenceCriteria, bool computeIsDeterministic = false)
{
return Compute(convergenceCriteria, new CancellationToken(), computeIsDeterministic);
}
Expand All @@ -103,15 +103,35 @@ public ImpactAreaScenarioResults Compute(ConvergenceCriteria convergenceCriteria
return _ImpactAreaScenarioResults;
}


PopulateRandomNumbers(convergenceCriteria);
bool computeWithDamage = true;

if (_StageDamageFunctions.Count == 0)
{
computeWithDamage = false;
Threshold systemResponseThreshold = new(thresholdID: 0, _SystemResponseFunction, convergenceCriteria);
_ImpactAreaScenarioResults.PerformanceByThresholds.AddThreshold(systemResponseThreshold);

//need to at least specify a levee to evaluate performance
//TODO, we could lessen this restriction to at least need a user entered threshold
if (_SystemResponseFunction.IsNull)
{
_ImpactAreaScenarioResults = new ImpactAreaScenarioResults(_ImpactAreaID, true); //I would like to just return regular Null here but I'm unsure who is relying on this behavior. BBB
return _ImpactAreaScenarioResults;
}
else
{
ThresholdEnum thresholdEnum;
if (_SystemResponseFunction.Xvals.Length <= 2)
{
thresholdEnum = ThresholdEnum.TopOfLevee;
}
else
{
thresholdEnum = ThresholdEnum.LeveeSystemResponse;
}
Threshold systemResponseThreshold = new(thresholdID: 0, _SystemResponseFunction, convergenceCriteria, thresholdEnum, _TopOfLeveeElevation);
_ImpactAreaScenarioResults.PerformanceByThresholds.AddThreshold(systemResponseThreshold);
}
}
else
{
Expand Down Expand Up @@ -142,7 +162,7 @@ private void PopulateRandomNumbers(ConvergenceCriteria convergenceCriteria)
{
//generate slightly more random numbers than max iterations because it is possible that we keep iterating beyond max
//before re-checking for convergence
int quantityOfRandomNumbers = Convert.ToInt32(convergenceCriteria.MaxIterations*1.25);
int quantityOfRandomNumbers = Convert.ToInt32(convergenceCriteria.MaxIterations * 1.25);

if (_FrequencyDischarge != null)
{
Expand Down Expand Up @@ -315,7 +335,7 @@ private void ComputeIterations(ConvergenceCriteria convergenceCriteria, bool com
PairedData frequencyDischarge;
if (_FrequencyDischargeGraphical.CurveMetaData.IsNull)
{
frequencyDischarge = _FrequencyDischarge.BootstrapToPairedData(thisComputeIteration, utilities.DoubleGlobalStatics.RequiredExceedanceProbabilities, computeIsDeterministic);
frequencyDischarge = _FrequencyDischarge.BootstrapToPairedData(thisComputeIteration, utilities.DoubleGlobalStatics.RequiredExceedanceProbabilities, computeIsDeterministic);
}
else
{
Expand All @@ -331,7 +351,7 @@ private void ComputeIterations(ConvergenceCriteria convergenceCriteria, bool com
}
else
{
PairedData inflow_outflow_sample = _UnregulatedRegulated.SamplePairedData(thisComputeIteration, computeIsDeterministic);
PairedData inflow_outflow_sample = _UnregulatedRegulated.SamplePairedData(thisComputeIteration, computeIsDeterministic);
PairedData transformff = inflow_outflow_sample.compose(frequencyDischarge);
PairedData discharge_stage_sample = _DischargeStage.SamplePairedData(thisComputeIteration, computeIsDeterministic);
PairedData frequency_stage = discharge_stage_sample.compose(transformff);
Expand Down Expand Up @@ -409,7 +429,7 @@ private void ComputeFromStageFrequency(PairedData frequency_stage, long thisComp
}
else
{
PairedData systemResponse_sample = _SystemResponseFunction.SamplePairedData(thisComputeIteration, computeIsDeterministic);
PairedData systemResponse_sample = _SystemResponseFunction.SamplePairedData(thisComputeIteration, computeIsDeterministic);
if (computeWithDamage)
{
ComputeDamagesFromStageFrequency_WithLevee(frequency_stage, systemResponse_sample, thisComputeIteration, thisChunkIteration, computeIsDeterministic);
Expand All @@ -430,7 +450,7 @@ private void ComputeFromStageFrequency(PairedData frequency_stage, long thisComp
}
else
{
PairedData _channelstage_floodplainstage_sample = _ChannelStageFloodplainStage.SamplePairedData(thisComputeIteration, computeIsDeterministic);
PairedData _channelstage_floodplainstage_sample = _ChannelStageFloodplainStage.SamplePairedData(thisComputeIteration, computeIsDeterministic);
PairedData frequency_floodplainstage = _channelstage_floodplainstage_sample.compose(frequency_stage);
//levees
if (_SystemResponseFunction.CurveMetaData.IsNull)
Expand All @@ -443,7 +463,7 @@ private void ComputeFromStageFrequency(PairedData frequency_stage, long thisComp
}
else
{
PairedData systemResponse_sample = _SystemResponseFunction.SamplePairedData(thisComputeIteration, computeIsDeterministic);
PairedData systemResponse_sample = _SystemResponseFunction.SamplePairedData(thisComputeIteration, computeIsDeterministic);
if (computeWithDamage)
{
ComputeDamagesFromStageFrequency_WithLeveeAndInteriorExterior(_channelstage_floodplainstage_sample, frequency_stage, systemResponse_sample, thisComputeIteration, thisChunkIteration, computeIsDeterministic);
Expand Down Expand Up @@ -474,7 +494,7 @@ private void ComputeDamagesFromStageFrequency(PairedData frequency_stage, long t
_ImpactAreaScenarioResults.ConsequenceResults.AddConsequenceRealization(eadEstimate, stageUncertainDamage.CurveMetaData.DamageCategory, stageUncertainDamage.CurveMetaData.AssetCategory, _ImpactAreaID, thisChunkIteration);
}
}
private void ComputeDamagesFromStageFrequency_WithLevee(PairedData frequency_stage, PairedData systemResponse, long thisComputeIteration, long thisChunkIteration, bool computeIsDeterministic)
private void ComputeDamagesFromStageFrequency_WithLevee(PairedData frequency_stage, PairedData systemResponse, long thisComputeIteration, long thisChunkIteration, bool computeIsDeterministic)
{
foreach (UncertainPairedData stageUncertainDamage in _StageDamageFunctions)
{
Expand Down
11 changes: 7 additions & 4 deletions HEC.FDA.Model/metrics/ImpactAreaScenarioResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,16 @@ public void ParallelResultsAreConverged(double upperConfidenceLimitProb, double
public PairedData GetDamageFrequency(string damageCategory, string assetCategory)
{
PairedData returnValue = new(new double[] {0, 1},new double[] {0, 1});
foreach ((CurveMetaData, PairedData) pairedData in DamageFrequencyFunctions)
if (DamageFrequencyFunctions != null)
{
if (pairedData.Item1.DamageCategory == damageCategory)
foreach ((CurveMetaData, PairedData) pairedData in DamageFrequencyFunctions)
{
if (pairedData.Item1.AssetCategory == assetCategory)
if (pairedData.Item1.DamageCategory == damageCategory)
{
returnValue = pairedData.Item2 as PairedData;
if (pairedData.Item1.AssetCategory == assetCategory)
{
returnValue = pairedData.Item2 as PairedData;
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion HEC.FDA.View/ImpactAreaScenario/Editor/IASEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<TextBlock Grid.Column="1" Text="{Binding StageDamageText}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,15,0"/>


<Label Grid.Column="1" Content="*" Foreground="Red" HorizontalAlignment="Right" VerticalAlignment="Center" />
<Label Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" />
<ComboBox Grid.Column="2" Height="26" HorizontalAlignment="Stretch" ItemsSource="{Binding StageDamageElements}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedStageDamageElement}" Margin="0,0,10,0" />

<TextBlock Grid.Column="3" Visibility="{Binding HasNonFailureStageDamage,Converter={StaticResource BoolToVisibilityConverter}}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,15,0">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ public static void CheckForOverlappingRanges(ChildElementComboItem SelectedFrequ
//check outflows with rating flows
CheckRangeValues(SelectedRatingCurveElement, SelectedInflowOutflowElement, true, false, RATING, FLOW, messageRows);
//check rating stages with stage-damage stages
CheckRangeWithStageDamage(StageDamageElement, SelectedRatingCurveElement, SelectedDamageCurve, messageRows);
if (SelectedDamageCurve != null)
{
CheckRangeWithStageDamage(StageDamageElement, SelectedRatingCurveElement, SelectedDamageCurve, messageRows);
}
}
}
else if(ratingSelected)
Expand All @@ -55,7 +58,10 @@ public static void CheckForOverlappingRanges(ChildElementComboItem SelectedFrequ
CheckRangeValues(SelectedRatingCurveElement, SelectedFrequencyElement, true, false, RATING, FLOW, messageRows);

//check rating stages with stage-damage stages
CheckRangeWithStageDamage(StageDamageElement, SelectedRatingCurveElement, SelectedDamageCurve, messageRows);
if (SelectedDamageCurve != null)
{
CheckRangeWithStageDamage(StageDamageElement, SelectedRatingCurveElement, SelectedDamageCurve, messageRows);
}
}
}

Expand Down
41 changes: 3 additions & 38 deletions HEC.FDA.ViewModel/ImpactAreaScenario/Editor/SpecificIASEditorVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -492,27 +492,6 @@ private FdaValidationResult GetRatingCurveValidationResult()
}
return vr;
}
private FdaValidationResult GetStageDamageValidationResult()
{
ChildElementComboItem selectedStageDamage = _SelectedStageDamage();
FdaValidationResult vr = new();
if (selectedStageDamage == null || selectedStageDamage.ChildElement == null)
{
vr.AddErrorMessage("A Stage Damage is required. ");
}
else
{
List<StageDamageCurve> stageDamageCurves = GetStageDamageCurves();
if (stageDamageCurves.Count == 0)
{
//todo: maybe get the impact area name for this message?
//todo: this name exists in multiple places. look into it.
vr.AddErrorMessage("The aggregated stage damage element '" + _SelectedStageDamage().ChildElement.Name + "' did not contain any curves that are associated " +
"with the impact area.");
}
}
return vr;
}

#endregion

Expand All @@ -530,25 +509,12 @@ public void UpdateSufficientToCompute()
}
}

private FdaValidationResult GetNonFailureValidationResult()
{
FdaValidationResult vr = new();
if (HasNonFailureStageDamage && (NonFailureSelectedStageDamage == null || NonFailureSelectedStageDamage.ChildElement == null))
{
//then a selection is required
vr.AddErrorMessage("A non failure stage-damage curve is required.");
}
return vr;
}

public FdaValidationResult GetValidationResults()
{
FdaValidationResult vr = new();

vr.AddErrorMessage(GetFrequencyRelationshipValidationResult().ErrorMessage);
vr.AddErrorMessage(GetRatingCurveValidationResult().ErrorMessage);
vr.AddErrorMessage(GetStageDamageValidationResult().ErrorMessage);
vr.AddErrorMessage(GetNonFailureValidationResult().ErrorMessage);

if (!vr.IsValid)
{
Expand Down Expand Up @@ -580,9 +546,8 @@ private void PreviewCompute()
sc.WithAdditionalThreshold(threshold);
}

FdaValidationResult configurationValidationResult = sc.IsConfigurationValid();
if (configurationValidationResult.IsValid)
{
//might need to be able to handle no stage damage here elegantly

ImpactAreaScenarioSimulation simulation = sc.BuildSimulation();
ImpactAreaScenarioResults result = simulation.PreviewCompute();
if (result == null)
Expand All @@ -594,7 +559,7 @@ private void PreviewCompute()
EAD = result.ConsequenceResults.MeanDamage(_selectedDamageCategory, _selectedAssetCategory, CurrentImpactArea.ID);
_DamageFrequencyCurve = result.GetDamageFrequency(_selectedDamageCategory, _selectedAssetCategory);
}
}


}

Expand Down
10 changes: 7 additions & 3 deletions HEC.FDA.ViewModel/ImpactAreaScenario/Results/PerformanceAEPVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ private void LoadData(ScenarioResults iasResult, int impactAreaID, List<Threshol
Threshold threshold = thresholdComboItems[i].Metric;
ThresholdEnum thresholdType = threshold.ThresholdType;
int thresholdID = threshold.ThresholdID;
Mean = iasResult.MeanAEP(impactAreaID, thresholdID);
Median = iasResult.MedianAEP(impactAreaID, thresholdID);
NinetyPercentAssurance = iasResult.AEPWithGivenAssurance(impactAreaID, assurance:0.9, thresholdID);
double mean = iasResult.MeanAEP(impactAreaID, thresholdID);
double median = iasResult.MedianAEP(impactAreaID, thresholdID);
double ninetyPercentAssurance = iasResult.AEPWithGivenAssurance(impactAreaID, assurance:0.9, thresholdID);
List<IPerformanceRowItem> rows = new List<IPerformanceRowItem>();
//get the table values
List<double> xVals = new List<double>() { .1, .04, .02, .01, .004, .002 };
Expand All @@ -41,12 +41,16 @@ private void LoadData(ScenarioResults iasResult, int impactAreaID, List<Threshol
}

MetricsToRows.Add(threshold, rows);
ThresholdToMetrics.Add(threshold, (mean, median, ninetyPercentAssurance));
LoadHistogramData(iasResult, impactAreaID, threshold);
}

if(MetricsToRows.Count>0)
{
Rows = MetricsToRows.First().Value;
Mean = ThresholdToMetrics.First().Value.Item1;
Median = ThresholdToMetrics.First().Value.Item2;
NinetyPercentAssurance = ThresholdToMetrics.First().Value.Item3;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

namespace HEC.FDA.ViewModel.ImpactAreaScenario.Results
{
/// <summary>
/// I very much dislike the design of this class. Some of the inhereting vms use the mean, median, ninety, and some don't. I'm not stoked about the threshhold dictionaries either. I'd like to take the time to rethink and refactor this someday if remain in this UI for
/// and extended period. TODO.
/// </summary>
public abstract class PerformanceVMBase : BaseViewModel
{
private List<IPerformanceRowItem> _rows;
Expand All @@ -28,6 +32,7 @@ public double NinetyPercentAssurance
set { _NinetyPctAssurance = value; NotifyPropertyChanged(); }
}
public Dictionary<Threshold, List<IPerformanceRowItem>> MetricsToRows { get;} = new Dictionary<Threshold, List<IPerformanceRowItem>>();
public Dictionary<Threshold, (double, double, double)> ThresholdToMetrics { get; } = [];
public List<IPerformanceRowItem> Rows
{
get { return _rows; }
Expand All @@ -40,14 +45,20 @@ public virtual void UpdateHistogram(ThresholdComboItem metric)
//Is there a reason that this is empty?
}

public void updateSelectedMetric(ThresholdComboItem metric)
public void UpdateSelectedMetric(ThresholdComboItem metric)
{
if (metric != null)
{
if (MetricsToRows.ContainsKey(metric.Metric))
{
Rows = MetricsToRows[metric.Metric];
}
if(ThresholdToMetrics.ContainsKey(metric.Metric))
{
Mean = ThresholdToMetrics[metric.Metric].Item1;
Median = ThresholdToMetrics[metric.Metric].Item2;
NinetyPercentAssurance = ThresholdToMetrics[metric.Metric].Item3;
}
UpdateHistogram(metric);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,18 @@ private void loadVMs(List<string> damCats, ScenarioResults scenarioResults, int
_damageWithUncertaintyVM = new DamageWithUncertaintyVM(scenarioResults,impactAreaID);
_damageByDamageCategoryVM = new DamageByDamCatVM(_IASResult, damCats, discountRate, period);
_performanceAEPVM = new PerformanceAEPVM(scenarioResults, impactAreaID, Thresholds);
_performanceAEPVM.updateSelectedMetric(SelectedThreshold);
_performanceAEPVM.UpdateSelectedMetric(SelectedThreshold);
_performanceAssuranceOfThresholdVM = new PerformanceAssuranceOfThresholdVM(_IASResult, Thresholds);
_performanceAssuranceOfThresholdVM.updateSelectedMetric(SelectedThreshold);
_performanceAssuranceOfThresholdVM.UpdateSelectedMetric(SelectedThreshold);
_performanceLongTermRiskVM = new PerformanceLongTermRiskVM(_IASResult, Thresholds);
_performanceLongTermRiskVM.updateSelectedMetric(SelectedThreshold);
_performanceLongTermRiskVM.UpdateSelectedMetric(SelectedThreshold);
}

private void ThresholdChanged()
{
if (_currentResultVM is PerformanceVMBase currentResult)
{
currentResult.updateSelectedMetric(SelectedThreshold);
currentResult.UpdateSelectedMetric(SelectedThreshold);
}
}

Expand Down
7 changes: 1 addition & 6 deletions HEC.FDA.ViewModel/ImpactAreaScenario/SpecificIAS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,7 @@ private FdaValidationResult DoesScenarioChildElementsStillExist()
{
vr.AddErrorMessage(CreateElementDoesntExistMessage("frequency element"));
}
if (stageDamageElem == null)
{
vr.AddErrorMessage(CreateElementDoesntExistMessage("stage damage element"));
}



return vr;
}

Expand Down
Loading