Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/TestFiles/Operational/Profile2DTests/CalculateStabilityInside2DInput.xml
===================================================================
diff -u -r5865 -r6063
--- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/TestFiles/Operational/Profile2DTests/CalculateStabilityInside2DInput.xml (.../CalculateStabilityInside2DInput.xml) (revision 5865)
+++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/TestFiles/Operational/Profile2DTests/CalculateStabilityInside2DInput.xml (.../CalculateStabilityInside2DInput.xml) (revision 6063)
@@ -33,22 +33,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -93,21 +77,21 @@
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
@@ -168,19 +152,17 @@
+
-
-
-
@@ -231,14 +213,15 @@
+
+
-
@@ -257,6 +240,7 @@
+
@@ -279,6 +263,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -304,67 +314,17 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -391,30 +351,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
+
@@ -439,39 +423,25 @@
-
+
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
+
-
+
@@ -481,34 +451,20 @@
-
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -523,18 +479,18 @@
-
+
-
-
+
+
-
+
-
-
+
+
@@ -551,18 +507,18 @@
-
+
-
-
+
+
-
+
-
-
+
+
@@ -579,25 +535,25 @@
-
+
-
+
-
-
+
+
-
-
+
+
@@ -608,14 +564,10 @@
-
-
-
-
@@ -636,70 +588,58 @@
-
+
-
+
-
+
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/TestFiles/Operational/Profile2DTests/CalculateStabilityInside2DOutput.xml
===================================================================
diff -u -r5870 -r6063
Binary files differ
Index: DamEngine/trunk/src/Deltares.DamEngine.Data/General/Sensors/SensorEnumerations.cs
===================================================================
diff -u -r4540 -r6063
--- DamEngine/trunk/src/Deltares.DamEngine.Data/General/Sensors/SensorEnumerations.cs (.../SensorEnumerations.cs) (revision 4540)
+++ DamEngine/trunk/src/Deltares.DamEngine.Data/General/Sensors/SensorEnumerations.cs (.../SensorEnumerations.cs) (revision 6063)
@@ -21,14 +21,14 @@
namespace Deltares.DamEngine.Data.General.Sensors;
-public enum DataSourceTypeSensors //Sensors
+public enum DataSourceTypeSensors
{
Ignore,
LocationData,
Sensor
}
-public enum SensorType //Sensors
+public enum SensorType
{
PiezometricHead,
WaterLevel,
Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/OperationalStabilityProfile2DTests.cs
===================================================================
diff -u -r5911 -r6063
--- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/OperationalStabilityProfile2DTests.cs (.../OperationalStabilityProfile2DTests.cs) (revision 5911)
+++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/OperationalStabilityProfile2DTests.cs (.../OperationalStabilityProfile2DTests.cs) (revision 6063)
@@ -21,55 +21,232 @@
using System.IO;
using System.Linq;
+using Deltares.DamEngine.Data.General.PlLines;
+using Deltares.DamEngine.Interface;
using Deltares.DamEngine.Io;
+using Deltares.DamEngine.Io.XmlInput;
using Deltares.DamEngine.Io.XmlOutput;
using Deltares.DamEngine.TestHelpers;
+using Deltares.MacroStability.Io;
+using Deltares.MacroStability.Io.XmlInput;
using KellermanSoftware.CompareNetObjects;
using NUnit.Framework;
+using CharacteristicPointType = Deltares.DamEngine.Data.Geotechnics.CharacteristicPointType;
+using SurfaceLinePoint = Deltares.DamEngine.Io.XmlInput.SurfaceLinePoint;
namespace Deltares.DamEngine.IntegrationTests.IntegrationTests;
[TestFixture]
public class OperationalStabilityProfile2DTests
{
+ private const double tolerance = 0.0000001;
+
+ private const uint sourceTypeLocationData = 1;
+ private const uint sourceTypeSensor = 2;
+
+ private const string projectPath = "Profile2DTests";
+ private const string testFilesLocation = @".\TestFiles\Operational\Profile2DTests\";
+ private const string inputFilename = testFilesLocation + "CalculateStabilityInside2DInput.xml";
+ private const string outputFilename = testFilesLocation + "CalculateStabilityInside2DOutput.xml";
+
+ // Characteristic points
+ private SurfaceLinePoint outsideLimit;
+ private SurfaceLinePoint dikeTopAtRiver;
+ private SurfaceLinePoint dikeTopAtPolder;
+ private SurfaceLinePoint shoulderInside;
+ private SurfaceLinePoint dikeToeAtPolder;
+ private SurfaceLinePoint insideLimit;
+
///
- /// The following test is based on the DamLive test Deltares.DamLive.Tests.StabilityInside2DTest
+ /// The following test is based on the DamLive test Deltares.DamLive.Tests.StabilityInside2DTest.
+ /// Two soil profiles (with and without in-between aquifer) are tested for 2 time steps, so 4 locations in total.
+ /// Two types of source data are tested: location data or sensor.
+ /// The expected Pl-lines are re-calculated using the input.
///
- [Test, Category(Categories.WorkInProgress)]
- public void GivenStabilityInsideProfile2DProject_WhenCalculating_ThenExpectedResultIsGenerated()
+ [Test]
+ [TestCase(false)]
+ [TestCase(true)]
+ public void GivenStabilityProjectWithTwoSoilProfiles2DAndTwoTimeSteps_WhenCalculating_ThenExpectedWaternetIsGeneratedPerProfileAndPerTimeStep(bool isUseLocationData)
{
- const string calcDir = "DAMLive.Calc";
- const string testFilesLocation = @".\TestFiles\Operational\Profile2DTests\";
- const string baseOutputName = "CalculateStabilityInside2D";
- const string inputFilename = baseOutputName + "Input.xml";
- const string outputFilename = baseOutputName + "Output.xml";
+ // Setup
+ const string calcDir = $"DAMLive.Calc.";
if (Directory.Exists(calcDir))
{
Directory.Delete(calcDir, true); // delete previous results
}
-
- const string expectedOutputFileName = testFilesLocation + outputFilename;
- Output expectedOutput = DamXmlSerialization.LoadOutputFromXmlFile(expectedOutputFileName);
- // Given
- string inputString = File.ReadAllText(testFilesLocation + inputFilename);
- inputString = XmlAdapter.ChangeValueInXml(inputString, "ProjectPath", baseOutputName); // Current directory will be used
- inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used
-
- // When
- Output actualOutput = GeneralHelper.RunAfterInputValidation(inputString, true, outputFilename);
-
- // Then
- Assert.Multiple(() =>
+ Input input = DamXmlSerialization.LoadInputFromXmlFile(inputFilename);
+ input.CalculationMap = calcDir;
+ input.ProjectPath = projectPath;
+ FillSensorData(input, isUseLocationData);
+ string inputString = DamXmlSerialization.SaveInputAsXmlString(input);
+ DamXmlSerialization.SaveInputAsXmlFile(inputFilename, input);
+ Assert.That(input.Locations, Has.Length.EqualTo(4));
+
+ // Run
+ Output output = GeneralHelper.RunAfterInputValidation(inputString, true, outputFilename);
+ Assert.That(output, Is.Not.Null);
+
+ outsideLimit = input.SurfaceLines[0].Points.First(p => p.PointType == ConversionHelper.ConvertToInputPointType(CharacteristicPointType.SurfaceLevelOutside));
+ dikeTopAtRiver = input.SurfaceLines[0].Points.First(p => p.PointType == ConversionHelper.ConvertToInputPointType(CharacteristicPointType.DikeTopAtRiver));
+ dikeTopAtPolder = input.SurfaceLines[0].Points.First(p => p.PointType == ConversionHelper.ConvertToInputPointType(CharacteristicPointType.DikeTopAtPolder));
+ dikeToeAtPolder = input.SurfaceLines[0].Points.First(p => p.PointType == ConversionHelper.ConvertToInputPointType(CharacteristicPointType.DikeToeAtPolder));
+ shoulderInside = input.SurfaceLines[0].Points.First(p => p.PointType == ConversionHelper.ConvertToInputPointType(CharacteristicPointType.ShoulderBaseInside));
+ insideLimit = input.SurfaceLines[0].Points.First(p => p.PointType == ConversionHelper.ConvertToInputPointType(CharacteristicPointType.SurfaceLevelInside));
+
+ // Check the created PL lines for the 4 locations
+ for (var indexLocation = 0; indexLocation < 4; indexLocation++)
+ {
+ int indexTimeStep = indexLocation is 0 or 1 ? 0 : 1;
+ WaternetType waternet = ReadWaternetFromCreatedSkxFile(calcDir, indexTimeStep, indexLocation);
+ CheckPhreaticLine(waternet, input, indexLocation, indexTimeStep, isUseLocationData);
+ CheckPl3AndPl4(waternet, input, indexLocation, indexTimeStep, isUseLocationData);
+ }
+
+ // Check safety factors
+ Output expectedOutput = DamXmlSerialization.LoadOutputFromXmlFile(outputFilename);
+ Assert.That(expectedOutput, Is.Not.Null);
+ CompareOutput(expectedOutput, output);
+ }
+
+ private static void FillSensorData(Input input, bool isUseLocationData)
+ {
+ for (var indexSensorLocation = 0; indexSensorLocation < 2; indexSensorLocation++)
+ {
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl1WaterLevelAtRiver = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl1PlLineOffsetBelowShoulderBaseInside = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl1WaterLevelAtPolder = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl3 = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ input.SensorData.SensorLocations[indexSensorLocation].SourceTypePl4 = isUseLocationData ? sourceTypeLocationData : sourceTypeSensor;
+ }
+
+ for (var indexLocation = 0; indexLocation < 4; indexLocation++)
+ {
+ double difference = indexLocation is 0 or 2 ? 0 : 0.11;
+ input.Locations[indexLocation].DesignScenarios[0].RiverLevel = isUseLocationData ? -2.0 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].PlLineOffsetBelowDikeTopAtRiver = isUseLocationData ? 0.6 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].PlLineOffsetBelowDikeTopAtPolder = isUseLocationData ? 1.6 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].PlLineOffsetBelowShoulderBaseInside = isUseLocationData ? 0.2 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].PlLineOffsetBelowDikeToeAtPolder = isUseLocationData ? 0.3 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].PolderLevel = isUseLocationData ? -4.5 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].HeadPl3 = isUseLocationData ? -1.8 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].HeadPl3Specified = isUseLocationData;
+ input.Locations[indexLocation].DesignScenarios[0].HeadPl4 = isUseLocationData ? -1.6 + difference : double.NaN;
+ input.Locations[indexLocation].DesignScenarios[0].HeadPl4Specified = isUseLocationData;
+ }
+ }
+
+ private static WaternetType ReadWaternetFromCreatedSkxFile(string calcDir, int indexTimeStep, int indexLocation)
+ {
+ string kernelInputFilename = $"{projectPath}\\{calcDir}\\Stability\\Bishop\\Dik(dike)_Loc(LocationOnlyPL3)_Stp("
+ + indexTimeStep + ")_Mdl(Bishop)_2016-03-02T03_" + (indexTimeStep + 1) + "0_00_Pro(SoilProfile_NoInbetweenAquifer_stix).skx";
+ if (indexLocation is 1 or 3)
+ {
+ kernelInputFilename = $"{projectPath}\\{calcDir}\\Stability\\Bishop\\Dik(dike)_Loc(LocationPL3AndPL4)_Stp("
+ + indexTimeStep + ")_Mdl(Bishop)_2016-03-02T03_" + (indexTimeStep + 1) + "0_00_Pro(SoilProfile_OneInbetweenAquifer_stix).skx";
+ }
+
+ FullInputModelType macrostabilityInput = MacroStabilityXmlSerialization.LoadInputFromXmlFile(kernelInputFilename);
+ return macrostabilityInput.StabilityModel.ConstructionStages[0].Waternet;
+ }
+
+ private void CheckPhreaticLine(WaternetType waternet, Input input, int indexLocation, int indexTimeStep, bool isUseLocationData)
+ {
+ WaternetLineType phreaticLine = waternet.PhreaticLine.WaternetLine;
+
+ string sensor = indexLocation is 0 or 2 ? "SensorLoc1" : "SensorLoc2";
+ LocationDesignScenario locData = input.Locations[indexLocation].DesignScenarios[0];
+ double riverLevelUsed = isUseLocationData ? locData.RiverLevel : FetchValue(input, sensor + "_PL1_River", indexTimeStep).Z;
+ // Note that the polder level is not the sensor value of "SensorLoc1_PL1_Polder" or the locData.PolderLevel,
+ // but it is the sensor value of the sensor "_PL1_Ditch" because it is situated within the ditch width.
+ double polderLevelUsed = FetchValue(input, sensor + "_PL1_Ditch", indexTimeStep).Z;
+
+ // Expected phreatic line
+ var expectedPhreaticLine = new PlLine();
+ expectedPhreaticLine.Points.Add(new PlLinePoint(outsideLimit.X, riverLevelUsed));
+ // Point 2 is the intersection between dike and River level (X coord not calculated here)
+ expectedPhreaticLine.Points.Add(new PlLinePoint(double.NaN, riverLevelUsed));
+ expectedPhreaticLine.Points.Add(FetchValue(input, sensor + "_PL1_DikeMiddleCrest", indexTimeStep));
+ // Point 4 is the intersection of the polder level with the (X coord not calculated here).
+ expectedPhreaticLine.Points.Add(new PlLinePoint(double.NaN, polderLevelUsed));
+ expectedPhreaticLine.Points.Add(new PlLinePoint(FetchValue(input, sensor + "_PL1_Ditch", indexTimeStep).X, polderLevelUsed));
+ // Point 6 is the intersection between the ditch and the polder level (X coord not calculated here).
+ expectedPhreaticLine.Points.Add(new PlLinePoint(double.NaN, polderLevelUsed));
+ expectedPhreaticLine.Points.Add(new PlLinePoint(insideLimit.X, polderLevelUsed));
+
+ if (isUseLocationData)
+ {
+ expectedPhreaticLine.Points.Insert(2, new PlLinePoint(dikeTopAtRiver.X, riverLevelUsed - locData.PlLineOffsetBelowDikeTopAtRiver));
+ expectedPhreaticLine.Points.Insert(4, new PlLinePoint(dikeTopAtPolder.X, riverLevelUsed - locData.PlLineOffsetBelowDikeTopAtPolder));
+ expectedPhreaticLine.Points.Insert(5, new PlLinePoint(shoulderInside.X, shoulderInside.Z - locData.PlLineOffsetBelowShoulderBaseInside));
+ expectedPhreaticLine.Points.Insert(6, new PlLinePoint(dikeToeAtPolder.X, dikeToeAtPolder.Z - locData.PlLineOffsetBelowDikeToeAtPolder));
+ }
+
+ CheckPoints(phreaticLine, expectedPhreaticLine, "Incorrect point in location index " + indexLocation + " for phreatic line");
+ }
+
+ private void CheckPl3AndPl4(WaternetType waternet, Input input, int indexLocation, int indexTimeStep, bool isUseLocationData)
+ {
+ for (var indexHeadLine = 0; indexHeadLine < 2; indexHeadLine++)
+ {
+ // No PL 4 available for locations without in-between aquifer present
+ if (indexHeadLine == 1 && indexLocation is 0 or 2)
{
- Assert.That(actualOutput, Is.Not.Null);
- Assert.That(expectedOutput, Is.Not.Null);
+ continue;
}
- );
- Assert.That(actualOutput.Results.CalculationMessages.Any(message => message.MessageType == MessageMessageType.Error), Is.False, "No errors should occur during the calculation");
- CompareOutput(expectedOutput, actualOutput);
+
+ WaternetLineType actualPlLine = waternet.HeadLines[indexHeadLine].WaternetLine;
+
+ // Expected PL-line
+ string location = indexLocation is 0 or 2 ? "SensorLoc1_" : "SensorLoc2_";
+ string plType = indexHeadLine == 0 ? "PL3" : "PL4";
+ string sensorPrefix = location + plType;
+ LocationDesignScenario locData = input.Locations[indexLocation].DesignScenarios[0];
+ double headPl3Used = isUseLocationData ? (indexHeadLine == 0 ? locData.HeadPl3 : locData.HeadPl4) : FetchValue(input, sensorPrefix + "_River", indexTimeStep).Z;
+
+ var expectedPlLine = new PlLine();
+ expectedPlLine.Points.Add(new PlLinePoint(outsideLimit.X, headPl3Used));
+ expectedPlLine.Points.Add(FetchValue(input, sensorPrefix + "_River", indexTimeStep));
+ // Point 3 is the intersection between dike and River level (X coord not calculated here)
+ expectedPlLine.Points.Add(new PlLinePoint(double.NaN, headPl3Used));
+ expectedPlLine.Points.Add(FetchValue(input, sensorPrefix + "_DikeMiddleCrest", indexTimeStep));
+ expectedPlLine.Points.Add(FetchValue(input, sensorPrefix + "_Ditch", indexTimeStep));
+ expectedPlLine.Points.Add(FetchValue(input, sensorPrefix + "_Polder", indexTimeStep));
+ expectedPlLine.Points.Add(new PlLinePoint(insideLimit.X, FetchValue(input, sensorPrefix + "_Polder", indexTimeStep).Z));
+
+ CheckPoints(actualPlLine, expectedPlLine, "Incorrect point in location index " + indexLocation + " for " + plType);
+ }
}
+ private static void CheckPoints(WaternetLineType actualPlLine, PlLine expectedPlLine, string message)
+ {
+ Assert.That(actualPlLine.Points, Has.Length.EqualTo(expectedPlLine.Points.Count));
+ for (var i = 0; i < actualPlLine.Points.Length; i++)
+ {
+ if (!double.IsNaN(expectedPlLine.Points[i].X))
+ {
+ Assert.That(actualPlLine.Points[i].X, Is.EqualTo(expectedPlLine.Points[i].X).Within(tolerance), message);
+ }
+
+ Assert.That(actualPlLine.Points[i].Z, Is.EqualTo(expectedPlLine.Points[i].Z).Within(tolerance), message);
+ }
+ }
+
+ private static PlLinePoint FetchValue(Input input, string sensorName, int indexTimeStep)
+ {
+ double z = input.OperationalInputTimeSeries.First(t => t.LocationId == sensorName).Entries.TimeSerieEntry[indexTimeStep].Value;
+ double x = input.SensorData.Sensors.First(t => t.Name == sensorName).RelativeLocation;
+
+ return new PlLinePoint
+ {
+ X = x,
+ Z = z
+ };
+ }
+
private static void CompareOutput(Output expected, Output actual)
{
var compare = new CompareLogic
Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/SensorPlLine1Creator.cs
===================================================================
diff -u -r5658 -r6063
--- DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/SensorPlLine1Creator.cs (.../SensorPlLine1Creator.cs) (revision 5658)
+++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/PlLinesCreator/SensorPlLine1Creator.cs (.../SensorPlLine1Creator.cs) (revision 6063)
@@ -346,7 +346,7 @@
lineConstructor.Insert(new PlLinePoint(xLocation, depth));
- // always continue horiontal to end
+ // always continue horizontal to end
lineConstructor.Insert(new PlLinePoint(XEndBoundary, depth));
/*