Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs =================================================================== diff -u -r2150 -r2718 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs (.../PlLinesCreatorTest.cs) (revision 2150) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/PlLinesCreatorTest.cs (.../PlLinesCreatorTest.cs) (revision 2718) @@ -335,7 +335,7 @@ } /// - /// Test if PL1 is created correctly with expert knowledge when low water below surface level + /// Test if PL1 is refused correctly with expert knowledge when low water below surface level /// [Test] public void CreatePL1LowLowFor1DGeometryWithExpertKnowledgeLinearInDike() @@ -355,18 +355,7 @@ plLineCreator.SoilProfile = FactoryForSoilProfiles.CreateClaySandClaySandProfile(); plLineCreator.SurfaceLine = surfacelineSimpleDike; plLineCreator.WaterLevelPolder = plLineCreator.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z - 1.0; - PlLine plLine = plLineCreator.CreatePlLineByExpertKnowledge(PlLineType.Pl1, 0.02); - Assert.AreEqual(5, plLine.Points.Count); - Assert.AreEqual(0.0, plLine.Points[0].X, cTolerance); - Assert.AreEqual(2.0, plLine.Points[0].Z, cTolerance); - Assert.AreEqual(1.0, plLine.Points[1].X, cTolerance); - Assert.AreEqual(2.0, plLine.Points[1].Z, cTolerance); - Assert.AreEqual(3.0, plLine.Points[2].X, cTolerance); - Assert.AreEqual(3.9, plLine.Points[2].Z, cTolerance); - Assert.AreEqual(10, plLine.Points[3].X, cTolerance); - Assert.AreEqual(0.9, plLine.Points[3].Z, cTolerance); - Assert.AreEqual(12, plLine.Points[4].X, cTolerance); - Assert.AreEqual(0.9, plLine.Points[4].Z, cTolerance); + Assert.That(() => plLineCreator.CreatePlLineByExpertKnowledge(PlLineType.Pl1, 0.02), Throws.TypeOf(typeof(SurfaceLineException)).With.Message.Contains("should be higher than dike toe at river side")); } } @@ -425,7 +414,7 @@ } /// - /// Test if PL1 is created correctly with expert knowledge when low water below multi segment surface level + /// Test if PL1 is refused correctly with expert knowledge when low water below multi segment surface level /// [Test] public void CreatePL1LowLowFor1DGeometryWithExpertKnowledgeLinearInDikeWithMultiSegmentTalud() @@ -458,22 +447,7 @@ plLineCreator.SurfaceLine.EnsurePointOfType(12.0, 1.0, CharacteristicPointType.SurfaceLevelInside); plLineCreator.SurfaceLine.Geometry.SyncCalcPoints(); plLineCreator.WaterLevelPolder = plLineCreator.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z - 1.0; - PlLine plLine = plLineCreator.CreatePlLineByExpertKnowledge(PlLineType.Pl1, 0.02); - Assert.AreEqual(7, plLine.Points.Count); - Assert.AreEqual(0.0, plLine.Points[0].X, cTolerance); - Assert.AreEqual(2.0, plLine.Points[0].Z, cTolerance); - Assert.AreEqual(1.0, plLine.Points[1].X, cTolerance); - Assert.AreEqual(2.0, plLine.Points[1].Z, cTolerance); - Assert.AreEqual(1.5, plLine.Points[2].X, cTolerance); - Assert.AreEqual(2.4, plLine.Points[2].Z, cTolerance); - Assert.AreEqual(2.5, plLine.Points[3].X, cTolerance); - Assert.AreEqual(2.9, plLine.Points[3].Z, cTolerance); - Assert.AreEqual(3.0, plLine.Points[4].X, cTolerance); - Assert.AreEqual(3.9, plLine.Points[4].Z, cTolerance); - Assert.AreEqual(10, plLine.Points[5].X, cTolerance); - Assert.AreEqual(0.9, plLine.Points[5].Z, cTolerance); - Assert.AreEqual(12, plLine.Points[6].X, cTolerance); - Assert.AreEqual(0.9, plLine.Points[6].Z, cTolerance); + Assert.That(() => plLineCreator.CreatePlLineByExpertKnowledge(PlLineType.Pl1, 0.02), Throws.TypeOf(typeof(SurfaceLineException)).With.Message.Contains("should be higher than dike toe at river side")); } } @@ -852,10 +826,10 @@ } /// - /// Test if PL1 is created correctly with expert knowledge with complex profile and low waterlevel below toe of dike riverside + /// Test if PL1 is created correctly with expert knowledge with complex profile and low waterlevel just above toe of dike riverside /// [Test] - public void CreatePL1LowBelowToeFor1DGeometryWithExpertKnowledgeRRD() + public void CreatePL1LowJustAboveToeFor1DGeometryWithExpertKnowledgeRRD() { const double cTolerance = 0.0001; var surfacelineSimpleDike = FactoryForSurfaceLines.CreateSurfacelineSimpleDike(); @@ -864,7 +838,7 @@ Assert.IsNotNull(plLineCreator); plLineCreator.SoilProfile = FactoryForSoilProfiles.CreateComplexProfile(); plLineCreator.WaterLevelRiverHigh = 4.0; - plLineCreator.WaterLevelRiverLow = 1.0; + plLineCreator.WaterLevelRiverLow = 2.1; plLineCreator.IsUseLowWaterLevel = true; plLineCreator.ModelParametersForPlLines.DampingFactorPl3 = 0.3; plLineCreator.ModelParametersForPlLines.DampingFactorPl4 = 0.4; @@ -878,23 +852,19 @@ // Create Pl1 plLineCreator.WaterLevelPolder = plLineCreator.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z - 1.0; PlLine plLine = plLineCreator.CreatePlLineByExpertKnowledge(PlLineType.Pl1, 0.02); - Assert.AreEqual(8, plLine.Points.Count); + Assert.AreEqual(6, plLine.Points.Count); Assert.AreEqual(-2.0, plLine.Points[0].X, cTolerance); - Assert.AreEqual(1.0, plLine.Points[0].Z, cTolerance); - Assert.AreEqual(-1.0, plLine.Points[1].X, cTolerance); - Assert.AreEqual(1.0, plLine.Points[1].Z, cTolerance); - Assert.AreEqual(0, plLine.Points[2].X, cTolerance); - Assert.AreEqual(1.9, plLine.Points[2].Z, cTolerance); - Assert.AreEqual(1, plLine.Points[3].X, cTolerance); - Assert.AreEqual(1.9, plLine.Points[3].Z, cTolerance); - Assert.AreEqual(4, plLine.Points[4].X, cTolerance); - Assert.AreEqual(3.5, plLine.Points[4].Z, cTolerance); - Assert.AreEqual(7, plLine.Points[5].X, cTolerance); - Assert.AreEqual(2.5, plLine.Points[5].Z, cTolerance); - Assert.AreEqual(10, plLine.Points[6].X, cTolerance); - Assert.AreEqual(0.9, plLine.Points[6].Z, cTolerance); - Assert.AreEqual(12, plLine.Points[7].X, cTolerance); - Assert.AreEqual(0.9, plLine.Points[7].Z, cTolerance); + Assert.AreEqual(2.1, plLine.Points[0].Z, cTolerance); + Assert.AreEqual(1.1, plLine.Points[1].X, cTolerance); + Assert.AreEqual(2.1, plLine.Points[1].Z, cTolerance); + Assert.AreEqual(4, plLine.Points[2].X, cTolerance); + Assert.AreEqual(3.5, plLine.Points[2].Z, cTolerance); + Assert.AreEqual(7, plLine.Points[3].X, cTolerance); + Assert.AreEqual(2.5, plLine.Points[3].Z, cTolerance); + Assert.AreEqual(10, plLine.Points[4].X, cTolerance); + Assert.AreEqual(0.9, plLine.Points[4].Z, cTolerance); + Assert.AreEqual(12, plLine.Points[5].X, cTolerance); + Assert.AreEqual(0.9, plLine.Points[5].Z, cTolerance); } } Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SurfaceLine2Extensions.cs =================================================================== diff -u -r1974 -r2718 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SurfaceLine2Extensions.cs (.../SurfaceLine2Extensions.cs) (revision 1974) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SurfaceLine2Extensions.cs (.../SurfaceLine2Extensions.cs) (revision 2718) @@ -425,7 +425,7 @@ } /// - /// Make sure river level is above the bottom of the river. + /// Check whether river level is above the dike toe at river side. If not, throw error /// /// The evaluated surfaceline. /// The current river level. @@ -434,16 +434,17 @@ /// when /// is not null. /// - public static double? EnsureWaterLevelIsAboveRiverBottom(this SurfaceLine2 line, double? riverLevel) + public static void CheckWaterLevelIsAboveDikeToeRiverSide(this SurfaceLine2 line, double? riverLevel) { - // Waterlevel is supposed to be at level of SurfaceLevelOutside when waterlevel - // is below SurfaceLevelOutside (is the bottom of the river) + // Waterlevel MUST be above level of dike toe at river side if (riverLevel.HasValue) { - double z = line.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).Z; - riverLevel = Math.Max(z, riverLevel.Value); - } - return riverLevel; + double z = line.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).Z; + if (riverLevel <= z) + { + ThrowWhenLevelBelowDikeToeDike(z, riverLevel.Value); + } + } } /// @@ -652,6 +653,13 @@ level, dikeTopAtRiver.Z)); } } + + private static void ThrowWhenLevelBelowDikeToeDike(double levelDikeToeRiverSide, double riverLevel) + { + throw new SurfaceLineException(String.Format( + "River level ({0:F2} m) should be higher than dike toe at river side ({1:F2}))", + riverLevel, levelDikeToeRiverSide)); + } #endregion Private methods } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs =================================================================== diff -u -r2619 -r2718 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs (.../PlLinesCreator.cs) (revision 2619) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/PlLinesCreator.cs (.../PlLinesCreator.cs) (revision 2718) @@ -311,7 +311,6 @@ // Split layer at separation level var extraLayer = new SoilLayer1D(); extraLayer.Assign(separationLayer); - //extraLayer.Id = this.SoilProfile1D.GetNewUniqueLayerName(); ##Bka extraLayer.TopLevel = separationLevel; this.SoilProfile.Layers.Insert(this.SoilProfile.Layers.IndexOf(separationLayer) + 1, extraLayer); } @@ -1705,7 +1704,7 @@ // Discussion about this was done between Vastenburg, Knoeff and The. // After a renewed discussion with Vastenburg, Van der Zwan and Bka, it has been decided that the PL1 should follow the // surfaceline (with offset) until either end of surface line or polder level. Note: this is only needed when the phreatic level - // at dike toe is above polder level. + // at dike toe is above polder level. ##Bka if (phreaticLine.Points[phreaticLine.Points.Count - 1].Z > WaterLevelPolder) { AddPhreaticLineAlongSurfaceLevel(phreaticLine); @@ -1860,22 +1859,23 @@ new Point2D(pointEndOfprofile.X, polderLevel)); ThrowWhenWaterLevelAboveDike(polderLevel, SurfaceLine); - - int startPosition = 0; - int endPosition = 0; - startPosition = SurfaceLine.Geometry.Points.IndexOf(SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver)); - endPosition = SurfaceLine.Geometry.Points.IndexOf(SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder)); - for (int surfacePointIndex = startPosition; surfacePointIndex < endPosition; surfacePointIndex++) + // Find intersection between dike top (riverside because that is taken as default DTH) and dike toe (polder side) with polder level. + // Start at dike toe and work your way back to dike top. + var startPosition = SurfaceLine.Geometry.Points.IndexOf(SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder)); + var endPosition = SurfaceLine.Geometry.Points.IndexOf(SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver)); + for (int surfacePointIndex = startPosition; surfacePointIndex > endPosition; surfacePointIndex--) { var surfaceLineSegment = new Line(); - surfaceLineSegment.SetBeginAndEndPoints(new Point2D(SurfaceLine.Geometry.Points[surfacePointIndex].X, SurfaceLine.Geometry.Points[surfacePointIndex].Z), - new Point2D(SurfaceLine.Geometry.Points[surfacePointIndex + 1].X, SurfaceLine.Geometry.Points[surfacePointIndex + 1].Z)); + surfaceLineSegment.SetBeginAndEndPoints(new Point2D(SurfaceLine.Geometry.Points[surfacePointIndex - 1].X, + SurfaceLine.Geometry.Points[surfacePointIndex - 1].Z), new Point2D(SurfaceLine.Geometry.Points[surfacePointIndex].X, + SurfaceLine.Geometry.Points[surfacePointIndex].Z)); GeometryPoint intersectPoint = new GeometryPoint(); if (LineHelper.GetStrictIntersectionPoint(surfaceLineSegment, polderlevelLine, ref intersectPoint)) { return new PlLinePoint(intersectPoint.X, intersectPoint.Z); } } + // When polder level is below all points in the given surface line segment, there is no intersection point. return null; } @@ -1992,8 +1992,8 @@ PlLine phreaticLine = new PlLine(); phreaticLine.IsPhreatic = true; double? waterLevel = WaterLevelToUse(); - // Waterlevel is supposed to be at level of SurfaceLevelOutside when waterlevel is below SurfaceLevelOutside (is the bottom of the river) - waterLevel = this.SurfaceLine.EnsureWaterLevelIsAboveRiverBottom(waterLevel); + // Waterlevel MUST be above of Dike Toe At River Side, if not, an error is thrown + surfaceLine.CheckWaterLevelIsAboveDikeToeRiverSide(waterLevel); phreaticLine.Points.Add(new PlLinePoint(startXCoordinate, waterLevel.Value)); PlLinePoint intersectionPhreaticDike = null; @@ -2030,7 +2030,6 @@ ValidatePhreaticBelowDike(phreaticLine); // currentPL1Line is needed when calculating uplift reduction for PL3 and Pl4 - //AdaptPL1ForNonWaterRetainingObject(ref phreaticLine); ##Bka currentPl1Line = phreaticLine; return phreaticLine; } Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/SensorPlLine1Creator.cs =================================================================== diff -u -r1965 -r2718 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/SensorPlLine1Creator.cs (.../SensorPlLine1Creator.cs) (revision 1965) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/SensorPlLine1Creator.cs (.../SensorPlLine1Creator.cs) (revision 2718) @@ -57,8 +57,8 @@ throw new PlLinesCreatorException("There was an error trying to read the water level", e); } - // Make sure there is an intersection with the surfaceline - waterLevel = this.SensorLocation.SurfaceLine.EnsureWaterLevelIsAboveRiverBottom(waterLevel).Value; + // Waterlevel MUST be above of Dike Toe At River Side, if not, an error is thrown + SensorLocation.SurfaceLine.CheckWaterLevelIsAboveDikeToeRiverSide(waterLevel); // Add begin boundary lineConstructor.Insert(new PlLinePoint(XBeginBoundary, waterLevel)); Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/Sensors/SensorPLLineCreatorTest.cs =================================================================== diff -u -r1970 -r2718 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/Sensors/SensorPLLineCreatorTest.cs (.../SensorPLLineCreatorTest.cs) (revision 1970) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/Sensors/SensorPLLineCreatorTest.cs (.../SensorPLLineCreatorTest.cs) (revision 2718) @@ -287,6 +287,71 @@ Assert.AreEqual(expectedEndPoint, lastPoint.Z); } + [TestCase(0.0)] + [TestCase(-10.0)] + [TestCase(10.0)] + public void CreatePlLine_Pl1WithIllegalWaterLevel_Throws(double riverLevel) + { + // setup + var surfaceLine = new SurfaceLine2 + { + CharacteristicPoints = { GeometryMustContainPoint = true }, + Geometry = new GeometryPointString() + }; + var location = new Location("test") + { + RiverLevel = riverLevel, + PolderLevel = -1 + }; + location.AddSensorLocation(); + location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.LocationData; + + surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside); + surfaceLine.EnsurePointOfType(50.0, 0.0, CharacteristicPointType.DikeToeAtRiver); + surfaceLine.EnsurePointOfType(85.0, 8.0, CharacteristicPointType.DikeTopAtRiver); + surfaceLine.EnsurePointOfType(95.0, 8.0, CharacteristicPointType.DikeTopAtPolder); + surfaceLine.EnsurePointOfType(108.0, 4.0, CharacteristicPointType.ShoulderBaseInside); + surfaceLine.EnsurePointOfType(116.0, 3.0, CharacteristicPointType.ShoulderTopInside); + surfaceLine.EnsurePointOfType(121.0, 0.0, CharacteristicPointType.DikeToeAtPolder); + surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside); + location.SurfaceLine = surfaceLine; + + var sensor1 = new Sensor { ID = 1, Name = "Test1", Depth = 2, RelativeLocation = 50, PlLineMappings = new[] { PlLineType.Pl1 }, SensorType = SensorType.WaterLevel }; + var sensor2 = new Sensor { ID = 2, Name = "Test2", Depth = 2, RelativeLocation = 90, PlLineMappings = new[] { PlLineType.Pl1 } }; + var sensor3 = new Sensor { ID = 3, Name = "Test3", Depth = 2, RelativeLocation = 104, PlLineMappings = new[] { PlLineType.Pl1 } }; + var sensor4 = new Sensor { ID = 4, Name = "Test4", Depth = 2, RelativeLocation = 123.3, PlLineMappings = new[] { PlLineType.Pl1 } }; + + var repository = new SensorRepository(location); + + repository.Add(sensor1); + repository.Add(sensor2); + repository.Add(sensor3); + repository.Add(sensor4); + + IDictionary sensorValues = new Dictionary() + { + {sensor1, 1}, + {sensor2, 1}, + {sensor3, 1}, + {sensor4, 1}, + }; + + var sensorLocation = location.SensorLocation; + + var creator = new SensorPlLine1Creator(sensorLocation, sensorValues); + // call + if (riverLevel > 8) + { + Assert.That(() => creator.CreatePlLine(), Throws.TypeOf(typeof(SurfaceLineException)).With.Message.Contains("should NOT be higher than surface line")); + } + if (riverLevel <= 0) + { + Assert.That(() => creator.CreatePlLine(), + Throws.TypeOf(typeof(SurfaceLineException)).With.Message + .Contains("should be higher than dike toe at river side")); + } + } + [Test, Ignore("Test must be reviewed.")] public void CreatePlLine_Pl1DikeToeAtPolderToSurfaceLevelInsideAndNoLocationData_ZValueShouldBeSurfaceLevel() {