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