Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs =================================================================== diff -u -r5565 -r5992 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 5565) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 5992) @@ -354,11 +354,10 @@ /// Start considering instances from /// starting from this index. /// The height level of the horizontal line. - /// Optional: Discard intersections whose X value is less then - /// or equal to this value. + /// Optional: Discard intersections whose X value is less than or equal to this value. /// The first intersection point matching the criteria. /// - public double GetXatZStartingAt(int start, double z, double xmin = Double.MinValue) + public double GetXatZStartingAt(int start, double z, double xMin = double.MinValue) { for (int i = start; i < calcPoints.Count - 1; i++) { @@ -371,13 +370,13 @@ } double x = GetXIntersectingZ(z, current, next); - if (x > xmin) + if (x > xMin) { return x; } } - return Double.NaN; + return double.NaN; } /// Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/PipingBlighTests.cs =================================================================== diff -u -r5453 -r5992 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/PipingBlighTests.cs (.../PipingBlighTests.cs) (revision 5453) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/PipingBlighTests.cs (.../PipingBlighTests.cs) (revision 5992) @@ -180,10 +180,12 @@ Output output = GeneralHelper.RunAfterInputValidation(inputString); - var locationIndex = 0; - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 0].PipingDesignResults.BlighFactor, Is.EqualTo(1.313).Within(tolerance)); - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 1].PipingDesignResults.BlighFactor, Is.EqualTo(1.295).Within(tolerance)); - Assert.That(output.Results.CalculationResults.Length, Is.EqualTo((locationIndex + 1) * 2)); + Assert.That(output.Results.CalculationResults, Has.Length.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(output.Results.CalculationResults[0].PipingDesignResults.BlighFactor, Is.EqualTo(1.299).Within(tolerance)); + Assert.That(output.Results.CalculationResults[1].PipingDesignResults.BlighFactor, Is.EqualTo(-1.000).Within(tolerance)); + }); } [Test] @@ -201,15 +203,18 @@ Output output = GeneralHelper.RunAfterInputValidation(inputString); - Assert.That(output.Results.CalculationResults.Length, Is.EqualTo(2)); - Assert.That(output.Results.CalculationResults[1].PipingDesignResults.ResultMessage, Is.EqualTo("The new shoulder length is too large to fit in the current surface line.")); - Assert.That(ConversionHelper.ConvertToCalculationResult(output.Results.CalculationResults[1].CalculationResult), Is.EqualTo(CalculationResult.RunFailed)); - Assert.That(output.Results.CalculationMessages.Length, Is.EqualTo(2)); + Assert.That(output.Results.CalculationResults, Has.Length.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(output.Results.CalculationResults[1].PipingDesignResults.ResultMessage, + Is.EqualTo("The design was not successful. Factor achieved = 1.546, Factor required = 8.000.")); + Assert.That(ConversionHelper.ConvertToCalculationResult(output.Results.CalculationResults[1].CalculationResult), Is.EqualTo(CalculationResult.RunFailed)); + Assert.That(output.Results.CalculationMessages, Has.Length.EqualTo(2)); + }); Assert.That(output.Results.CalculationMessages[0].Message1, Is.EqualTo("Location '101', subsoil scenario 'segment1_1D1', design scenario '1': " + - "The calculation failed with error message " + - "'The design was not successful. " + - "The new shoulder length is too large to fit in the current surface line.'")); + "The calculation failed with error message 'The design was not successful. " + + "The design was not successful. Factor achieved = 1.299, Factor required = 8.000.'")); } [Test] @@ -224,22 +229,21 @@ Output output = GeneralHelper.RunAfterInputValidation(inputString); - var locationIndex = 0; - Assert.That(output.Results.CalculationResults[locationIndex + 0].PipingDesignResults.BlighFactor, Is.EqualTo(1.516).Within(tolerance)); - Assert.That(output.Results.CalculationResults[locationIndex + 1].PipingDesignResults.BlighFactor, Is.EqualTo(1.497).Within(tolerance)); - locationIndex++; - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 0].PipingDesignResults.BlighFactor, Is.EqualTo(1.313).Within(tolerance)); - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 1].PipingDesignResults.BlighFactor, Is.EqualTo(1.295).Within(tolerance)); - locationIndex++; - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 0].PipingDesignResults.BlighFactor, Is.EqualTo(2.166).Within(tolerance)); - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 1].PipingDesignResults.BlighFactor, Is.EqualTo(1.312).Within(tolerance)); - locationIndex++; - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 0].PipingDesignResults.BlighFactor, Is.EqualTo(1.486).Within(tolerance)); - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 1].PipingDesignResults.BlighFactor, Is.EqualTo(1.356).Within(tolerance)); - locationIndex++; - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 0].PipingDesignResults.BlighFactor, Is.EqualTo(1.722).Within(tolerance)); - Assert.That(output.Results.CalculationResults[locationIndex * 2 + 1].PipingDesignResults.BlighFactor, Is.EqualTo(1.311).Within(tolerance)); - Assert.That(output.Results.CalculationResults.Length, Is.EqualTo((locationIndex + 1) * 2)); + Assert.That(output.Results.CalculationResults, Has.Length.EqualTo(10)); + Assert.Multiple(() => + { + Assert.That(output.Results.CalculationResults[0].PipingDesignResults.BlighFactor, Is.EqualTo(1.516).Within(tolerance)); + Assert.That(output.Results.CalculationResults[1].PipingDesignResults.BlighFactor, Is.EqualTo(1.497).Within(tolerance)); + Assert.That(output.Results.CalculationResults[2].PipingDesignResults.BlighFactor, Is.EqualTo(1.299).Within(tolerance)); + Assert.That(output.Results.CalculationResults[3].PipingDesignResults.BlighFactor, Is.EqualTo(-1.000).Within(tolerance)); + Assert.That(output.Results.CalculationResults[4].PipingDesignResults.BlighFactor, Is.EqualTo(2.166).Within(tolerance)); + Assert.That(output.Results.CalculationResults[5].PipingDesignResults.BlighFactor, Is.EqualTo(1.312).Within(tolerance)); + Assert.That(output.Results.CalculationResults[6].PipingDesignResults.BlighFactor, Is.EqualTo(1.486).Within(tolerance)); + Assert.That(output.Results.CalculationResults[7].PipingDesignResults.BlighFactor, Is.EqualTo(1.356).Within(tolerance)); + Assert.That(output.Results.CalculationResults[8].PipingDesignResults.BlighFactor, Is.EqualTo(1.722).Within(tolerance)); + Assert.That(output.Results.CalculationResults[9].PipingDesignResults.BlighFactor, Is.EqualTo(1.311).Within(tolerance)); + }); + } [Test] @@ -264,7 +268,7 @@ Assert.That(output.Results.CalculationResults, Has.Length.EqualTo(6)); Assert.Multiple(() => { - Assert.That(output.Results.CalculationResults[0].PipingDesignResults.BlighFactor, Is.EqualTo(17.208).Within(tolerance)); + Assert.That(output.Results.CalculationResults[0].PipingDesignResults.BlighFactor, Is.EqualTo(1.207).Within(tolerance)); Assert.That(output.Results.CalculationResults[1].PipingDesignResults.BlighFactor, Is.EqualTo(90.000).Within(tolerance)); Assert.That(output.Results.CalculationResults[2].PipingDesignResults.BlighFactor, Is.EqualTo(90.000).Within(tolerance)); Assert.That(output.Results.CalculationResults[3].PipingDesignResults.BlighFactor, Is.EqualTo(90.000).Within(tolerance)); Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs =================================================================== diff -u -r5989 -r5992 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs (.../PlLinesCreator.cs) (revision 5989) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs (.../PlLinesCreator.cs) (revision 5992) @@ -38,6 +38,7 @@ /// public class PlLinesCreator { + private const double toleranceAlmostEquals = 1e-6; private const double cUpliftFactorEquilibrium = 1.0; private const double cOffsetPhreaticLineBelowSurface = 0.01; protected readonly Dictionary cachedSoilProfiles1D = new Dictionary(); @@ -419,17 +420,12 @@ plLine.Points.Add(new PlLinePoint(SurfaceLine.Geometry.Points.First().X, headValue)); plLine.Points.Add(new PlLinePoint(SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X, headValue)); - // Code temporary disabled - /*SoilProfile2D soilProfile2D = SoilProfileType == SoilProfileType.ProfileType2D ? SoilProfile2D : DetermineSoilProfile2DFrom1D(); - SoilProfile2DHelper.LayerType aquiferType = plLineType == PlLineType.Pl3 ? SoilProfile2DHelper.LayerType.BottomAquiferCluster : SoilProfile2DHelper.LayerType.InBetweenAquiferCluster; - double xStart = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X; - - if (SoilProfile2DHelper.IsSurfaceLineIntersectedByAquifer(aquiferType, soilProfile2D, xStart, out GeometryPoint intersectionAquifer)) + if (IsSurfaceLineIntersectedByAquiferAtPolder(plLineType, out GeometryPoint intersectionAquifer)) { - ReducePlLineToPl1(soilProfile2D, intersectionAquifer, plLine); + ReducePlLineToPl1(intersectionAquifer, plLine); } else - {*/ + { plLine.Points.Add(new PlLinePoint(SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X, headAtPolderDikeToe)); // Now continue PlLine to the end with a slope of SlopeGradient @@ -439,7 +435,7 @@ { AdjustLineAccordingToTrwUplift(plLine, plLineType, slopeGradient); } - //} + } EnsureDescendingLine(plLine); @@ -453,12 +449,11 @@ /// Refer to Word document "20250116 Schematisatie freatische lijn en waterspanningen waarbij teensloot een aquifer insnijdt" /// in doc/Work folder for details on the reduction of the PL-line. /// - /// The soil profile. /// The intersection point of the surface line (often ditch) with the aquifer. /// The PL-line. - private void ReducePlLineToPl1(SoilProfile2D soilProfile2D, GeometryPoint intersectionAquifer, PlLine plLine) + private void ReducePlLineToPl1(GeometryPoint intersectionAquifer, PlLine plLine) { - if (IsDitchIntersectedByPl1(soilProfile2D, intersectionAquifer, out GeometryPoint intersectDitchPl1)) + if (IsDitchIntersectedByPl1(intersectionAquifer, out GeometryPoint intersectDitchPl1)) { plLine.Points.Add(new PlLinePoint(intersectDitchPl1.X, intersectDitchPl1.Z)); plLine.Points.Add(new PlLinePoint(SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X, intersectDitchPl1.Z)); @@ -1728,59 +1723,82 @@ validator.ValidateSoilProfileForPlLinesCreator(); } - private SoilProfile2D DetermineSoilProfile2DFrom1D() + private bool IsSurfaceLineIntersectedByAquiferAtPolder(PlLineType plLineType, out GeometryPoint intersectionPoint) { - var soilSurfaceProfile = new SoilSurfaceProfile + // If all the layers below the dike toe at polder are aquifer, no intersection point can be found + SoilProfile1D relevantSoilProfile = GetRelevantSoilProfileForAquiferLayersSearch(); + if (relevantSoilProfile.Layers.All(layer => layer.IsAquifer)) { - SoilProfile = SoilProfile, - SurfaceLine2 = SurfaceLine, - DikeEmbankmentMaterial = DikeEmbankmentMaterial, - Name = SoilProfile.Name - }; + intersectionPoint = null; + return false; + } - return soilSurfaceProfile.ConvertToSoilProfile2D(); + // Soil profile 2D + double xStartSearch = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X; + if (SoilProfileType == SoilProfileType.ProfileType2D) + { + SoilProfile2DHelper.LayerType aquiferType = plLineType == PlLineType.Pl3 ? SoilProfile2DHelper.LayerType.BottomAquiferCluster : SoilProfile2DHelper.LayerType.InBetweenAquiferCluster; + return SoilProfile2DHelper.IsSurfaceLineIntersectedByAquifer(aquiferType, SoilProfile2D, xStartSearch, out intersectionPoint); + } + + // Soil profile 1D + double topAquifer = GetRelevantAquiferLayer(plLineType, relevantSoilProfile).TopLevel; + int indexStartSearch = SurfaceLine.Geometry.Points.FindIndex(p => p.X.IsNearEqual(xStartSearch, toleranceAlmostEquals)); + double xIntersection = SurfaceLine.Geometry.GetXatZStartingAt(indexStartSearch, topAquifer); + if (!double.IsNaN(xIntersection)) + { + intersectionPoint = new GeometryPoint + { + X = xIntersection, + Z = topAquifer + }; + return true; + } + + intersectionPoint = null; + return false; } - /// - /// The intersection of PL 1 with the ditch is found starting at . - /// If PL 1 (polder level) is higher than , search in the outward direction. - /// If PL 1 (polder level) is lower than , search in the inward direction. - /// Return the first intersection point found as . - /// - /// The soil profile 2D. - /// The intersection point of the ditch with the aquifer. - /// Returns the intersection point of the ditch with PL 1. If no intersection point is - /// found, returns null. - /// true if the ditch intersects the polder level; otherwise, false. - private bool IsDitchIntersectedByPl1(SoilProfile2D soilProfile2D, GeometryPoint intersectionDitchAquifer, out GeometryPoint intersectionDitchPl1) - { - const double toleranceAlmostEquals = 1e-6; - intersectionDitchPl1 = new GeometryPoint(); - bool isPl1AboveAquifer = currentPl1Line.Points.Last().Z.IsGreaterThanOrEqualTo(intersectionDitchAquifer.Z); - GeometryPoint dikeToeAtPolder = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); - int indexStart = soilProfile2D.Geometry.SurfaceLine.Points.FindIndex(p => p.X.AlmostEquals(intersectionDitchAquifer.X, toleranceAlmostEquals)); - int indexDikeToeAtPolder = soilProfile2D.Geometry.SurfaceLine.Points.FindIndex(p => p.X.AlmostEquals(dikeToeAtPolder.X, toleranceAlmostEquals)); - int indexEnd = isPl1AboveAquifer ? indexDikeToeAtPolder : soilProfile2D.Geometry.SurfaceLine.Points.Count - 1; - int index = indexStart; - while (index != indexEnd) + /// + /// The intersection of PL 1 with the ditch is found starting the search at . + /// If PL 1 (polder level) is higher than , search in the outward direction. + /// If PL 1 (polder level) is lower than , search in the inward direction. + /// Return the first intersection point found as . + /// + /// The intersection point of the ditch with the aquifer. + /// Returns the intersection point of the ditch with PL 1. If no intersection point is + /// found, returns null. + /// true if the ditch intersects the polder level; otherwise, false. + private bool IsDitchIntersectedByPl1(GeometryPoint intersectionDitchAquifer, out GeometryPoint intersectionDitchPl1) { - GeometryPoint currentPoint = soilProfile2D.Geometry.SurfaceLine.Points[index]; - GeometryPoint nextPoint = soilProfile2D.Geometry.SurfaceLine.Points[index + 1]; - var surfaceLineSegment = new Line(); - surfaceLineSegment.SetBeginAndEndPoints(new Point2D(currentPoint.X, currentPoint.Z), new Point2D(nextPoint.X, nextPoint.Z)); - var phreaticPolderPartialLine = new Line(); - PlLinePoint endPl1 = currentPl1Line.Points.Find(p => p.X.IsGreaterThanOrEqualTo(currentPoint.X, toleranceAlmostEquals)); - PlLinePoint beginPl1 = currentPl1Line.Points.Find(p => p.X.IsLessThan(currentPoint.X, toleranceAlmostEquals)); - phreaticPolderPartialLine.SetBeginAndEndPoints(new Point2D(beginPl1.X, beginPl1.Z), new Point2D(endPl1.X, endPl1.Z)); - if (LineHelper.DetermineStrictIntersectionPoint(surfaceLineSegment, phreaticPolderPartialLine, ref intersectionDitchPl1)) + intersectionDitchPl1 = new GeometryPoint(); + bool isPl1AboveAquifer = currentPl1Line.Points.Last().Z.IsGreaterThanOrEqualTo(intersectionDitchAquifer.Z, toleranceAlmostEquals); + GeometryPoint dikeToeAtPolder = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); + double xStart = SurfaceLine.Geometry.Points.First(p => p.X.IsGreaterThanOrEqualTo(intersectionDitchAquifer.X, toleranceAlmostEquals)).X; + int indexStart = SurfaceLine.Geometry.Points.FindIndex(p => p.X.AlmostEquals(xStart, toleranceAlmostEquals)) - 1; + int indexDikeToeAtPolder = SurfaceLine.Geometry.Points.FindIndex(p => p.X.AlmostEquals(dikeToeAtPolder.X, toleranceAlmostEquals)); + int indexEnd = isPl1AboveAquifer ? indexDikeToeAtPolder : SurfaceLine.Geometry.Points.Count - 1; + + int index = indexStart; + while (index != indexEnd) { - return true; + GeometryPoint currentPoint = SurfaceLine.Geometry.Points[index]; + GeometryPoint nextPoint = SurfaceLine.Geometry.Points[index + 1]; + var surfaceLineSegment = new Line(); + surfaceLineSegment.SetBeginAndEndPoints(new Point2D(currentPoint.X, currentPoint.Z), new Point2D(nextPoint.X, nextPoint.Z)); + var phreaticPolderPartialLine = new Line(); + PlLinePoint endPl1 = currentPl1Line.Points.Find(p => p.X.IsGreaterThanOrEqualTo(currentPoint.X, toleranceAlmostEquals)); + PlLinePoint beginPl1 = currentPl1Line.Points.Find(p => p.X.IsLessThan(currentPoint.X, toleranceAlmostEquals)); + phreaticPolderPartialLine.SetBeginAndEndPoints(new Point2D(beginPl1.X, beginPl1.Z), new Point2D(endPl1.X, endPl1.Z)); + if (LineHelper.DetermineStrictIntersectionPoint(surfaceLineSegment, phreaticPolderPartialLine, ref intersectionDitchPl1)) + { + return true; + } + index = isPl1AboveAquifer ? index - 1 : index + 1; } - index = isPl1AboveAquifer ? index - 1 : index + 1; - } - intersectionDitchPl1 = null; - return false; - } -} \ No newline at end of file + intersectionDitchPl1 = null; + return false; + } + } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs =================================================================== diff -u -r5985 -r5992 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs (.../PlLinesCreatorTest.cs) (revision 5985) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs (.../PlLinesCreatorTest.cs) (revision 5992) @@ -2050,12 +2050,12 @@ /// Bottom aquifer X=59.5 /// ------------------------------------------------------------- Level -10 m /// - [Test, Ignore("Test temporary ignored (MWDAM-2691)")] + [Test] [TestCase(false, -4.0, 59.000)] // PL 1 above bottom aquifer - [TestCase(false, -7.0, 59.375)] // PL 1 below bottom aquifer + [TestCase(false, -7.0, 59.375)] // PL 1 below bottom aquifer but above ditch bottom [TestCase(false, -9.0, 59.250)] // PL 1 below ditch [TestCase(true, -1.0, 58.625, 58.625)] // PL 1 above in-between aquifer - [TestCase(true, -7.0, 59.375, 59.375)] // PL 1 below in-between aquifer + [TestCase(true, -7.0, 59.375, 59.375)] // PL 1 below in-between aquifer but above ditch bottom [TestCase(true, -9.0, 59.250, 58.750)] // PL 1 below ditch public void GivenSoilProfile2DWithAquifersCuttingTheDitch_WhenCreatingPlLines_ThenExpectedPlLinesReturned(bool isInBetweenLayerAquifer, double waterLevelPolder, double expectedXPl3, double expectedXPl4 = 0) {