// 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;
surfaceLine.Geometry.SyncCalcPoints();
// 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;
surfaceLine.Geometry.SyncCalcPoints();
// 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;
surfaceLine.Geometry.SyncCalcPoints();
// 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;
surfaceLine.Geometry.SyncCalcPoints();
// 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;
}
}