//-----------------------------------------------------------------------
//
// Copyright (c) 2009 Deltares. All rights reserved.
//
// B.S.T.I.M. The
// tom.the@deltares.nl
// 16-12-2009
// Perform single calculation which is specified in DamFailureMechanismeCalculationSpecification
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using Deltares.FlowSlide.Data;
using Deltares.Geometry;
using Deltares.Geotechnics;
using Deltares.Geotechnics.Soils;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Mathematics;
using Deltares.Piping.Data;
using Deltares.Probabilistic;
using Deltares.Standard;
using Deltares.Standard.IO.Xml;
using Deltares.Standard.Language;
using Deltares.Standard.Logging;
using Deltares.Standard.Validation;
namespace Deltares.Dam.Data
{
public class MaximumRedesignIterationsReachedException : Exception
{
public MaximumRedesignIterationsReachedException() : base("Maximum number of iterations in redesign reached.")
{
}
}
///
///
///
public class DamFailureMechanismeCalculator
{
private const int PipingRedesingMaxIterations = 400;
private const double defaultMaxFractionOfDikeHeightForShoulderHeight = 0.67;
private const double CMinimumShoulderElevation = 0.5;
private const double CMinimumShoulderExtraElevation = 0.05;
private const double CMinimumShoulderWidth = 2;
private const double CMinimumShoulderExtraWidth = 1;
private const double CToleranceShoulderChanges = 0.001;
private readonly DamFailureMechanismeCalculationSpecification damFailureMechanismeCalculationSpecification;
private readonly string mstabProgramPath;
private readonly ProgramType programType;
private readonly string slopeWProgramPath;
private AnalysisType analysisType;
private List errorMessages = new List();
private int progressSofar;
public DamFailureMechanismeCalculator(ProgramType programType, DamFailureMechanismeCalculationSpecification damFailureMechanismeCalculationSpecification,
string mstabProgramPath, string slopeWProgramPath, string mapForSoilGeometries2D, ProbabilisticType probabilisticType)
{
this.programType = programType;
this.damFailureMechanismeCalculationSpecification = damFailureMechanismeCalculationSpecification;
this.mstabProgramPath = mstabProgramPath;
this.slopeWProgramPath = slopeWProgramPath;
MapForSoilGeometries2D = mapForSoilGeometries2D;
ProbabilisticType = probabilisticType;
}
public string CalculationBaseDirectory { get; set; }
public string MapForSoilGeometries2D { get; set; }
public ProbabilisticType ProbabilisticType { get; set; }
public NonWaterRetainingObject NonWaterRetainingObject { get; set; }
public List ErrorMessages
{
get
{
return errorMessages;
}
set
{
errorMessages = value;
}
}
///
/// Main calculation call
///
///
///
public void Calculate(AnalysisType analysisTypeGiven, Scenario scenario)
{
Debug.WriteLine("Location '{0}', scenario '{1}' DamFailureMechanismeCalculator.Calculation", scenario.Location.Name, scenario.LocationScenarioID);
analysisType = analysisTypeGiven;
switch (analysisType)
{
case AnalysisType.NoAdaption:
CalculateForScenario(scenario);
break;
case AnalysisType.AdaptGeometry:
RedesignSurfaceLinesForAllScenarios(scenario);
break;
case AnalysisType.AdaptNWO:
ImplementNWOInSurfaceLinesForAllScenarios(scenario);
break;
}
}
///
/// Selects the probabilities for specific failure mechanism.
///
/// Type of the failure mechanism system.
/// The soil profile probabilities.
///
public static List SelectProbabilitiesForFailureMechanism(FailureMechanismSystemType failureMechanismSystemType, IList soilProfileProbabilities)
{
switch (failureMechanismSystemType)
{
case FailureMechanismSystemType.StabilityInside:
case FailureMechanismSystemType.StabilityOutside:
case FailureMechanismSystemType.HorizontalBalance:
return SelectStabilityProbabilities(soilProfileProbabilities);
case FailureMechanismSystemType.Piping:
return SelectPipingProbabilities(soilProfileProbabilities);
case FailureMechanismSystemType.FlowSlide:
return SelectFlowSlideProbabilities(soilProfileProbabilities);
}
return null;
}
///
/// Redesigns the height of the surface line.
///
/// Type of the failure mechanism system.
/// The scenario.
/// The surface line.
///
public static SurfaceLine2 RedesignSurfaceLineHeight(FailureMechanismSystemType failureMechanismSystemType, Scenario scenario, SurfaceLine2 surfaceLine)
{
double? dikeHeight = surfaceLine.GetDikeHeight();
if (dikeHeight.HasValue)
{
if (scenario.DikeTableHeight > dikeHeight.Value)
{
var surfaceLineHeightAdapter = new SurfaceLineHeightAdapter(surfaceLine, scenario.Location);
SurfaceLine2 adaptedSurfaceLine = surfaceLineHeightAdapter.ConstructNewSurfaceLine(scenario.DikeTableHeight ?? surfaceLine.GetDefaultDikeTableHeight() ?? 0);
if (adaptedSurfaceLine != null)
{
var validationError = adaptedSurfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error);
if (validationError != null)
{
adaptedSurfaceLine.Dispose();
throw new SurfaceLineException(validationError.Text);
}
surfaceLine = adaptedSurfaceLine;
foreach (var soilProfileProbability in scenario.Location.Segment.SoilProfileProbabilities)
{
if (soilProfileProbability.SegmentFailureMechanismType == failureMechanismSystemType || soilProfileProbability.SegmentFailureMechanismType == null)
{
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, surfaceLine);
}
}
}
}
}
return surfaceLine;
}
///
/// Cleanup directory where the piping project files are created
///
public static void ClearPipingCalculationBaseDirectory()
{
string pipingBaseDirectory = GetPipingCalculationBaseDirectory();
if (Directory.Exists(pipingBaseDirectory))
{
Directory.Delete(pipingBaseDirectory, true);
}
}
private void CalculateForScenario(Scenario scenario)
{
switch (damFailureMechanismeCalculationSpecification.FailureMechanismSystemType)
{
case FailureMechanismSystemType.StabilityInside:
case FailureMechanismSystemType.StabilityOutside:
CalculateStabilityForScenario(scenario, 0);
break;
case FailureMechanismSystemType.Piping:
CalculatePipingForScenario(scenario);
break;
case FailureMechanismSystemType.FlowSlide:
CalculateFlowSlideForScenario(scenario);
break;
}
}
///
/// Checks the and adapt betas water levels when needed.
///
/// The betas.
/// The water levels.
/// The scenario.
/// The new surface line.
/// The piping calculator.
/// The soil profile probability.
///
private bool CheckAndAdaptBetasWaterLevelsWhenNeeded(double[] betas, double[] waterLevels, Scenario scenario, SurfaceLine2 newSurfaceLine, PipingCalculator pipingCalculator, SoilGeometryProbability soilProfileProbability)
{
int nrValidItems = 0;
for (int i = 0; i < 3; i++)
{
// If beta >= 10, then in fact no uplift occured and probability of failure is in fact 0. Such a value would be invalid for the design point calculation.
if (betas[i] < 10)
{
nrValidItems++;
}
}
if ((nrValidItems == 0) || (nrValidItems == 3))
{
return (nrValidItems == 3);
}
else
{
if (nrValidItems == 1)
{
// extra calculation(s) needed to determine a second valid beta (<10) to be able to perform a design point calculation. Search between toplevel
// (beta[0]) and middle level a waterlevel at which a beta is valid and use that one (adapt the levels too of course).
double? betaloc = null;
bool lReady = false;
double locLevel = (waterLevels[0] + waterLevels[1])*0.5;
var waterLevelProbabilistic = new ProbabilisticStruct(0.0, 0.01, (int) DistributionType.LogNormal, false);
waterLevelProbabilistic.Distribution = (int) DistributionType.LogNormal;
waterLevelProbabilistic.StandardDeviation = 0.01;
waterLevelProbabilistic.IsUsed = false;
while (!lReady)
{
waterLevelProbabilistic.Mean = locLevel;
betaloc = CalculatePipingReliabilityIndexForSurface(scenario, newSurfaceLine, pipingCalculator, soilProfileProbability,
waterLevelProbabilistic);
lReady = betaloc.Value < 10;
if (lReady)
{
betas[1] = betaloc.Value;
waterLevels[1] = locLevel;
}
else
{
locLevel = locLevel + (waterLevels[0] + locLevel)*0.5;
lReady = Math.Abs(locLevel - waterLevels[0]) < 0.0001;
}
}
// now set nrValidItems to 2 to get the required third valid beta by axtrapolation
nrValidItems = 2;
}
if (nrValidItems == 2)
{
// use the 2 valid betas to extrapolate a valid third beta value.
betas[2] = Routines2D.LinInpolY(waterLevels[0], betas[0], waterLevels[1], betas[1], waterLevels[2]);
}
return true;
}
}
private double? CalculatePipingFailureProbabilityAdvanced(PipingCalculator pipingCalculator, Scenario scenario,
SoilGeometryProbability soilProfileProbability, SurfaceLine2 newSurfaceLine)
{
double[] waterLevels = scenario.DetermineProperWaterlevelsForProbabilisticAdvanced();
var betas = new double[3];
var waterLevelProbabilistic = new ProbabilisticStruct(0.0, 0.01, (int) DistributionType.LogNormal, false);
for (int i = 0; i < 3; i++)
{
betas[i] = 1;
waterLevelProbabilistic.Mean = waterLevels[i];
string calculationName = String.Format("Prob{0}_Loc({1})_Sce({2})_Pro({3})_wl({4})",
PipingModelType.Sellmeijer.ToString(), scenario.Location.Name, scenario.LocationScenarioID, soilProfileProbability.SoilGeometryName, i);
calculationName = Regex.Replace(calculationName, @"[\\\/:\*\?""'<>|.]", "_");
pipingCalculator.FilenameCalculation = pipingCalculator.PipingCalculationDirectory + calculationName;
double? betaloc = CalculatePipingReliabilityIndexForSurface(scenario, newSurfaceLine, pipingCalculator, soilProfileProbability, waterLevelProbabilistic);
if (betaloc != null)
{
betas[i] = betaloc.Value;
}
}
// Note Bka: For now, set MHW to original max water level (= river level + WaterHeightDecimeringsHoogte) and set
// Decimate to the original WaterHeightDecimeringsHoogte. Han Best has to approve this!
// After consulting Best, the next decision is made. MHW should be the riverlevel. And if the maxwaterlevel is smaller than MHW,then a designpoint
// calculation is not longer required as the safety is determined by the maxwaterlevel. So just return the Beta[0] (= beta at maxwaterlevel) in
// that case.
if (scenario.RiverLevel > scenario.MaxWaterLevel)
{
return Probabilistic.Probabilistic.NormalDistribution(-betas[0]);
}
else
{
if (CheckAndAdaptBetasWaterLevelsWhenNeeded(betas, waterLevels, scenario, newSurfaceLine, pipingCalculator, soilProfileProbability))
{
var designPointWater = new DesignPointCalculation();
designPointWater.Betas = betas;
designPointWater.Waterlevels = waterLevels;
designPointWater.MHW = (double) (scenario.RiverLevel);
designPointWater.Decimate = (double) scenario.WaterHeightDecimeringsHoogte;
designPointWater.Exceed = DesignPointCalculation.ExceedingSet.twoThousend;
designPointWater.IsMaxLevelUsed = false;
designPointWater.MaxLevel = 0;
if (designPointWater.CalculateTheWaterDesignpoint())
{
return Probabilistic.Probabilistic.NormalDistribution(-designPointWater.Beta);
}
else
{
// result could not be determined.
throw new DamFailureMechanismeCalculatorException("Water design point calculation failed");
}
}
else
{
// total situation is safe, so return 0.
return 0;
}
}
}
///
///
///
///
///
///
///
///
///
private double? CalculatePipingReliabilityIndexForSurface(Scenario scenario, SurfaceLine2 newSurfaceLine, PipingCalculator pipingCalculator, SoilGeometryProbability soilProfileProbability,
ProbabilisticStruct waterLevel)
{
double? betaloc;
if (newSurfaceLine != null)
{
betaloc = pipingCalculator.CalculateReliabilityIndex(scenario.Location, newSurfaceLine, soilProfileProbability.SoilProfile, waterLevel);
}
else
{
betaloc = pipingCalculator.CalculateReliabilityIndex(scenario.Location, scenario.GetMostRecentSurfaceLine(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName), soilProfileProbability.SoilProfile, waterLevel);
}
return betaloc;
}
///
///
///
///
///
///
private void CalculatePipingForScenario(Scenario scenario)
{
var waterLevelProbabilistic = new ProbabilisticStruct(0.0, 0.01, (int) DistributionType.LogNormal, false);
string pipingCalculationDirectory = GetPipingCalculationBaseDirectory();
try
{
var validSoilProfileProbabilities = SelectPipingProbabilities(scenario.Location.Segment.SoilProfileProbabilities);
if (validSoilProfileProbabilities.Count == 0)
{
throw new DamFailureMechanismeCalculatorException(String.Format("No piping profiles to calcutate for location {0}", scenario.Location.Name));
}
foreach (var soilProfileProbability in validSoilProfileProbabilities)
{
try
{
var pipingResults = new PipingResults();
foreach (PipingModelType pipingCalculationType in Enum.GetValues(typeof(PipingModelType)))
{
var pipingProbabilisticParameters = new PipingProbabilisticParameters(scenario.Location.LayerHeightDistribution, scenario.Location.LayerHeightDeviation);
PipingCalculator pipingCalculator = pipingCalculatorFactory(scenario.Location, scenario.Location.CreateModelParametersForPLLines(),
pipingCalculationType,
scenario.GetUpliftCriterionPiping(scenario.Location.ModelFactors.UpliftCriterionPiping),
scenario.GetRequiredSafetyFactorPiping(scenario.Location.ModelFactors.RequiredSafetyFactorPiping),
pipingProbabilisticParameters);
pipingCalculator.PipingCalculationDirectory = pipingCalculationDirectory;
double? safetyFactor = null;
double? failureProbability = null;
double? failureProbabilityAdvanced = null;
double? pipingExitPointX = null;
double? upliftFactor = null;
double? heaveFactor = null;
try
{
switch (ProbabilisticType)
{
case ProbabilisticType.Deterministic:
safetyFactor = pipingCalculator.CalculatePipingFactor(
scenario.Location,
scenario.GetMostRecentSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName),
soilProfileProbability.SoilProfile,
scenario.RiverLevel);
if (pipingCalculator.UpliftLocationAndResult != null)
{
pipingExitPointX = pipingCalculator.UpliftLocationAndResult.X;
upliftFactor = pipingCalculator.UpliftLocationAndResult.UpliftFactor;
heaveFactor = pipingCalculator.HeaveFactor;
}
break;
case ProbabilisticType.Probabilistic:
waterLevelProbabilistic.Mean = scenario.RiverLevel;
string calculationName = String.Format("Prob{0}_Loc({1})_Sce({2})_Pro({3})",
pipingCalculationType.ToString(), scenario.Location.Name, scenario.LocationScenarioID, soilProfileProbability.SoilGeometryName);
calculationName = Regex.Replace(calculationName, @"[\\\/:\*\?""'<>|.]", "_");
pipingCalculator.FilenameCalculation = pipingCalculator.PipingCalculationDirectory + calculationName;
failureProbability =
pipingCalculator.CalculatePipingFailureProbability(
scenario.Location,
scenario.GetMostRecentSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName),
soilProfileProbability.SoilProfile,
waterLevelProbabilistic);
break;
case ProbabilisticType.ProbabilisticFragility:
failureProbabilityAdvanced = CalculatePipingFailureProbabilityAdvanced(pipingCalculator, scenario, soilProfileProbability, null);
break;
}
}
catch (Exception exception)
{
throw new DamFailureMechanismeCalculatorException(exception.Message);
}
if (pipingCalculationType == PipingModelType.Sellmeijer)
{
scenario.SetSafetyFactorPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, safetyFactor);
if (ProbabilisticType == ProbabilisticType.ProbabilisticFragility)
{
scenario.SetFailureProbabilityPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName,
failureProbabilityAdvanced);
}
else
{
scenario.SetFailureProbabilityPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName,
failureProbability);
}
}
pipingResults.CalculationName = pipingCalculator.FilenameCalculation;
pipingResults.CalculationSubDir = @"PipingCalculation\\";
pipingResults.PipingExitPointX = pipingExitPointX;
pipingResults.UpliftFactor = upliftFactor;
pipingResults.HeaveFactor = heaveFactor;
switch (pipingCalculationType)
{
case PipingModelType.Bligh:
pipingResults.BlighHCritical = pipingCalculator.HCritical;
pipingResults.BlighPipingFactor = safetyFactor;
break;
case PipingModelType.Sellmeijer:
pipingResults.SellmeijerHCritical = pipingCalculator.HCritical;
pipingResults.SellmeijerPipingFactor = safetyFactor;
break;
case PipingModelType.Sellmeijer2Forces:
pipingResults.Sellmeijer2ForcesHCritical = pipingCalculator.HCritical;
pipingResults.Sellmeijer2ForcesPipingFactor = safetyFactor;
break;
case PipingModelType.Sellmeijer4Forces:
pipingResults.Sellmeijer4ForcesHCritical = pipingCalculator.HCritical;
pipingResults.Sellmeijer4ForcesPipingFactor = safetyFactor;
break;
case PipingModelType.Wti2017:
pipingResults.Wti2017HCritical = pipingCalculator.HCritical;
pipingResults.Wti2017PipingFactor = safetyFactor;
break;
}
}
scenario.SetPipingResults(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, pipingResults);
}
catch (DamFailureMechanismeCalculatorException calculatorException)
{
string errorMessage = "FAIL: " + calculatorException.Message;
Exception innerException = calculatorException.InnerException;
while (innerException != null)
{
errorMessage = errorMessage + ";" + innerException.Message;
innerException = innerException.InnerException;
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, errorMessage);
calculatorException.Scenario = scenario;
throw calculatorException;
}
}
}
catch (Exception exception)
{
scenario.Errors.Add(exception.Message);
Exception innerException = exception.InnerException;
while (innerException != null)
{
scenario.Errors.Add(innerException.Message);
innerException = innerException.InnerException;
}
}
}
///
/// Calculates failuremechanism flowslide for scenario.
///
/// The scenario.
private void CalculateFlowSlideForScenario(Scenario scenario)
{
try
{
var validSoilProfileProbabilities = SelectFlowSlideProbabilities(scenario.Location.Segment.SoilProfileProbabilities);
if (validSoilProfileProbabilities.Count == 0)
{
throw new DamFailureMechanismeCalculatorException(String.Format("No profiles to calcutate for location {0}", scenario.Location.Name));
}
foreach (var soilProfileProbability in validSoilProfileProbabilities)
{
try
{
if (soilProfileProbability.SoilProfile == null)
{
throw new DamFailureMechanismeCalculatorException(String.Format("Soilprofile is not 1D for location {0}",
scenario.Location.Name));
}
var flowSlideCalculations = new FlowSlideCalculations();
using (var flowSlideProject = CreateFlowSlideProject(scenario, soilProfileProbability))
{
string calculationName = StabilityCalculator.DetermineCalculationFilename(scenario.Location.Name, scenario.LocationScenarioID,
soilProfileProbability.SoilGeometryName, 0);
WriteFlowSlideProjectToFile(flowSlideProject, calculationName);
flowSlideCalculations.RunCalculation(flowSlideProject);
double safetyFactor = flowSlideProject.ResultOverallFactor;
scenario.SetSafetyFactorFlowSlide(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, safetyFactor);
}
}
catch (DamFailureMechanismeCalculatorException calculatorException)
{
string errorMessage = "FAIL: " + calculatorException.Message;
Exception innerException = calculatorException.InnerException;
while (innerException != null)
{
errorMessage = errorMessage + ";" + innerException.Message;
innerException = innerException.InnerException;
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, errorMessage);
calculatorException.Scenario = scenario;
throw calculatorException;
}
}
}
catch (Exception exception)
{
scenario.Errors.Add(exception.Message);
Exception innerException = exception.InnerException;
while (innerException != null)
{
scenario.Errors.Add(innerException.Message);
innerException = innerException.InnerException;
}
}
}
///
/// Creates the flowslide project.
///
/// The scenario.
/// The soil profile probability.
///
private static FlowSlideProject CreateFlowSlideProject(Scenario scenario, SoilGeometryProbability soilProfileProbability)
{
var flowSlideProject = new FlowSlideProject();
flowSlideProject.FlowSlideCalculationParameters.UseFlowSlideCalculation = UseFlowSlideCalculation.Global;
flowSlideProject.SurfaceLine2 = scenario.Location.LocalXZSurfaceLine2;
flowSlideProject.SoilProfile = soilProfileProbability.SoilProfile;
flowSlideProject.Soils.Clear();
var projectSoils = new List();
foreach (var layer in soilProfileProbability.SoilProfile.Layers)
{
if (!projectSoils.Exists(T => layer.Soil.Name.Equals(T.Name)))
{
projectSoils.Add(layer.Soil);
flowSlideProject.Soils.Add(layer.Soil);
}
}
flowSlideProject.FlowSlideCalculationParameters.CalculationParametersGeneral.Waterlevel = scenario.RiverLevel;
return flowSlideProject;
}
///
/// Writes the flowslide project to file.
///
/// The flow slide project.
/// Name of the calculation.
private void WriteFlowSlideProjectToFile(FlowSlideProject flowSlideProject, string calculationName)
{
string flowslideCalculationDirectory = Path.Combine(CalculationBaseDirectory, @"Flowslide\");
if (!Directory.Exists(flowslideCalculationDirectory))
{
Directory.CreateDirectory(flowslideCalculationDirectory);
}
string filenameExtension = ".fsx";
string fileName = calculationName + filenameExtension;
string flowslideProjectFilename = Path.Combine(flowslideCalculationDirectory, fileName);
var xmlSerializer = new XmlSerializer();
xmlSerializer.Serialize(flowSlideProject, flowslideProjectFilename);
}
///
/// Selects the soilProfileProbabilities for piping.
///
/// The soil profile probabilities.
///
private static List SelectPipingProbabilities(IList soilProfileProbabilities)
{
var validSoilProfileProbabilities =
new List(soilProfileProbabilities.Where(
p => ((p.SegmentFailureMechanismType == FailureMechanismSystemType.Piping) ||
(p.SegmentFailureMechanismType == null))));
return validSoilProfileProbabilities;
}
///
/// Selects the soilProfileProbabilities for stability.
///
/// The soil profile probabilities.
///
private static List SelectStabilityProbabilities(IList soilProfileProbabilities)
{
var validSoilProfileProbabilities = new List(soilProfileProbabilities.Where(
p => ((p.SegmentFailureMechanismType == FailureMechanismSystemType.StabilityInside) ||
(p.SegmentFailureMechanismType == FailureMechanismSystemType.StabilityOutside) ||
(p.SegmentFailureMechanismType == null))));
return validSoilProfileProbabilities;
}
///
/// Selects the flowslide probabilities.
///
/// The soil profile probabilities.
///
private static List SelectFlowSlideProbabilities(IList soilProfileProbabilities)
{
// For now use the stability probabilities
return SelectStabilityProbabilities(soilProfileProbabilities);
}
///
/// Consistency check to be performed before stability calculation
///
///
private void ConsistencyCheckStability(Scenario scenario)
{
ConsistencyCheckStabilityPerScenario(scenario);
}
private void ConsistencyCheckStabilityPerScenario(Scenario scenario)
{
// If outward stability calculation then low waterlevel is required
if (damFailureMechanismeCalculationSpecification.FailureMechanismeParamatersMStab.MStabParameters.GridPosition == MStabGridPosition.Left)
{
if (!scenario.RiverLevelLow.HasValue)
{
throw new DamFailureMechanismeCalculatorException(String.Format(
"Location {0} scenario {1} has no low waterlevel defined, which is required for outward stability calculation (grid at left).",
scenario.Location.Name, scenario.LocationScenarioID));
}
}
}
///
/// Stability calculation
///
///
private void CalculateStabilityForScenario(Scenario scenario, int iter)
{
try
{
ConsistencyCheckStability(scenario);
Location location = scenario.Location;
var modelParametersForPLLines = new ModelParametersForPLLines
{
PenetrationLength = location.PenetrationLength,
DampingFactorPL3 = location.DampingFactorPL3,
DampingFactorPL4 = location.DampingFactorPL4,
PLLineCreationMethod = location.PLLineCreationMethod
};
var requiredSafetyFactorStabilityInnerSlope = scenario.RequiredSafetyFactorStabilityInnerSlope ??
location.ModelFactors.RequiredSafetyFactorStabilityInnerSlope;
using (var stabilityCalculator =
new StabilityCalculator(
damFailureMechanismeCalculationSpecification.FailureMechanismeParamatersMStab,
programType,
modelParametersForPLLines,
location.TrafficLoad,
location.MinimalCircleDepth,
requiredSafetyFactorStabilityInnerSlope.Value,
mstabProgramPath, slopeWProgramPath,
location.GaugePLLines,
location.Gauges,
location.SoilbaseDB,
location.SoilList,
ProbabilisticType)
{
SelectedStabilityKernelType = damFailureMechanismeCalculationSpecification.StabilityKernelType
})
{
//stabilityCalculator.CalculationBaseDirectory = this.CalculationBaseDirectory;
var validSoilProfileProbabilities = SelectStabilityProbabilities(scenario.Location.Segment.SoilProfileProbabilities);
if (validSoilProfileProbabilities.Count == 0)
{
throw new DamFailureMechanismeCalculatorException(String.Format("No stability profiles to calcutate for location {0}", scenario.Location.Name));
}
int errorCount = 0;
var scenarioErrorMessages = new List();
foreach (var soilProfileProbability in validSoilProfileProbabilities)
{
try
{
UpliftSituation? upliftSituation = scenario.GetStabilityUpliftSituation(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName);
// The calculation for UpliftVan will only will done if there is Uplift
if (IsCalculationRequired(upliftSituation))
{
stabilityCalculator.Calculate(scenario, soilProfileProbability.SoilProfile, GetFullSoilGeometry2DName(soilProfileProbability.SoilGeometry2DName), iter);
MStabResults? mStabResults = scenario.GetMStabResults(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName);
if ((mStabResults != null) && (AnalysisType.AdaptNWO == analysisType))
{
// Store the NWO results
stabilityCalculator.NWOPhreaticAdaption = NonWaterRetainingObject.PhreaticAdaption;
var results = new NonWaterRetainingObjectResults();
results.NwoId = NonWaterRetainingObject.NwoId;
var coordinateSystemConverter = new CoordinateSystemConverter();
coordinateSystemConverter.DefineGlobalXYZBasedOnLine(scenario.Location.SurfaceLine2.Geometry);
results.AdaptedSurfaceLine = scenario.Location.LocalXZSurfaceLine2.FullDeepClone();
coordinateSystemConverter.ConvertLocalXZToGlobalXYZ(results.AdaptedSurfaceLine.Geometry);
results.LocationXrdStart = results.AdaptedSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.NonWaterRetainingObjectPoint1).X;
results.LocationYrdStart = results.AdaptedSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.NonWaterRetainingObjectPoint1).Y;
results.LocationZrdStart = results.AdaptedSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.NonWaterRetainingObjectPoint1).Z;
results.LocationXrdEnd = results.AdaptedSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.NonWaterRetainingObjectPoint4).X;
results.LocationYrdEnd = results.AdaptedSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.NonWaterRetainingObjectPoint4).Y;
results.LocationZrdEnd = results.AdaptedSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.NonWaterRetainingObjectPoint4).Z;
results.MStabResults = mStabResults.Value;
results.SoilProfileProbability = soilProfileProbability;
scenario.NwoResults.Add(results);
}
}
// assign original surfaceline to redesigned surfaceline (not for NWODesign as that would provide wrong surface line)
if (analysisType != AnalysisType.AdaptNWO)
{
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName,
scenario.Location.SurfaceLine2);
}
}
catch (DamFailureMechanismeCalculatorException calculatorException)
{
string errorMessage = "FAIL: " + calculatorException.Message;
Exception innerException = calculatorException.InnerException;
while (innerException != null)
{
errorMessage = errorMessage + ";" + innerException.Message;
innerException = innerException.InnerException;
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, errorMessage);
calculatorException.Scenario = scenario;
errorCount++;
scenarioErrorMessages.Add(errorMessage);
}
}
if (errorCount > 0)
{
string errorMessage = String.Format("{0} calculation error(s) in location {1} scenario {2}",
errorCount, location.Name, scenario.LocationScenarioID);
foreach (var scenarioErrorMessage in scenarioErrorMessages)
{
errorMessage = String.Format("{0}; {1}", errorMessage, scenarioErrorMessage);
}
var calculatorException = new DamFailureMechanismeCalculatorException(errorMessage)
{
Scenario = scenario
};
throw calculatorException;
}
}
}
catch (Exception exception)
{
scenario.Errors.Add(exception.Message);
Exception innerException = exception.InnerException;
while (innerException != null)
{
scenario.Errors.Add(innerException.Message);
innerException = innerException.InnerException;
}
throw;
}
}
///
/// Check if calculation should be done
/// (In case of UpliftVan and no uplift this is not the case)
///
/// The uplift situation.
///
/// true if [is calculation required] ; otherwise, false.
///
private bool IsCalculationRequired(UpliftSituation? upliftSituation)
{
bool isUplift = upliftSituation.HasValue && upliftSituation.Value.IsUplift;
bool isSkipCalculation = (!isUplift &&
damFailureMechanismeCalculationSpecification.FailureMechanismeParamatersMStab.IsStabilityCheckOnUplift &&
(damFailureMechanismeCalculationSpecification.FailureMechanismSystemType == FailureMechanismSystemType.StabilityInside) &&
(damFailureMechanismeCalculationSpecification.FailureMechanismeParamatersMStab.MStabParameters.Model == MStabModelType.UpliftVan));
return !isSkipCalculation;
}
///
///
///
///
private void ImplementNWOInSurfaceLinesForAllScenarios(Scenario scenario)
{
try
{
ImplementNWOInSurfaceLine(scenario);
}
catch (Exception exception)
{
scenario.Errors.Add(exception.Message);
Exception innerException = exception.InnerException;
while (innerException != null)
{
scenario.Errors.Add(innerException.Message);
innerException = innerException.InnerException;
}
}
}
private void CalculateScenario(Scenario scenario, int iter)
{
switch (damFailureMechanismeCalculationSpecification.FailureMechanismSystemType)
{
case FailureMechanismSystemType.StabilityInside:
case FailureMechanismSystemType.StabilityOutside:
ConsistencyCheckStabilityPerScenario(scenario);
CalculateStabilityForScenario(scenario, iter);
break;
case FailureMechanismSystemType.Piping:
CalculatePipingForScenario(scenario);
break;
}
}
///
///
///
///
///
private double? ImplementNWOInSurfaceLine(Scenario scenario)
{
double? safetyFactor = null;
if (scenario.Location != null)
{
SurfaceLine2 originalLocalXzSurfaceLine = scenario.Location.LocalXZSurfaceLine2.FullDeepClone();
try
{
// fit the non water retaining object in the current surfaceline. If it does (no longer) fit, surfaceline is returned as null and
// the calculation is finished. The phreaticline may have to be adapted to the new surfaceline.
var nwoInSurfacleLine = new NonWaterRetainingObjectInSurfaceLine();
nwoInSurfacleLine.NonWaterRetainingObject = NonWaterRetainingObject;
nwoInSurfacleLine.SurfaceLine = scenario.Location.LocalXZSurfaceLine2;
nwoInSurfacleLine.GridPosition = damFailureMechanismeCalculationSpecification.FailureMechanismeParamatersMStab.MStabParameters.GridPosition;
nwoInSurfacleLine.StepSizeX = NonWaterRetainingObject.StepSizeX;
double fitPositionX = nwoInSurfacleLine.DetermineStartLocationForNonWaterRetainingObject(true);
if (nwoInSurfacleLine.DoesPositionXFitInSurfaceLine(fitPositionX))
{
var iter = 0;
bool doneFittingNWO = false;
while (!doneFittingNWO)
{
// try to fit NWO in surfaceline. If successfull, calculate it, else this is finished.
SurfaceLine2 localXzSurfaceLine = nwoInSurfacleLine.FitNonWaterRetainingObjectInSurfaceLine(fitPositionX);
if (localXzSurfaceLine != null)
{
var validationError = localXzSurfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error);
if (validationError != null)
{
localXzSurfaceLine.Dispose();
throw new SurfaceLineException(validationError.Text);
}
scenario.Location.LocalXZSurfaceLine2.Dispose();
scenario.Location.LocalXZSurfaceLine2 = localXzSurfaceLine;
// calculate with this surfaceline and store the results.
CalculateScenario(scenario, iter);
// Get new fitPositionX (based on stepsize X and gridposition)
fitPositionX = nwoInSurfacleLine.DetermineNewFitPostionX(fitPositionX, true);
iter++;
}
else
{
doneFittingNWO = true;
}
}
if (iter > 0)
{
// restore the original surface line
// Note: 'originalLocalXzSurfaceLine' is only used if now exception have occurred and
scenario.Location.LocalXZSurfaceLine2 = originalLocalXzSurfaceLine;
}
else
{
throw new DamFailureMechanismeCalculatorException(
"NonWaterRetainingObject does not fit within Surfaceline.");
}
}
else
{
throw new DamFailureMechanismeCalculatorException(
"NonWaterRetainingObject does not fit within Surfaceline.");
}
}
catch (Exception e)
{
originalLocalXzSurfaceLine.Dispose(); // Clone has become an orphan, so dispose and discard
// Add scenario if having a failure mechanism calculation exception:
var calculatorException = e as DamFailureMechanismeCalculatorException;
if (calculatorException != null)
{
calculatorException.Scenario = scenario;
}
throw;
}
}
return safetyFactor;
}
///
///
///
///
private void RedesignSurfaceLinesForAllScenarios(Scenario scenario)
{
try
{
RedesignSurfaceLine(scenario);
}
catch (Exception exception)
{
scenario.Errors.Add(exception.Message);
Exception innerException = exception.InnerException;
while (innerException != null)
{
scenario.Errors.Add(innerException.Message);
innerException = innerException.InnerException;
}
}
}
///
///
///
///
///
private void RedesignSurfaceLine(Scenario scenario)
{
try
{
if (scenario.Location != null)
{
SurfaceLine2 surfaceLine = scenario.Location.LocalXZSurfaceLine2.FullDeepClone(); //TODO: I really have no clue this object should be in a using clause or not... :(
if (scenario.Location.RedesignDikeHeight)
{
// Dike height adaptation
var redesignedSurfaceLine = RedesignSurfaceLineHeight(damFailureMechanismeCalculationSpecification.FailureMechanismSystemType,
scenario, surfaceLine);
var validationError = redesignedSurfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error);
if (validationError != null)
{
redesignedSurfaceLine.Dispose();
throw new SurfaceLineException(validationError.Text);
}
// No error, so replace clone with redesigned surfaceline
surfaceLine.Dispose();
surfaceLine = redesignedSurfaceLine;
}
if (scenario.Location.RedesignDikeShoulder)
{
// Shoulder and slope adaption
double? safetyFactor = null;
switch (damFailureMechanismeCalculationSpecification.FailureMechanismSystemType)
{
case FailureMechanismSystemType.StabilityInside:
case FailureMechanismSystemType.StabilityOutside:
safetyFactor = scenario.ModelFactors.RequiredSafetyFactorStabilityInnerSlope;
RedesignSurfaceLineStabilityInside(scenario, safetyFactor);
break;
case FailureMechanismSystemType.Piping:
safetyFactor = scenario.ModelFactors.RequiredSafetyFactorPiping;
RedesignSurfaceLinePipingShoulder(damFailureMechanismeCalculationSpecification.PipingModelType,
scenario, ref safetyFactor, ref surfaceLine);
break;
case FailureMechanismSystemType.FlowSlide:
RedesignSurfaceLineFlowSlide(scenario, safetyFactor, ref surfaceLine);
break;
}
}
}
}
catch (DamFailureMechanismeCalculatorException calculatorException)
{
calculatorException.Scenario = scenario;
throw;
}
}
///
///
///
///
///
///
///
private void RedesignSurfaceLinePipingShoulder(PipingModelType pipingModelType, Scenario scenario, ref double? safetyFactor, ref SurfaceLine2 surfaceLine)
{
var modelParametersForPLLines = new ModelParametersForPLLines
{
PenetrationLength = scenario.Location.PenetrationLength,
DampingFactorPL3 = scenario.Location.DampingFactorPL3,
DampingFactorPL4 = scenario.Location.DampingFactorPL4,
PLLineCreationMethod = scenario.Location.PLLineCreationMethod
};
var pipingProbabilisticParameters = new PipingProbabilisticParameters(scenario.Location.LayerHeightDistribution,
scenario.Location.LayerHeightDeviation);
var pipingUpliftCriterion = scenario.GetUpliftCriterionPiping(scenario.Location.ModelFactors.UpliftCriterionPiping);
if (pipingUpliftCriterion <= 0)
{
throw new DamFailureMechanismeCalculatorException(String.Format("Invalid piping uplift criterion {0} for location {1} scenario {2}",
pipingUpliftCriterion, scenario.Location.Name, scenario.LocationScenarioID));
}
var requiredSafetyFactorPiping = 0.0;
if (scenario.RequiredSafetyFactorPiping != null)
{
requiredSafetyFactorPiping = scenario.RequiredSafetyFactorPiping.Value;
}
if (safetyFactor != null)
{
requiredSafetyFactorPiping = safetyFactor.Value;
}
if (requiredSafetyFactorPiping <= 0)
{
throw new DamFailureMechanismeCalculatorException(String.Format("Invalid required safetyfactor piping {0} for location {1} scenario {2}",
requiredSafetyFactorPiping, scenario.Location.Name, scenario.LocationScenarioID));
}
PipingCalculator pipingCalculator = pipingCalculatorFactory(scenario.Location, modelParametersForPLLines, pipingModelType,
pipingUpliftCriterion,
requiredSafetyFactorPiping,
pipingProbabilisticParameters);
var validSoilProfileProbabilities = SelectPipingProbabilities(scenario.Location.Segment.SoilProfileProbabilities);
if (validSoilProfileProbabilities.Count == 0)
{
throw new DamFailureMechanismeCalculatorException(String.Format("No piping profiles to calcutate for location {0}", scenario.Location.Name));
}
foreach (var soilProfileProbability in validSoilProfileProbabilities)
{
try
{
SurfaceLine2 newSurfaceLine = surfaceLine.FullDeepClone();
switch (ProbabilisticType)
{
case ProbabilisticType.Deterministic:
{
var newCandidate = DetermineNewSafeSurfaceLinePipingDeterministic(scenario, soilProfileProbability, pipingCalculator, newSurfaceLine, ref safetyFactor);
if (!ReferenceEquals(newSurfaceLine, newCandidate))
{
newSurfaceLine.Dispose();
newSurfaceLine = newCandidate;
}
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, newSurfaceLine);
scenario.SetSafetyFactorPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, safetyFactor);
PipingResults pipingResults = GetPipingResults(safetyFactor, pipingModelType, pipingCalculator);
scenario.SetPipingResults(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, pipingResults);
break;
}
case ProbabilisticType.Probabilistic:
case ProbabilisticType.ProbabilisticFragility:
{
//Todo Adapt the determination of the piping design to the way it should be (See Detrministic and functional design)
double[] waterLevels = scenario.DetermineProperWaterlevelsForProbabilisticAdvanced();
double waterLevel = scenario.RiverLevel;
// for test of deterministic as initialisation for probabilistic, use next line.
// newSurfaceLine = GetNewSafeSurfaceLine(scenario, soilProfileProbability, pipingCalculator, newSurfaceLine, ref requiredSafetyFactor);
bool upLiftOccured = false;
if (ProbabilisticType == ProbabilisticType.ProbabilisticFragility)
{
waterLevel = waterLevels[1];
}
// start by checking the uplift first (if so, a newShoulderHeight can be determined). If uplift is not an issue then
// probability of failure = 0. If uplift is an issue, add a berm until uplift is no longer an issue.
double? newShoulderHeight = pipingCalculator.CalculateDesignShoulderHeight(scenario.Location, newSurfaceLine,
soilProfileProbability.SoilProfile, waterLevel);
double currentShoulderHeight = 0;
double currentShoulderWidth = 0;
double newShoulderWidth = 0;
double slopeFactor = 0;
if (newShoulderHeight != null)
{
// Debug.Write(String.Format("New Shoulder Height {0:0.000}\n", newShoulderHeight));
// if a new shoulderheight could be found, uplift is an issue. The new found shoulderheight might however not be the correct one
// as with this height we insert or adjust a berm. This new/adjusted berm has to be checked until uplift is no longer an issue.
upLiftOccured = true;
// Start by adding the new shoulder. Note that there might be an existing shoulder.
var shoulderTopInside = newSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderTopInside);
var dikeToeAtPolder = newSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder);
if (newSurfaceLine.HasShoulderInside())
{
// there was a shoulder which now has to be extended.
currentShoulderWidth = shoulderTopInside.X -
newSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderBaseInside).X;
currentShoulderHeight = shoulderTopInside.Z - dikeToeAtPolder.Z;
// shoulder must grow in length, it should be passed the uplift location
newShoulderWidth = currentShoulderWidth + pipingCalculator.UpliftLocationAndResult.X - shoulderTopInside.X;
// in height it should grow with the calculated amount.
newShoulderHeight = newShoulderHeight.Value + currentShoulderHeight;
}
else
{
// there was no shoulder, so create one
var dikeTopAtPolder = newSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder);
slopeFactor = (dikeToeAtPolder.X - dikeTopAtPolder.X)/(dikeTopAtPolder.Z - dikeToeAtPolder.Z);
newShoulderWidth = 0.5 + newShoulderHeight.Value*slopeFactor;
}
// Make sure new berm is not too small
newShoulderHeight = Math.Max(newShoulderHeight.Value, CMinimumShoulderElevation);
newShoulderWidth = Math.Max(newShoulderWidth, CMinimumShoulderWidth);
currentShoulderWidth = newShoulderWidth;
currentShoulderHeight = newShoulderHeight.Value;
bool finished = false;
double maxShoulderLevel = CalculateMaximumShoulderLevel(newSurfaceLine, 1.0); // no limit to height of shoulder
while ((newShoulderHeight != null) && (!finished))
{
var surfaceLineShoulderAdapter = new SurfaceLineShoulderAdapter(newSurfaceLine, scenario.Location);
surfaceLineShoulderAdapter.MaxShoulderLevel = maxShoulderLevel;
newSurfaceLine = surfaceLineShoulderAdapter.ConstructNewSurfaceLine(newShoulderWidth, newShoulderHeight.Value, true);
newShoulderHeight = pipingCalculator.CalculateDesignShoulderHeight(scenario.Location, newSurfaceLine,
soilProfileProbability.SoilProfile, waterLevel);
finished = (pipingCalculator.UpliftLocationAndResult.X > shoulderTopInside.X);
if (newShoulderHeight != null && (!finished))
{
// make sure new height is at least cMinimumShoulderExtraElevation higher
if (newShoulderHeight.Value < CMinimumShoulderExtraElevation)
{
newShoulderHeight = currentShoulderHeight + CMinimumShoulderExtraElevation;
}
else
{
newShoulderHeight = currentShoulderHeight + newShoulderHeight.Value;
}
// shoulder must grow in length, it should be passed the uplift location and at least the minimum grow value
newShoulderWidth = currentShoulderWidth + CMinimumShoulderExtraWidth;
currentShoulderWidth = currentShoulderWidth + pipingCalculator.UpliftLocationAndResult.X -
shoulderTopInside.X;
newShoulderWidth = Math.Max(currentShoulderWidth, newShoulderWidth);
currentShoulderWidth = newShoulderWidth;
currentShoulderHeight = newShoulderHeight.Value;
}
}
}
// if no shoulder needed (i.e. when no uplift occurs) then failure probability is always cDefaultMinReturnValue = 0.0
double? failureProbability = PipingCalculator.cDefaultMinReturnValue;
if (upLiftOccured)
{
// Uplift occured, so calculate failureProbability
if (ProbabilisticType == ProbabilisticType.Probabilistic)
{
var waterLevelProbabilistic = new ProbabilisticStruct(0.0, 0.01, (int) DistributionType.LogNormal, false);
waterLevelProbabilistic.Mean = scenario.RiverLevel;
failureProbability = pipingCalculator.CalculatePipingFailureProbability(scenario.Location, newSurfaceLine,
soilProfileProbability.SoilProfile, waterLevelProbabilistic);
}
else
{
failureProbability = CalculatePipingFailureProbabilityAdvanced(pipingCalculator, scenario, soilProfileProbability,
newSurfaceLine);
}
if (failureProbability != null)
{
int iterationIndex = 1;
bool isRedesignRequired = (failureProbability.Value > scenario.ModelFactors.RequiredProbabilityOfFailurePiping);
double maxShoulderLevel = CalculateMaximumShoulderLevel(newSurfaceLine, 1.0); // no limit to height of shoulder
while (isRedesignRequired && newSurfaceLine != null)
{
// Debug.Write(String.Format("Iteration {0} failureProbability {1:0.0000000000}, currentShoulderWidth {2:0.000}, currentShoulderHeight {3:0.000}\n", iterationIndex, failureProbability, currentShoulderWidth, currentShoulderHeight));
iterationIndex++;
currentShoulderWidth = currentShoulderWidth + 1;
// Due to different calculation types, raise the shoulder too next to making it wider.
currentShoulderHeight = currentShoulderHeight + CMinimumShoulderExtraElevation;
var surfaceLineShoulderAdapter = new SurfaceLineShoulderAdapter(newSurfaceLine, scenario.Location);
surfaceLineShoulderAdapter.MaxShoulderLevel = maxShoulderLevel;
newSurfaceLine = surfaceLineShoulderAdapter.ConstructNewSurfaceLine(currentShoulderWidth, currentShoulderHeight, true);
if (ProbabilisticType == ProbabilisticType.Probabilistic)
{
var waterLevelProbabilistic = new ProbabilisticStruct(0.0, 0.01, (int) DistributionType.LogNormal, false);
waterLevelProbabilistic.Mean = scenario.RiverLevel;
failureProbability = pipingCalculator.CalculatePipingFailureProbability(
scenario.Location, newSurfaceLine,
soilProfileProbability.SoilProfile, waterLevelProbabilistic);
}
else
{
failureProbability = CalculatePipingFailureProbabilityAdvanced(pipingCalculator, scenario,
soilProfileProbability, newSurfaceLine);
}
if (failureProbability != null)
{
isRedesignRequired = (failureProbability.Value > scenario.ModelFactors.RequiredProbabilityOfFailurePiping);
}
else
{
isRedesignRequired = true;
}
if (iterationIndex >= PipingRedesingMaxIterations)
{
// #BKA: vraag voor Ray set the results in case of failure too to provide feedback. (of niet Tom???) Voorlopig even niet. Ray was net naar huis dus nog navragen.
// scenario.SetFailureProbabilityPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName,
// failureProbability);
// scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName,
// newSurfaceLine);
throw new MaximumRedesignIterationsReachedException();
}
}
}
}
if (failureProbability != null)
{
scenario.SetFailureProbabilityPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName,
failureProbability);
}
else
{
scenario.SetFailureProbabilityPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName,
999);
}
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, newSurfaceLine);
break;
}
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, "Succes");
}
catch (Exception exception)
{
string errorMessage = String.Format("Location '{0}', Soilprofile '{1}': {2}",
scenario.Location.Name, soilProfileProbability.SoilGeometryName, exception.Message);
PipingResults pipingResults = GetPipingResults(-1, pipingModelType, pipingCalculator);
scenario.SetPipingResults(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, pipingResults);
scenario.SetSafetyFactorPiping(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, -1);
scenario.Errors.Add("FAIL: " + errorMessage);
scenario.SetResultMessage(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, "FAIL: " + errorMessage);
}
}
}
private PipingResults GetPipingResults(double? safetyFactor, PipingModelType pipingModelType, PipingCalculator pipingCalculator)
{
var pipingResults = new PipingResults();
switch (pipingModelType)
{
case PipingModelType.Bligh:
pipingResults.BlighHCritical = pipingCalculator.HCritical;
pipingResults.BlighPipingFactor = safetyFactor;
break;
case PipingModelType.Sellmeijer:
pipingResults.SellmeijerHCritical = pipingCalculator.HCritical;
pipingResults.SellmeijerPipingFactor = safetyFactor;
break;
case PipingModelType.Sellmeijer2Forces:
pipingResults.Sellmeijer2ForcesHCritical = pipingCalculator.HCritical;
pipingResults.Sellmeijer2ForcesPipingFactor = safetyFactor;
break;
case PipingModelType.Sellmeijer4Forces:
pipingResults.Sellmeijer4ForcesHCritical = pipingCalculator.HCritical;
pipingResults.Sellmeijer4ForcesPipingFactor = safetyFactor;
break;
case PipingModelType.Wti2017:
pipingResults.Wti2017HCritical = pipingCalculator.HCritical;
pipingResults.Wti2017PipingFactor = safetyFactor;
break;
}
return pipingResults;
}
///
/// Ensures that the points on the surface line are never more than cDiff (0.5) apart.
///
///
///
private IEnumerable GetCheckedSurfaceLine(IEnumerable originalLine)
{
const double cDiff = 0.5;
var newLine = new List();
double X = originalLine.First().X;
foreach (var point in originalLine)
{
while (point.X > X + cDiff)
{
var newPoint = new GeometryPoint(point)
{
X = X + cDiff
};
if (newPoint.X > newLine.Last().X)
{
newPoint.Z = newLine.Last().Z + ((newPoint.X - newLine.Last().X)/(point.X - newLine.Last().X))*
(point.Z - newLine.Last().Z);
newLine.Add(newPoint);
}
X = newPoint.X;
}
newLine.Add(point);
}
return newLine;
}
private SurfaceLine2 DetermineNewSafeSurfaceLinePipingDeterministic(Scenario scenario, SoilGeometryProbability soilProfileProbability, PipingCalculator pipingCalculator, SurfaceLine2 surfaceLine, ref double? safetyFactor)
{
double orgShoulderLength = surfaceLine.DetermineShoulderWidth();
double orgShoulderHeight = surfaceLine.DetermineShoulderHeight();
double desiredShoulderLength = orgShoulderLength;
double desiredShoulderHeight = orgShoulderHeight;
double oldDesiredShoulderLength = orgShoulderLength;
double oldDesiredShoulderHeight = orgShoulderHeight;
GeometryPoint startSurfacePoint = surfaceLine.GetDikeToeInward();
IEnumerable relevantSurfacePointsList = from GeometryPoint point in surfaceLine.Geometry.Points
where point.X >= startSurfacePoint.X
orderby point.X ascending
select point;
relevantSurfacePointsList = GetCheckedSurfaceLine(relevantSurfacePointsList);
int pointCount = 0;
foreach (var point in relevantSurfacePointsList)
{
pointCount++;
// Determine calculation filename to output piping calculation file
//pipingCalculator.PipingCalculationDirectory = GetPipingCalculationBaseDirectory();
//string fileNameCalculation =String.Format("Calc({0})_Loc({1})_Pro({2})_Pnt({3}))",
// pipingCalculator.CalculationModelIdentifier, scenario.Location.Name, soilProfileProbability.SoilProfile.Name, pointCount.ToString("d4")); ;
//pipingCalculator.FilenameCalculation = Path.Combine(pipingCalculator.PipingCalculationDirectory, fileNameCalculation);
// Calculate the piping design at the given point. This returns the required adaption (berm length and height) if any.
var pipingDesign = pipingCalculator.CalculateDesignAtPoint(scenario.Location, surfaceLine,
soilProfileProbability.SoilProfile,
scenario.RiverLevel, point);
if (pipingDesign != null)
{
// Piping is an issue so adapt the surfaceline for it
desiredShoulderLength = pipingDesign.PipingLengthFromToe;
desiredShoulderLength = Math.Max(desiredShoulderLength, oldDesiredShoulderLength);
oldDesiredShoulderLength = desiredShoulderLength;
// shoulder height is height above surfacelevel!!
desiredShoulderHeight = pipingDesign.ShoulderHeightFromToe;
desiredShoulderHeight = Math.Max(desiredShoulderHeight, oldDesiredShoulderHeight);
oldDesiredShoulderHeight = desiredShoulderHeight;
}
}
if (desiredShoulderLength > 0)
{
desiredShoulderLength = Math.Max(desiredShoulderLength, CMinimumShoulderWidth);
}
if (desiredShoulderLength > 0)
{
desiredShoulderHeight = Math.Max(desiredShoulderHeight, CMinimumShoulderElevation);
}
bool isNewShoulderSameAsOriginal = ((Math.Abs(desiredShoulderLength - orgShoulderLength) < CToleranceShoulderChanges) &&
(Math.Abs(desiredShoulderHeight - orgShoulderHeight) < CToleranceShoulderChanges));
if (isNewShoulderSameAsOriginal)
{
return surfaceLine;
}
else
{
// Adapt the surfaceline for the finally required shoulder dimensions.
double maxShoulderLevel = CalculateMaximumShoulderLevel(surfaceLine, 1.0); // no limit to height of shoulder
var surfaceLineShoulderAdapter = new SurfaceLineShoulderAdapter(surfaceLine, scenario.Location);
surfaceLineShoulderAdapter.MaxShoulderLevel = maxShoulderLevel;
SurfaceLine2 newSurfaceLine = surfaceLineShoulderAdapter.ConstructNewSurfaceLine(desiredShoulderLength, desiredShoulderHeight, true);
safetyFactor = pipingCalculator.CalculatePipingFactor(scenario.Location, newSurfaceLine, soilProfileProbability.SoilProfile, scenario.RiverLevel);
if (safetyFactor < scenario.RequiredSafetyFactorPiping)
{
throw new DamFailureMechanismeCalculatorException("Deterministic Design: Piping is not safe yet.");
}
return newSurfaceLine;
}
}
///
/// Create the initial geometry to be used to determine layers for embankment for design
///
///
///
///
///
///
///
private void CreateInitialGeometry(Scenario scenario, StabilityCalculator stabilityCalculator, SoilGeometryProbability soilProfileProbability, SurfaceLine2 surfaceLine, out String initialgeometryFile)
{
const int IterationIndex = -1;
initialgeometryFile = StabilityCalculator.DetermineCalculationFilename(scenario.Location.Name, scenario.LocationScenarioID, soilProfileProbability.SoilGeometryName, IterationIndex);
initialgeometryFile = initialgeometryFile + stabilityCalculator.GetFilenameExtension();
initialgeometryFile = Path.Combine(stabilityCalculator.GetStabilityCalculationDirectory(), initialgeometryFile);
double riverLevel = 0.5*(surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).Z +
surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver).Z);
string soilgeometry2DFilename = null;
if (soilProfileProbability.SoilGeometry2DName != null)
{
soilgeometry2DFilename =
Path.GetFullPath(Path.Combine(DamProject.ProjectMap, Path.Combine(scenario.Location.MapForSoilGeometries2D, soilProfileProbability.SoilGeometry2DName)));
}
XDocument mstabXML = stabilityCalculator.CreateMStabXmlDoc(initialgeometryFile, scenario, soilProfileProbability.SoilProfile,
soilgeometry2DFilename, riverLevel, null, surfaceLine);
mstabXML.Save(initialgeometryFile + ".xml");
var stabilityServiceAgent = new StabilityServiceAgent();
stabilityServiceAgent.CreateProjectFile(mstabXML.ToString());
if (!File.Exists(initialgeometryFile))
{
throw new DamFailureMechanismeCalculatorException("Initial geometry file (sti) is not created.");
}
}
///
/// Redesigns the surface line for mechanism stability inside.
///
/// The scenario.
/// The safety factor.
private void RedesignSurfaceLineStabilityInside(Scenario scenario, double? requiredSafetyFactor)
{
Location location = scenario.Location;
var modelParametersForPLLines = new ModelParametersForPLLines
{
PenetrationLength = location.PenetrationLength,
DampingFactorPL3 = location.DampingFactorPL3,
DampingFactorPL4 = location.DampingFactorPL4,
PLLineCreationMethod = location.PLLineCreationMethod
};
using (var stabilityCalculator =
new StabilityCalculator(damFailureMechanismeCalculationSpecification.FailureMechanismeParamatersMStab,
programType,
modelParametersForPLLines,
location.TrafficLoad,
location.MinimalCircleDepth,
requiredSafetyFactor.Value,
mstabProgramPath,
slopeWProgramPath,
location.GaugePLLines,
location.Gauges,
location.SoilbaseDB,
location.SoilList,
ProbabilisticType)
{
SelectedStabilityKernelType = damFailureMechanismeCalculationSpecification.StabilityKernelType
})
{
var validSoilProfileProbabilities = SelectStabilityProbabilities(scenario.Location.Segment.SoilProfileProbabilities);
if (validSoilProfileProbabilities.Count == 0)
{
throw new DamFailureMechanismeCalculatorException(String.Format("No stability profiles to calcutate for location {0}", scenario.Location.Name));
}
foreach (var soilProfileProbability in validSoilProfileProbabilities)
{
// The calculation for UpliftVan will only will done if there is Uplift
UpliftSituation? upliftSituation = scenario.GetStabilityUpliftSituation(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName);
if (IsCalculationRequired(upliftSituation))
{
switch (scenario.Location.StabilityDesignMethod)
{
// Bij WTIkernel is het soilprofile2D nog null in de soilProfileProbability en daarom gat Adapt Geometry fout.
// nagaan bij classic Delphi of dat daar ook leeg is. Daarnaast is het probleem groter. Je moet denk ik de geometrie geheel regenereren NADAT de surfaceline
// is aangepast. Dan moet de soilprofile2D goed gezet worden (en ook de sti + naam sti!?!?!?! uitzoeken!) op de nieuwe 2Dgeom. En die moet goed in de kernel terecht komen.
// Dus dat kan nog niet hier want de nieuwe surfaceline is nog niet bekend. Gebruik maken van de surf2dprof combiner!!
case StabilityDesignMethod.OptimizedSlopeAndShoulderAdaption:
{
RedesignCombinedSlopeAdaptionAndShoulderAdaption(scenario, stabilityCalculator, soilProfileProbability);
break;
}
case StabilityDesignMethod.SlopeAdaptionBeforeShoulderAdaption:
{
RedesignFirstSlopeAdaptionThenShoulderAdaption(scenario, stabilityCalculator, soilProfileProbability);
break;
}
}
}
}
}
}
///
/// Redesign for Stability:
/// Dependent on the exit point of the stability circle.
/// If the exit point is in the slope, the slope will be adapted.
/// If the exit point is not in the slope, a shoulder will be made,
/// or if the shoulder exists, the shoulder will be enlarged.
///
///
///
///
///
private void RedesignCombinedSlopeAdaptionAndShoulderAdaption(Scenario scenario, StabilityCalculator stabilityCalculator,
SoilGeometryProbability soilProfileProbability)
{
Location location = scenario.Location;
double requiredSafetyFactor = scenario.ModelFactors.RequiredSafetyFactorStabilityInnerSlope ??
scenario.Location.ModelFactors.RequiredSafetyFactorStabilityInnerSlope.Value;
double betaRequired = scenario.ModelFactors.RequiredProbabilityOfFailureStabilityInnerslope ??
scenario.Location.ModelFactors.RequiredProbabilityOfFailureStabilityInnerslope.Value;
const int maxRedesignIterations = 200;
int iterationIndex = 1;
string previousFilename;
SurfaceLine2 orgSurfaceLine = scenario.Location.LocalXZSurfaceLine2;
// Create the file with the initial geometry to be used to determine which layers have to be defined as dike embankment material
CreateInitialGeometry(scenario, stabilityCalculator, soilProfileProbability, orgSurfaceLine, out previousFilename);
SurfaceLine2 surfaceLine = scenario.GetMostRecentSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName).FullDeepClone();
var mstabDesignEmbankment = new MStabDesignEmbankment
{
EmbankmentMaterialname = location.DikeEmbankmentMaterial,
PreviousGeometry2DFilename = previousFilename
};
try
{
double? beta;
bool isRedesignRequired;
double? exitPointXCoordinate;
scenario.Location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine);
stabilityCalculator.Calculate(scenario, soilProfileProbability.SoilProfile,
GetFullSoilGeometry2DName(soilProfileProbability.SoilGeometry2DName),
iterationIndex, mstabDesignEmbankment);
mstabDesignEmbankment.PreviousGeometry2DFilename = stabilityCalculator.StabilityProjectFilename;
mstabDesignEmbankment.EmbankmentMaterialname = location.ShoulderEmbankmentMaterial;
MStabResults? mStabResults = scenario.GetMStabResults(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
double? safetyFactor = mStabResults.Value.zone1.safetyFactor;
beta = scenario.GetFailureProbabilityStability(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
isRedesignRequired = IsRedesignRequired(safetyFactor, requiredSafetyFactor, betaRequired, beta);
exitPointXCoordinate = mStabResults.Value.zone1.circleSurfacePointRightXCoordinate;
if (!isRedesignRequired && surfaceLine != null)
{
// Set redesigned surfaceline to original, so in case no redesign is needed, the original surfaceline will be returned
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, surfaceLine);
}
else
{
double maxFractionOfDikeHeightForShoulderHeight = scenario.Location.UseNewMaxHeightShoulderAsFraction ?
scenario.Location.NewMaxHeightShoulderAsFraction : defaultMaxFractionOfDikeHeightForShoulderHeight;
double maxShoulderLevel = CalculateMaximumShoulderLevel(surfaceLine, maxFractionOfDikeHeightForShoulderHeight);
while (isRedesignRequired && surfaceLine != null)
{
iterationIndex++;
if (iterationIndex >= maxRedesignIterations)
{
throw new MaximumRedesignIterationsReachedException();
}
GeometryPoint limitPointForShoulderDesign = surfaceLine.GetLimitPointForShoulderDesign();
if (exitPointXCoordinate > limitPointForShoulderDesign.X)
{
// If exit point of circle is after the limitPointForShoulderDesign then enlarge the shoulder
// Determine new width and height for shoulder
double shoulderHeight;
double shoulderWidth;
DetermineNewShoulderWidthAndHeight(scenario.Location.StabilityShoulderGrowDeltaX,
scenario.Location.StabilityShoulderGrowSlope, surfaceLine, limitPointForShoulderDesign, out shoulderHeight, out shoulderWidth);
// Create new shoulder
var surfaceLineShoulderAdapter = new SurfaceLineShoulderAdapter(surfaceLine, scenario.Location);
surfaceLineShoulderAdapter.MaxShoulderLevel = maxShoulderLevel;
surfaceLine = surfaceLineShoulderAdapter.ConstructNewSurfaceLine(shoulderWidth, shoulderHeight, false);
var validationError = surfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error);
if (validationError != null)
{
throw new SurfaceLineException(validationError.Text);
}
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, surfaceLine);
}
else
{
// If exit point of circle is in the slope (inward) of the dike or the top of the shoulder then adapt slope
var surfaceLineSlopeAdapter = new SurfaceLineSlopeAdapter(surfaceLine, scenario.Location);
surfaceLine = surfaceLineSlopeAdapter.ConstructNewSurfaceLine(scenario.Location.StabilitySlopeAdaptionDeltaX);
var validationError = surfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error);
if (validationError != null)
{
throw new SurfaceLineException(validationError.Text);
}
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, surfaceLine);
}
scenario.Location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine);
stabilityCalculator.Calculate(scenario, soilProfileProbability.SoilProfile,
GetFullSoilGeometry2DName(soilProfileProbability.SoilGeometry2DName),
iterationIndex, mstabDesignEmbankment);
mStabResults = scenario.GetMStabResults(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
safetyFactor = mStabResults.Value.zone1.safetyFactor;
beta = scenario.GetFailureProbabilityStability(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
isRedesignRequired = IsRedesignRequired(safetyFactor, requiredSafetyFactor, betaRequired, beta);
exitPointXCoordinate = mStabResults.Value.zone1.circleSurfacePointRightXCoordinate;
}
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, "Succes");
}
catch (Exception exception)
{
string errorMessage = "FAIL: " + exception.Message;
Exception innerException = exception.InnerException;
while (innerException != null)
{
errorMessage = errorMessage + ";" + innerException.Message;
innerException = innerException.InnerException;
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, errorMessage);
// Add message to log too for output tab.
errorMessage = scenario.Location.Name + ", scenario " + scenario.LocationScenarioID + ", " + soilProfileProbability.SoilGeometryName + " " + errorMessage;
stabilityCalculator.ErrorMessages.Add(new LogMessage(LogMessageType.Error, this, errorMessage));
scenario.CalculationResult = CalculationResult.RunFailed;
// Redesign not succesful, so no redesigned surfaceline will be returned
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, null);
}
foreach (var errorMessage in stabilityCalculator.ErrorMessages)
{
errorMessages.Add(errorMessage);
}
}
///
/// Determines the new height and width of the shoulder width
///
/// The shoulder grow delta X.
/// The shoulder grow slope.
/// The surface line.
/// The limit point for shoulder design.
/// New height of the shoulder.
/// New width of the shoulder.
private static void DetermineNewShoulderWidthAndHeight(double shoulderGrowDeltaX, double shoulderGrowSlope,
SurfaceLine2 surfaceLine, GeometryPoint limitPointForShoulderDesign, out double shoulderHeight, out double shoulderWidth)
{
// Determine new shoulderpoint
var newShoulderPoint = new GeometryPoint()
{
X = limitPointForShoulderDesign.X + shoulderGrowDeltaX,
Z = limitPointForShoulderDesign.Z + shoulderGrowDeltaX*shoulderGrowSlope
};
// Determine new shoulder width and height
shoulderWidth = surfaceLine.DetermineShoulderLengthForGivenShoulderTopInside(newShoulderPoint);
shoulderHeight = newShoulderPoint.Z - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z;
}
///
/// Redesign for Stability:
/// - first do slope adaption (until required safety is reached)
/// * slope adaption is done in a range between startCoTangent and endCoTangent in steps of stepCoTangent
/// * and while the exit point of the slipcircle is in the slope (so currentCoTangent could be larger than endCoTangent
/// - than (if required safety is not reached) do shoulder adaption
/// Note: Use same slope for shoulder as for dike.
///
///
///
///
///
private void RedesignFirstSlopeAdaptionThenShoulderAdaption(Scenario scenario, StabilityCalculator stabilityCalculator,
SoilGeometryProbability soilProfileProbability)
{
Location location = scenario.Location;
double requiredSafetyFactor = scenario.ModelFactors.RequiredSafetyFactorStabilityInnerSlope ??
scenario.Location.ModelFactors.RequiredSafetyFactorStabilityInnerSlope.Value;
double betaRequired = scenario.ModelFactors.RequiredProbabilityOfFailureStabilityInnerslope ??
scenario.Location.ModelFactors.RequiredProbabilityOfFailureStabilityInnerslope.Value;
const int maxRedesignIterations = 200;
int iterationIndex = 1;
string previousFilename;
SurfaceLine2 orgSurfaceLine = scenario.Location.LocalXZSurfaceLine2;
// Create the file with the initial geometry to be used to determine which layers have to be defined as dike embankment material
CreateInitialGeometry(scenario, stabilityCalculator, soilProfileProbability, orgSurfaceLine, out previousFilename);
SurfaceLine2 surfaceLine = scenario.GetMostRecentSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName).FullDeepClone();
var mstabDesignEmbankment = new MStabDesignEmbankment
{
EmbankmentMaterialname = location.DikeEmbankmentMaterial,
PreviousGeometry2DFilename = previousFilename
};
try
{
double? beta;
bool isRedesignRequired;
double? exitPointXCoordinate;
scenario.Location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine);
stabilityCalculator.Calculate(scenario, soilProfileProbability.SoilProfile,
GetFullSoilGeometry2DName(soilProfileProbability.SoilGeometry2DName),
iterationIndex, mstabDesignEmbankment);
mstabDesignEmbankment.PreviousGeometry2DFilename = stabilityCalculator.StabilityProjectFilename;
mstabDesignEmbankment.EmbankmentMaterialname = location.ShoulderEmbankmentMaterial;
MStabResults? mStabResults = scenario.GetMStabResults(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
double? safetyFactor = mStabResults.Value.zone1.safetyFactor;
beta = scenario.GetFailureProbabilityStability(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
isRedesignRequired = IsRedesignRequired(safetyFactor, requiredSafetyFactor, betaRequired, beta);
exitPointXCoordinate = mStabResults.Value.zone1.circleSurfacePointRightXCoordinate;
if (!isRedesignRequired && surfaceLine != null)
{
// Set redesigned surfaceline to original, so in case no redesign is needed, the original surfaceline will be returned
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, surfaceLine);
}
else
{
double maxFractionOfDikeHeightForShoulderHeight = scenario.Location.UseNewMaxHeightShoulderAsFraction ?
scenario.Location.NewMaxHeightShoulderAsFraction : defaultMaxFractionOfDikeHeightForShoulderHeight;
double maxShoulderLevel = CalculateMaximumShoulderLevel(surfaceLine, maxFractionOfDikeHeightForShoulderHeight);
while (isRedesignRequired && surfaceLine != null)
{
// First slope adaption
double startCoTangent = location.SlopeAdaptionStartCotangent;
double endCoTangent = location.SlopeAdaptionEndCotangent;
double stepCoTangent = location.SlopeAdaptionStepCotangent;
var orgCotangent = surfaceLine.GetCotangentOfInnerSlope();
double coTangent = startCoTangent;
double currentCoTangent = orgCotangent;
// Find out for which cotangent we want to start designing
while (coTangent <= orgCotangent)
{
coTangent += stepCoTangent;
}
// Design for slope adaption
GeometryPoint limitPointForShoulderDesign = surfaceLine.GetLimitPointForShoulderDesign();
while (isRedesignRequired && (coTangent < endCoTangent))
{
iterationIndex++;
if (iterationIndex >= maxRedesignIterations)
{
throw new MaximumRedesignIterationsReachedException();
}
var surfaceLineSlopeAdapter = new SurfaceLineSlopeAdapter(surfaceLine, scenario.Location);
// The parameter for ConstructNewSurfaceLineBySlope is the tangent of the slope, so use reciproce value
surfaceLine = surfaceLineSlopeAdapter.ConstructNewSurfaceLineBySlope(1/coTangent);
currentCoTangent = coTangent;
var validationError = surfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error);
if (validationError != null)
{
throw new SurfaceLineException(validationError.Text);
}
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, surfaceLine);
// Recalculate new surfaceline
scenario.Location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine);
stabilityCalculator.Calculate(scenario, soilProfileProbability.SoilProfile,
GetFullSoilGeometry2DName(soilProfileProbability.SoilGeometry2DName),
iterationIndex, mstabDesignEmbankment);
mStabResults = scenario.GetMStabResults(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
safetyFactor = mStabResults.Value.zone1.safetyFactor;
exitPointXCoordinate = mStabResults.Value.zone1.circleSurfacePointRightXCoordinate;
beta = scenario.GetFailureProbabilityStability(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
isRedesignRequired = IsRedesignRequired(safetyFactor, requiredSafetyFactor, betaRequired, beta);
limitPointForShoulderDesign = surfaceLine.GetLimitPointForShoulderDesign();
coTangent += stepCoTangent;
}
// Then shoulder adaption
while (isRedesignRequired && surfaceLine != null)
{
iterationIndex++;
if (iterationIndex >= maxRedesignIterations)
{
throw new MaximumRedesignIterationsReachedException();
}
// Determine new width and height for shoulder
double shoulderHeight;
double shoulderWidth;
DetermineNewShoulderWidthAndHeight(scenario.Location.StabilityShoulderGrowDeltaX,
scenario.Location.StabilityShoulderGrowSlope, surfaceLine, limitPointForShoulderDesign, out shoulderHeight, out shoulderWidth);
// Create new shoulder
var surfaceLineShoulderAdapter = new SurfaceLineShoulderAdapter(surfaceLine, scenario.Location);
surfaceLineShoulderAdapter.MaxShoulderLevel = maxShoulderLevel;
surfaceLineShoulderAdapter.SlopeOfNewShoulder = currentCoTangent;
surfaceLine = surfaceLineShoulderAdapter.ConstructNewSurfaceLine(shoulderWidth, shoulderHeight, false);
var validationError = surfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error);
if (validationError != null)
{
throw new SurfaceLineException(validationError.Text);
}
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, surfaceLine);
// Recalculate new surfaceline
scenario.Location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine);
stabilityCalculator.Calculate(scenario, soilProfileProbability.SoilProfile,
GetFullSoilGeometry2DName(soilProfileProbability.SoilGeometry2DName),
iterationIndex, mstabDesignEmbankment);
mStabResults = scenario.GetMStabResults(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName);
safetyFactor = mStabResults.Value.zone1.safetyFactor;
beta = scenario.GetFailureProbabilityStability(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName);
isRedesignRequired = IsRedesignRequired(safetyFactor, requiredSafetyFactor, betaRequired, beta);
limitPointForShoulderDesign = surfaceLine.GetLimitPointForShoulderDesign();
}
}
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, "Succes");
}
catch (Exception exception)
{
string errorMessage = "FAIL: " + exception.Message;
Exception innerException = exception.InnerException;
while (innerException != null)
{
errorMessage = errorMessage + ";" + innerException.Message;
innerException = innerException.InnerException;
}
scenario.SetResultMessage(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, errorMessage);
scenario.CalculationResult = CalculationResult.RunFailed;
// Redesign not succesful, so no redesigned surfaceline will be returned
scenario.SetRedesignedSurfaceLine(soilProfileProbability.SoilProfile, soilProfileProbability.SoilGeometry2DName, null);
}
foreach (var errorMessage in stabilityCalculator.ErrorMessages)
{
errorMessages.Add(errorMessage);
}
}
///
/// Redesigns the surface line flow slide.
///
/// The scenario.
/// The safety factor.
/// The surface line.
private void RedesignSurfaceLineFlowSlide(Scenario scenario, double? safetyFactor, ref SurfaceLine2 surfaceLine)
{
throw new DamFailureMechanismeCalculatorException("Geometry adaption not supported for Flowslide");
}
///
/// Check if a stability redesign is required
///
///
///
///
///
///
private bool IsRedesignRequired(double? safetyFactor, double requiredSafetyFactor, double betaRequired, double? beta)
{
bool isRedesignRequired;
if (ProbabilisticType == ProbabilisticType.ProbabilisticFragility)
{
isRedesignRequired = beta > betaRequired;
}
else
{
isRedesignRequired = safetyFactor < requiredSafetyFactor;
}
return isRedesignRequired;
}
///
///
///
///
///
private PipingCalculator pipingCalculatorFactory(Location location, ModelParametersForPLLines modelParametersForPLLines, PipingModelType pipingModelType, double upliftCriterion, double requiredSafetyFactorPiping, PipingProbabilisticParameters? pipingProbabilisticParameters)
{
switch (pipingModelType)
{
case PipingModelType.Bligh:
return new PipingCalculatorBligh(modelParametersForPLLines,
requiredSafetyFactorPiping, location.GaugePLLines, location.Gauges, upliftCriterion);
case PipingModelType.Sellmeijer:
PipingProbabilisticParameters? actualPipingProbabilisticParameters = null;
if ((ProbabilisticType == ProbabilisticType.Probabilistic) || (ProbabilisticType == ProbabilisticType.ProbabilisticFragility))
{
actualPipingProbabilisticParameters = pipingProbabilisticParameters;
}
return new PipingCalculatorSellmeijer(modelParametersForPLLines,
requiredSafetyFactorPiping, location.GaugePLLines, location.Gauges, actualPipingProbabilisticParameters, upliftCriterion);
case PipingModelType.Sellmeijer2Forces:
return new PipingCalculatorSellmeijer2Forces(modelParametersForPLLines,
requiredSafetyFactorPiping, location.GaugePLLines, location.Gauges, upliftCriterion);
case PipingModelType.Sellmeijer4Forces:
return new PipingCalculatorSellmeijer4Forces(modelParametersForPLLines,
requiredSafetyFactorPiping, location.GaugePLLines, location.Gauges, upliftCriterion);
case PipingModelType.Wti2017:
return new PipingCalculatorWti2017(modelParametersForPLLines,
requiredSafetyFactorPiping, location.GaugePLLines, location.Gauges, upliftCriterion);
}
return null;
}
///
///
///
///
///
private string GetFullSoilGeometry2DName(string soilGeometry2DName)
{
if (soilGeometry2DName == null)
{
return null;
}
else
{
string fullSoilGeometry2DName = Path.Combine(DamProject.ProjectMap, Path.Combine(MapForSoilGeometries2D, soilGeometry2DName));
return fullSoilGeometry2DName;
}
}
///
/// Get the directory where to create the piping project files
///
///
private static string GetPipingCalculationBaseDirectory()
{
return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "PipingCalculation\\");
}
///
/// Calculates the maximum level for the shoulder.
///
/// The surface line.
/// The fraction of dike height to determine maximimum shoulder height.
///
private double CalculateMaximumShoulderLevel(SurfaceLine2 surfaceLine, double maxFractionOfDikeHeightForShoulderHeight)
{
var top = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).Z;
var bottom = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z;
if (top - bottom <= 0)
{
throw new SurfaceLineAdapterException(LocalizationManager.GetTranslatedText(this, "SurfaceLineShoulderAdapterMaxShoulderHeightError"));
}
double maxHeight = Math.Abs((top - bottom)*maxFractionOfDikeHeightForShoulderHeight);
return bottom + maxHeight;
}
}
}