Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.nl-NL.resx =================================================================== diff -u -r1050 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.nl-NL.resx (.../Resources.nl-NL.resx) (revision 1050) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.nl-NL.resx (.../Resources.nl-NL.resx) (revision 1052) @@ -183,4 +183,7 @@ Er is geen hoogtegeometrie gedefinieerd voor locatie '{0}'. + + De kruin van het dijkprofiel ligt beneden of is gelijk aan de dijkteen. Bermontwikkeling is daardoor niet mogelijk. + \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/DamPipingBligh/DamPipingBlighKernelWrapper.cs =================================================================== diff -u -r1040 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/DamPipingBligh/DamPipingBlighKernelWrapper.cs (.../DamPipingBlighKernelWrapper.cs) (revision 1040) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/DamPipingBligh/DamPipingBlighKernelWrapper.cs (.../DamPipingBlighKernelWrapper.cs) (revision 1052) @@ -322,8 +322,9 @@ }; UpliftLocationAndResult upliftLocationAndResult = upliftLocationDeterminator.GetUpliftFactorAtPoint(point); // ============================ End of SetupCalculationAtGivePoint() - double requiredFoS = damKernelInput.DesignScenario.GetRequiredSafetyFactorPiping(null); - double upliftCriterion = damKernelInput.DesignScenario.GetUpliftCriterionPiping(null); + + double requiredFoS = location.ModelFactors.RequiredSafetyFactorPiping.Value; + double upliftCriterion = location.UpliftCriterionPiping.Value; // if there is no uplift, then there is no piping so return null if (upliftLocationAndResult != null) { Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.Designer.cs =================================================================== diff -u -r1050 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 1050) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 1052) @@ -260,5 +260,14 @@ return ResourceManager.GetString("NoSurfaceLineDefinedForLocation", resourceCulture); } } + + /// + /// Looks up a localized string similar to The heigth of the dike top is equal to or lower than the dike toe so redesign is NOT possible.. + /// + internal static string SurfaceLineShoulderAdapterMaxShoulderHeightError { + get { + return ResourceManager.GetString("SurfaceLineShoulderAdapterMaxShoulderHeightError", resourceCulture); + } + } } } Index: DamEngine/trunk/src/Deltares.DamEngine.Interface.Tests/PipingBlighTests.cs =================================================================== diff -u -r987 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Interface.Tests/PipingBlighTests.cs (.../PipingBlighTests.cs) (revision 987) +++ DamEngine/trunk/src/Deltares.DamEngine.Interface.Tests/PipingBlighTests.cs (.../PipingBlighTests.cs) (revision 1052) @@ -22,7 +22,6 @@ using System.IO; using Deltares.DamEngine.Io; using NUnit.Framework; -using NUnit.Framework.Constraints; namespace Deltares.DamEngine.Interface.Tests { @@ -87,6 +86,10 @@ Assert.AreEqual(0.7825, output.Results.CalculationResults.DesignResults[0].PipingDesignResults.BlighFactor, tolerance); Assert.AreEqual(0.8089, output.Results.CalculationResults.DesignResults[121].PipingDesignResults.BlighFactor, tolerance); } + + /// + /// This test is based on the project "PipingVoorbeeld1_geometry_Bligh" + /// [Test, Category("Work_In_Progress")] public void CanPerformBlighDesignWithAdaptionPipingVoorbeeld1() { Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj =================================================================== diff -u -r1050 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj (.../Deltares.DamEngine.Calculators.csproj) (revision 1050) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj (.../Deltares.DamEngine.Calculators.csproj) (revision 1052) @@ -58,6 +58,7 @@ + Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/SurfaceLineAdapterException.cs =================================================================== diff -u -r971 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/SurfaceLineAdapterException.cs (.../SurfaceLineAdapterException.cs) (revision 971) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/SurfaceLineAdapterException.cs (.../SurfaceLineAdapterException.cs) (revision 1052) @@ -25,7 +25,7 @@ namespace Deltares.DamEngine.Calculators.DikesDesign { /// - /// Exception class for the SurfaceLineAdpter classes + /// Exception class for the SurfaceLineAdapter classes /// /// [Serializable] Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorException.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorException.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculatorException.cs (revision 1052) @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Deltares.DamEngine.Calculators.DikesDesign +{ + /// + /// Exception for DesignCalculator + /// + /// + public class DesignCalculatorException : Exception + { + public DesignCalculatorException(string message): base(message) + { + } + } +} Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.resx =================================================================== diff -u -r1050 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.resx (.../Resources.resx) (revision 1050) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.resx (.../Resources.resx) (revision 1052) @@ -183,4 +183,7 @@ Specified z-level {0} in AquitardEvaluator is outside soilprofile '{1}' (should be between {2} and {3}). + + The heigth of the dike top is equal to or lower than the dike toe so redesign is NOT possible. + \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculator.cs =================================================================== diff -u -r1040 -r1052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculator.cs (.../DesignCalculator.cs) (revision 1040) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/DesignCalculator.cs (.../DesignCalculator.cs) (revision 1052) @@ -27,6 +27,7 @@ using Deltares.DamEngine.Calculators.KernelWrappers.Common; using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces; 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.Geometry; @@ -40,6 +41,12 @@ /// public class DesignCalculator { + private const double CMinimumShoulderElevation = 0.5; + private const double CMinimumShoulderExtraElevation = 0.05; + private const double CMinimumShoulderWidth = 2; + private const double CMinimumShoulderExtraWidth = 1; + private const double CToleranceShoulderChanges = 0.001; + /// /// Performs the design calculation /// @@ -77,7 +84,7 @@ damKernelInput.RiverLevelHigh = damKernelInput.DesignScenario.RiverLevel; damKernelInput.RiverLevelLow = damKernelInput.DesignScenario.RiverLevelLow; AnalysisType analysisType = DamProjectCalculationSpecification.SelectedAnalysisType; - SynchronizeScenarioDataWithLocationData(damKernelInput); + SynchronizeDesignScenarioDataWithLocationData(damKernelInput.DesignScenario, damKernelInput.Location); IKernelDataInput kernelDataInput; IKernelDataOutput kernelDataOutput; PrepareResult prepareResult = kernelWrapper.Prepare(damKernelInput, 0, out kernelDataInput, out kernelDataOutput); @@ -129,51 +136,62 @@ /// Synchronizes the scenario data with location data. /// Note that scenario data is leading when available. /// - /// The dam kernel input. - private void SynchronizeScenarioDataWithLocationData(DamKernelInput damKernelInput) + /// The design scenario. + /// The location. + private void SynchronizeDesignScenarioDataWithLocationData(DesignScenario designScenario, Location location) { - var scenario = damKernelInput.DesignScenario; - if (scenario.PlLineOffsetBelowDikeToeAtPolder.HasValue) + // Synchronize PlLinescreator parameters + if (designScenario.PlLineOffsetBelowDikeToeAtPolder.HasValue) { - scenario.Location.PlLineOffsetBelowDikeToeAtPolder = scenario.PlLineOffsetBelowDikeToeAtPolder.Value; + location.PlLineOffsetBelowDikeToeAtPolder = designScenario.PlLineOffsetBelowDikeToeAtPolder.Value; } - if (scenario.PlLineOffsetBelowDikeTopAtPolder.HasValue) + if (designScenario.PlLineOffsetBelowDikeTopAtPolder.HasValue) { - scenario.Location.PlLineOffsetBelowDikeTopAtPolder = scenario.PlLineOffsetBelowDikeTopAtPolder.Value; + location.PlLineOffsetBelowDikeTopAtPolder = designScenario.PlLineOffsetBelowDikeTopAtPolder.Value; } - if (scenario.PlLineOffsetBelowDikeTopAtRiver.HasValue) + if (designScenario.PlLineOffsetBelowDikeTopAtRiver.HasValue) { - scenario.Location.PlLineOffsetBelowDikeTopAtRiver = scenario.PlLineOffsetBelowDikeTopAtRiver.Value; + location.PlLineOffsetBelowDikeTopAtRiver = designScenario.PlLineOffsetBelowDikeTopAtRiver.Value; } - if (scenario.PlLineOffsetBelowShoulderBaseInside.HasValue) + if (designScenario.PlLineOffsetBelowShoulderBaseInside.HasValue) { - scenario.Location.PlLineOffsetBelowShoulderBaseInside = scenario.PlLineOffsetBelowShoulderBaseInside.Value; + location.PlLineOffsetBelowShoulderBaseInside = designScenario.PlLineOffsetBelowShoulderBaseInside.Value; } - if (scenario.PlLineOffsetBelowDikeCrestMiddle.HasValue) + if (designScenario.PlLineOffsetBelowDikeCrestMiddle.HasValue) { - scenario.Location.PlLineOffsetBelowDikeCrestMiddle = scenario.PlLineOffsetBelowDikeCrestMiddle; + location.PlLineOffsetBelowDikeCrestMiddle = designScenario.PlLineOffsetBelowDikeCrestMiddle; } - if (scenario.PlLineOffsetFactorBelowShoulderCrest.HasValue) + if (designScenario.PlLineOffsetFactorBelowShoulderCrest.HasValue) { - scenario.Location.PlLineOffsetFactorBelowShoulderCrest = scenario.PlLineOffsetFactorBelowShoulderCrest; + location.PlLineOffsetFactorBelowShoulderCrest = designScenario.PlLineOffsetFactorBelowShoulderCrest; } - if (scenario.UsePlLineOffsetBelowDikeCrestMiddle.HasValue) + if (designScenario.UsePlLineOffsetBelowDikeCrestMiddle.HasValue) { - scenario.Location.UsePlLineOffsetBelowDikeCrestMiddle = scenario.UsePlLineOffsetBelowDikeCrestMiddle; + location.UsePlLineOffsetBelowDikeCrestMiddle = designScenario.UsePlLineOffsetBelowDikeCrestMiddle; } - if (scenario.UsePlLineOffsetFactorBelowShoulderCrest.HasValue) + if (designScenario.UsePlLineOffsetFactorBelowShoulderCrest.HasValue) { - scenario.Location.UsePlLineOffsetFactorBelowShoulderCrest = scenario.UsePlLineOffsetFactorBelowShoulderCrest; + location.UsePlLineOffsetFactorBelowShoulderCrest = designScenario.UsePlLineOffsetFactorBelowShoulderCrest; } - if (scenario.HeadPl3.HasValue) + if (designScenario.HeadPl3.HasValue) { - scenario.Location.HeadPl3 = scenario.HeadPl3.Value; + location.HeadPl3 = designScenario.HeadPl3.Value; } - if (scenario.HeadPl4.HasValue) + if (designScenario.HeadPl4.HasValue) { - scenario.Location.HeadPl4 = scenario.HeadPl4.Value; + location.HeadPl4 = designScenario.HeadPl4.Value; } + + // Synchronize piping design parameters + if (designScenario.UpliftCriterionPiping.HasValue) + { + location.UpliftCriterionPiping = designScenario.UpliftCriterionPiping.Value; + } + if (designScenario.RequiredSafetyFactorPiping.HasValue) + { + location.ModelFactors.RequiredSafetyFactorPiping = designScenario.RequiredSafetyFactorPiping.Value; + } } private static void PerformSingleCalculation(IKernelWrapper kernelWrapper, IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, DamKernelInput damKernelInput, @@ -245,11 +263,32 @@ return newLine; } + /// + /// Calculates the maximum level for the shoulder. + /// + /// The surface line. + /// The fraction of dike height to determine maximimum shoulder height. + /// + 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 DesignCalculatorException(Resources.SurfaceLineShoulderAdapterMaxShoulderHeightError); + } + double maxHeight = Math.Abs((top - bottom) * maxFractionOfDikeHeightForShoulderHeight); + return bottom + maxHeight; + } private static void PerformDesignCalculation(IKernelWrapper kernelWrapper, IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, DamKernelInput damKernelInput, List calculationMessages, List designCalculations) { List locationCalculationMessages = new List(); - var surfaceLine = damKernelInput.Location.SurfaceLine; + var location = damKernelInput.Location; + var surfaceLine = location.SurfaceLine; + double orgShoulderLength = surfaceLine.DetermineShoulderWidth(); + double orgShoulderHeight = surfaceLine.DetermineShoulderHeight(); + GeometryPoint startSurfacePoint = surfaceLine.GetDikeToeInward(); IEnumerable relevantSurfacePointsList = from GeometryPoint point in surfaceLine.Geometry.Points @@ -258,18 +297,13 @@ select point; relevantSurfacePointsList = GetCheckedSurfaceLine(relevantSurfacePointsList); double oldDesiredShoulderLength = 0.0; - double desiredShoulderLength; - double desiredShoulderHeight; + double desiredShoulderLength = 0.0; + double desiredShoulderHeight = 0.0; double oldDesiredShoulderHeight = 0.0; int pointCount = 0; foreach (var point in relevantSurfacePointsList) { pointCount++; - // Determine calculation filename to output piping calculation file - //pipingCalculator.PipingCalculationDirectory = GetPipingCalculationBaseDirectory(); - //string fileNameCalculation =String.Format("Calc({0})_Loc({1})_Pro({2})_Pnt({3}))", - // pipingCalculator.CalculationModelIdentifier, scenario.Location.Name, soilProfileProbability.SoilProfile.Name, pointCount.ToString("d4")); ; - //pipingCalculator.FilenameCalculation = Path.Combine(pipingCalculator.PipingCalculationDirectory, fileNameCalculation); // Calculate the piping design at the given point. This returns the required adaption (berm length and height) if any. var pipingDesign = kernelWrapper.CalculateDesignAtPoint(damKernelInput, kernelDataInput, kernelDataOutput, point, out locationCalculationMessages); @@ -283,9 +317,56 @@ desiredShoulderHeight = pipingDesign.ShoulderHeightFromToe; desiredShoulderHeight = Math.Max(desiredShoulderHeight, oldDesiredShoulderHeight); oldDesiredShoulderHeight = desiredShoulderHeight; - } + } + if (desiredShoulderLength > 0) + { + desiredShoulderLength = Math.Max(desiredShoulderLength, CMinimumShoulderWidth); + } + if (desiredShoulderLength > 0) + { + desiredShoulderHeight = Math.Max(desiredShoulderHeight, CMinimumShoulderElevation); + } + bool isNewShoulderSameAsOriginal = ((Math.Abs(desiredShoulderLength - orgShoulderLength) < CToleranceShoulderChanges) && + (Math.Abs(desiredShoulderHeight - orgShoulderHeight) < CToleranceShoulderChanges)); + SurfaceLine2 newSurfaceLine = null; + if (isNewShoulderSameAsOriginal) + { + newSurfaceLine = surfaceLine; + } + else + { + // Adapt the surfaceline for the finally required shoulder dimensions. + double maxShoulderLevel = CalculateMaximumShoulderLevel(surfaceLine, 1.0); // no limit to height of shoulder + var surfaceLineShoulderAdapter = new SurfaceLineShoulderAdapter(surfaceLine, location); + surfaceLineShoulderAdapter.MaxShoulderLevel = maxShoulderLevel; + newSurfaceLine = surfaceLineShoulderAdapter.ConstructNewSurfaceLine(desiredShoulderLength, desiredShoulderHeight, true); + + } + damKernelInput.Location.SurfaceLine = newSurfaceLine; + kernelWrapper.Prepare(damKernelInput, 0, out kernelDataInput, out kernelDataOutput); + kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out locationCalculationMessages); + // Process output + calculationMessages.AddRange(locationCalculationMessages); + List designResults; + StringBuilder sb = new StringBuilder(); + foreach (var message in locationCalculationMessages) + { + sb.Append(message.Message + Environment.NewLine); + } + string resultMessage = sb.ToString(); + kernelWrapper.PostProcess(damKernelInput, kernelDataOutput, resultMessage, out designResults); + foreach (var designResult in designResults) + { + designCalculations.Add(designResult); + } + // safetyFactor = pipingCalculator.CalculatePipingFactor(location, newSurfaceLine, soilProfileProbability.SoilProfile, scenario.RiverLevel); + // if (safetyFactor < scenario.RequiredSafetyFactorPiping) + // { + // throw new DamFailureMechanismeCalculatorException("Deterministic Design: Piping is not safe yet."); + // } + // return newSurfaceLine; } } }