// 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; } } }