// Copyright (C) Stichting Deltares 2024. All rights reserved. // // This file is part of the Dam Engine. // // The Dam Engine is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Linq; using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon; using Deltares.DamEngine.Data.General; using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; using Deltares.DamEngine.TestHelpers.Factories; using NUnit.Framework; using Soil = Deltares.DamEngine.Data.Geotechnics.Soil; namespace Deltares.DamEngine.Calculators.Tests.KernelWrappers.MacroStabilityCommon; [TestFixture] public class MacroStabilityCommonHelperTests { private readonly double cTolerance = 0.001; [Test] public void GivenSoilGeometryProbabilityWithSoilProfile1DAndSurfaceLineWhenCombiningThenSoilProfile2DIsCreated() { SoilGeometryProbability soilGeometryProbability = FactoryForSoilGeometryProbabilities.CreateSoilGeometryProbabilityWithSoilProfile1D(); SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineWithDikeAndDitch(); var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(1)); Assert.That(geometry.Left, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().X, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().Z, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().X, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().Z, Is.EqualTo(0.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndMatchingSurfaceLineWhenCombiningThenSoilProfile2DIsUnchanged() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); // Create the same surfaceline as is used for creating the SoilProfile2D in the SoilGeometryProbability SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineWithDikeAndDitch(); // Now combine the soilGeometryProbability with the same SurfaceLine2 which should result in the same SoilProfile2D MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = soilGeometryProbability.SoilProfile2D.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(1)); Assert.That(geometry.Left, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().X, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().Z, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().X, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().Z, Is.EqualTo(0.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndMatchingSurfaceLineShortOnLeftWhenCombiningThenSoilProfile2DIsCutOnTheLeft() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); // Create the same surfaceline as is used for creating the SoilProfile2D in the SoilGeometryProbability // But now the SurfaceLine2 is shorter on the left side (5.0 instead of 0.0) SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineWithDikeAndDitch(); surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).X = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).X + 5.0; // Now combine the soilGeometryProbability with the same SurfaceLine2 which should result the SoilProfile2D // being cut on the left with 5.0 meters var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(1)); Assert.That(geometry.Left, Is.EqualTo(5.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().X, Is.EqualTo(5.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().Z, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().X, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().Z, Is.EqualTo(0.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndMatchingSurfaceLineLongerOnLeftWhenCombiningThenSoilProfile2DIsExtendedToTheLeft() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); // Create the same surfaceline as is used for creating the SoilProfile2D in the SoilGeometryProbability // But now the SurfaceLine2 is longer on the left side (-5.0 instead of 0.0) SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineWithDikeAndDitch(); surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).X = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).X - 5.0; // Now combine the soilGeometryProbability with the same SurfaceLine2 which should result the SoilProfile2D // being extended to the left with 5.0 meters var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(2)); Assert.That(geometry.Left, Is.EqualTo(-5.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndMatchingSurfaceLineShortOnRightWhenCombiningThenSoilProfile2DIsCutOnTheRight() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); // Create the same surfaceline as is used for creating the SoilProfile2D in the SoilGeometryProbability // But now the SurfaceLine2 is shorter on the right side (70.0 instead of 75.0) SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineWithDikeAndDitch(); surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X - 5.0; // Now combine the soilGeometryProbability with the same SurfaceLine2 which should result the SoilProfile2D // being cut on the right with 5.0 meters var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(1)); Assert.That(geometry.Left, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(70.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().X, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.First().Z, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().X, Is.EqualTo(70.0).Within(cTolerance)); Assert.That(geometry.SurfaceLine.Points.Last().Z, Is.EqualTo(0.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndMatchingSurfaceLineLongerOnRightWhenCombiningThenSoilProfile2DIsExtendedToTheRight() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); // Create the same surfaceline as is used for creating the SoilProfile2D in the SoilGeometryProbability // But now the SurfaceLine2 is longer on the right side (80.0 instead of 75.0) SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineWithDikeAndDitch(); surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X + 5.0; // Now combine the soilGeometryProbability with the same SurfaceLine2 which should result the SoilProfile2D // being extended to the right with 5.0 meters var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(2)); Assert.That(geometry.Left, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(80.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndSurfaceLineFullyAboveTopBoundarySoilProfile2DWhenCombiningThenLayerIsAddedOnTopOfSoilProfile2D() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineAboveSurfaceLineDikeAndDitch(); // Now combine the soilGeometryProbability with the surfaceLine which should result that a layer is added on // top of the SoilProfile2D var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; // For debugging purposes // GeometryExporter.ExportToFile(geometry, GeometryExporter.VisualizationFolder + "Geometry.txt"); // GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + // GeometryExporter.ExportJasonFile, geometry, surfaceLine.Geometry); Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(2)); Assert.That(geometry.Left, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); Assert.That(geometry.MaxGeometryPointsZ, Is.EqualTo(10.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndSurfaceLineFullyBelowTopBoundarySoilProfile2DWhenCombiningThenMaterialAboveIsRemoved() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineBelowSurfaceLineDikeAndDitch(); // Now combine the soilGeometryProbability with the surfaceLine which should result that the top part of the // SoilProfile2D is removed (between top boundary of the SoilProfile2D and the surfaceLine) var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(1)); Assert.That(geometry.Left, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); Assert.That(geometry.MaxGeometryPointsZ, Is.EqualTo(-5.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndSurfaceLineCuttingTopBoundarySoilProfile2DWhenCombiningThenCorrectSoilProfile2DIsCreated() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineCuttingSurfaceLineDikeAndDitch(); // Now combine the soilGeometryProbability with the surfaceLine which should result that the top part of the // SoilProfile2D is removed (between top boundary of the SoilProfile2D and the surfaceLine) var combinedProfile = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); GeometryData geometry = combinedProfile.Geometry; Assert.Multiple(() => { Assert.That(soilGeometryProbability.SoilProfileType, Is.EqualTo(SoilProfileType.ProfileType2D)); Assert.That(geometry.Surfaces, Has.Count.EqualTo(1)); Assert.That(geometry.Left, Is.EqualTo(0.0).Within(cTolerance)); Assert.That(geometry.Right, Is.EqualTo(75.0).Within(cTolerance)); Assert.That(geometry.Bottom, Is.EqualTo(-20.0).Within(cTolerance)); Assert.That(geometry.MaxGeometryPointsZ, Is.EqualTo(3.0).Within(cTolerance)); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndSurfaceLinePartlyBelowSoilProfile2DBottomWhenCombiningThenExceptionIsRaised() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineDike(-22.0, "PartlyBelowBottom"); // Now combine the soilGeometryProbability with the surfaceLine which should in an exception, because the surfaceLine // is partly below the bottom of the SoilProfile2D Assert.Throws(() => { MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); }); } [Test] public void GivenSoilGeometryProbabilityWithSoilProfile2DAndSurfaceLineNonSscanedingWhenCombiningThenExceptionIsRaised() { SoilGeometryProbability soilGeometryProbability = CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike(); SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineDikeNonStrictAscending(); // Now combine the soilGeometryProbability with the surfaceLine which should in an exception, because the surfaceLine // is not strictly ascending Assert.Throws(() => { MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); }); } private static SoilGeometryProbability CreateSoilGeometryProbabilityWithSoilProfile2DWithSurfaceLineDitchDike() { SoilGeometryProbability soilGeometryProbability = FactoryForSoilGeometryProbabilities.CreateSoilGeometryProbabilityWithSoilProfile1D(); SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineWithDikeAndDitch(); MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilGeometryProbability, surfaceLine, new Soil()); return soilGeometryProbability; } }