Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorFirstSlopeAdaptionThenShoulderAdaption.cs =================================================================== diff -u -r1216 -r1218 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorFirstSlopeAdaptionThenShoulderAdaption.cs (.../DesignCalculatorFirstSlopeAdaptionThenShoulderAdaption.cs) (revision 1216) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorFirstSlopeAdaptionThenShoulderAdaption.cs (.../DesignCalculatorFirstSlopeAdaptionThenShoulderAdaption.cs) (revision 1218) @@ -64,11 +64,11 @@ bool isRedesignRequired; location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine); List locationCalculationMessages; - KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); + DesignCalculatorUtils.KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); calculationMessages.AddRange(locationCalculationMessages); - DesignAdvise designAdivse; + DesignAdvise designAdvise; string evaluationMessage; - isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdivse, out evaluationMessage); + isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdvise, out evaluationMessage); if (!isRedesignRequired && surfaceLine != null) { // Set redesigned surfaceline to original, so in case no redesign is needed, the original surfaceline will be returned @@ -78,7 +78,7 @@ { double maxFractionOfDikeHeightForShoulderHeight = designScenario.Location.UseNewMaxHeightShoulderAsFraction ? designScenario.Location.NewMaxHeightShoulderAsFraction : defaultMaxFractionOfDikeHeightForShoulderHeight; - double maxShoulderLevel = CalculateMaximumShoulderLevel(surfaceLine, maxFractionOfDikeHeightForShoulderHeight); + double maxShoulderLevel = DesignCalculatorUtils.CalculateMaximumShoulderLevel(surfaceLine, maxFractionOfDikeHeightForShoulderHeight); // First slope adaption double startCoTangent = location.SlopeAdaptionStartCotangent; @@ -98,7 +98,7 @@ while (isRedesignRequired && (coTangent < endCoTangent)) { iterationIndex++; - ThrowWhenMaxIterationsExceeded(iterationIndex, maxRedesignIterations); + DesignCalculatorUtils.ThrowWhenMaxIterationsExceeded(iterationIndex, maxRedesignIterations); var surfaceLineSlopeAdapter = new SurfaceLineSlopeAdapter(surfaceLine, location); // The parameter for ConstructNewSurfaceLineBySlope is the tangent of the slope, so use reciproce value @@ -117,9 +117,9 @@ location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine); damKernelInput.Location.SurfaceLine = surfaceLine; kernelWrapper.PrepareDesign(kernelDataInput, kernelDataOutput, damKernelInput, iterationIndex, out embankmentDesignParameters); - KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); + DesignCalculatorUtils.KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); calculationMessages.AddRange(locationCalculationMessages); - isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdivse, out evaluationMessage); + isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdvise, out evaluationMessage); coTangent += stepCoTangent; } @@ -128,13 +128,13 @@ while (isRedesignRequired && surfaceLine != null) { iterationIndex++; - ThrowWhenMaxIterationsExceeded(iterationIndex, maxRedesignIterations); + DesignCalculatorUtils.ThrowWhenMaxIterationsExceeded(iterationIndex, maxRedesignIterations); // Determine new width and height for shoulder double shoulderHeight; double shoulderWidth; GeometryPoint limitPointForShoulderDesign = surfaceLine.GetLimitPointForShoulderDesign(); - DetermineNewShoulderWidthAndHeight(designScenario.Location.StabilityShoulderGrowDeltaX, + DesignCalculatorUtils.DetermineNewShoulderWidthAndHeight(designScenario.Location.StabilityShoulderGrowDeltaX, designScenario.Location.StabilityShoulderGrowSlope, surfaceLine, limitPointForShoulderDesign, out shoulderHeight, out shoulderWidth); @@ -155,9 +155,9 @@ designScenario.Location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine); damKernelInput.Location.SurfaceLine = surfaceLine; kernelWrapper.PrepareDesign(kernelDataInput, kernelDataOutput, damKernelInput, iterationIndex, out embankmentDesignParameters); - KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); + DesignCalculatorUtils.KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); calculationMessages.AddRange(locationCalculationMessages); - isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdivse, out evaluationMessage); + isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdvise, out evaluationMessage); } } designScenario.SetResultMessage(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName, "Succes"); @@ -181,78 +181,5 @@ } designCalculations.AddRange(designResults); } - - private static void ThrowWhenMaxIterationsExceeded(int iterationIndex, int maxRedesignIterations) - { - if (iterationIndex >= maxRedesignIterations) - { - throw new DesignCalculatorException(string.Format(Resources.DesignMaxIterationsExceeded, maxRedesignIterations)); - } - } - - /// - /// Call the kernel calculation. - /// - /// The kernel data input. - /// The kernel wrapper. - /// The kernel data output. - /// The dam kernel input. - /// Index of the iteration. - /// The location calculation messages. - /// - private static void KernelCalculate(out IKernelDataInput kernelDataInput, IKernelWrapper kernelWrapper, out IKernelDataOutput kernelDataOutput, DamKernelInput damKernelInput, - int iterationIndex, out List locationCalculationMessages) - { - locationCalculationMessages = new List(); - PrepareResult prepareResult = kernelWrapper.Prepare(damKernelInput, iterationIndex, out kernelDataInput, out kernelDataOutput); - if (prepareResult != PrepareResult.Successful) - { - throw new DesignCalculatorException(Resources.KernelCalculationFailed); - } - kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out locationCalculationMessages); - } - - /// - /// Determines the new height and width of the shoulder width - /// - /// The shoulder grow delta X. - /// The shoulder grow slope. - /// The surface line. - /// The limit point for shoulder design. - /// New height of the shoulder. - /// New width of the shoulder. - private static void DetermineNewShoulderWidthAndHeight(double shoulderGrowDeltaX, double shoulderGrowSlope, - SurfaceLine2 surfaceLine, GeometryPoint limitPointForShoulderDesign, out double shoulderHeight, out double shoulderWidth) - { - // Determine new shoulderpoint - var newShoulderPoint = new GeometryPoint() - { - X = limitPointForShoulderDesign.X + shoulderGrowDeltaX, - Z = limitPointForShoulderDesign.Z + shoulderGrowDeltaX * shoulderGrowSlope - }; - - // Determine new shoulder width and height - shoulderWidth = surfaceLine.DetermineShoulderLengthForGivenShoulderTopInside(newShoulderPoint); - shoulderHeight = newShoulderPoint.Z - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z; - } - - /// - /// Calculates the maximum shoulder level. - /// - /// The surface line. - /// Maximum height of the fraction of dike height for shoulder. - /// - /// - private static double CalculateMaximumShoulderLevel(SurfaceLine2 surfaceLine, double maxFractionOfDikeHeightForShoulderHeight) - { - var top = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).Z; - var bottom = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z; - if (top - bottom <= 0) - { - throw new SurfaceLineAdapterException(Resources.SurfaceLineShoulderAdapterMaxShoulderHeightError); - } - double maxHeight = Math.Abs((top - bottom) * maxFractionOfDikeHeightForShoulderHeight); - return bottom + maxHeight; - } } } Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorUtils.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorUtils.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorUtils.cs (revision 1218) @@ -0,0 +1,115 @@ +// Copyright (C) Stichting Deltares 2018. 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 Deltares.DamEngine.Calculators.KernelWrappers.Common; +using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces; +using Deltares.DamEngine.Calculators.Properties; +using Deltares.DamEngine.Data.Geometry; +using Deltares.DamEngine.Data.Geotechnics; +using Deltares.DamEngine.Data.Standard.Logging; + +namespace Deltares.DamEngine.Calculators.DikesDesign +{ + public class DesignCalculatorUtils + { + /// + /// Determines the new height and width of the shoulder width + /// + /// The shoulder grow delta X. + /// The shoulder grow slope. + /// The surface line. + /// The limit point for shoulder design. + /// New height of the shoulder. + /// New width of the shoulder. + public static void DetermineNewShoulderWidthAndHeight(double shoulderGrowDeltaX, double shoulderGrowSlope, + SurfaceLine2 surfaceLine, GeometryPoint limitPointForShoulderDesign, out double shoulderHeight, out double shoulderWidth) + { + // Determine new shoulderpoint + var newShoulderPoint = new GeometryPoint() + { + X = limitPointForShoulderDesign.X + shoulderGrowDeltaX, + Z = limitPointForShoulderDesign.Z + shoulderGrowDeltaX * shoulderGrowSlope + }; + + // Determine new shoulder width and height + shoulderWidth = surfaceLine.DetermineShoulderLengthForGivenShoulderTopInside(newShoulderPoint); + shoulderHeight = newShoulderPoint.Z - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z; + } + + /// + /// Throws the when maximum iterations exceeded. + /// + /// Index of the iteration. + /// The maximum redesign iterations. + /// + public static void ThrowWhenMaxIterationsExceeded(int iterationIndex, int maxRedesignIterations) + { + if (iterationIndex >= maxRedesignIterations) + { + throw new DesignCalculatorException(string.Format(Resources.DesignMaxIterationsExceeded, maxRedesignIterations)); + } + } + + /// + /// Calculates the maximum shoulder level. + /// + /// The surface line. + /// Maximum height of the fraction of dike height for shoulder. + /// + /// + public static double CalculateMaximumShoulderLevel(SurfaceLine2 surfaceLine, double maxFractionOfDikeHeightForShoulderHeight) + { + var top = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).Z; + var bottom = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z; + if (top - bottom <= 0) + { + throw new SurfaceLineAdapterException(Resources.SurfaceLineShoulderAdapterMaxShoulderHeightError); + } + double maxHeight = Math.Abs((top - bottom) * maxFractionOfDikeHeightForShoulderHeight); + return bottom + maxHeight; + } + + /// + /// Call the kernel calculation. + /// + /// The kernel data input. + /// The kernel wrapper. + /// The kernel data output. + /// The dam kernel input. + /// Index of the iteration. + /// The location calculation messages. + /// + public static void KernelCalculate(out IKernelDataInput kernelDataInput, IKernelWrapper kernelWrapper, out IKernelDataOutput kernelDataOutput, DamKernelInput damKernelInput, + int iterationIndex, out List locationCalculationMessages) + { + locationCalculationMessages = new List(); + PrepareResult prepareResult = kernelWrapper.Prepare(damKernelInput, iterationIndex, out kernelDataInput, out kernelDataOutput); + if (prepareResult != PrepareResult.Successful) + { + throw new DesignCalculatorException(Resources.KernelCalculationFailed); + } + kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out locationCalculationMessages); + } + + } +} Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorCombinedSlopeAndShoulderAdaption.cs =================================================================== diff -u -r1217 -r1218 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorCombinedSlopeAndShoulderAdaption.cs (.../DesignCalculatorCombinedSlopeAndShoulderAdaption.cs) (revision 1217) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorCombinedSlopeAndShoulderAdaption.cs (.../DesignCalculatorCombinedSlopeAndShoulderAdaption.cs) (revision 1218) @@ -22,8 +22,16 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Deltares.DamEngine.Calculators.KernelWrappers.Common; +using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces; +using Deltares.DamEngine.Data.Design; +using Deltares.DamEngine.Data.General; +using Deltares.DamEngine.Data.General.Results; +using Deltares.DamEngine.Data.Geometry; +using Deltares.DamEngine.Data.Geotechnics; +using Deltares.DamEngine.Data.Standard.Calculation; +using Deltares.DamEngine.Data.Standard.Logging; +using Deltares.DamEngine.Data.Standard.Validation; namespace Deltares.DamEngine.Calculators.DikesDesign { @@ -32,5 +40,136 @@ /// public class DesignCalculatorCombinedSlopeAndShoulderAdaption { + private const double defaultMaxFractionOfDikeHeightForShoulderHeight = 0.67; + /// + /// Performs the design calculation combined slope adaption and shoulder adaption. + /// + /// The kernel wrapper. + /// The kernel data input. + /// The kernel data output. + /// The dam kernel input. + /// The design scenario. + /// The calculation messages. + /// The design calculations. + /// + /// + /// + public static void PerformDesignCalculationCombinedSlopeAdaptionAndShoulderAdaption( + IKernelWrapper kernelWrapper, IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, + DamKernelInput damKernelInput, DesignScenario designScenario, + List calculationMessages, List designCalculations) + { + List designResults; + Location location = damKernelInput.Location; + SoilGeometryProbability subSoilScenario = damKernelInput.SubSoilScenario; + const int maxRedesignIterations = 200; + string resultMessage = ""; + int iterationIndex = -1; + + // Create the file with the initial geometry to be used to determine which layers have to be defined as dike embankment material + EmbankmentDesignParameters embankmentDesignParameters; + kernelWrapper.PrepareDesign(kernelDataInput, kernelDataOutput, damKernelInput, iterationIndex, out embankmentDesignParameters); + SurfaceLine2 surfaceLine = designScenario.GetMostRecentSurfaceLine(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName).FullDeepClone(); + + try + { + bool isRedesignRequired; + location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine); + List locationCalculationMessages; + DesignCalculatorUtils.KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); + calculationMessages.AddRange(locationCalculationMessages); + DesignAdvise designAdvise; + string evaluationMessage; + isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdvise, out evaluationMessage); + + if (!isRedesignRequired && surfaceLine != null) + { + // Set redesigned surfaceline to original, so in case no redesign is needed, the original surfaceline will be returned + designScenario.SetRedesignedSurfaceLine(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName, surfaceLine); + } + else + { + double maxFractionOfDikeHeightForShoulderHeight = location.UseNewMaxHeightShoulderAsFraction ? + location.NewMaxHeightShoulderAsFraction : defaultMaxFractionOfDikeHeightForShoulderHeight; + double maxShoulderLevel = DesignCalculatorUtils.CalculateMaximumShoulderLevel(surfaceLine, + maxFractionOfDikeHeightForShoulderHeight); + while (isRedesignRequired && surfaceLine != null) + { + iterationIndex++; + DesignCalculatorUtils.ThrowWhenMaxIterationsExceeded(iterationIndex, maxRedesignIterations); + + GeometryPoint limitPointForShoulderDesign = surfaceLine.GetLimitPointForShoulderDesign(); + if (designAdvise == DesignAdvise.ShoulderInwards) + { + // If exit point of circle is after the limitPointForShoulderDesign then enlarge the shoulder + // Determine new width and height for shoulder + double shoulderHeight; + double shoulderWidth; + DesignCalculatorUtils.DetermineNewShoulderWidthAndHeight(location.StabilityShoulderGrowDeltaX, + location.StabilityShoulderGrowSlope, surfaceLine, limitPointForShoulderDesign, out shoulderHeight, out shoulderWidth); + + // Create new shoulder + var surfaceLineShoulderAdapter = new SurfaceLineShoulderAdapter(surfaceLine, location); + surfaceLineShoulderAdapter.MaxShoulderLevel = maxShoulderLevel; + surfaceLine = surfaceLineShoulderAdapter.ConstructNewSurfaceLine(shoulderWidth, shoulderHeight, false); + + var validationError = surfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error); + if (validationError != null) + { + throw new SurfaceLineException(validationError.Text); + } + + designScenario.SetRedesignedSurfaceLine(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName, surfaceLine); + } + else if (designAdvise == DesignAdvise.SlopeInwards) + { + // If exit point of circle is in the slope (inward) of the dike or the top of the shoulder then adapt slope + var surfaceLineSlopeAdapter = new SurfaceLineSlopeAdapter(surfaceLine, location); + surfaceLine = surfaceLineSlopeAdapter.ConstructNewSurfaceLine(location.StabilitySlopeAdaptionDeltaX); + + var validationError = surfaceLine.Validate().FirstOrDefault(vr => vr.MessageType == ValidationResultType.Error); + if (validationError != null) + { + throw new SurfaceLineException(validationError.Text); + } + designScenario.SetRedesignedSurfaceLine(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName, surfaceLine); + } + else + { + throw new NotImplementedException(); + } + + // Calculate again + designScenario.Location.AlignBoundaryPointsOfPL1LineWithAdaptedSurfaceLine(surfaceLine); + DesignCalculatorUtils.KernelCalculate(out kernelDataInput, kernelWrapper, out kernelDataOutput, damKernelInput, iterationIndex, out locationCalculationMessages); + calculationMessages.AddRange(locationCalculationMessages); + isRedesignRequired = !kernelWrapper.EvaluateDesign(damKernelInput, kernelDataInput, kernelDataOutput, out designAdvise, out evaluationMessage); + } + } + calculationMessages.AddRange(locationCalculationMessages); + designScenario.SetResultMessage(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName, "Succes"); + kernelWrapper.PostProcess(damKernelInput, kernelDataOutput, designScenario, resultMessage, out designResults); + } + catch (Exception exception) + { + string errorMessage = "FAIL: " + exception.Message; + Exception innerException = exception.InnerException; + while (innerException != null) + { + errorMessage = errorMessage + ";" + innerException.Message; + innerException = innerException.InnerException; + } + designScenario.SetResultMessage(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName, errorMessage); + // Add message to log too for output tab. + errorMessage = location.Name + ", scenario " + designScenario.LocationScenarioID + ", " + subSoilScenario.StiFileName + " " + errorMessage; + // stabilityCalculator.ErrorMessages.Add(new LogMessage(LogMessageType.Error, this, errorMessage)); + designScenario.CalculationResult = CalculationResult.RunFailed; + // Redesign not succesful, so no redesigned surfaceline will be returned + designScenario.SetRedesignedSurfaceLine(subSoilScenario.SoilProfile1D, subSoilScenario.StiFileName, null); + kernelWrapper.PostProcess(damKernelInput, kernelDataOutput, designScenario, errorMessage, out designResults); + } + designCalculations.AddRange(designResults); + + } } } Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj =================================================================== diff -u -r1205 -r1218 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj (.../Deltares.DamEngine.Calculators.csproj) (revision 1205) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj (.../Deltares.DamEngine.Calculators.csproj) (revision 1218) @@ -63,6 +63,7 @@ + Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculator.cs =================================================================== diff -u -r1217 -r1218 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculator.cs (.../DesignCalculator.cs) (revision 1217) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculator.cs (.../DesignCalculator.cs) (revision 1218) @@ -160,7 +160,10 @@ calculationMessages, designCalculations); break; case DesignStrategy.OptimizedSlopeAndShoulderAdaption: - throw new NotImplementedException("OptimizedSlopeAndShoulderAdaption design strategy is not implemented yet."); + DesignCalculatorCombinedSlopeAndShoulderAdaption.PerformDesignCalculationCombinedSlopeAdaptionAndShoulderAdaption( + kernelWrapper, kernelDataInput, kernelDataOutput, damKernelInput, designScenario, + calculationMessages, designCalculations); + break; } }