// 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;
using System.Collections.Generic;
using System.Linq;
using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon;
using NUnit.Framework;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon.MacroStabilityIo;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard.Logging;
using Deltares.DamEngine.TestHelpers;
using Deltares.DamEngine.TestHelpers.Factories;
using Deltares.MacroStability.CSharpWrapper.Output;
using KellermanSoftware.CompareNetObjects;
using CharacteristicPointSet = Deltares.DamEngine.Data.Geotechnics.CharacteristicPointSet;
using HeadLine = Deltares.DamEngine.Data.Geometry.HeadLine;
using MacroStabilityOutput = Deltares.MacroStability.CSharpWrapper.Output.MacroStabilityOutput;
using SoilProfile2D = Deltares.DamEngine.Data.Geotechnics.SoilProfile2D;
using SurfaceLine2 = Deltares.DamEngine.Data.Geotechnics.SurfaceLine2;
using Waternet = Deltares.DamEngine.Data.Geometry.Waternet;
using WaternetLine = Deltares.DamEngine.Data.Geometry.WaternetLine;
namespace Deltares.DamEngine.Calculators.Tests.KernelWrappers.MacroStabilityCommon
{
[TestFixture]
public class MacroStabilityIoTests
{
private static readonly List SoilParametersToIgnore = new List()
{
"StrengthIncreaseExponent",
"RRatio",
"RheologicalCoefficient",
"BondStressCurve",
"UseSoilType",
"UseDefaultShearStrengthModel"
};
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
public void GivenCSharpWrapperOutputWhenGoingToAndFromEngineTheDataIsEqual(int testNumber)
{
//ToDo fill this
var expectedKernelOutput = CreateKernelOutputForTest(testNumber);
var engineOutput = new Calculators.KernelWrappers.MacroStabilityInwards.MacroStabilityOutput();
List logMessages;
FillEngineFromMacroStabilityWrapperOutput.FillEngineDataWithResults(expectedKernelOutput, engineOutput, out logMessages);
var kernelOutput = FillMacroStabilityWrapperOutputFromEngine.FillMacroStabilityWrapperOutput(engineOutput, logMessages);
var compare = new CompareLogic { Config = { MaxDifferences = 100 } };
ComparisonResult result;
result = compare.Compare(expectedKernelOutput, kernelOutput);
Assert.AreEqual(0, result.Differences.Count, "Differences found read/write kernel Output");
}
[Test]
public void GivenDamEngineDataModelWhenGoingToAndFromCSharpWrapperForInputTheDataIsEqual()
{
// Given DamEngine data (DamProjectData)
DamProjectData expectedDamProjectData = CreateExampleDamProjectData();
Waternet expectedWaternet = CreateExampleWaternet();
UpliftVanCalculationGrid expectedUpliftVanCalculationGrid = CreateExampleUpliftVanCalculationGrid();
Location expectedLocation = expectedDamProjectData.Dike.Locations[0];
SoilList expectedSoilList = expectedDamProjectData.Dike.SoilList;
SoilProfile2D expectedSoilProfile2D = expectedLocation.Segment.SoilProfileProbabilities[0].SoilProfile2D;
SurfaceLine2 expectedSurfaceLine2D = expectedLocation.SurfaceLine;
FailureMechanismParametersMStab expectedParametersMStab = expectedDamProjectData.DamProjectCalculationSpecification.CurrentSpecification.FailureMechanismParametersMStab;
TrafficLoad expectedTrafficLoad = new TrafficLoad
{
Pressure = 6.0,
XStart = expectedSurfaceLine2D.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadInside).X,
XEnd = expectedSurfaceLine2D.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadOutside).X,
};
var fillMacroStabilityWrapperInputFromEngine = new FillMacroStabilityWrapperInputFromEngine
{
UpliftVanCalculationGrid = expectedUpliftVanCalculationGrid,
TrafficLoad = expectedTrafficLoad
};
var damKernelInput = new DamKernelInput
{
SubSoilScenario = expectedLocation.Segment.SoilProfileProbabilities[0],
Location = expectedLocation,
DamFailureMechanismeCalculationSpecification = expectedDamProjectData.DamProjectCalculationSpecification.CurrentSpecification
};
// get the input for the CSharp wrapper
var expectedMacrostabilityInput =
fillMacroStabilityWrapperInputFromEngine.CreateMacroStabilityInput(damKernelInput, expectedParametersMStab, expectedWaternet);
// reverse that input to the engine data
var fillEngineFromMacroStabilityWrapperInput = new FillEngineFromMacroStabilityWrapperInput();
fillEngineFromMacroStabilityWrapperInput.FillDamProjectDataFromKernelModel(expectedMacrostabilityInput);
// Then the data models are equal
CompareStabilityModel(expectedParametersMStab, fillEngineFromMacroStabilityWrapperInput.FailureMechanismParametersMStab);
CompareSoilModel(expectedSoilList, fillEngineFromMacroStabilityWrapperInput.SoilList);
CompareSoilProfile2D(expectedSoilProfile2D, fillEngineFromMacroStabilityWrapperInput.SoilProfile2D);
CompareSurfaceLine(expectedSurfaceLine2D, fillEngineFromMacroStabilityWrapperInput.SurfaceLine2);
CompareTrafficLoad(expectedTrafficLoad, fillEngineFromMacroStabilityWrapperInput.TrafficLoad);
SlipCircleDefinition expectedUpliftVanCalculationGridSettings = expectedParametersMStab.MStabParameters.SlipCircleDefinition;
CompareUpliftVanCalculationGridSettings(expectedUpliftVanCalculationGridSettings,
fillEngineFromMacroStabilityWrapperInput.SlipCircleDefinition);
bool isAutoTangentLine = expectedUpliftVanCalculationGridSettings.UpliftVanTangentLinesDefinition == TangentLinesDefinition.Specified;
CompareUpliftVanCalculationGrid(expectedUpliftVanCalculationGrid, fillEngineFromMacroStabilityWrapperInput.UpliftVanCalculationGrid, isAutoTangentLine);
CompareWaternet(expectedWaternet, fillEngineFromMacroStabilityWrapperInput.Waternet);
//Todo : add and or implement comparer per item as these are added to the code
}
private static UpliftVanCalculationGrid CreateExampleUpliftVanCalculationGrid()
{
var random = new Random(21);
var upliftVanCalculationGrid = new UpliftVanCalculationGrid
{
LeftGridXLeft = random.NextDouble(),
LeftGridXRight = random.NextDouble(),
LeftGridZTop = random.NextDouble(),
LeftGridZBottom = random.NextDouble(),
LeftGridXCount = random.Next(),
LeftGridZCount = random.Next(),
RightGridXLeft = random.NextDouble(),
RightGridXRight = random.NextDouble(),
RightGridZTop = random.NextDouble(),
RightGridZBottom = random.NextDouble(),
RightGridXCount = random.Next(),
RightGridZCount = random.Next(),
IsTangentLinesAutomatic = true,
TangentLineZBottom = 0,
TangentLineZTop = 10,
TangentLineCount = 10
};
return upliftVanCalculationGrid;
}
private static Waternet CreateExampleWaternet()
{
var waterNet = new Waternet
{
IsGenerated = false,
UnitWeight = 9.81,
Name = "Test Waternet",
};
var random = new Random(21);
var phreaticLine = new PhreaticLine
{
Name = "Test Phreatic line"
};
waterNet.PhreaticLine = phreaticLine;
SetGeometry(phreaticLine, random.Next());
// Head line
const int nrOfHeadLines = 10;
for (int i = 0; i < nrOfHeadLines; i++)
{
var headLine = new HeadLine
{
Name = $"Test Head line{i}"
};
SetGeometry(headLine, random.Next());
waterNet.HeadLineList.Add(headLine);
}
// Waternet line
for (int i = 0; i < nrOfHeadLines; i++)
{
var waternetLine = new WaternetLine
{
Name = $"Test Waternet line {i}",
HeadLine = waterNet.HeadLineList[i]
};
SetGeometry(waternetLine, random.Next());
waterNet.WaternetLineList.Add(waternetLine);
}
return waterNet;
}
private static void SetGeometry(GeometryPointString geometry, int seed)
{
var random = new Random(seed);
for (int i = 0; i < 10; i++)
{
geometry.CalcPoints.Add(new Point2D(random.NextDouble(), random.NextDouble()));
}
}
private void CompareTrafficLoad(TrafficLoad expectedTrafficLoad, TrafficLoad actualTrafficLoad)
{
var compare = new CompareLogic { Config = { MaxDifferences = 100 } };
compare.Config.MembersToInclude = new List()
{
"XEnd",
"XStart",
"Pressure"
};
ComparisonResult result;
result = compare.Compare(expectedTrafficLoad, actualTrafficLoad);
Assert.AreEqual(0, result.Differences.Count, "Differences found read/write kernel Traffic Load");
}
private static void CompareUpliftVanCalculationGridSettings(SlipCircleDefinition expectedSlipCircleDefinition,
SlipCircleDefinition actualSlipCircleDefinition)
{
Assert.AreEqual(expectedSlipCircleDefinition.GridSizeDetermination, actualSlipCircleDefinition.GridSizeDetermination);
Assert.AreEqual(expectedSlipCircleDefinition.UpliftVanTangentLinesDefinition, actualSlipCircleDefinition.UpliftVanTangentLinesDefinition);
// Note: do not test UpliftVanTangentLinesDistance as there is no way to be sure of equal values as determination to and from involves rounding.
//Assert.AreEqual(expectedSlipCircleDefinition.UpliftVanTangentLinesDistance, actualSlipCircleDefinition.UpliftVanTangentLinesDistance);
}
private static void CompareUpliftVanCalculationGrid(UpliftVanCalculationGrid expectedSlipPlaneUpliftVan,
UpliftVanCalculationGrid actualSlipPlaneUpliftVan, bool isAutoTangentLine)
{
Assert.AreEqual(expectedSlipPlaneUpliftVan.LeftGridXLeft, actualSlipPlaneUpliftVan.LeftGridXLeft);
Assert.AreEqual(expectedSlipPlaneUpliftVan.LeftGridXRight, actualSlipPlaneUpliftVan.LeftGridXRight);
Assert.AreEqual(expectedSlipPlaneUpliftVan.LeftGridZTop, actualSlipPlaneUpliftVan.LeftGridZTop);
Assert.AreEqual(expectedSlipPlaneUpliftVan.LeftGridZBottom, actualSlipPlaneUpliftVan.LeftGridZBottom);
Assert.AreEqual(expectedSlipPlaneUpliftVan.LeftGridXCount, actualSlipPlaneUpliftVan.LeftGridXCount);
Assert.AreEqual(expectedSlipPlaneUpliftVan.LeftGridZCount, actualSlipPlaneUpliftVan.LeftGridZCount);
Assert.AreEqual(expectedSlipPlaneUpliftVan.RightGridXLeft, actualSlipPlaneUpliftVan.RightGridXLeft);
Assert.AreEqual(expectedSlipPlaneUpliftVan.RightGridXRight, actualSlipPlaneUpliftVan.RightGridXRight);
Assert.AreEqual(expectedSlipPlaneUpliftVan.RightGridZTop, actualSlipPlaneUpliftVan.RightGridZTop);
Assert.AreEqual(expectedSlipPlaneUpliftVan.RightGridZBottom, actualSlipPlaneUpliftVan.RightGridZBottom);
Assert.AreEqual(expectedSlipPlaneUpliftVan.RightGridXCount, actualSlipPlaneUpliftVan.RightGridXCount);
Assert.AreEqual(expectedSlipPlaneUpliftVan.RightGridZCount, actualSlipPlaneUpliftVan.RightGridZCount);
if (!isAutoTangentLine)
{
CollectionAssert.AreEqual(expectedSlipPlaneUpliftVan.TangentLineLevels, actualSlipPlaneUpliftVan.TangentLineLevels);
}
}
private static void CompareWaternet(Waternet expectedWaternet, Waternet actualWaternet)
{
Assert.AreEqual(expectedWaternet.Name, actualWaternet.Name);
CompareLine(expectedWaternet.PhreaticLine, actualWaternet.PhreaticLine);
CompareWaternetHeadLines(expectedWaternet.HeadLineList, actualWaternet.HeadLineList);
CompareWaternetLines(actualWaternet.WaternetLineList, expectedWaternet.WaternetLineList);
}
private static void CompareWaternetLines(IEnumerable actualWaternetLines,
IEnumerable expectedWaternetLines)
{
int expectedNrOfWaternetLines = actualWaternetLines.Count();
Assert.AreEqual(expectedNrOfWaternetLines, actualWaternetLines.Count());
for (int i = 0; i < expectedNrOfWaternetLines; i++)
{
WaternetLine expectedWaternetLine = expectedWaternetLines.ElementAt(i);
WaternetLine actualWaternetLine = actualWaternetLines.ElementAt(i);
CompareLine(expectedWaternetLine, actualWaternetLine);
CompareLine(expectedWaternetLine.HeadLine, actualWaternetLine.HeadLine);
}
}
private static void CompareWaternetHeadLines(IEnumerable expectedHeadLines,
IEnumerable actualHeadLines)
{
int expectedNrOfHeadLines = expectedHeadLines.Count();
Assert.AreEqual(expectedNrOfHeadLines, actualHeadLines.Count());
for (int i = 0; i < expectedNrOfHeadLines; i++)
{
HeadLine expectedHeadLine = expectedHeadLines.ElementAt(i);
HeadLine actualHeadLine = actualHeadLines.ElementAt(i);
CompareLine(expectedHeadLine, actualHeadLine);
}
}
private static void CompareLine(TLineType expectedHeadLine, TLineType actualHeadLine)
where TLineType : GeometryPointString
{
Assert.AreEqual(expectedHeadLine.Name, actualHeadLine.Name);
var expectedCalcPoints = expectedHeadLine.CalcPoints;
int expectedNrOfCalcPoints = expectedCalcPoints.Count;
var actualCalcPoints = actualHeadLine.CalcPoints;
Assert.AreEqual(expectedNrOfCalcPoints, actualCalcPoints.Count);
for (int i = 0; i < expectedNrOfCalcPoints; i++)
{
Point2D expectedCoordinate = expectedCalcPoints[i];
Point2D actualCoordinate = actualCalcPoints[i];
Assert.True(expectedCoordinate.LocationEquals(actualCoordinate));
}
}
private void CompareSurfaceLine(SurfaceLine2 expectedSurfaceLine2, SurfaceLine2 actualSurfaceLine2)
{
CharacteristicPointSet expectedCharacteristicPoints = expectedSurfaceLine2.CharacteristicPoints;
CharacteristicPointSet actualCharacteristicPoints = actualSurfaceLine2.CharacteristicPoints;
var compare = new CompareLogic {Config = {MaxDifferences = 100}};
compare.Config.MembersToIgnore = new List()
{
"Owner"
};
var result = compare.Compare(expectedCharacteristicPoints, actualCharacteristicPoints);
Assert.AreEqual(0, result.Differences.Count, "Differences found read/write kernel SurfaceLine");
}
private void CompareSoilProfile2D(SoilProfile2D expectedSoilProfile, SoilProfile2D actualSoilProfile)
{
var compare = new CompareLogic {Config = {MaxDifferences = 100}};
compare.Config.MembersToIgnore = SoilParametersToIgnore;
compare.Config.MembersToIgnore.Add("Name");
var result = compare.Compare(expectedSoilProfile, actualSoilProfile);
Assert.AreEqual(0, result.Differences.Count, "Differences found read/write kernel SoilProfile2D");
}
private void CompareSoilModel(SoilList expectedSoils, SoilList actualSoils)
{
Assert.AreEqual(expectedSoils.Soils.Count, actualSoils.Soils.Count, "Soil Count does not match");
foreach (Soil expectedSoil in expectedSoils.Soils)
{
var actualSoil = actualSoils.Soils.SingleOrDefault(soil => soil.Name.Equals(expectedSoil.Name));
Assert.IsNotNull(actualSoil, string.Format("Soil {0} not found", expectedSoil.Name));
var compare = new CompareLogic {Config = {MaxDifferences = 100}};
compare.Config.MembersToIgnore = SoilParametersToIgnore;
var result = compare.Compare(expectedSoil, actualSoil);
Assert.AreEqual(0, result.Differences.Count, "Differences found read/write kernel SoilModel");
}
}
private void CompareStabilityModel(FailureMechanismParametersMStab expectedStabilityModel, FailureMechanismParametersMStab actualStabilityModel)
{
Assert.AreEqual(expectedStabilityModel.MStabParameters.SearchMethod, actualStabilityModel.MStabParameters.SearchMethod);
Assert.AreEqual(expectedStabilityModel.MStabParameters.Model, actualStabilityModel.MStabParameters.Model);
Assert.AreEqual(expectedStabilityModel.MStabParameters.GridPosition, actualStabilityModel.MStabParameters.GridPosition);
}
private DamProjectData CreateExampleDamProjectData()
{
return FactoryForDamProjectData.CreateExampleDamProjectData();
}
private MacroStabilityOutput CreateKernelOutputForTest(int choice)
{
var output = new MacroStabilityOutput();
var messagesOutput = new List();
if (choice == 1)
{
// Result 1: succeeded, has a SafetyFactor of ca. 3.856, no messages
output.ResultType = CalculationResultType.Succeeded;
output.StabilityOutput = new StabilityOutput
{
SafetyFactor = 3.856,
ModelOptionType = StabilityModelOptionType.UpliftVan
};
}
else if (choice == 2)
{
// Result 2: succeeded, has a SafetyFactor of ca. 1.857, has info and warning, but no error messages
messagesOutput.Clear();
var infoMessage = new Message();
infoMessage.Content = "Info";
infoMessage.MessageType = MessageType.Info;
messagesOutput.Add(infoMessage);
var warningMessage = new Message();
warningMessage.Content = "Warning";
warningMessage.MessageType = MessageType.Warning;
messagesOutput.Add(warningMessage);
output.ResultType = CalculationResultType.Succeeded;
output.StabilityOutput = new StabilityOutput
{
SafetyFactor = 1.857,
Messages = messagesOutput,
ModelOptionType = StabilityModelOptionType.UpliftVan
};
}
else
{
// Result 3 failed - has a SafetyFactor of NaN, has an error message
messagesOutput.Clear();
var errorMessage = new Message();
errorMessage.Content = "Error";
errorMessage.MessageType = MessageType.Error;
messagesOutput.Add(errorMessage);
output.StabilityOutput = new StabilityOutput();
output.ResultType = CalculationResultType.RunFailed;
output.StabilityOutput.SafetyFactor = double.NaN;
output.StabilityOutput.Messages = messagesOutput;
}
return output;
}
}
}