Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile1D.cs =================================================================== diff -u -r6404 -r6747 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile1D.cs (.../SoilProfile1D.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile1D.cs (.../SoilProfile1D.cs) (revision 6747) @@ -141,14 +141,6 @@ } /// - /// Gets the infiltration layer. - /// - /// - /// The infiltration layer. - /// - public SoilLayer1D InfiltrationLayer { get; } - - /// /// Gets the highest aquifer layer of the deepest cluster of aquifers /// /// Index: DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/Factories/FactoryForSoilProfiles.cs =================================================================== diff -u -r6404 -r6747 --- DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/Factories/FactoryForSoilProfiles.cs (.../FactoryForSoilProfiles.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/Factories/FactoryForSoilProfiles.cs (.../FactoryForSoilProfiles.cs) (revision 6747) @@ -457,65 +457,8 @@ soilProfile.BottomLevel = -10.0; return soilProfile; } - + /// - /// Create three layer soil profile with pleistocene and intermediate sand layer - /// - /// soil profile - public static SoilProfile1D CreatePipingSellmeijerProfileWithTwoSandlayers() - { - var soilProfile = new SoilProfile1D(); - - var layer = new SoilLayer1D - { - Name = GetNewUniqueLayerId(soilProfile) - }; - layer.TopLevel = 10.0; - layer.Soil = new Soil("Topmaterial", 1.0, 1.0); - layer.Soil.PermeabKx = 0.0003; - layer.Soil.DiameterD70 = 0.0003; - layer.IsAquifer = false; - soilProfile.Layers.Add(layer); - - layer = new SoilLayer1D - { - Name = GetNewUniqueLayerId(soilProfile) - }; - layer.TopLevel = -2.0; - layer.Soil = new Soil("Sand upper", 22.0, 20.0); - layer.Soil.PermeabKx = 0.0001; - layer.Soil.DiameterD70 = 0.0002; - layer.IsAquifer = true; - soilProfile.Layers.Add(layer); - - layer = new SoilLayer1D - { - Name = GetNewUniqueLayerId(soilProfile) - }; - layer.TopLevel = -3.99; - layer.Soil = new Soil("Clay", 22.0, 20.0); - layer.Soil.PermeabKx = 0.0001; - layer.Soil.DiameterD70 = 0.0002; - layer.IsAquifer = false; - soilProfile.Layers.Add(layer); - - layer = new SoilLayer1D - { - Name = GetNewUniqueLayerId(soilProfile) - }; - layer.TopLevel = -4.0; - layer.Soil = new Soil("Sand lower", 22.0, 20.0); - layer.Soil.PermeabKx = 0.0002; - layer.Soil.DiameterD70 = 0.0003; - layer.IsAquifer = true; - soilProfile.Layers.Add(layer); - - soilProfile.BottomLevel = -10.0; - - return soilProfile; - } - - /// /// Create two layer soil profile with pleistocene sand layer (no intermediate layer) /// /// soil profile @@ -559,339 +502,8 @@ return soilProfile; } - + /// - /// Creates a test profile. - /// - /// soil profile - public static SoilProfile1D CreateTestProfile() - { - var sand = new Soil(); - sand.Name = "zand"; - sand.AbovePhreaticLevel = 15; - sand.BelowPhreaticLevel = 17; - - var clay = new Soil(); - clay.Name = "klei"; - clay.AbovePhreaticLevel = 18; - clay.BelowPhreaticLevel = 20; - - var clay2 = new Soil(); - clay2.Name = "klei2"; - clay2.AbovePhreaticLevel = 20; - clay2.BelowPhreaticLevel = 22; - - var soilProfile = new SoilProfile1D(); - soilProfile.Name = "TestProf"; - - var layer1 = new SoilLayer1D(); - layer1.Name = "layer1"; - layer1.TopLevel = 10; - layer1.Soil = clay; - layer1.IsAquifer = false; - soilProfile.Layers.Add(layer1); - - var layer2 = new SoilLayer1D(); - layer2.Name = "layer2"; - layer2.TopLevel = -3; - layer2.Soil = clay2; - layer2.IsAquifer = false; - soilProfile.Layers.Add(layer2); - - var layer3 = new SoilLayer1D(); - layer3.Name = "layer3"; - layer3.TopLevel = -10; - layer3.Soil = sand; - layer3.IsAquifer = true; - soilProfile.Layers.Add(layer3); - - return soilProfile; - } - - /// - /// Creates a simple test profile. - /// - /// soil profile - public static SoilProfile1D CreateSimpleTestProfile() - { - var sand = new Soil(); - sand.Name = "zand"; - sand.AbovePhreaticLevel = 15; - sand.BelowPhreaticLevel = 17; - - var clay = new Soil(); - clay.Name = "klei"; - clay.AbovePhreaticLevel = 18; - clay.BelowPhreaticLevel = 20; - - var soilProfile = new SoilProfile1D(); - soilProfile.Name = "TestProf"; - - var layer1 = new SoilLayer1D(); - layer1.Name = "layer1"; - layer1.TopLevel = 10; - layer1.Soil = clay; - layer1.IsAquifer = false; - soilProfile.Layers.Add(layer1); - - var layer2 = new SoilLayer1D(); - layer2.Name = "layer2"; - layer2.TopLevel = -3; - layer2.Soil = sand; - layer2.IsAquifer = true; - soilProfile.Layers.Add(layer2); - - return soilProfile; - } - - /// - /// Creates a test profile with two aquifers. - /// - /// soil profile - public static SoilProfile1D CreateTestProfileTwoAquifers() - { - var sandTop = new Soil(); - sandTop.Name = "zandtop"; - sandTop.AbovePhreaticLevel = 18; - sandTop.BelowPhreaticLevel = 20; - - var clay = new Soil(); - clay.Name = "klei"; - clay.AbovePhreaticLevel = 18; - clay.BelowPhreaticLevel = 20; - - var sandBottom = new Soil(); - sandBottom.Name = "zandbottom"; - sandBottom.AbovePhreaticLevel = 15; - sandBottom.BelowPhreaticLevel = 17; - - var peat = new Soil(); - peat.Name = "veen"; - peat.AbovePhreaticLevel = 5; - peat.BelowPhreaticLevel = 10.5; - - var soilProfile = new SoilProfile1D(); - soilProfile.Name = "TestProf"; - - var layer1 = new SoilLayer1D(); - layer1.Name = "layer1"; - layer1.TopLevel = 10; - layer1.Soil = clay; - layer1.IsAquifer = false; - soilProfile.Layers.Add(layer1); - - var layer2 = new SoilLayer1D(); - layer2.Name = "layer2"; - layer2.TopLevel = -5; - layer2.Soil = sandTop; - layer2.IsAquifer = true; - soilProfile.Layers.Add(layer2); - - var layer3 = new SoilLayer1D(); - layer3.Name = "layer3"; - layer3.TopLevel = -6; - layer3.Soil = peat; - layer3.IsAquifer = false; - soilProfile.Layers.Add(layer3); - - var layer4 = new SoilLayer1D(); - layer4.Name = "layer4"; - layer4.TopLevel = -10; - layer4.Soil = sandBottom; - layer4.IsAquifer = true; - soilProfile.Layers.Add(layer4); - - var layer5 = new SoilLayer1D(); - layer5.Name = "layer5"; - layer5.TopLevel = -13; - layer5.Soil = clay; - layer5.IsAquifer = false; - soilProfile.Layers.Add(layer5); - - return soilProfile; - } - - /// - /// Creates a test profile with three cover sublayers and one aquifer. - /// - /// soil profile - public static SoilProfile1D CreateTestProfileThreeCoverSublayersOneAquifer() - { - var coverSublayer1 = new Soil(); - coverSublayer1.Name = "cover sublayer 1"; - coverSublayer1.AbovePhreaticLevel = 15; - coverSublayer1.BelowPhreaticLevel = 17; - - var coverSublayer2 = new Soil(); - coverSublayer2.Name = "cover sublayer 2"; - coverSublayer2.AbovePhreaticLevel = 12; - coverSublayer2.BelowPhreaticLevel = 14; - - var coverSublayer3 = new Soil(); - coverSublayer3.Name = "cover sublayer 3"; - coverSublayer3.AbovePhreaticLevel = 10; - coverSublayer3.BelowPhreaticLevel = 10.5; - - var pleistocene = new Soil(); - pleistocene.Name = "pleistocene"; - pleistocene.AbovePhreaticLevel = 18; - pleistocene.BelowPhreaticLevel = 20; - - var soilProfile = new SoilProfile1D(); - soilProfile.Name = "TestProfileWithThreeCoverSublayersOneAquifer"; - - var layer1 = new SoilLayer1D(); - layer1.Name = "layer1"; - layer1.TopLevel = 100; - layer1.Soil = coverSublayer1; - layer1.IsAquifer = false; - soilProfile.Layers.Add(layer1); - - var layer2 = new SoilLayer1D(); - layer2.Name = "layer2"; - layer2.TopLevel = -1.9; - layer2.Soil = coverSublayer2; - layer2.IsAquifer = false; - soilProfile.Layers.Add(layer2); - - var layer3 = new SoilLayer1D(); - layer3.Name = "layer3"; - layer3.TopLevel = -2.5; - layer3.Soil = coverSublayer3; - layer3.IsAquifer = false; - soilProfile.Layers.Add(layer3); - - var layer4 = new SoilLayer1D(); - layer4.Name = "layer4"; - layer4.TopLevel = -3.1; - layer4.Soil = pleistocene; - layer4.IsAquifer = true; - soilProfile.Layers.Add(layer4); - - return soilProfile; - } - - /// - /// Creates a test profile with two cover sublayers and two aquifers. - /// - /// soil profile - public static SoilProfile1D CreateTestProfileTwoCoverSublayersTwoAquifers() - { - var coverSublayer1 = new Soil(); - coverSublayer1.Name = "cover sublayer 1"; - coverSublayer1.AbovePhreaticLevel = 15; - coverSublayer1.BelowPhreaticLevel = 17; - - var coverSublayer2 = new Soil(); - coverSublayer2.Name = "cover sublayer 2"; - coverSublayer2.AbovePhreaticLevel = 12; - coverSublayer2.BelowPhreaticLevel = 14; - - var aquifer1 = new Soil(); - aquifer1.Name = "aquifer 1"; - aquifer1.AbovePhreaticLevel = 10; - aquifer1.BelowPhreaticLevel = 10.5; - - var aquifer2 = new Soil(); - aquifer2.Name = "aquifer 2"; - aquifer2.AbovePhreaticLevel = 18; - aquifer2.BelowPhreaticLevel = 20; - - var soilProfile = new SoilProfile1D(); - soilProfile.Name = "TestProfileWithTwoCoverSublayersTwoAquifers"; - - var layer1 = new SoilLayer1D(); - layer1.Name = "layer1"; - layer1.TopLevel = 100; - layer1.Soil = coverSublayer1; - layer1.IsAquifer = false; - soilProfile.Layers.Add(layer1); - - var layer2 = new SoilLayer1D(); - layer2.Name = "layer2"; - layer2.TopLevel = -1.9; - layer2.Soil = coverSublayer2; - layer2.IsAquifer = false; - soilProfile.Layers.Add(layer2); - - var layer3 = new SoilLayer1D(); - layer3.Name = "layer3"; - layer3.TopLevel = -2.5; - layer3.Soil = aquifer1; - layer3.IsAquifer = true; - soilProfile.Layers.Add(layer3); - - var layer4 = new SoilLayer1D(); - layer4.Name = "layer4"; - layer4.TopLevel = -3.1; - layer4.Soil = aquifer2; - layer4.IsAquifer = true; - soilProfile.Layers.Add(layer4); - - return soilProfile; - } - - /// - /// Creates a test profile with one cover layer and one in-between aquifer. - /// - /// soil profile - public static SoilProfile1D CreateTestProfileOneCoverLayerOneInBetweenAquifer() - { - var coverLayer = new Soil(); - coverLayer.Name = "cover layer"; - coverLayer.AbovePhreaticLevel = 15; - coverLayer.BelowPhreaticLevel = 17; - - var inBetweenAquifer = new Soil(); - inBetweenAquifer.Name = "in between aquifer"; - inBetweenAquifer.AbovePhreaticLevel = 12; - inBetweenAquifer.BelowPhreaticLevel = 14; - - var deepAquitard = new Soil(); - deepAquitard.Name = "deep aquitard"; - deepAquitard.AbovePhreaticLevel = 10; - deepAquitard.BelowPhreaticLevel = 10.5; - - var deepAquifer = new Soil(); - deepAquifer.Name = "deep aquifer"; - deepAquifer.AbovePhreaticLevel = 18; - deepAquifer.BelowPhreaticLevel = 20; - - var soilProfile = new SoilProfile1D(); - soilProfile.Name = "TestProfileWithOneCoverLayerOneInBetweenAquifer"; - - var layer1 = new SoilLayer1D(); - layer1.Name = "layer1"; - layer1.TopLevel = 100; - layer1.Soil = coverLayer; - layer1.IsAquifer = false; - soilProfile.Layers.Add(layer1); - - var layer2 = new SoilLayer1D(); - layer2.Name = "layer2"; - layer2.TopLevel = -1.9; - layer2.Soil = inBetweenAquifer; - layer2.IsAquifer = true; - soilProfile.Layers.Add(layer2); - - var layer3 = new SoilLayer1D(); - layer3.Name = "layer3"; - layer3.TopLevel = -2.5; - layer3.Soil = deepAquitard; - layer3.IsAquifer = false; - soilProfile.Layers.Add(layer3); - - var layer4 = new SoilLayer1D(); - layer4.Name = "layer4"; - layer4.TopLevel = -3.1; - layer4.Soil = deepAquifer; - layer4.IsAquifer = true; - soilProfile.Layers.Add(layer4); - - return soilProfile; - } - - /// /// Create a soil layer with the given top level and soil name /// /// The toplevel. @@ -1306,6 +918,46 @@ return soilProfile1D; } + + /// + /// /------\ + /// / \ + /// _____________/ \______________________________ Level 10 m + /// Aquitard + /// _______________________________________________________ Level 6 m + /// In between aquifer + /// _______________________________________________________ Level 2 m + /// Aquitard + /// _______________________________________________________ Level -2 m + /// In between aquifer + /// ______________ Level -3 m + /// ____________/ \___________________________ Level -4 m + /// Aquitard + /// _______________________________________________________ Level -6 m + /// Bottom aquifer + /// _______________________________________________________ Level -10 m + /// + public static SoilProfile2D CreateSoilProfile2DWithNonHorizontalBottomAquitard(out SurfaceLine2 surfaceLine) + { + const double almostEqual = 1e-09; + + surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineDike(10); + SoilProfile1D soilProfile1D = CreateClaySandClaySandClaySandProfile(10, 6, 2, -2, -4, -6); + soilProfile1D.BottomLevel = -10; + var soilSurfaceProfile = new SoilSurfaceProfile + { + SoilProfile = soilProfile1D, + SurfaceLine2 = surfaceLine, + DikeEmbankmentMaterial = new Soil(), + Name = "Test" + }; + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); + Point2D point1 = soilProfile2D.Geometry.Points.First(p => Math.Abs(p.X - 34.5) < almostEqual && Math.Abs(p.Z + 4) < almostEqual); + point1.Z = -3; + Point2D point2 = soilProfile2D.Geometry.Points.First(p => Math.Abs(p.X - 40.5) < almostEqual && Math.Abs(p.Z + 4) < almostEqual); + point2.Z = -3; + return soilProfile2D; + } public static SoilLayer2D CreateRectangularSoilLayer2D(double topCoord, double bottomCoord, double leftCoord, double rightCoord, SoilProfile2D soilProfile2D, Soil soil = null, bool isAquifer = false) Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs =================================================================== diff -u -r6404 -r6747 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs (.../PlLinesCreatorTest.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs (.../PlLinesCreatorTest.cs) (revision 6747) @@ -591,7 +591,7 @@ } /// - /// Test if PL1 creation expert knowledge with does not create pl-line below polderlevel + /// Test if PL1 creation expert knowledge with does not create pl-line below polder level /// [Test] public void CreatePL1_WithPointBelowDikeTopAtPolderLowerPolderLevel_ReturnsPointAtPolderLevel() @@ -1262,7 +1262,6 @@ Assert.That(plLine.Points[1].LocationEquals(new PlLinePoint(21.0, cHeadPl2)), Is.True); Assert.That(plLineCreator.SoilProfile.BottomAquiferLayer, Is.Not.Null); Assert.That(plLineCreator.SoilProfile.InBetweenAquiferLayer, Is.Not.Null); - Assert.That(plLineCreator.SoilProfile.InfiltrationLayer, Is.Null); }); Assert.Multiple(() => { @@ -1308,7 +1307,6 @@ Assert.That(plLine.Points[1].LocationEquals(new PlLinePoint(21.0, cHeadPl2)), Is.True); Assert.That(plLineCreator.SoilProfile.BottomAquiferLayer, Is.Not.Null); Assert.That(plLineCreator.SoilProfile.InBetweenAquiferLayer, Is.Not.Null); - Assert.That(plLineCreator.SoilProfile.InfiltrationLayer, Is.Null); }); Assert.Multiple(() => { @@ -1354,7 +1352,6 @@ Assert.That(plLine.Points[1].LocationEquals(new PlLinePoint(21.0, cHeadPl2)), Is.True); Assert.That(plLineCreator.SoilProfile.BottomAquiferLayer, Is.Not.Null); Assert.That(plLineCreator.SoilProfile.InBetweenAquiferLayer, Is.Not.Null); - Assert.That(plLineCreator.SoilProfile.InfiltrationLayer, Is.Null); }); Assert.Multiple(() => { @@ -2402,7 +2399,102 @@ Assert.That(plLine.Points[5].Z, Is.EqualTo(0.9).Within(tolerance4Decimals)); }); } + + [Test] + [TestCase(1, true)] // top level penetration zone in bottom aquitard (OK) + [TestCase(1.99, true)] // top level penetration zone in bottom aquitard (OK) + [TestCase(2, true)] // top level penetration zone coincides partly with in-between aquifer (OK) + [TestCase(2.01, false)] // top level penetration zone partly above in-between aquifer (not OK) + [TestCase(4.5, false)] // top level penetration zone in middle aquitard (not OK) + [TestCase(16.5, false)] // top level penetration zone partly above surface line (not OK) + [TestCase(21.5, false)] // top level penetration zone completely above surface line (not OK) + public void IsPenetrationZoneCompletelyWithinInfiltrationZoneTest(double penetrationLength, bool expectedResult) + { + var plLineCreator = new Calculators.PlLinesCreator.PlLinesCreator + { + SoilProfileType = SoilProfileType.ProfileType2D, + SoilProfile = null, + SoilProfile2D = FactoryForSoilProfiles.CreateSoilProfile2DWithNonHorizontalBottomAquitard(out SurfaceLine2 line), + ModelParametersForPlLines = + { + PenetrationLength = penetrationLength + }, + SurfaceLine = line + }; + + bool result = plLineCreator.IsPenetrationZoneCompletelyWithinInfiltrationZone(penetrationLength); + + Assert.That(result, Is.EqualTo(expectedResult)); + + } + + [Test] + [TestCase(1, false)] // top level penetration zone (-5m) in bottom aquitard + [TestCase(2.5, true)] // top level penetration zone (-3.5m) half in bottom aquitard, half in in-between aquifer + [TestCase(4.5, true)] // top level penetration zone (-2.5m) in middle aquitard + [TestCase(16.5, true)] // top level penetration zone (10.5m) partly above surface line + public void Given2DGeometry_WhenTopLevelOfPenetrationIsInAquifer_ThenPl2IsEqualToPl4(double penetrationLength, bool isPl2EqualToPl4) + { + const double headPl4 = 3.2; + const double headPl2 = 2.5; + var plLineCreator = new Calculators.PlLinesCreator.PlLinesCreator + { + ModelParametersForPlLines = + { + PlLineCreationMethod = PlLineCreationMethod.ExpertKnowledgeRRD, + PenetrationLength = penetrationLength, + DampingFactorPl4 = 0 + }, + HeadInPlLine4 = headPl4, + WaterLevelRiverHigh = 11.0, + WaterLevelPolder = 9.0, + HeadInPlLine2 = headPl2, + SoilProfile2D = FactoryForSoilProfiles.CreateSoilProfile2DWithNonHorizontalBottomAquitard(out SurfaceLine2 line), + SoilProfileType = SoilProfileType.ProfileType2D, + SurfaceLine = line, + DikeEmbankmentMaterial = new Soil() + }; + var location = new Location(); + // Call + PlLines plLines = plLineCreator.CreateAllPlLines(location); + + // Assert + Assert.That(plLines.Lines[PlLineType.Pl4], Is.Not.Null); + Assert.That(plLines.Lines[PlLineType.Pl4].Points, Has.Count.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(plLines.Lines[PlLineType.Pl4].Points[0].X, Is.EqualTo(0).Within(tolerance4Decimals)); + Assert.That(plLines.Lines[PlLineType.Pl4].Points[0].Z, Is.EqualTo(headPl4).Within(tolerance4Decimals)); + Assert.That(plLines.Lines[PlLineType.Pl4].Points[1].X, Is.EqualTo(75).Within(tolerance4Decimals)); + Assert.That(plLines.Lines[PlLineType.Pl4].Points[1].Z, Is.EqualTo(headPl4).Within(tolerance4Decimals)); + + Assert.That(plLines.Lines[PlLineType.Pl2], Is.Not.Null); + }); + Assert.That(plLines.Lines[PlLineType.Pl2].Points, Has.Count.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(plLines.Lines[PlLineType.Pl2].Points[0].X, Is.EqualTo(0).Within(tolerance4Decimals)); + Assert.That(plLines.Lines[PlLineType.Pl2].Points[1].X, Is.EqualTo(75).Within(tolerance4Decimals)); + }); + if (isPl2EqualToPl4) + { + Assert.Multiple(() => + { + Assert.That(plLines.Lines[PlLineType.Pl2].Points[0].Z, Is.EqualTo(headPl4).Within(tolerance4Decimals)); + Assert.That(plLines.Lines[PlLineType.Pl2].Points[1].Z, Is.EqualTo(headPl4).Within(tolerance4Decimals)); + }); + } + else + { + Assert.Multiple(() => + { + Assert.That(plLines.Lines[PlLineType.Pl2].Points[0].Z, Is.EqualTo(headPl2).Within(tolerance4Decimals)); + Assert.That(plLines.Lines[PlLineType.Pl2].Points[1].Z, Is.EqualTo(headPl2).Within(tolerance4Decimals)); + }); + } + } + /// /// _______ Level 10 m /// / Clay \ @@ -2434,7 +2526,7 @@ }; return soilSurfaceProfile.ConvertToSoilProfile2D(); } - + private void CheckPl3For1DGeometryWithExpertKnowledgeRrd(PlLine plLine) { // PlLine is supposed to have adjusted points at both banks of the ditch Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs =================================================================== diff -u -r6404 -r6747 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 6747) @@ -552,7 +552,7 @@ return intersectionPointsWithLine; } - private RelativeXzPosition PositionXzOfPointRelatedToExtrapolatedLine(Point2D point, + public RelativeXzPosition PositionXzOfPointRelatedToExtrapolatedLine(Point2D point, ExtraPolationMode extraPolationMode = ExtraPolationMode.Beyond) { return IsPointConsideredBeyondLine(point, extraPolationMode) ? RelativeXzPosition.BeyondGeometricLine : DeterminePositionWithRespectToExtrapolatedLine(point, extraPolationMode); Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs =================================================================== diff -u -r6404 -r6747 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs (.../PlLinesCreator.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs (.../PlLinesCreator.cs) (revision 6747) @@ -306,6 +306,16 @@ return false; } + internal bool IsPenetrationZoneCompletelyWithinInfiltrationZone(double penetrationLength) + { + return SoilProfileType switch + { + SoilProfileType.ProfileType1D => IsPenetrationZoneCompletelyWithinInfiltrationZoneFor1DGeometry(penetrationLength), + SoilProfileType.ProfileType2D => IsPenetrationZoneCompletelyWithinInfiltrationZoneFor2DGeometry(penetrationLength), + _ => false + }; + } + private double? headInPlLine3 { get; set; } private double? headInPlLine4 { get; set; } @@ -397,7 +407,7 @@ /// private PlLine CreatePlLine2ByExpertKnowledge(double penetrationLength, double? headInPlLine2) { - PlLine plLine = null; + var plLine = new PlLine(); if (penetrationLength < 0.0) { @@ -406,88 +416,70 @@ if (penetrationLength.AlmostEquals(0.0) || (headInPlLine2 == null)) { - // No penetration, or no Head Pl2 defined, so empty pl-line will be returned - plLine = new PlLine(); + return plLine; } - else + + if (IsPenetrationZoneCompletelyWithinInfiltrationZone(penetrationLength)) { - switch (SoilProfileType) - { - case SoilProfileType.ProfileType1D: - plLine = CreatePlLine2ByExpertKnowledgeFor1DGeometry(penetrationLength, headInPlLine2); - break; - case SoilProfileType.ProfileType2D: - plLine = CreatePlLine2ByExpertKnowledgeFor2DGeometry(headInPlLine2); - break; - } + plLine = new PlLine(); + plLine.Points.Add(new PlLinePoint(SurfaceLine.Geometry.Points.First().X, headInPlLine2.Value)); + plLine.Points.Add(new PlLinePoint(SurfaceLine.Geometry.Points.Last().X, headInPlLine2.Value)); } return plLine; } - /// - /// Create PL2 (is pl line for penetration) for 2d-geometry - /// - /// The head in pl line2. - /// - /// Head PL2 not defined - private PlLine CreatePlLine2ByExpertKnowledgeFor2DGeometry(double? headInPlLine2) + private bool IsPenetrationZoneCompletelyWithinInfiltrationZoneFor1DGeometry(double penetrationLength) { - if (headInPlLine2 == null) + SoilProfile1D relevantSoilProfile = GetRelevantSoilProfileForAquiferLayersSearch(); + // The infiltration layers are the aquitards situated between the bottom aquifer and: + // - the surface line if no in-between aquifer is present + // - the lowest in-between aquifer if at least one in-between aquifer is present + IList infiltrationLayers = (from SoilLayer1D layer in relevantSoilProfile.Layers + where (relevantSoilProfile.InBetweenAquiferLayer == null || layer.TopLevel < relevantSoilProfile.GetInBetweenAquiferClusters.Last().Item2.TopLevel) && + layer.TopLevel > relevantSoilProfile.BottomAquiferLayer.TopLevel + select layer).ToList(); + + if (infiltrationLayers.Count > 0) { - throw new PlLinesCreatorException("Head PL2 not defined"); + double penetrationZoneTopLevel = relevantSoilProfile.BottomAquiferLayer.TopLevel + penetrationLength; + + return penetrationZoneTopLevel <= infiltrationLayers.First().TopLevel; } - var plLine = new PlLine(); - plLine.Points.Add(new PlLinePoint(SurfaceLine.Geometry.Points.First().X, headInPlLine2.Value)); - plLine.Points.Add(new PlLinePoint(SurfaceLine.Geometry.Points.Last().X, headInPlLine2.Value)); - return plLine; + return false; } - /// - /// Create PL2 (is pl line for penetration) for 1d-geometry - /// - /// - /// - /// - private PlLine CreatePlLine2ByExpertKnowledgeFor1DGeometry(double penetrationLength, double? headInPlLine2) + private bool IsPenetrationZoneCompletelyWithinInfiltrationZoneFor2DGeometry(double penetrationLength) { - if (headInPlLine2 == null) + // Determine the top level of the infiltration zone (= lowest zone with only aquitards) + SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(SoilProfile2D, out List inBetweenAquiferUpperCoordinates, + out List inBetweenAquiferLowerCoordinates); + GeometryPointString topLevelInfiltrationLayers; + if (inBetweenAquiferUpperCoordinates.Count > 0 && inBetweenAquiferLowerCoordinates.Count > 0) { - throw new PlLinesCreatorException("Head PL2 not defined"); + topLevelInfiltrationLayers = inBetweenAquiferLowerCoordinates.Last(); } + else + { + topLevelInfiltrationLayers = SoilProfile2D.Surfaces.First().GeometrySurface.DetermineTopGeometrySurface(); + } - var plLine = new PlLine(); - if (SoilProfile != null) + // Determine the top level of the (user-defined) penetration zone + SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.BottomAquiferCluster, SoilProfile2D, out Point2D[] bottomAquiferCoordinates, out _); + List topLevelPenetrationZone = bottomAquiferCoordinates.Select(p => new Point2D(p.X, p.Z + penetrationLength)).ToList(); + + // Compare both lines + foreach (Point2D point in topLevelPenetrationZone) { - SoilProfile1D relevantSoilProfile = GetRelevantSoilProfileForAquiferLayersSearch(); - IList aquiferLayers = relevantSoilProfile.GetAquiferLayers(); - if (aquiferLayers.Count == 0) + RelativeXzPosition position = topLevelInfiltrationLayers.PositionXzOfPointRelatedToExtrapolatedLine(point); + if (position is RelativeXzPosition.AboveGeometricLine or RelativeXzPosition.BeyondGeometricLine) { - throw new PlLinesCreatorException("Soil profile contains no aquifer layers."); + return false; } - - if (penetrationLength > 0 && aquiferLayers.Count > 0) - { - IList infiltrationLayers = (from SoilLayer1D layer in relevantSoilProfile.Layers - where (relevantSoilProfile.InBetweenAquiferLayer == null || layer.TopLevel < relevantSoilProfile.InBetweenAquiferLayer.TopLevel) && - layer.TopLevel > relevantSoilProfile.BottomAquiferLayer.TopLevel - select layer).ToList(); - - if (infiltrationLayers.Count > 0) - { - double separationLevel = relevantSoilProfile.BottomAquiferLayer.TopLevel + penetrationLength; - - if (separationLevel <= infiltrationLayers.First().TopLevel) - { - plLine.Points.Add(new PlLinePoint(SurfaceLine.Geometry.Points.First().X, headInPlLine2.Value)); - plLine.Points.Add(new PlLinePoint(SurfaceLine.Geometry.Points.Last().X, headInPlLine2.Value)); - } - } - } } - return plLine; + return true; } ///