// Copyright (C) Stichting Deltares 2021. All rights reserved.
//
// This file is part of the Dam Engine.
//
// The Dam Engine is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using Deltares.DamEngine.Calculators.DikesDesign;
using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces;
using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon;
using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon.MacroStabilityIo;
using Deltares.DamEngine.Calculators.Properties;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.Results;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.MacroStability.CSharpWrapper;
using Deltares.MacroStability.CSharpWrapper.Input;
using Deltares.MacroStability.CSharpWrapper.Output;
using Deltares.StixFileWriter;
using CharacteristicPointType = Deltares.DamEngine.Data.Geotechnics.CharacteristicPointType;
using GeometryPoint = Deltares.DamEngine.Data.Geometry.GeometryPoint;
using LogMessage = Deltares.DamEngine.Data.Standard.Logging.LogMessage;
using LogMessageType = Deltares.DamEngine.Data.Standard.Logging.LogMessageType;
using Soil = Deltares.DamEngine.Data.Geotechnics.Soil;
namespace Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityInwards
{
public class MacroStabilityInwardsKernelWrapper : IKernelWrapper
{
private Calculator stabilityCalculator;
private string fileNameForCalculation;
private int lastIterationIndex;
///
/// Gets or sets the failure mechanism parameters for MStab.
///
///
/// The failure mechanism parameters MStab.
///
public FailureMechanismParametersMStab FailureMechanismParametersMStab { get; set; }
///
/// Prepares the specified dam kernel input.
///
/// The dam kernel input.
/// The number of the current iteration.
/// The kernel data input.
/// The kernel data output
///
/// Result of the prepare
///
public PrepareResult Prepare(DamKernelInput damKernelInput, int iterationIndex, out IKernelDataInput kernelDataInput, out IKernelDataOutput kernelDataOutput)
{
fileNameForCalculation = "";
var macroStabilityInput = new MacroStabilityKernelDataInput();
kernelDataInput = macroStabilityInput;
var macroStabilityOutput = new MacroStabilityOutput
{
CalculationResult = CalculationResult.NoRun
};
kernelDataOutput = macroStabilityOutput;
if (damKernelInput.SubSoilScenario.SegmentFailureMechanismType != null &&
damKernelInput.SubSoilScenario.SegmentFailureMechanismType.Value == SegmentFailureMechanismType.Stability)
{
try
{
EnsureSoilProfile2DIsFilled(damKernelInput.SubSoilScenario, damKernelInput.Location.SurfaceLine, damKernelInput.Location.GetDikeEmbankmentSoil());
const bool useRivelLevelLow = false;
var plLines = UpliftHelper.DeterminePlLinesForStability(damKernelInput, useRivelLevelLow, out var upliftSituation);
var left = damKernelInput.Location.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).X;
var right = damKernelInput.Location.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X;
var penetrationLength = damKernelInput.Location.ModelParametersForPlLines.PenetrationLength;
var soilProfile1D = damKernelInput.SubSoilScenario.SoilProfile2D.GetSoilProfile1D(
damKernelInput.Location.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X);
var waterNet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile1D, penetrationLength, left, right);
var fillMacroStabilityWrapperFromEngine = new FillMacroStabilityWrapperInputFromEngine();
var slipCircleDefinition = damKernelInput.DamFailureMechanismeCalculationSpecification
.FailureMechanismParametersMStab.MStabParameters.SlipCircleDefinition;
switch (FailureMechanismParametersMStab.MStabParameters.Model)
{
case MStabModelType.Bishop:
{
// Define slip circle Bishop
var minimumCircleDepth = damKernelInput.DamFailureMechanismeCalculationSpecification
.FailureMechanismParametersMStab.MStabParameters.CalculationOptions.MinimalCircleDepth;
var bishopCalculationGrid = BishopGridCreator.DetermineGridsFromSettings(
slipCircleDefinition, damKernelInput.Location.SurfaceLine);
var centerOfLeftGridXCoordinate = (bishopCalculationGrid.GridXLeft + bishopCalculationGrid.GridXRight) * 0.5;
var soilProfile1DAtCenterOfLeftGridXCoordinate =
damKernelInput.SubSoilScenario.DetermineSoilProfile1DAtX(centerOfLeftGridXCoordinate, damKernelInput.Location.SurfaceLine,
damKernelInput.Location.GetDikeEmbankmentSoil());
BishopGridCreator.DetermineTangentLines(bishopCalculationGrid, slipCircleDefinition,
soilProfile1DAtCenterOfLeftGridXCoordinate, minimumCircleDepth);
fillMacroStabilityWrapperFromEngine.BishopCalculationGrid = bishopCalculationGrid;
break;
}
case MStabModelType.UpliftVan:
{
// Determine whether there is uplift
upliftSituation.IsUplift = UpliftHelper.DetermineIsUplift(plLines, damKernelInput.Location, damKernelInput.SubSoilScenario);
macroStabilityOutput.UpliftSituation = upliftSituation;
if (!upliftSituation.IsUplift)
{
return PrepareResult.NotRelevant;
}
// Define traffic load
TrafficLoad trafficLoad = null;
if (damKernelInput.Location.StabilityOptions != null && damKernelInput.Location.StabilityOptions.TrafficLoad.HasValue &&
!(Math.Abs(damKernelInput.Location.StabilityOptions.TrafficLoad.Value) < 1e-6))
{
trafficLoad = new TrafficLoad
{
Pressure = damKernelInput.Location.StabilityOptions.TrafficLoad.Value,
XStart = damKernelInput.Location.SurfaceLine
.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadInside).X,
XEnd = damKernelInput.Location.SurfaceLine
.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadOutside).X
};
}
// Define slip circle UpliftVan
var minimumCircleDepth = damKernelInput.DamFailureMechanismeCalculationSpecification
.FailureMechanismParametersMStab.MStabParameters.CalculationOptions.MinimalCircleDepth;
var upliftVanCalculationGrid = UpliftVanGridCreator.DetermineGridsFromSettings(
slipCircleDefinition, damKernelInput.Location.SurfaceLine);
var centerOfLeftGridXCoordinate =
(upliftVanCalculationGrid.LeftGridXLeft + upliftVanCalculationGrid.LeftGridXRight) * 0.5;
var soilProfile1DAtCenterOfLeftGridXCoordinate =
damKernelInput.SubSoilScenario.DetermineSoilProfile1DAtX(centerOfLeftGridXCoordinate, damKernelInput.Location.SurfaceLine,
damKernelInput.Location.GetDikeEmbankmentSoil());
UpliftVanGridCreator.DetermineTangentLines(upliftVanCalculationGrid, slipCircleDefinition,
soilProfile1DAtCenterOfLeftGridXCoordinate, minimumCircleDepth);
fillMacroStabilityWrapperFromEngine.TrafficLoad = trafficLoad;
fillMacroStabilityWrapperFromEngine.UpliftVanCalculationGrid = upliftVanCalculationGrid;
break;
}
default:
throw new ArgumentOutOfRangeException(nameof(FailureMechanismParametersMStab.MStabParameters.Model));
}
macroStabilityInput.Input = fillMacroStabilityWrapperFromEngine.CreateMacroStabilityInput(damKernelInput, FailureMechanismParametersMStab, waterNet);
fileNameForCalculation = GetStabilityInputFileName(damKernelInput, iterationIndex, FailureMechanismParametersMStab.MStabParameters.Model);
var inputForStixFile = macroStabilityInput.Input;
if (slipCircleDefinition.GridSizeDetermination != GridSizeDetermination.Specified)
{
var surfaceLine = damKernelInput.Location.SurfaceLine;
switch (FailureMechanismParametersMStab.MStabParameters.Model)
{
case MStabModelType.Bishop:
BishopGridCreator.DetermineStixGrid(slipCircleDefinition, surfaceLine, inputForStixFile.StabilityModel.BishopCalculationCircle.Grid);
break;
case MStabModelType.UpliftVan:
UpliftVanGridCreator.DetermineStixGrids(slipCircleDefinition, surfaceLine, inputForStixFile.StabilityModel.UpliftVanCalculationGrid);
break;
default:
throw new ArgumentOutOfRangeException(nameof(FailureMechanismParametersMStab.MStabParameters.Model));
}
}
WriteStixFileBasedOnInputAndSearchGrid(fileNameForCalculation, inputForStixFile);
return PrepareKernel(macroStabilityInput.Input);
}
catch(Exception e)
{
macroStabilityOutput.Message = new LogMessage { MessageType = LogMessageType.FatalError, Message = e.Message };
kernelDataOutput = macroStabilityOutput;
return PrepareResult.Failed;
}
}
kernelDataInput = null;
return PrepareResult.NotRelevant;
}
private void EnsureSoilProfile2DIsFilled(SoilGeometryProbability subSoilScenario, SurfaceLine2 surfaceLine2, Soil dikeEmbankmentSoil)
{
var soilProfile2D = subSoilScenario.SoilProfile2D;
if (soilProfile2D == null)
{
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = subSoilScenario.SoilProfile1D,
SurfaceLine2 = surfaceLine2,
Name = subSoilScenario.SoilProfile1D.Name,
DikeEmbankmentMaterial = dikeEmbankmentSoil
};
// Convert the soilsurfacesoilprofile to a SoilProfile2D to be able to edit it properly.
var soilProfile2DNew = soilSurfaceProfile.ConvertToSoilProfile2D();
subSoilScenario.SoilProfile2D = soilProfile2DNew;
subSoilScenario.SoilProfile2DName = soilProfile2DNew.Name;
subSoilScenario.SoilProfileType = SoilProfileType.ProfileType2D;
subSoilScenario.SoilProfile1D = null;
}
}
private PrepareResult PrepareKernel(MacroStabilityInput input)
{
try
{
stabilityCalculator = new Calculator(input);
// For now a simple check to see if any data has been past at all.
var inputAsXml = stabilityCalculator.KernelInputXml;
File.WriteAllText(fileNameForCalculation, inputAsXml);
if (inputAsXml.Length > 10)
{
return PrepareResult.Successful;
}
else
{
return PrepareResult.Failed;
}
}
catch
{
return PrepareResult.Failed;
}
}
///
/// Validates the specified kernel data input.
///
/// The kernel data input.
/// The kernel data output.
/// The return messages.
///
/// Zero when there are no errors, one when there are errors that prevent a calculation
///
public int Validate(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out List messages)
{
MacroStabilityKernelDataInput macroStabilityKernelDataInput = (MacroStabilityKernelDataInput)kernelDataInput;
messages = new List();
try
{
var result = new Validator(macroStabilityKernelDataInput.Input).Validate();
if (result.IsValid)
{
return 0;
}
if (kernelDataOutput != null)
{
((MacroStabilityOutput)kernelDataOutput).CalculationResult = CalculationResult.InvalidInputData;
}
foreach (var resultMessage in result.Messages)
{
var message = new LogMessage();
message.Message = resultMessage.Content;
switch (resultMessage.MessageType)
{
case MessageType.Error:
{
message.MessageType = LogMessageType.Error;
break;
}
case MessageType.Info:
{
message.MessageType = LogMessageType.Info;
break;
}
case MessageType.Warning:
{
message.MessageType = LogMessageType.Warning;
break;
}
}
messages.Add(message);
}
return 1;
}
catch (Exception e)
{
var message = new LogMessage { MessageType = LogMessageType.FatalError, Message = e.Message };
messages.Add(message);
if (kernelDataOutput != null)
{
((MacroStabilityOutput)kernelDataOutput).CalculationResult = CalculationResult.InvalidInputData;
}
return 1;
}
}
///
/// Executes the kernel.
///
/// The kernel data input.
/// The kernel data output.
/// The return messages.
public void Execute(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out List messages)
{
MacroStabilityKernelDataInput macroStabilityKernelDataInput = (MacroStabilityKernelDataInput)kernelDataInput;
MacroStabilityOutput macroStabilityOutput = (MacroStabilityOutput)kernelDataOutput;
ThrowWhenMacroStabilityKernelInputNull(macroStabilityKernelDataInput);
ThrowWhenMacroStabilityKernelOutputNull(macroStabilityOutput);
PerformStabilityCalculation(macroStabilityKernelDataInput, macroStabilityOutput, out messages);
var fileName = Path.GetFileNameWithoutExtension(fileNameForCalculation);
foreach (var logMessage in messages)
{
logMessage.Message = fileName + ": " + logMessage.Message;
}
}
private void PerformStabilityCalculation(MacroStabilityKernelDataInput input, MacroStabilityOutput macroStabilityOutput, out List messages)
{
macroStabilityOutput.CalculationResult = CalculationResult.NoRun;
macroStabilityOutput.StabilityOutputItems = new List();
messages = new List();
try
{
var macroStabilityOutputKernel = stabilityCalculator.Calculate();
FillEngineFromMacroStabilityWrapperOutput.FillEngineDataWithResults(macroStabilityOutputKernel, macroStabilityOutput,
out messages);
WriteStixFileBasedOnInputAndResultsSlipPlane(input, macroStabilityOutput);
}
catch (Exception e)
{
macroStabilityOutput.CalculationResult = CalculationResult.UnexpectedError;
messages.Add(new LogMessage(LogMessageType.Error, null, e.Message));
}
}
private void WriteStixFileBasedOnInputAndSearchGrid(string fileName, MacroStabilityInput input)
{
if (!(input.StabilityModel.ModelOption == StabilityModelOptionType.UpliftVan &&
input.StabilityModel.SearchAlgorithm == SearchAlgorithm.Beeswarm))
{
var fileNameForCalculationAsStix = DetermineStixFilename(fileName, "input");
var inputStixFile = new StixWriter();
inputStixFile.FillInfo("DAM Engine", Path.GetDirectoryName(fileName),
Path.GetFileName(fileName), true);
StixFileWrite(inputStixFile, fileNameForCalculationAsStix, input);
}
}
private void WriteStixFileBasedOnInputAndResultsSlipPlane(MacroStabilityKernelDataInput input,
MacroStabilityOutput macroStabilityOutput)
{
if (macroStabilityOutput.CalculationResult == CalculationResult.Succeeded)
{
foreach (var macroStabilityOutputItem in macroStabilityOutput.StabilityOutputItems)
{
macroStabilityOutputItem.CalculationPath = Path.GetDirectoryName(fileNameForCalculation);
macroStabilityOutputItem.ProjectName = Path.GetFileName(fileNameForCalculation);
var fileNameForCalculationAsStix = DetermineStixFilename(fileNameForCalculation, "result");
var resultStixWrite = new StixWriter();
resultStixWrite.FillInfo("DAM Engine", macroStabilityOutputItem.CalculationPath,
macroStabilityOutputItem.ProjectName, true);
if (macroStabilityOutputItem.StabilityModelType == MStabModelType.Bishop)
{
resultStixWrite.FillCalculatedCircle(macroStabilityOutputItem.ActiveCenterPoint.X,
macroStabilityOutputItem.ActiveCenterPoint.Z,
macroStabilityOutputItem.ActiveCenterPointRadius);
}
if (macroStabilityOutputItem.StabilityModelType == MStabModelType.UpliftVan)
{
resultStixWrite.FillCalculatedDualCircle(macroStabilityOutputItem.ActiveCenterPoint.X,
macroStabilityOutputItem.ActiveCenterPoint.Z,
macroStabilityOutputItem.ActiveCenterPointRadius,
macroStabilityOutputItem.PassiveCenterPoint.X,
macroStabilityOutputItem.PassiveCenterPoint.Z);
}
StixFileWrite(resultStixWrite, fileNameForCalculationAsStix, input.Input);
}
}
}
private void StixFileWrite(StixWriter stixWriter, string fileName, MacroStabilityInput input)
{
if (File.Exists(fileName))
{
File.Delete(fileName);
}
stixWriter.WriteStixFile(fileName, input);
}
private string DetermineStixFilename(string fileNameForCalc, string suffix, string extension = ".stix")
{
return Path.Combine(Path.GetDirectoryName(fileNameForCalc),
$"{Path.GetFileNameWithoutExtension(fileNameForCalc)}_{suffix}{extension}");
}
///
/// Fills the design results with the kernel output.
///
/// The dam kernel input.
/// The kernel data output.
/// The design scenario.
/// The result message.
/// The design results.
///
public void PostProcess(DamKernelInput damKernelInput, IKernelDataOutput kernelDataOutput, DesignScenario designScenario,
string resultMessage, out List designResults)
{
ThrowWhenMacroStabilityDamKernelInputNull(damKernelInput);
MacroStabilityOutput macroStabilityOutput = kernelDataOutput as MacroStabilityOutput;
ThrowWhenMacroStabilityKernelOutputNull(macroStabilityOutput);
designResults = new List();
if (macroStabilityOutput != null && macroStabilityOutput.StabilityOutputItems.Count > 0)
{
var macroStabilityOutputItem = macroStabilityOutput.StabilityOutputItems[0];
if (macroStabilityOutputItem != null)
{
var designResult = NewDesignResult(damKernelInput, designScenario);
FillDesignResult(macroStabilityOutputItem, designResult);
designResult.StabilityDesignResults.NumberOfIterations = lastIterationIndex;
designResult.StabilityDesignResults.UpliftSituation = macroStabilityOutput.UpliftSituation;
if ((macroStabilityOutputItem.StabilityModelType == MStabModelType.Bishop) || (macroStabilityOutputItem.StabilityModelType == MStabModelType.UpliftVan))
{
designResult.StabilityDesignResults.ActiveCenterPoint =
macroStabilityOutputItem.ActiveCenterPoint;
designResult.StabilityDesignResults.ActiveCenterPointRadius =
macroStabilityOutputItem.ActiveCenterPointRadius;
designResult.StabilityDesignResults.ResultSlices = macroStabilityOutputItem.ResultSlices;
}
if (macroStabilityOutputItem.StabilityModelType == MStabModelType.UpliftVan)
{
designResult.StabilityDesignResults.PassiveCenterPoint =
macroStabilityOutputItem.PassiveCenterPoint;
designResult.StabilityDesignResults.PassiveCenterPointRadius =
macroStabilityOutputItem.PassiveCenterPointRadius;
}
designResults.Add(designResult);
}
}
}
private DesignResult NewDesignResult(DamKernelInput damKernelInput, DesignScenario designScenario)
{
string soilProfile2DName = damKernelInput.SubSoilScenario.ToString();
var designResult = new DesignResult(damKernelInput.DamFailureMechanismeCalculationSpecification,
designScenario, damKernelInput.SubSoilScenario.SoilProfile1D, soilProfile2DName)
{
// initialize as failed
CalculationResult = CalculationResult.RunFailed
};
designResult.StabilityDesignResults = new StabilityDesignResults();
var stabilityDesignResults = new StabilityDesignResults();
stabilityDesignResults.RedesignedSurfaceLine = damKernelInput.Location.SurfaceLine;
designResult.ProfileName = soilProfile2DName;
designResult.StabilityDesignResults = stabilityDesignResults;
designResult.CalculationSubDir = damKernelInput.CalculationDir;
return designResult;
}
private static void FillDesignResult(MacroStabilityOutputItem macroStabilityOutputItem, DesignResult designResult)
{
designResult.BaseFileName = Path.GetFileNameWithoutExtension(macroStabilityOutputItem.ProjectName);
designResult.CalculationSubDir = macroStabilityOutputItem.CalculationPath;
designResult.CalculationResult = macroStabilityOutputItem.CalculationResult;
designResult.StabilityDesignResults.StabilityModelType = macroStabilityOutputItem.StabilityModelType;
if (designResult.CalculationResult == CalculationResult.Succeeded)
{
designResult.StabilityDesignResults.SafetyFactor = macroStabilityOutputItem.SafetyFactor;
}
}
///
/// Throws the when macro stability kernel input is not assigned.
///
/// The dam macro stability input.
///
public static void ThrowWhenMacroStabilityKernelInputNull(MacroStabilityKernelDataInput macroStabilityKernelDataInput)
{
if (macroStabilityKernelDataInput == null)
{
throw new NoNullAllowedException(Resources.MacroStabilityKernelWrapper_NoMacroStabilityInputObjectDefined);
}
}
///
/// Throws the when macro stability kernel output is not assigned.
///
/// The dam macro stability output.
///
private static void ThrowWhenMacroStabilityKernelOutputNull(MacroStabilityOutput macroStabilityOutput)
{
if (macroStabilityOutput == null)
{
throw new NoNullAllowedException(Resources.MacroStabilityKernelWrapper_NoMacroStabilityOutputObjectDefined);
}
}
///
/// Throws the when macro stability dam kernel input is not assigned.
///
/// The dam kernel input.
///
private static void ThrowWhenMacroStabilityDamKernelInputNull(DamKernelInput damKernelInput)
{
if (damKernelInput == null)
{
throw new NoNullAllowedException(Resources.MacroStabilityKernelWrapper_NoDamInputObjectDefinedForMacroStability);
}
}
///
/// Calculates the design at point.
///
/// The dam kernel input.
/// The kernel data input.
/// The kernel data output.
/// The point.
/// The messages.
///
///
public ShoulderDesign CalculateDesignAtPoint(DamKernelInput damKernelInput, IKernelDataInput kernelDataInput,
IKernelDataOutput kernelDataOutput, GeometryPoint point, out List messages)
{
// ToDo: Not clear yet if this must be done or how
throw new NotImplementedException();
}
///
/// Evaluates the design (current factor greater than desired factor)
///
/// The dam kernel input.
/// The kernel data input.
/// The kernel data output.
/// The design advise.
/// The evaluation message.
///
/// if the design was successful
///
///
public bool EvaluateDesign(DamKernelInput damKernelInput, IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput,
out DesignAdvise designAdvise, out string evaluationMessage)
{
MacroStabilityKernelDataInput macroStabilityKernelDataInput = kernelDataInput as MacroStabilityKernelDataInput;
MacroStabilityOutput macroStabilityOutput = kernelDataOutput as MacroStabilityOutput;
ThrowWhenMacroStabilityKernelInputNull(macroStabilityKernelDataInput);
ThrowWhenMacroStabilityKernelOutputNull(macroStabilityOutput);
ThrowWhenMacroStabilityDamKernelInputNull(damKernelInput);
double fosRequired = damKernelInput.Location.ModelFactors.RequiredSafetyFactorStabilityInnerSlope;
if (macroStabilityOutput != null)
{
double fosAchieved = macroStabilityOutput.StabilityOutputItems[0].SafetyFactor;
double exitPointXCoordinate = macroStabilityOutput.StabilityOutputItems[0].CircleSurfacePointRightXCoordinate;
GeometryPoint limitPointForShoulderDesign = damKernelInput.Location.SurfaceLine.GetLimitPointForShoulderDesign();
evaluationMessage = string.Format(Resources.FactorAchievedVsFactorRequired, fosAchieved, fosRequired);
if (exitPointXCoordinate > limitPointForShoulderDesign.X)
{
designAdvise = DesignAdvise.ShoulderInwards;
}
else
{
designAdvise = DesignAdvise.SlopeInwards;
}
bool isDesignReady = fosAchieved >= fosRequired;
if (isDesignReady)
{
designAdvise = DesignAdvise.None;
}
return isDesignReady;
}
designAdvise = DesignAdvise.None;
evaluationMessage = "No Output";
return false;
}
///
/// Prepares the design.
///
/// The kernel data input.
/// The kernel data output.
/// The dam kernel input.
/// Index of the iteration.
/// The embankment design parameters.
public void PrepareDesign(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, DamKernelInput damKernelInput,
int iterationIndex, out EmbankmentDesignParameters embankmentDesignParameters)
{
MacroStabilityKernelDataInput macroStabilityKernelDataInput = kernelDataInput as MacroStabilityKernelDataInput;
ThrowWhenMacroStabilityKernelInputNull(macroStabilityKernelDataInput);
lastIterationIndex = iterationIndex;
var location = damKernelInput.Location;
if (iterationIndex < 1)
{
// This is the first (initial) call to prepareDesign.
// The embankment material is set to DikeEmbankmentMaterial, because the next iteration (Index = 1) will be height adaption
embankmentDesignParameters = new EmbankmentDesignParameters()
{
EmbankmentMaterialname = location.DikeEmbankmentMaterial,
};
FailureMechanismParametersMStab.EmbankmentDesignParameters = embankmentDesignParameters;
}
else
{
// Calculation iterations start with IterationIndex = 1.
// When IterationIndex = 1: height adaption.
// When Iteration > 1: Slope/Shoulder adaption.
// Starting from IterationIndex 2 the following parameters should be used:
// - The embankment material is set to ShoulderEmbankmentMaterial.
// - The previous geometry is set to the height adapted geometry (name is constructed with iteration index 1).
if (iterationIndex == 2)
{
FailureMechanismParametersMStab.EmbankmentDesignParameters.EmbankmentMaterialname = location.ShoulderEmbankmentMaterial;
}
// In the following prepareDesign calls just return the stored embankmentDesignParameters
embankmentDesignParameters = FailureMechanismParametersMStab.EmbankmentDesignParameters;
}
throw new MacroStabilityException(Resources.MacroStabilityKernelWrapper_PrepareForMacroStabilityDidNotSucceed);
}
///
/// Gets the design strategy
///
///
///
public DesignStrategy GetDesignStrategy(DamKernelInput damKernelInput)
{
switch (damKernelInput.Location.StabilityDesignMethod)
{
case StabilityDesignMethod.OptimizedSlopeAndShoulderAdaption:
return DesignStrategy.OptimizedSlopeAndShoulderAdaption;
case StabilityDesignMethod.SlopeAdaptionBeforeShoulderAdaption:
return DesignStrategy.SlopeAdaptionBeforeShoulderAdaption;
default:
return DesignStrategy.NoDesignPossible;
}
}
private string GetStabilityInputFileName(DamKernelInput damKernelInput, int iterationIndex, MStabModelType model)
{
// Assume 2D sti-file, then check on type being 1D
string soilGeometryName = damKernelInput.SubSoilScenario.SoilProfile2DName;
string calculationName = DetermineCalculationFilename(damKernelInput.FilenamePrefix, soilGeometryName, iterationIndex);
const string filenameExtension = ".skx";
string fileName = calculationName + filenameExtension;
string stabilityDirectory = GetStabilityCalculationDirectory(model, damKernelInput.CalculationDir);
return Path.Combine(stabilityDirectory, fileName);
}
private string DetermineCalculationFilename(string filenamePrefix, string soilGeometryName, int iterationIndex)
{
string calculationName;
if (iterationIndex <= 0)
{
calculationName = String.Format("{0}_Pro({1})", filenamePrefix, soilGeometryName);
}
else
{
calculationName = String.Format("{0}_Pro({1})_Ite({2})", filenamePrefix, soilGeometryName, iterationIndex);
}
return Regex.Replace(calculationName, @"[\\\/:\*\?""'<>|.]", "_");
}
private string GetStabilityCalculationDirectory(MStabModelType model, string projectWorkingPath)
{
string calculationBaseDirectory = projectWorkingPath;
var stabilitySubDir = GetCalculationSubDir(model);
string stabilityDirectory = Path.Combine(calculationBaseDirectory, stabilitySubDir);
if (!Directory.Exists(stabilityDirectory))
Directory.CreateDirectory(stabilityDirectory);
return stabilityDirectory;
}
private static string GetCalculationSubDir(MStabModelType model)
{
const string stabilitySubDir = @"Stability\";
var modelSubDirectory = model.ToString();
var dir = Path.Combine(stabilitySubDir, modelSubDirectory);
return dir;
}
}
}