// Copyright (C) Stichting Deltares 2019. 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.Collections.Generic;
using System.Data;
using System.IO;
using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces;
using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityInwards;
using Deltares.DamEngine.Calculators.Tests.KernelWrappers.TestHelpers;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.Results;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.DamEngine.Interface;
using Deltares.DamEngine.Io;
using Deltares.DamEngine.TestHelpers;
using Deltares.DamEngine.TestHelpers.Factories;
using Deltares.MacroStability.CSharpWrapper.Input;
using NUnit.Framework;
using NUnit.Framework.Constraints;
using CharacteristicPointType = Deltares.DamEngine.Data.Geotechnics.CharacteristicPointType;
using LogMessage = Deltares.DamEngine.Data.Standard.Logging.LogMessage;
using MacroStabilityOutput = Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityInwards.MacroStabilityOutput;
namespace Deltares.DamEngine.Calculators.Tests.KernelWrappers.MacroStabilityInwards
{
[TestFixture]
public class MacroStabilityInwardsKernelWrapperTests
{
private const string TestFolder = @"..\..\Deltares.DamEngine.IntegrationTests\TestFiles";
private string inputXmlForDamEngine = Path.Combine(TestFolder, "StabilityDesign1Dbased.xml");
[Test]
public void TestPrepare()
{
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
kernelWrapper.FailureMechanismParametersMStab = new FailureMechanismParametersMStab();
IKernelDataInput kernelDataInput;
IKernelDataOutput kernelDataOutput;
var kernelInput = CreateDamKernelInputForTest();
kernelInput.SubSoilScenario.SoilProfile2D.Surfaces[0].IsAquifer = false;
// Situation 1: no uplift. Expected PrepareResult.NotRelevant
kernelInput.Location.ModelFactors.UpliftCriterionStability = 0.8;
var prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput);
Assert.AreEqual(PrepareResult.NotRelevant, prepareResult);
MacroStabilityOutput damMacroStabilityOutput = (MacroStabilityOutput)kernelDataOutput;
Assert.AreEqual(CalculationResult.NoRun, damMacroStabilityOutput.CalculationResult);
Assert.AreEqual(false, damMacroStabilityOutput.UpliftSituation.IsUplift);
// Situation 2: there is uplift and prepare succeeds. Expected PrepareResult.Successful
kernelInput.Location.ModelFactors.UpliftCriterionStability = 1.2;
prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput);
Assert.AreEqual(PrepareResult.Successful, prepareResult);
damMacroStabilityOutput = (MacroStabilityOutput)kernelDataOutput;
Assert.AreEqual(CalculationResult.NoRun, damMacroStabilityOutput.CalculationResult);
Assert.AreEqual(true, damMacroStabilityOutput.UpliftSituation.IsUplift);
// Situation 3: prepare fails. Expected PrepareResult.Failed
kernelInput.Location.ModelFactors.UpliftCriterionStability = 1.2;
kernelInput.Location.SurfaceLine.CharacteristicPoints.Clear();
prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput);
Assert.AreEqual(PrepareResult.Failed, prepareResult);
damMacroStabilityOutput = (MacroStabilityOutput)kernelDataOutput;
Assert.AreEqual(CalculationResult.NoRun, damMacroStabilityOutput.CalculationResult);
}
[Test, ]
[Category(Categories.WorkInProgress)] // Check validation of grid
public void TestValidate()
{
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
kernelWrapper.FailureMechanismParametersMStab = new FailureMechanismParametersMStab();
// Validate without setting values. Expected error messages.
var macroStabilityInput1 = new MacroStabilityKernelDataInput();
var macroStabilityOutput1 = new MacroStabilityOutput();
macroStabilityOutput1.CalculationResult = CalculationResult.NoRun;
List messages;
var errorCount = kernelWrapper.Validate(macroStabilityInput1, macroStabilityOutput1, out messages);
Assert.IsTrue(errorCount > 0);
Assert.AreEqual(CalculationResult.InvalidInputData, macroStabilityOutput1.CalculationResult);
// Validate the input when valid input is provided. Expected no messages.
var kernelInput = CreateDamKernelInputForTest();
kernelInput.SubSoilScenario.SoilProfile2D.Surfaces[0].IsAquifer = false;
kernelInput.Location.ModelFactors.UpliftCriterionStability = 1.2;
var prepareResult = kernelWrapper.Prepare(kernelInput, 0, out IKernelDataInput kernelDataInput, out IKernelDataOutput kernelDataOutput);
Assert.IsTrue(prepareResult == PrepareResult.Successful);
messages.Clear();
errorCount = kernelWrapper.Validate(kernelDataInput, kernelDataOutput, out messages);
Assert.IsTrue(errorCount == 0);
Assert.AreEqual(CalculationResult.NoRun, (kernelDataOutput as MacroStabilityOutput).CalculationResult);
}
[Test]
public void TestPostProcess()
{
const double diff = 0.0001;
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
var kernelInput = CreateDamKernelInputForTest();
MacroStabilityOutput macroStabilityOutput = new MacroStabilityOutput();
DesignScenario designScenario = new DesignScenario
{
Location = kernelInput.Location
};
List results;
macroStabilityOutput.CalculationResult = CalculationResult.Succeeded;
var macroStabilityOutputItem = new MacroStabilityOutputItem();
macroStabilityOutputItem.CalculationResult = CalculationResult.Succeeded;
macroStabilityOutput.UpliftSituation = new UpliftSituation { IsUplift = true };
macroStabilityOutputItem.SafetyFactor = 2.34;
macroStabilityOutput.StabilityOutputItems = new List();
macroStabilityOutput.StabilityOutputItems.Add(macroStabilityOutputItem);
kernelWrapper.PostProcess(kernelInput, macroStabilityOutput, designScenario, "", out results);
Assert.IsTrue(results.Count > 0);
foreach (var result in results)
{
Assert.AreEqual(CalculationResult.Succeeded, result.CalculationResult);
Assert.AreEqual(true, ((UpliftSituation)result.StabilityDesignResults.UpliftSituation).IsUplift);
Assert.AreEqual(0, result.StabilityDesignResults.NumberOfIterations); //NumberOfIterations can not be set for this test, so always zero here
Assert.AreEqual(2.34, result.StabilityDesignResults.SafetyFactor, diff);
Assert.AreEqual(kernelInput.Location.SurfaceLine, result.StabilityDesignResults.RedesignedSurfaceLine);
Assert.AreEqual(kernelInput.SubSoilScenario.ToString(), result.ProfileName);
}
}
[Test]
public void TestFullCalculationFails()
{
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
IKernelDataInput kernelDataInput = new MacroStabilityKernelDataInput();
IKernelDataOutput kernelDataOutput = new MacroStabilityOutput();
// Run the dll
List messages;
MacroStabilityKernelDataInput macroStabilityKernelDataInput = (MacroStabilityKernelDataInput)kernelDataInput;
kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out messages);
MacroStabilityOutput macroStabilityOutput = (MacroStabilityOutput)kernelDataOutput;
Assert.IsTrue(messages.Count > 0);
// as there is no data at all, expect unexpected error
Assert.AreEqual(CalculationResult.UnexpectedError, macroStabilityOutput.CalculationResult);
}
[Test]
[Category(Categories.WorkInProgress)] // Check validation of grid
public void TestFullCalculationFailsWithNoGrid()
{
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
kernelWrapper.FailureMechanismParametersMStab = new FailureMechanismParametersMStab();
// Prepare the wrapper. Result is input for the calculation dll
var kernelInput = CreateDamKernelInputForTest();
kernelInput.Location.ModelFactors.UpliftCriterionStability = 1.2;
PrepareResult prepareResult = kernelWrapper.Prepare(kernelInput, 0, out IKernelDataInput kernelDataInput, out IKernelDataOutput kernelDataOutput);
Assert.AreEqual(PrepareResult.Successful, prepareResult);
// Validate the input
List messages;
var errorCount = kernelWrapper.Validate(kernelDataInput, kernelDataOutput, out messages);
Assert.IsTrue(errorCount == 0);
// Run the dl; the grid position is defined i such a way that no valid circles can be found during calculation so this should fail.
kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out messages);
MacroStabilityOutput macroStabilityOutput = (MacroStabilityOutput)kernelDataOutput;
Assert.AreEqual(649, messages.Count);
Assert.AreEqual(CalculationResult.RunFailed, macroStabilityOutput.CalculationResult);
Assert.AreEqual("The kernel was not able to determine valid slip circles or slip planes.", messages[648].Message);
}
[Test]
[Category(Categories.WorkInProgress)] // check input and result
public void TestFullCalculationSucceeds()
{
const double diff = 0.0001;
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
kernelWrapper.FailureMechanismParametersMStab = new FailureMechanismParametersMStab();
// Prepare the wrapper. Result is input for the calculation dll
IKernelDataInput kernelDataInput;
IKernelDataOutput kernelDataOutput;
var kernelInput = CreateDamKernelInputForTest();
kernelInput.Location.ModelFactors.UpliftCriterionStability = 1.2;
PrepareResult prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput);
Assert.AreEqual(PrepareResult.Successful, prepareResult);
// Validate the input
List messages;
var errorCount = kernelWrapper.Validate(kernelDataInput, kernelDataOutput, out messages);
Assert.IsTrue(errorCount == 0);
// Run the dll
kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out messages);
MacroStabilityOutput macroStabilityOutput = (MacroStabilityOutput)kernelDataOutput;
Assert.AreEqual(0, messages.Count);
Assert.AreEqual(CalculationResult.Succeeded, macroStabilityOutput.CalculationResult);
Assert.AreEqual(1, macroStabilityOutput.StabilityOutputItems.Count);
Assert.AreEqual(1.357, macroStabilityOutput.StabilityOutputItems[0].SafetyFactor, diff); // ToDo replace by actual value when calculation is done and output is parsed
// Fill the design results
DesignScenario designScenario = new DesignScenario
{
Location = kernelInput.Location
};
List results;
kernelWrapper.PostProcess(kernelInput, macroStabilityOutput, designScenario, "", out results);
Assert.IsTrue(results.Count > 0);
foreach (var result in results)
{
Assert.AreEqual(CalculationResult.Succeeded, result.CalculationResult);
Assert.AreEqual(1.357, result.StabilityDesignResults.SafetyFactor);
// ToDo: Add all output items when it is clear what parts of StabilityDesignResults will be filled
}
}
[Test]
public void CalculationBishopBasedOnDamEngineXmlFailsForWrongType()
{
const string calcDir = "TestStabInwardsBishop";
if (Directory.Exists(calcDir))
{
Directory.Delete(calcDir, true); // delete previous results
}
Directory.CreateDirectory(calcDir);
string inputString = File.ReadAllText(inputXmlForDamEngine);
inputString = XmlAdapter.ChangeValueInXml(inputString, "ProjectPath", ""); // Current directory will be used
inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used
//inputString = XmlAdapter.ChangeValueInXml(inputString, "MapForSoilgeometries2D", @"TestFiles\DAM Tutorial Design.geometries2D.0\");
//inputString = XmlAdapter.ChangeValueInXml(inputString, "SoilDatabaseName", @"TestFiles\DAM Tutorial Design0.soilmaterials.mdb");
// inputString = XmlAdapter.ChangeValueInXml(inputString, "SegmentFailureMechanismType", segmentFailureMechanismType.ToString());
EngineInterface engineInterface = new EngineInterface(inputString);
Assert.IsNotNull(engineInterface.DamProjectData);
string outputString = engineInterface.Run();
Assert.IsNotNull(outputString);
var output = DamXmlSerialization.LoadOutputFromXmlString(outputString);
Assert.AreEqual(3,output.Results.CalculationMessages.Length, "No results available");
Assert.IsTrue(output.Results.CalculationMessages[0].Message1.Contains("Requested kernel not implemented"));
}
[Test]
[Category(Categories.WorkInProgress)] // check input and result
public void CalculationUpliftBasedOnDamEngineXmlWorks()
{
const string calcDir = "TestStabInwardsBishop";
if (Directory.Exists(calcDir))
{
Directory.Delete(calcDir, true); // delete previous results
}
Directory.CreateDirectory(calcDir);
string inputString = File.ReadAllText(inputXmlForDamEngine);
inputString = XmlAdapter.ChangeValueInXml(inputString, "ProjectPath", ""); // Current directory will be used
inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used
//inputString = XmlAdapter.ChangeValueInXml(inputString, "MapForSoilgeometries2D", @"TestFiles\DAM Tutorial Design.geometries2D.0\");
//inputString = XmlAdapter.ChangeValueInXml(inputString, "SoilDatabaseName", @"TestFiles\DAM Tutorial Design0.soilmaterials.mdb");
//inputString = XmlAdapter.ChangeValueInXml(inputString, "SegmentFailureMechanismType", segmentFailureMechanismType.ToString());
EngineInterface engineInterface = new EngineInterface(inputString);
Assert.IsNotNull(engineInterface.DamProjectData);
engineInterface.DamProjectData.DamProjectCalculationSpecification.CurrentSpecification.StabilityModelType =
MStabModelType.UpliftVanWti;
string outputString = engineInterface.Run();
Assert.IsNotNull(outputString);
var output = DamXmlSerialization.LoadOutputFromXmlString(outputString);
Assert.IsNotNull(output.Results.CalculationResults, "No results available");
Assert.AreEqual(1.282, output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, 0.1);
}
[Test]
[ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "Geen invoer object gedefinieerd voor Macrostabiliteit")]
[SetUICulture("nl-NL")]
public void TestLanguageNLThrowsExceptionWhenInputIsNull()
{
List messages;
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
kernelWrapper.Execute(null, null, out messages); ;
}
[Test]
[ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "No input object defined for Macro Stability")]
[SetUICulture("en-US")]
public void TestLanguageENThrowsExceptionWhenStabilityInputIsNull()
{
List messages;
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
kernelWrapper.Execute(null, null, out messages);
}
[Test]
[ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "Geen uitvoer object gedefinieerd voor Macrostabiliteit")]
[SetUICulture("nl-NL")]
public void TestThrowsExceptionWhenStabilityOutputIsNull()
{
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
List results;
kernelWrapper.PostProcess(new DamKernelInput(), null, null, "", out results);
}
[Test]
[ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "Geen Dam invoer object gedefinieerd voor Macrostabiliteit")]
[SetUICulture("nl-NL")]
public void TestThrowsExceptionWhenDamKernelInputIsNull()
{
var kernelWrapper = new MacroStabilityInwardsKernelWrapper();
List results;
kernelWrapper.PostProcess(null, null, null, "", out results);
}
private static DamKernelInput CreateDamKernelInputForTest()
{
var location = DamEngineDataTestFactory.CreateLocation(FactoryForSurfaceLines.CreateSurfaceLineTutorial1());
// Correction needed in order to make surface line as lengthy as the geometry is wide (100 meter wide).
location.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X =
100;
// Correction needed in order to make surface line points strictly increasing increasing (ditch was vertical at polderside,
// now this not allowed by the kernel validator!) So that needs to be fixed in the kernel.
location.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide).X =
62.5;
location.SurfaceLine.Geometry.SyncCalcPoints();
var subSoilScenario = new SoilGeometryProbability();
subSoilScenario.SoilProfileType = SoilProfileType.ProfileType2D;
subSoilScenario.StiFileName = "";
subSoilScenario.FullStiFileName = "";
subSoilScenario.SoilProfile2D = DamEngineDataTestFactory.CreateSoilProfile2D(location.SoilList);
subSoilScenario.SegmentFailureMechanismType = SegmentFailureMechanismType.Stability;
subSoilScenario.SoilProfile1D = DamEngineDataTestFactory.CreateSoilProfile1D();
var damKernelInput = new DamKernelInput();
damKernelInput.Location = location;
damKernelInput.SubSoilScenario = subSoilScenario;
damKernelInput.RiverLevelLow = null;
damKernelInput.DamFailureMechanismeCalculationSpecification = new DamFailureMechanismeCalculationSpecification();
return damKernelInput;
}
}
}