// 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 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 fileName = @"TestFiles\ShearStrengthModelsTests\InputFileShearStrengthModelsComparison.xml";
string inputString = File.ReadAllText(fileName);
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 fileName = @"TestFiles\ShearStrengthModelsTests\InputFileInvalidSigmaTauCurveNotStartingAt0.xml";
string inputString = File.ReadAllText(fileName);
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(3));
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationMessages[0].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[0].Message1, Is.EqualTo("Validation failed for location 'Comparison Mohr-Coulomb SigmaTau and SHANSEP', subsoil scenario 'SigmaTauMaterial', design scenario '1'"));
Assert.That(output.Results.CalculationMessages[1].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[1].Message1, Is.EqualTo("The first sigma value must be 0 for sigma/tau table "));
Assert.That(output.Results.CalculationMessages[2].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[2].Message1, Is.EqualTo("The first sigma value must be 0 for sigma/tau table "));
});
}
///
/// 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 fileName = @"TestFiles\ShearStrengthModelsTests\InputFileInvalidSuTableNotStartingAt0.xml";
string inputString = File.ReadAllText(fileName);
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(3));
});
Assert.Multiple(() =>
{
Assert.That(output.Results.CalculationMessages[0].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[0].Message1, Is.EqualTo("Validation failed for location 'Comparison models (constant tau)', subsoil scenario 'SuTableCsttSu', design scenario '1'"));
Assert.That(output.Results.CalculationMessages[1].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[1].Message1, Is.EqualTo("Su table first point must have an effective stress of 0"));
Assert.That(output.Results.CalculationMessages[2].MessageType, Is.EqualTo(MessageMessageType.Error));
Assert.That(output.Results.CalculationMessages[2].Message1, Is.EqualTo("Su table first point must have an effective stress of 0"));
});
}
}
}