//-----------------------------------------------------------------------
//
// Copyright (c) 2009 Deltares. All rights reserved.
//
// B.S.T.I.M. The
// tom.the@deltares.nl
// 04-06-2010
// Stability Calculator object
//-----------------------------------------------------------------------
using Deltares.Geotechnics;
using Deltares.MStab;
using Deltares.MStab.IO.Classic;
using Deltares.Stability;
using Deltares.Stability.Calculation;
using Deltares.Standard;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.Language;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using Deltares.Dam.Data.Assemblers;
using Deltares.Geotechnics.Soils;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Mathematics;
using Deltares.Soilbase;
using Deltares.Standard.IO.Xml;
using Deltares.Standard.Logging;
namespace Deltares.Dam.Data
{
public class StabilityCalculator : IDisposable
{
protected ModelParametersForPLLines modelParametersForPLLines;
private ProgramType programType;
private double trafficLoad;
private double minimalCircleDepth;
private double requiredSafetyFactor;
private string mstabProgramPath;
private string slopeWProgramPath;
private FailureMechanismeParamatersMStab failureMechanismeParamatersMStab;
private IList gaugePLLines;
private IList gauges;
private string stabilityProjectFilename = "";
private List errorMessages = new List();
public const string StabilitySubDir = @"Stability\";
public StabilityCalculator(FailureMechanismeParamatersMStab failureMechanismeParamatersMStab,
ProgramType programType,
ModelParametersForPLLines modelParametersForPLLines, double trafficLoad, double minimalCircleDepth,
double requiredSafetyFactor, string mstabProgramPath, string slopeWProgramPath,
IList gaugePLLines,
IList gauges, SoilbaseDB soilBaseDB, SoilList soilList, ProbabilisticType probabilisticType)
{
this.programType = programType;
this.modelParametersForPLLines = modelParametersForPLLines;
this.trafficLoad = trafficLoad;
this.minimalCircleDepth = minimalCircleDepth;
this.requiredSafetyFactor = requiredSafetyFactor;
this.mstabProgramPath = mstabProgramPath;
this.slopeWProgramPath = slopeWProgramPath;
// need to have own instance of failureMechanismeParamatersMStab because the calculation
// makes changes to this object (e.g. failureMechanismeParamatersMStab.PLLines)
// This will not function correctly when the calculations are performed
// multi threaded (MWDAM-568)
this.failureMechanismeParamatersMStab = failureMechanismeParamatersMStab.Clone();
this.gaugePLLines = gaugePLLines;
this.gauges = gauges;
this.SoilBaseDB = soilBaseDB;
this.SoilList = soilList;
ProbabilisticType = probabilisticType;
CalculationBaseDirectory = "";
}
public string CalculationBaseDirectory { get; set; }
public SoilbaseDB SoilBaseDB { get; set; }
public SoilList SoilList { get; set; }
public ProbabilisticType ProbabilisticType { get; set; }
public static string ModelSubDirectory = "";
private MStabProject dotNetMstabProjectResults;
public PhreaticAdaptionType? NWOPhreaticAdaption { get; set; }
///
/// Create PLLines with selected model
///
/// The location.
/// The surface line.
/// The soil profile.
/// Name of the soil geometry2 d.
/// The waterlevel.
/// The waterlevel low.
///
private PLLines CreateAllPLLines(Location location, SurfaceLine2 surfaceLine, SoilProfile soilProfile,
string soilGeometry2DName, double waterlevel, double? waterlevelLow)
{
switch (location.PLLineCreationMethod)
{
case PLLineCreationMethod.ExpertKnowledgeLinearInDike:
case PLLineCreationMethod.ExpertKnowledgeRRD:
case PLLineCreationMethod.GaugesWithFallbackToExpertKnowledgeRRD:
return CreateAllPLLinesExpertKnowledge(location, surfaceLine, soilProfile, soilGeometry2DName, waterlevel, waterlevelLow);
case PLLineCreationMethod.DupuitStatic:
return CreateAllPLLinesDupuit();
case PLLineCreationMethod.DupuitDynamic:
throw new StabilityCalculationException("PL-Line creation with DupuitDynamic not yet implemented");
default:
return null;
}
}
///
/// Create PLLines with Dupuit model
///
///
private PLLines CreateAllPLLinesDupuit()
{
return null;
}
///
/// Create PLLines with expert knowledge
///
/// The location.
/// The surface line.
/// The soil profile.
/// Name of the soil geometry2 d.
/// The waterlevel.
/// The waterlevel low.
///
private PLLines CreateAllPLLinesExpertKnowledge(Location location, SurfaceLine2 surfaceLine, SoilProfile soilProfile,
string soilGeometry2DName, double waterlevel, double? waterlevelLow)
{
PLLines plLines = null;
if (surfaceLine != null && surfaceLine.HasDike())
{
PLLinesCreator plLineCreator = new PLLinesCreator();
plLineCreator.SurfaceLine = surfaceLine;
plLineCreator.WaterLevelRiverHigh = waterlevel;
plLineCreator.WaterLevelRiverLow = waterlevelLow;
plLineCreator.IsUseLowWaterLevel = (failureMechanismeParamatersMStab.MStabParameters.GridPosition == MStabGridPosition.Left);
plLineCreator.WaterLevelPolder = location.PolderLevel;
plLineCreator.HeadInPLLine2 = location.HeadPL2;
plLineCreator.HeadInPLLine3 = location.HeadPl3;
plLineCreator.HeadInPLLine4 = location.HeadPl4;
plLineCreator.ModelParametersForPLLines = this.modelParametersForPLLines;
SoilProfile1D profile1D = soilProfile as SoilProfile1D;
if (profile1D != null)
{
plLineCreator.SoilProfile = profile1D;
plLineCreator.SoilGeometryType = SoilGeometryType.SoilGeometry1D;
}
else
{
plLineCreator.SoilGeometryType = SoilGeometryType.SoilGeometry2D;
string mapForSoilGeometries2D = location.MapForSoilGeometries2D;
soilGeometry2DName = Path.Combine(Path.Combine(DamProject.ProjectMap, mapForSoilGeometries2D), soilGeometry2DName);
plLineCreator.SoilGeometry2DName = soilGeometry2DName;
plLineCreator.SoilBaseDB = this.SoilBaseDB;
plLineCreator.SoilList = this.SoilList;
plLineCreator.DikeEmbankmentMaterial =
this.SoilList.GetSoilByName(location.DikeEmbankmentMaterial);
}
plLineCreator.GaugePLLines = this.gaugePLLines;
plLineCreator.Gauges = this.gauges;
plLineCreator.IsAdjustPL3AndPL4SoNoUpliftWillOccurEnabled = true;
// for stability this must be set to true
plLineCreator.PlLineOffsetBelowDikeTopAtRiver = location.PlLineOffsetBelowDikeTopAtRiver;
plLineCreator.PlLineOffsetBelowDikeTopAtPolder = location.PlLineOffsetBelowDikeTopAtPolder;
plLineCreator.PlLineOffsetBelowShoulderBaseInside = location.PlLineOffsetBelowShoulderBaseInside;
plLineCreator.PlLineOffsetBelowDikeToeAtPolder = location.PlLineOffsetBelowDikeToeAtPolder;
plLineCreator.PlLineOffsetBelowDikeCrestMiddle = location.PlLineOffsetBelowDikeCrestMiddle;
plLineCreator.PlLineOffsetFactorBelowShoulderCrest = location.PlLineOffsetFactorBelowShoulderCrest;
plLineCreator.UsePlLineOffsetBelowDikeCrestMiddle = location.UsePlLineOffsetBelowDikeCrestMiddle;
plLineCreator.UsePlLineOffsetFactorBelowShoulderCrest = location.UsePlLineOffsetFactorBelowShoulderCrest;
plLineCreator.NWOPhreaticAdaption = NWOPhreaticAdaption;
plLineCreator.XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin;
plLines = plLineCreator.CreateAllPLLines(location);
}
return plLines;
}
public string GetStabilityCalculationDirectory()
{
string stabilityDirectory = GetStabilityCalculationBaseDirectory();
if (StabilityCalculator.ModelSubDirectory != "")
stabilityDirectory = Path.Combine(stabilityDirectory, StabilityCalculator.ModelSubDirectory);
if (!Directory.Exists(stabilityDirectory))
Directory.CreateDirectory(stabilityDirectory);
return stabilityDirectory;
}
///
/// Get the directory where to create the MStab project files
///
///
private string GetStabilityCalculationBaseDirectory()
{
if (CalculationBaseDirectory == "")
{
CalculationBaseDirectory = DamProject.ProjectWorkingPath;
}
return Path.Combine(CalculationBaseDirectory, StabilitySubDir);
}
///
///
///
///
///
///
public void ConsistencyCheck(Scenario scenario, SoilProfile1D soilProfile, string soilGeometry2DName)
{
if (soilProfile != null)
{
if (soilProfile.BottomAquiferLayer == null)
{
throw new DamFailureMechanismeCalculatorException(
String.Format("Soilprofile '{0}' does not contain aquifer layers.", soilProfile.Name));
}
}
}
private void AddForbiddenZoneToMstabProject(MStabProject mStabProject, Scenario scenario, SurfaceLine2 surfaceLine)
{
if (failureMechanismeParamatersMStab.MStabParameters.CalculationOptions.ZonesType.Equals(
MStabZonesType.ForbiddenZone))
{
CreateForbiddenZone(scenario, surfaceLine);
AddMissingSlipPlaneConstraintInfo(mStabProject.Stability.SlipPlaneConstraints);
}
}
private void CalculateType(string stabilityProjectFilename, Scenario scenario, SoilProfile1D soilProfile,
string soilGeometry2DName,
StabilityServiceAgent stabilityServiceAgent, double riverLevel, MStabDesignEmbankment mstabDesignEmbankment)
{
//
// Here start of implementation of DesignPoint Probabilistic Calculation
// Perform DesignPoint Probabilistic Calculation when this.ProbabilisticType == ProbabilisticType.ProbabilisticAdvanced
//
if (dotNetMstabProjectResults != null)
{
dotNetMstabProjectResults.Dispose();
dotNetMstabProjectResults = null;
}
failureMechanismeParamatersMStab.MStabParameters.CalculationOptions = new MStabCalculationOptions
{
MinimalCircleDepth = this.minimalCircleDepth,
ZonesType = scenario.Location.StabilityZoneType
};
SoilProfile profile;
var surfaceLine = scenario.GetMostRecentSurfaceLine(soilProfile,
Path.GetFileName(soilGeometry2DName));
//create mstabproj using .NET, without using delphi dll and xml files
if (SelectedStabilityKernelType == StabilityKernelType.AdvancedWti)
{
profile = GetSoilProfileByType(soilProfile, scenario.Location.MapForSoilGeometries2D, soilGeometry2DName);
UpdateProfileSoilsToProjectSoils(profile);
var parameterValues = GetStabilityProjectParameterValues();
var stabilityProjectObjectCreator = new StabilityProjectObjectCreator();
MStabProject mStabProject = stabilityProjectObjectCreator.CreateMacroStabilityProject(scenario, profile, failureMechanismeParamatersMStab, riverLevel, parameterValues);
AddForbiddenZoneToMstabProject(mStabProject, scenario, surfaceLine);
RunStabilityCalculationWtiKernel(mStabProject);
return;
}
//use mstab stability kernel, create mstabproj using .NET
if (SelectedStabilityKernelType == StabilityKernelType.AdvancedDotNet)
{
profile = GetSoilProfileByType(soilProfile, scenario.Location.MapForSoilGeometries2D, soilGeometry2DName);
UpdateProfileSoilsToProjectSoils(profile);
var parameterValues = GetStabilityProjectParameterValues();
var stabilityProjectObjectCreator = new StabilityProjectObjectCreator();
MStabProject mStabProject = stabilityProjectObjectCreator.CreateMacroStabilityProject(scenario,
profile, failureMechanismeParamatersMStab, riverLevel, parameterValues);
AddForbiddenZoneToMstabProject(mStabProject, scenario, surfaceLine);
var projectString = SaveStabilityProjectFileToString(mStabProject);
RunMstabStabilityCalculation(projectString);
return;
}
XDocument mstabXML = CreateMStabXmlDoc(stabilityProjectFilename, scenario, soilProfile, soilGeometry2DName,
riverLevel, mstabDesignEmbankment, surfaceLine);
mstabXML.Save(stabilityProjectFilename + ".xml");
stabilityServiceAgent.CreateProjectFile(mstabXML.ToString());
// use the current stability kernel
if (SelectedStabilityKernelType == StabilityKernelType.DamClassic)
{
if (programType == ProgramType.SlopeW)
{
stabilityServiceAgent.CalculateSlopeWProject(stabilityProjectFilename);
}
else
{
stabilityServiceAgent.CalculateMStabProject(stabilityProjectFilename);
}
}
// use the converted .NET stability kernel
else if (SelectedStabilityKernelType == StabilityKernelType.DamClassicDotNet)
{
RunMstabStabilityCalculation(stabilityProjectFilename);
}
// use the WTI Stability Kernel, create mstabproj using delphi
else if (SelectedStabilityKernelType == StabilityKernelType.DamClassicWti)
{
MStabProject mStabProject = ReadStabilityModel(stabilityProjectFilename);
mStabProject.Stability.Location.WaterLevelRiver = riverLevel;
AddMissingSlipPlaneConstraintInfo(mStabProject.Stability.SlipPlaneConstraints);
mStabProject.Stability.SurfaceLine2 = surfaceLine;
RunStabilityCalculationWtiKernel(mStabProject);
}
}
///
/// Updates the profile soils to project soils.
///
/// The profile.
///
private void UpdateProfileSoilsToProjectSoils(SoilProfile profile)
{
// Assign the soils from the soillist to the soils in the profile
var soilProfile2D = profile as SoilProfile2D;
if (soilProfile2D != null)
{
foreach (var surface in soilProfile2D.Surfaces)
{
var soil = SoilList.GetSoilByName(surface.Soil.Name);
if (soil == null)
{
throw new StabilityCalculationException(String.Format("No matching soil found for {0}", surface.Soil.Name));
}
surface.Soil = soil;
}
}
else
{
var soilProfile1D = profile as SoilProfile1D;
if (soilProfile1D != null)
{
foreach (var layer in soilProfile1D.Layers)
{
var soil = SoilList.GetSoilByName(layer.Soil.Name);
if (soil == null)
{
throw new StabilityCalculationException(String.Format("No matching soil found for {0}", layer.Soil.Name));
}
layer.Soil = soil;
}
}
else
{
throw new StabilityCalculationException(String.Format("Profile '{0}' has unexpected soilprofile type ", profile.Name));
}
}
}
private void AddMissingSlipPlaneConstraintInfo(SlipplaneConstraints slipPlaneConstraints)
{
slipPlaneConstraints.CreateZones =
failureMechanismeParamatersMStab.MStabParameters.ZonesType == MStabZonesType.ForbiddenZone;
if (slipPlaneConstraints.CreateZones)
{
slipPlaneConstraints.SlipPlaneMinDepth = minimalCircleDepth;
if (failureMechanismeParamatersMStab.MStabParameters.ForbiddenZone.IsXEntryMaxUsed)
{
slipPlaneConstraints.XEntryMax = failureMechanismeParamatersMStab.MStabParameters.ForbiddenZone.XEntryMax;
}
else
{
slipPlaneConstraints.XEntryMax = double.NaN;
}
if (failureMechanismeParamatersMStab.MStabParameters.ForbiddenZone.IsXEntryMinUsed)
{
slipPlaneConstraints.XEntryMin = failureMechanismeParamatersMStab.MStabParameters.ForbiddenZone.XEntryMin;
}
else
{
slipPlaneConstraints.XEntryMin = double.NaN;
}
}
}
private static SoilProfile GetSoilProfileByType(SoilProfile1D soilProfile, string mapForSoilGeometries2D, string soilGeometry2DName)
{
SoilProfile profile = null;
if (soilProfile != null)
{
profile = soilProfile;
}
else
{
var projDir = Path.GetDirectoryName(DamProject.ProjectWorkingPath);
var fullPath = Path.Combine(projDir, mapForSoilGeometries2D, Path.GetFileName(soilGeometry2DName));
// Bka: for now, see if there is a dsx version too and if so prefer that.
var dsxPath = Path.ChangeExtension(fullPath, ".dsx");
MStabProject mStab = null;
//if (soilGeometry2DName.EndsWith(".dsx", StringComparison.OrdinalIgnoreCase))
if (File.Exists(dsxPath))
{
try
{
var xmlDeserializer = new XmlDeserializer();
mStab = (MStabProject) xmlDeserializer.XmlDeserialize(dsxPath, typeof (MStabProject));
}
catch (Exception ex)
{
LogManager.Add(new LogMessage(LogMessageType.Error, typeof (Converter), ex.Message));
}
if (mStab != null)
{
profile = mStab.Stability.SoilProfile;
mStab.Dispose();
}
}
else
{
var converter = new Converter();
mStab = new MStabProject();
mStab.Stability = converter.ConvertClassicMStab(fullPath);
if (mStab.Stability.SoilProfile.Surfaces != null && mStab.Stability.SoilProfile.Surfaces.Count > 0)
{
// Ensure that the bottom layer of the geometry is seen as Aquifer.
// There is no other way to get aquifer information as Delphi DGS does not work with aquifers and also not
// with soiltypes so you can not derive anything from that too.
mStab.Stability.SoilProfile.Surfaces[0].IsAquifer = true;
}
profile = mStab.Stability.SoilProfile;
mStab.Dispose();
}
}
return profile;
}
///
/// get stability project input parameters from DAM input
///
///
private StabilityProjectParameterValues GetStabilityProjectParameterValues()
{
StabilityProjectParameterValues parameterValues = new StabilityProjectParameterValues();
parameterValues.MinimalCircleDepth = minimalCircleDepth;
parameterValues.TrafficLoad = trafficLoad;
parameterValues.PhreaticAdaptionType = NWOPhreaticAdaption != null
? (PhreaticAdaptionType)NWOPhreaticAdaption
: PhreaticAdaptionType.None;
parameterValues.PLlineCreationMethod = modelParametersForPLLines.PLLineCreationMethod;
return parameterValues;
}
///
/// run stability calculation using WTI stability kernel
///
///
private void RunStabilityCalculationWtiKernel(MStabProject mStabProject)
{
StabilityModel stabilityModel = mStabProject.Stability;
stabilityModel.CalculationModel = CalculationModel.RTO;
var calculation = new Stability.Calculation2.StabilityCalculation();
calculation.RunCalculation(stabilityModel);
// Todo mstabproject still to be filled with the results from the stabilityModel calculation.
if (stabilityModel.MinimumSafetyCurve != null)
{
mStabProject.Result = CalculationResult.Succeeded;
mStabProject.SlidingData = new SlidingModel() { CurrentZone = new Zone() { MinimumSafetyCurve = stabilityModel.MinimumSafetyCurve } };
}
dotNetMstabProjectResults = mStabProject;
}
///
/// run stability calculation using classic .NET kernel
///
///
private void RunMstabStabilityCalculation(string projectString)
{
using (var calculation = new Stability.Calculation.StabilityCalculation())
{
CalculationResult loadResult = calculation.Load(projectString);
MStabProject loadedMStabProject = calculation.ClaimLoadedMStabProject();
if (loadResult == CalculationResult.Succeeded)
{
StabilityModel stabilityModel = loadedMStabProject.Stability;
stabilityModel.CalculationModel = CalculationModel.DSerie;
CalculationResult runResult = calculation.Run();
if (runResult == CalculationResult.Succeeded)
{
string results = null;
CalculationResult calculationResult = calculation.GetResults(ref results);
if (calculationResult == CalculationResult.Succeeded)
{
loadedMStabProject.ProcessResults(results);
dotNetMstabProjectResults = loadedMStabProject;
}
else
{
loadedMStabProject.Dispose();
throw new DamFailureMechanismeCalculatorException(calculation.Messages[0].Message);
}
}
}
}
}
public MStabProject GetDotNetStabilityKernelResults()
{
return dotNetMstabProjectResults;
}
private MStabProject ReadStabilityModel(string fileName)
{
MStabProject project = null;
DataEventPublisher.InvokeWithoutPublishingEvents(() =>
{
if (!fileName.EndsWith(".dsx"))
{
var converter = new Converter();
project = new MStabProject();
project.Stability = converter.ConvertClassicMStab(fileName);
}
else
{
XmlDeserializer deserializer = new XmlDeserializer();
project = (MStabProject)deserializer.XmlDeserialize(fileName, typeof(MStabProject));
}
});
return project;
}
///
/// Determine a filename based on the different inout parameters
///
///
///
///
///
///
public static string DetermineCalculationFilename(string locationName, string scenarioName,
string soilGeometryName, int iterationIndex)
{
string calculationName;
if (iterationIndex < 0)
{
calculationName = String.Format("Loc({0})_Sce({1})_Pro({2})", locationName, scenarioName,
soilGeometryName);
}
else
{
calculationName = String.Format("Loc({0})_Sce({1})_Pro({2})_Ite({3})", locationName, scenarioName,
soilGeometryName, iterationIndex);
}
return Regex.Replace(calculationName, @"[\\\/:\*\?""'<>|.]", "_");
}
///
///
///
///
///
///
///
public void Calculate(Scenario scenario, SoilProfile1D soilProfile, string soilGeometry2DName,
int iterationIndex)
{
Calculate(scenario, soilProfile, soilGeometry2DName, iterationIndex, null);
}
///
/// Calculate 1 scenario
///
///
///
///
///
public void Calculate(Scenario scenario, SoilProfile1D soilProfile, string soilGeometry2DName,
int iterationIndex, MStabDesignEmbankment mstabDesignEmbankment)
{
failureMechanismeParamatersMStab.MStabParameters.IsProbabilistic = ((this.ProbabilisticType ==
ProbabilisticType.Probabilistic) ||
(this.ProbabilisticType ==
ProbabilisticType
.ProbabilisticFragility));
string soilGeometryName;
if (!string.IsNullOrEmpty(soilGeometry2DName))
{
soilGeometryName = Path.GetFileName(soilGeometry2DName);
}
else
{
soilGeometryName = soilProfile.Name;
}
string calculationName = DetermineCalculationFilename(scenario.Location.Name, scenario.LocationScenarioID,
soilGeometryName, iterationIndex);
try
{
StabilityServiceAgent stabilityServiceAgent = new StabilityServiceAgent();
stabilityServiceAgent.ProgramType = this.programType;
stabilityServiceAgent.SlopeWExePath = this.slopeWProgramPath;
stabilityServiceAgent.MStabExePath = this.mstabProgramPath;
string stabilityDirectory = GetStabilityCalculationDirectory();
string filenameExtension = GetFilenameExtension();
string fileName = calculationName + filenameExtension;
stabilityProjectFilename = Path.Combine(stabilityDirectory, fileName);
MStabResults mStabResults = new MStabResults();
mStabResults.Init();
switch (ProbabilisticType)
{
case ProbabilisticType.Deterministic:
{
CalculateType(stabilityProjectFilename, scenario, soilProfile, soilGeometry2DName,
stabilityServiceAgent, scenario.RiverLevel, mstabDesignEmbankment);
scenario.SetFailureProbabilityStability(soilProfile, Path.GetFileName(soilGeometry2DName), null);
break;
}
case ProbabilisticType.Probabilistic:
{
CalculateType(stabilityProjectFilename, scenario, soilProfile, soilGeometry2DName,
stabilityServiceAgent, scenario.RiverLevel, mstabDesignEmbankment);
double beta = 0;
beta = stabilityServiceAgent.ExtractBeta(stabilityProjectFilename);
scenario.SetFailureProbabilityStability(soilProfile, soilGeometry2DName,
Probabilistic.Probabilistic.NormalDistribution(-beta));
break;
}
case ProbabilisticType.ProbabilisticFragility:
{
double[] waterLevels = scenario.DetermineProperWaterlevelsForProbabilisticAdvanced();
double[] betas = new double[3];
for (int i = 0; i < 3; i++)
{
string fileNameAdvanced = calculationName + "_WL" + i + ".sti";
stabilityProjectFilename = Path.Combine(stabilityDirectory, fileNameAdvanced);
CalculateType(stabilityProjectFilename, scenario, soilProfile, soilGeometry2DName,
stabilityServiceAgent, waterLevels[i], mstabDesignEmbankment);
betas[i] = stabilityServiceAgent.ExtractBeta(stabilityProjectFilename);
}
var designPointWater = new DesignPointCalculation();
designPointWater.Waterlevels = waterLevels;
designPointWater.Betas = betas;
// 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!
designPointWater.MHW = (double)(scenario.RiverLevel + scenario.WaterHeightDecimeringsHoogte);
designPointWater.Decimate = (double)scenario.WaterHeightDecimeringsHoogte;
designPointWater.Exceed = DesignPointCalculation.ExceedingSet.twoThousend;
designPointWater.IsMaxLevelUsed = false;
designPointWater.MaxLevel = 0;
if (designPointWater.CalculateTheWaterDesignpoint())
{
scenario.SetFailureProbabilityStability(soilProfile, soilGeometry2DName,
Probabilistic.Probabilistic.NormalDistribution(-designPointWater.Beta));
}
break;
}
}
if (SelectedStabilityKernelType == StabilityKernelType.DamClassic)
{
mStabResults = stabilityServiceAgent.ExtractStabilityResults(stabilityProjectFilename);
mStabResults = SetMStabAdministrationResults(mStabResults, iterationIndex, calculationName);
DetermineMStabResultsEntryPoint(ref mStabResults,
failureMechanismeParamatersMStab.MStabParameters.GridPosition);
DetermineMStabResultsExitPoint(ref mStabResults,
failureMechanismeParamatersMStab.MStabParameters.GridPosition);
scenario.SetMStabResults(soilProfile, Path.GetFileName(soilGeometry2DName), mStabResults);
}
else
{
if (dotNetMstabProjectResults != null)
{
string stabilityResultsFileName = stabilityProjectFilename.Replace("sti", "dsx");
if (File.Exists(stabilityResultsFileName))
{
File.Delete(stabilityResultsFileName);
}
var filledGeometry = dotNetMstabProjectResults.Geometry;
// Todo het juist vullen van het Mstab project met alle waarden op de benodige plek (iom Rob) dus ook de results
SaveStabilityProjectToDsxFile(stabilityResultsFileName, dotNetMstabProjectResults);
mStabResults = ExtractDotNetStabilityKernelResults();
mStabResults = SetMStabAdministrationResults(mStabResults, iterationIndex, calculationName);
if (dotNetMstabProjectResults.Stability.MinimumSafetyCurve == null &&
!IsSlidingDataMinimumSafetyCurveAvailable())
{
return;
}
var cn = Path.GetFileNameWithoutExtension(stabilityResultsFileName);
mStabResults.CalculationName = cn;
DetermineDotNetStabilityKernelResultsEntryPoint(mStabResults);
// TODO: Exit point is not read correctly
DetermineDotNetStabilityKernelResultsExitPoint(mStabResults);
scenario.SetMStabResults(soilProfile, Path.GetFileName(soilGeometry2DName), mStabResults);
}
}
}
catch (Exception e)
{
throw new DamFailureMechanismeCalculatorException(
String.Format("Error calculating stability factor for '{0}'", calculationName), e);
}
}
private static MStabResults SetMStabAdministrationResults(MStabResults mStabResults, int iterationIndex,
string calculationName)
{
mStabResults.CalculationName = calculationName;
mStabResults.CalculationSubDir = StabilitySubDir;
mStabResults.IterationNumber = iterationIndex;
if (StabilityCalculator.ModelSubDirectory != "")
{
mStabResults.CalculationSubDir = Path.Combine(mStabResults.CalculationSubDir,
StabilityCalculator.ModelSubDirectory);
}
return mStabResults;
}
private bool IsSlidingDataMinimumSafetyCurveAvailable()
{
var notAvailable = dotNetMstabProjectResults.SlidingData == null ||
dotNetMstabProjectResults.SlidingData.CurrentZone == null ||
dotNetMstabProjectResults.SlidingData.CurrentZone.MinimumSafetyCurve == null;
return !notAvailable;
}
private MStabResults ExtractDotNetStabilityKernelResults()
{
MStabResults mStabResults = new MStabResults();
if (dotNetMstabProjectResults.Stability.HasZonePlot)
{
throw new NotImplementedException("Zoning features are not implementen yet in the Wti Stability kernel");
}
else
{
if (dotNetMstabProjectResults.Stability.MinimumSafetyCurve == null)
{
if (!IsSlidingDataMinimumSafetyCurveAvailable())
{
return mStabResults;
}
else
{
dotNetMstabProjectResults.Stability.MinimumSafetyCurve =
dotNetMstabProjectResults.SlidingData.CurrentZone.MinimumSafetyCurve;
}
}
double safetyFactor = dotNetMstabProjectResults.Stability.MinimumSafetyCurve.SafetyFactor;
mStabResults.zone1.safetyFactor = safetyFactor;
mStabResults.zone1.circleSurfacePointLeftXCoordinate = dotNetMstabProjectResults.Stability.MinimumSafetyCurve.LeftPoint.X;
mStabResults.zone1.circleSurfacePointRightXCoordinate = dotNetMstabProjectResults.Stability.MinimumSafetyCurve.RightPoint.X;
if (dotNetMstabProjectResults.Stability.ModelOption == ModelOptions.UpliftVan ||
dotNetMstabProjectResults.Stability.ModelOption == ModelOptions.UpliftSpencer)
{
mStabResults.zone1.safetyFactor = safetyFactor / 1.05;
}
}
return mStabResults;
}
private void DetermineDotNetStabilityKernelResultsExitPoint(MStabResults results)
{
if (dotNetMstabProjectResults.Stability.GridOrientation == GridOrientation.Outwards)
{
if (dotNetMstabProjectResults.Stability.MinimumSafetyCurve.LeftPoint != null)
{
// Outward stability
results.zone1.exitPointXCoordinate = dotNetMstabProjectResults.Stability.MinimumSafetyCurve.LeftPoint.X;
if (results.zone2.HasValue)
{
}
}
}
else
{
// Inward stability
if (dotNetMstabProjectResults.Stability.MinimumSafetyCurve.RightPoint != null)
{
results.zone1.exitPointXCoordinate = dotNetMstabProjectResults.Stability.MinimumSafetyCurve.RightPoint.X;
if (results.zone2.HasValue)
{
}
}
}
}
private void DetermineDotNetStabilityKernelResultsEntryPoint(MStabResults mStabResults)
{
if (dotNetMstabProjectResults.Stability.GridOrientation == GridOrientation.Outwards)
{
if (dotNetMstabProjectResults.Stability.MinimumSafetyCurve.RightPoint != null)
{
mStabResults.zone1.entryPointXCoordinate =
dotNetMstabProjectResults.Stability.MinimumSafetyCurve.RightPoint.X;
if (mStabResults.zone2.HasValue)
{
/*MStabResultsSingleZone zone = mstabResults.zone2.Value;
zone.entryPointXCoordinate = zone.circleSurfacePointRightXCoordinate;
mstabResults.zone2 = zone;*/
}
}
}
else
{
if (dotNetMstabProjectResults.Stability.MinimumSafetyCurve.LeftPoint != null)
{
// Inward stability
mStabResults.zone1.entryPointXCoordinate =
dotNetMstabProjectResults.Stability.MinimumSafetyCurve.LeftPoint.X;
if (mStabResults.zone2.HasValue)
{
/*MStabResultsSingleZone zone = mstabResults.zone2.Value;
zone.entryPointXCoordinate = zone.circleSurfacePointLeftXCoordinate;
mstabResults.zone2 = zone;*/
}
}
}
}
///
/// Determine filename extension according to which failuremechanism is used
///
///
public string GetFilenameExtension()
{
string filenameExtension;
if (programType == ProgramType.SlopeW)
{
filenameExtension = ".xml";
}
else
{
filenameExtension = ".sti";
}
return filenameExtension;
}
///
/// Depending on outward/inward stability (position of grid) the entrypoint of the slipcricle is determined
///
///
///
private void DetermineMStabResultsEntryPoint(ref MStabResults mstabResults, MStabGridPosition mstabGridPosition)
{
if (mstabGridPosition == MStabGridPosition.Left)
{
// Outward stability
mstabResults.zone1.entryPointXCoordinate = mstabResults.zone1.circleSurfacePointRightXCoordinate;
if (mstabResults.zone2.HasValue)
{
MStabResultsSingleZone zone = mstabResults.zone2.Value;
zone.entryPointXCoordinate = zone.circleSurfacePointRightXCoordinate;
mstabResults.zone2 = zone;
}
}
else
{
// Inward stability
mstabResults.zone1.entryPointXCoordinate = mstabResults.zone1.circleSurfacePointLeftXCoordinate;
if (mstabResults.zone2.HasValue)
{
MStabResultsSingleZone zone = mstabResults.zone2.Value;
zone.entryPointXCoordinate = zone.circleSurfacePointLeftXCoordinate;
mstabResults.zone2 = zone;
}
}
}
///
/// Depending on outward/inward stability (position of grid) the exitpoint of the slipcricle is determined
///
///
///
private void DetermineMStabResultsExitPoint(ref MStabResults mstabResults, MStabGridPosition mstabGridPosition)
{
if (mstabGridPosition == MStabGridPosition.Left)
{
// Outward stability
mstabResults.zone1.exitPointXCoordinate = mstabResults.zone1.circleSurfacePointLeftXCoordinate;
if (mstabResults.zone2.HasValue)
{
MStabResultsSingleZone zone = mstabResults.zone2.Value;
zone.exitPointXCoordinate = zone.circleSurfacePointLeftXCoordinate;
mstabResults.zone2 = zone;
}
}
else
{
// Inward stability
mstabResults.zone1.exitPointXCoordinate = mstabResults.zone1.circleSurfacePointRightXCoordinate;
if (mstabResults.zone2.HasValue)
{
MStabResultsSingleZone zone = mstabResults.zone2.Value;
zone.exitPointXCoordinate = zone.circleSurfacePointRightXCoordinate;
mstabResults.zone2 = zone;
}
}
}
private void CreateForbiddenZone(Scenario scenario, SurfaceLine2 surfaceLine)
{
var dikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder);
// Zonestype is ForbiddenZone; TODO: Combine with code in StabilityCalculator?
double maxZoneX = dikeTopAtPolder.X +
scenario.Location.ForbiddenZoneFactor * (surfaceLine.GetDikeToeInward().X - dikeTopAtPolder.X);
failureMechanismeParamatersMStab.MStabParameters.ForbiddenZone = new MStabForbiddenZone
{
IsXEntryMinUsed = false,
XEntryMin = 0.0,
IsXEntryMaxUsed = true,
XEntryMax = maxZoneX
};
}
///
/// Create XML definition for Stability calculation
///
///
///
///
///
///
///
///
///
public XDocument CreateMStabXmlDoc(string mstabProjectFilename, Scenario scenario, SoilProfile soilProfile,
string soilGeometry2DName, double riverLevel,
MStabDesignEmbankment mstabDesignEmbankment, SurfaceLine2 surfaceLine)
{
SoilProfile1D profile1D = soilProfile as SoilProfile1D;
SoilProfile2D profile2D = soilProfile as SoilProfile2D;
ConsistencyCheck(scenario, profile1D, soilGeometry2DName);
failureMechanismeParamatersMStab.Location = scenario.Location;
if (profile1D != null)
{
failureMechanismeParamatersMStab.SoilProfile = profile1D;
// 1d-geometry
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.SoilGeometryType =
SoilGeometryType.SoilGeometry1D;
}
else
{
// 2d-geometry
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.SoilGeometryType =
SoilGeometryType.SoilGeometry2D;
}
// Geometry Creation Options
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.SoilGeometry2DFilename =
soilGeometry2DName;
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.MaterialForDike =
scenario.Location.DikeEmbankmentMaterial;
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.MaterialForShoulder =
scenario.Location.ShoulderEmbankmentMaterial;
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.IsUseOriginalPLLineAssignments =
scenario.Location.IsUseOriginalPLLineAssignments;
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.IsDesign =
(mstabDesignEmbankment != null);
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.XOffsetSoilGeometry2DOrigin =
-scenario.Location.XSoilGeometry2DOrigin;
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.PLLineAssignment =
CalculationHelper.PLLineCreationMethod2PLLineAssignment(scenario.Location.PLLineCreationMethod);
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.IntrusionVerticalWaterPressureType =
scenario.Location.IntrusionVerticalWaterPressure.Value;
failureMechanismeParamatersMStab.MStabParameters.GeometryCreationOptions.PenetrationLength =
scenario.Location.PenetrationLength;
// End of Geometry Creation Options
// Design options
failureMechanismeParamatersMStab.Design = mstabDesignEmbankment;
failureMechanismeParamatersMStab.SurfaceLine = surfaceLine;
failureMechanismeParamatersMStab.RiverLevel = riverLevel; // scenario.RiverLevel;
failureMechanismeParamatersMStab.DikeTableHeight =
scenario.DikeTableHeight ?? surfaceLine.GetDefaultDikeTableHeight() ?? 0;
failureMechanismeParamatersMStab.TrafficLoad = this.trafficLoad;
// Horizontal balance; TODO: Combine with code in StabilityCalculation
if (failureMechanismeParamatersMStab.MStabParameters.Model == MStabModelType.HorizontalBalance)
{
if (profile1D == null)
{
throw new DamFailureMechanismeCalculatorException(
"Model horizontal balance does not support 2d-geometries");
}
failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea = new HorizontalBalanceArea();
failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea.XLeft =
surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X;
failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea.XRight =
surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X;
failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea.YTop = riverLevel;
failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea.YBottom =
profile1D.InBetweenAquiferLayer != null
? profile1D.InBetweenAquiferLayer.TopLevel
: profile1D.BottomAquiferLayer.TopLevel;
int planeCount =
(int)(Math.Round((failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea.YTop -
failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea.YBottom) / 0.25));
failureMechanismeParamatersMStab.MStabParameters.HorizontalBalanceArea.PlaneCount = Math.Min(planeCount, 50);
}
// Zonestype is ZoneAreas; TODO: Combine with code in StabilityCalculation
var dikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder);
if (
failureMechanismeParamatersMStab.MStabParameters.CalculationOptions.ZonesType.Equals(
MStabZonesType.ZoneAreas))
{
double? dikeTableHeight = scenario.DikeTableHeight ?? surfaceLine.GetDefaultDikeTableHeight() ?? null;
if (!dikeTableHeight.HasValue)
throw new DamFailureMechanismeCalculatorException("Surface line has no dike table height.");
failureMechanismeParamatersMStab.MStabParameters.ZoneAreas = new MStabZoneAreas
{
DikeTableHeight = dikeTableHeight.Value,
DikeTableWidth = scenario.Location.ZoneAreaRestSlopeCrestWidth,
SafetyFactorZone1A = scenario.ModelFactors.RequiredSafetyFactorStabilityInnerSlope ?? this.requiredSafetyFactor,
SafetyFactorZone1B = scenario.ModelFactors.RequiredSafetyFactorStabilityInnerSlope ?? this.requiredSafetyFactor,
XCoordinateDikeTopAtPolder = dikeTopAtPolder.X,
XCoordinateDikeTopAtRiver = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver).X,
XCoordinateStartRestProfile = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver).X
};
}
if (failureMechanismeParamatersMStab.MStabParameters.CalculationOptions.ZonesType.Equals(
MStabZonesType.ForbiddenZone))
{
CreateForbiddenZone(scenario, surfaceLine);
}
// Make sure riverlevel is correct with respect to surfaceline
double riverLevelLow = double.NaN;
if (failureMechanismeParamatersMStab.MStabParameters.GridPosition == MStabGridPosition.Left && scenario.RiverLevelLow.HasValue)
{
riverLevelLow = scenario.RiverLevelLow.Value;
}
double? riverLevelHigh = riverLevel;
var surfaceLevelOutside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside);
if (riverLevelHigh < surfaceLevelOutside.Z)
{
var riverLevelHighIsBelowSurfaceLevelOutside = Path.GetFileName(mstabProjectFilename) + ": " +
LocalizationManager.GetTranslatedText(this.GetType(),
"riverLevelHighIsBelowSurfaceLevelOutside");
LogMessage logMessage = new LogMessage(LogMessageType.Warning, null,
String.Format(riverLevelHighIsBelowSurfaceLevelOutside, riverLevelHigh,
surfaceLevelOutside.Z));
errorMessages.Add(logMessage);
}
var currentSurfaceLine = scenario.GetMostRecentSurfaceLine(soilProfile, Path.GetFileName(soilGeometry2DName));
if (currentSurfaceLine == null)
{
currentSurfaceLine = surfaceLine;
}
if (SelectedStabilityKernelType == StabilityKernelType.AdvancedWti ||
SelectedStabilityKernelType == StabilityKernelType.AdvancedDotNet)
{
var lphreaticAdaptionType = NWOPhreaticAdaption != null
? (PhreaticAdaptionType)NWOPhreaticAdaption
: PhreaticAdaptionType.None;
var stabilityProjectObjectCreator = new StabilityProjectObjectCreator();
failureMechanismeParamatersMStab.PLLines = stabilityProjectObjectCreator.CreateAllPlLinesUsingWaternetCreator(scenario.Location,
currentSurfaceLine, soilProfile, lphreaticAdaptionType, modelParametersForPLLines.PenetrationLength, riverLevelHigh.Value, modelParametersForPLLines.PLLineCreationMethod, riverLevelLow);
}
else
{
failureMechanismeParamatersMStab.PLLines = CreateAllPLLines(scenario.Location, currentSurfaceLine,
soilProfile, soilGeometry2DName, riverLevelHigh.Value, riverLevelLow);
}
// Slip circle definition for Uplift Van; TODO: Combine with code in StabilityCalculation
if (this.failureMechanismeParamatersMStab.MStabParameters.Model == MStabModelType.UpliftVan)
{
// Determine right side of slip plane grid (right grid)
// This is the location with the lowest uplift factor or, if present, the second NWO point
var upliftLocationAndResult = this.GetLocationWithLowestUpliftFactor(currentSurfaceLine, soilProfile,
soilGeometry2DName,
failureMechanismeParamatersMStab.PLLines,
scenario.Location);
double upliftCriterion =
scenario.GetUpliftCriterionStability(scenario.Location.ModelFactors.UpliftCriterionStability);
bool isUplift = !(upliftLocationAndResult == null) &&
(upliftLocationAndResult.UpliftFactor < upliftCriterion);
double xCoordinateLastUpliftPoint = isUplift
? upliftLocationAndResult.X
: currentSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X;
var nonWaterRetaining2 = currentSurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.NonWaterRetainingObjectPoint2);
if (nonWaterRetaining2 !=
null)
{
xCoordinateLastUpliftPoint =
nonWaterRetaining2.X;
}
failureMechanismeParamatersMStab.MStabParameters.SlipCircleDefinition.XCoordinateLastUpliftPoint =
xCoordinateLastUpliftPoint;
}
failureMechanismeParamatersMStab.MStabParameters.ProjectFileName = mstabProjectFilename;
failureMechanismeParamatersMStab.MStabParameters.SoilDatabaseName = scenario.Location.SoildatabaseName;
if (!failureMechanismeParamatersMStab.IsComplete)
{
throw new Exception("Not all required data is available");
}
DamMStabAssembler assembler = new DamMStabAssembler();
XDocument mstabXML = assembler.CreateDataTransferObject(failureMechanismeParamatersMStab);
return mstabXML;
}
///
/// Determines which MStabResults of 2, contains the smallest safety factor
///
///
///
/// MStab results with the minimum safety factor
public static MStabResults MinMStabResults(MStabResults mStabResults1, MStabResults mStabResults2)
{
if (mStabResults2.zone1.safetyFactor < mStabResults1.zone1.safetyFactor)
{
return mStabResults2;
}
else
{
return mStabResults1;
}
}
///
/// This is the place where we determine where the DGeoStability executable is located
///
public static string MStabExePath
{
get
{
return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
@"DGeoStability.exe");
}
}
public string StabilityProjectFilename
{
get { return stabilityProjectFilename; }
}
public List ErrorMessages
{
get { return errorMessages; }
set { errorMessages = value; }
}
// option of various computation kernel types
public StabilityKernelType SelectedStabilityKernelType { get; set; }
///
/// save stability project to dsx file
///
///
///
public void SaveStabilityProjectToDsxFile(string fileName, MStabProject project)
{
DataEventPublisher.InvokeWithoutPublishingEvents(() =>
{
var xmlSerializer = new XmlSerializer();
xmlSerializer.Serialize(project, fileName, AppDomain.CurrentDomain.BaseDirectory + "Mstab.xsl");
});
}
private string SaveStabilityProjectFileToString(object stabilityProject)
{
var xmlSerializer = new XmlSerializer();
return xmlSerializer.SerializeToString(stabilityProject);
}
///
/// Gets the location with lowest uplift factor.
///
/// The surface line.
/// The soil profile.
/// Name of the soil geometry2 D.
/// The pl lines.
/// The location.
///
public UpliftLocationAndResult GetLocationWithLowestUpliftFactor(SurfaceLine2 surfaceLine,
SoilProfile soilProfile, string soilGeometry2DName, PLLines plLines, Location location)
{
var profile1D = soilProfile as SoilProfile1D;
var profile2D = soilProfile as SoilProfile2D;
UpliftLocationDeterminator upliftLocationDeterminator = new UpliftLocationDeterminator()
{
SurfaceLine = surfaceLine,
SoilProfile = profile1D,
SoilProfile2D = profile2D,
SoilGeometry2DName = soilGeometry2DName,
SoilBaseDB = location.SoilbaseDB,
SoilList = location.SoilList,
DikeEmbankmentMaterial = location.GetDikeEmbankmentSoil(),
PLLines = plLines,
XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin
};
return upliftLocationDeterminator.GetLocationAtWithLowestUpliftFactor();
}
public void Dispose()
{
if (dotNetMstabProjectResults != null)
{
dotNetMstabProjectResults.Dispose();
}
}
}
}