// Copyright (C) Stichting Deltares 2025. 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.IO;
using System.Text;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.DamEngine.Interface;
using Deltares.DamEngine.Io.XmlOutput;
using Deltares.DamEngine.TestHelpers;
using NUnit.Framework;
namespace Deltares.DamEngine.IntegrationTests.IntegrationTests
{
[TestFixture]
public class ShearStrengthModelsTests
{
private const double tolerance6Decimals = 0.00000051;
///
/// This test compares the safety factor calculated with the different in 2 cases:
/// - CASE 1: The shear stress is not constant but almost equals in the 4 following shear strength models:
/// - Mohr-Coulomb (c=5, phi=psi=45) leading to a shear stress of Tau = 5 + NormalEffectiveStress
/// - SigmaTau table with one segment line (0, 5)-(400, 405) equivalent to Mohr-Coulomb
/// - SHANSEP (m=S=1, POP=5) leading to a shear stress of Tau = 5 + VerticalEffectiveStress
/// - SuTable with one segment line (0, 5)-(1000, 1005) equivalent to Shansep
/// Expected is that both shear strength models Mohr-Coulomb and SigmaTau return the same result.
/// However, due to the "cut-off" method (reduction of the bottom angle of the slices when too high) which applies to
/// Mohr-Coulomb but not SigmaTau table, a small difference in the safety factor is expected.
/// But SHANSEP should return a higher safety factor because the VerticalEffectiveStress is higher than the NormalEffectiveStress.
/// Both shear strength models SHANSEP and SigmaTau should return the same result.
/// - CASE 2: The shear stress is constant in the 3 following shear strength models:
/// - Mohr-Coulomb (c=15, phi=psi=0) leading to a shear stress of Tau = 15
/// - SigmaTau table with one segment line (0, 15)-(400, 15) leading to Tau = 15
/// - SuTable with one segment line (0, 15)-(1000, 15) leading to Tau = 15
/// Expected is that the 3 models return the same result.
///
[Test]
public void GivenSoilProfilesWithDifferentShearStrengthModelWhenRunningThenExpectedResultsAreReturned()
{
const string calcDir = "GivenSoilProfilesWithDifferentShearStrengthModelWhenRunningThenExpectedResultsAreReturned";
if (Directory.Exists(calcDir))
{
Directory.Delete(calcDir, true); // delete previous results
}
Directory.CreateDirectory(calcDir);
const string fileName = @"TestFiles\ShearStrengthModelsTests\InputFileShearStrengthModelsComparison.xml";
string inputString = File.ReadAllText(fileName);
inputString = XmlAdapter.ChangeValueInXml(inputString, "ProjectPath", ""); // Current directory will be used
inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used
Output output = GeneralHelper.RunAfterInputValidation(inputString);
Assert.That(output.Results.CalculationResults, Has.Length.EqualTo(7));
for (var i = 0; i < 7; i++)
{
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationResults[i].CalculationResult, Is.EqualTo(ConversionHelper.ConvertToOutputCalculationResult(CalculationResult.Succeeded)));
Assert.That(output.Results.CalculationResults[i].StabilityDesignResults.ResultMessage, Is.EqualTo(""));
});
}
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationResults[0].LocationName, Is.EqualTo("Comparison models (constant tau)"));
Assert.That(output.Results.CalculationResults[0].ProfileName, Is.EqualTo("MohrCoulombPhi0"));
Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.080048).Within(tolerance6Decimals));
Assert.That(output.Results.CalculationResults[1].ProfileName, Is.EqualTo("SigmaTauCsttTau"));
Assert.That(output.Results.CalculationResults[1].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.080048).Within(tolerance6Decimals));
Assert.That(output.Results.CalculationResults[2].ProfileName, Is.EqualTo("SuTableCsttSu"));
Assert.That(output.Results.CalculationResults[2].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.080048).Within(tolerance6Decimals));
Assert.That(output.Results.CalculationResults[3].LocationName, Is.EqualTo("Comparison models (not constant tau)"));
Assert.That(output.Results.CalculationResults[3].ProfileName, Is.EqualTo("MohrCoulombPhi45"));
Assert.That(output.Results.CalculationResults[3].StabilityDesignResults.SafetyFactor, Is.EqualTo(3.064123).Within(tolerance6Decimals));
Assert.That(output.Results.CalculationResults[4].ProfileName, Is.EqualTo("SigmaTauPhi45"));
Assert.That(output.Results.CalculationResults[4].StabilityDesignResults.SafetyFactor, Is.EqualTo(3.066645).Within(tolerance6Decimals));
Assert.That(output.Results.CalculationResults[5].ProfileName, Is.EqualTo("ShansepPhi45"));
Assert.That(output.Results.CalculationResults[5].StabilityDesignResults.SafetyFactor, Is.EqualTo(3.484979).Within(tolerance6Decimals));
Assert.That(output.Results.CalculationResults[6].ProfileName, Is.EqualTo("SuTablePhi45"));
Assert.That(output.Results.CalculationResults[6].StabilityDesignResults.SafetyFactor, Is.EqualTo(3.484979).Within(tolerance6Decimals));
});
}
///
/// This test uses the same data as location "Comparison models (not constant tau)" in test
/// GivenSoilProfilesWithDifferentShearStrengthModelWhenRunningThenExpectedResultsAreReturned (without SuTable),
/// except for the sigma-tau curve which starts at 2 instead of 0.
/// Expected is that the soil profile SigmaTauMaterial returns no result and that a clear calculation error message is displayed.
///
[Test]
public void GivenInvalidSigmaTauCurveNotStartingAt0WhenCalculatingReturnsCalculationErrorMessage()
{
const string calcDir = "GivenInvalidSigmaTauCurveNotStartingAt0WhenCalculatingReturnsCalculationErrorMessage";
if (Directory.Exists(calcDir))
{
Directory.Delete(calcDir, true); // delete previous results
}
Directory.CreateDirectory(calcDir);
const string fileName = @"TestFiles\ShearStrengthModelsTests\InputFileInvalidSigmaTauCurveNotStartingAt0.xml";
string inputString = File.ReadAllText(fileName);
inputString = XmlAdapter.ChangeValueInXml(inputString, "ProjectPath", ""); // Current directory will be used
inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used
Output output = GeneralHelper.RunAfterInputValidation(inputString);
Assert.That(output.Results.CalculationResults, Has.Length.EqualTo(2));
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationResults[0].ProfileName, Is.EqualTo("MohrCoulombMaterial"));
Assert.That(output.Results.CalculationResults[0].CalculationResult, Is.EqualTo(ConversionHelper.ConvertToOutputCalculationResult(CalculationResult.Succeeded)));
Assert.That(output.Results.CalculationResults[1].ProfileName, Is.EqualTo("ShansepMaterial"));
Assert.That(output.Results.CalculationResults[1].CalculationResult, Is.EqualTo(ConversionHelper.ConvertToOutputCalculationResult(CalculationResult.Succeeded)));
});
Assert.That(output.Results.CalculationMessages, Has.Length.EqualTo(1));
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationMessages[0].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[0].Message1, Is.EqualTo(
new StringBuilder()
.Append("Validation failed for location 'Comparison Mohr-Coulomb SigmaTau and SHANSEP', subsoil scenario 'SigmaTauMaterial', design scenario '1'.")
.AppendLine("The first sigma value must be 0 for sigma/tau table ")
.AppendLine("The first sigma value must be 0 for sigma/tau table ")
.ToString()));
});
}
///
/// This test uses the same data as test GivenSoilProfilesWithDifferentShearStrengthModelWhenRunningThenExpectedResultsAreReturned,
/// except for the su table nr. 2 which starts at 2 instead of 0.
/// Expected is that the soil profile SuTableCsttTau returns no result and that a clear calculation error message is displayed.
///
[Test]
public void GivenInvalidSuTableNotStartingAt0WhenCalculatingReturnsCalculationErrorMessage()
{
const string calcDir = "GivenInvalidSuTableNotStartingAt0WhenCalculatingReturnsCalculationErrorMessage";
if (Directory.Exists(calcDir))
{
Directory.Delete(calcDir, true); // delete previous results
}
Directory.CreateDirectory(calcDir);
const string fileName = @"TestFiles\ShearStrengthModelsTests\InputFileInvalidSuTableNotStartingAt0.xml";
string inputString = File.ReadAllText(fileName);
inputString = XmlAdapter.ChangeValueInXml(inputString, "ProjectPath", ""); // Current directory will be used
inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used
Output output = GeneralHelper.RunAfterInputValidation(inputString);
Assert.That(output.Results.CalculationResults, Has.Length.EqualTo(6));
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationResults[0].ProfileName, Is.EqualTo("MohrCoulombPhi0"));
Assert.That(output.Results.CalculationResults[1].ProfileName, Is.EqualTo("SigmaTauCsttTau"));
Assert.That(output.Results.CalculationResults[2].ProfileName, Is.EqualTo("MohrCoulombPhi45"));
Assert.That(output.Results.CalculationResults[3].ProfileName, Is.EqualTo("SigmaTauPhi45"));
Assert.That(output.Results.CalculationResults[4].ProfileName, Is.EqualTo("ShansepPhi45"));
Assert.That(output.Results.CalculationResults[5].ProfileName, Is.EqualTo("SuTablePhi45"));
Assert.That(output.Results.CalculationMessages, Has.Length.EqualTo(1));
});
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationMessages[0].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[0].Message1, Is.EqualTo(
new StringBuilder()
.Append("Validation failed for location 'Comparison models (constant tau)', subsoil scenario 'SuTableCsttSu', design scenario '1'.")
.AppendLine("Su table first point must have an effective stress of 0")
.AppendLine("Su table first point must have an effective stress of 0")
.ToString()));
});
}
}
}