// 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; } } }