// Copyright (C) Stichting Deltares 2023. 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.Globalization; using System.IO; using System.Threading; using System.Linq; using Deltares.DamEngine.Data.General; using Deltares.DamEngine.Interface; using Deltares.DamEngine.Io; using Deltares.DamEngine.Io.XmlOutput; using Deltares.DamEngine.TestHelpers; using NUnit.Framework; using TimeSerie = Deltares.DamEngine.Io.XmlOutput.TimeSerie; using Deltares.DamEngine.Calculators.DikesOperational; using Deltares.DamEngine.Data.General.TimeSeries; namespace Deltares.DamEngine.IntegrationTests.IntegrationTests; [TestFixture] public class MultiCoreMacroStabilityTests { private const string mapTestFiles = @"TestFiles\"; const string testWorkingFolder = @"MultiCore\"; private const double tol2Digits = 0.005; private const double tolerance = 0.0005; [OneTimeSetUp] public void Setup() { RemoveTestWorkingDirectory(testWorkingFolder); // to be sure no test directory exist from previous tests } [OneTimeTearDown] public void TearDown() { RemoveTestWorkingDirectory(testWorkingFolder); // to be sure no test directory exist after the tests } [Test, Category("MultiCore")] [TestCase("OperationalBishopGrid1Core.xml")] [TestCase("OperationalBishopGrid2Cores.xml")] [TestCase("OperationalBishopGrid4Cores.xml")] [TestCase("OperationalBishopGrid8Cores.xml")] [TestCase("OperationalBishopGrid18Cores.xml")] public void OperationalBishopGridTestsWithXmlInputFile(string aFileName) { string fullInputFilename = Path.Combine(mapTestFiles, aFileName); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string inputString = File.ReadAllText(fullInputFilename); var engineInterface = new EngineInterface(inputString); Assert.IsNotNull(engineInterface.DamProjectData); engineInterface.DamProjectData.ProjectPath = @"MultiCore\"; string result = engineInterface.Validate(); Assert.IsNull(result, "Validation must succeed but does not, see output xml in debugger"); string outputString = engineInterface.Run(); File.WriteAllText("Output.xml", outputString); Output output = DamXmlSerialization.LoadOutputFromXmlString(outputString); int errorCount = GeneralHelper.DetermineNumberOfCalculationErrors(engineInterface.DamProjectData.CalculationMessages); Assert.AreEqual(0, errorCount, "There should be no errors during the calculation."); Assert.AreEqual(output.Results.CalculationMessages.Length, engineInterface.DamProjectData.CalculationMessages.Count); if (engineInterface.DamProjectData.DamProjectType == DamProjectType.Design) { Assert.AreNotEqual(null, output.Results.CalculationResults); } else { Assert.AreEqual(8, output.Results.OperationalOutputTimeSeries.Length); int numberOfResults = 0; int numberOfRealResults = 0; foreach (TimeSerie resultSerie in output.Results.OperationalOutputTimeSeries) { numberOfResults += resultSerie.Entries.TimeSerieEntry.Length; foreach (TimeSerieEntriesTimeSerieEntry timeSerieEntriesTimeSerieEntry in resultSerie.Entries.TimeSerieEntry) { if (!Double.IsNaN(timeSerieEntriesTimeSerieEntry.Value) && (timeSerieEntriesTimeSerieEntry.Value > 0) && (timeSerieEntriesTimeSerieEntry.Value < 100000)) { numberOfRealResults++; } } } Assert.AreEqual(16, numberOfResults); Assert.AreEqual(16, numberOfRealResults); } } [Test, Category("MultiCore")] [TestCase("DesignBishopGrid1Core.xml")] [TestCase("DesignBishopGrid2Cores.xml")] [TestCase("DesignBishopGrid4Cores.xml")] [TestCase("DesignBishopGrid8Cores.xml")] [TestCase("DesignBishopGrid18Cores.xml")] public void DebugDesignWithXmlInputFile(string aFileName) { string fullInputFilename = Path.Combine(mapTestFiles, aFileName); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string inputString = File.ReadAllText(fullInputFilename); var engineInterface = new EngineInterface(inputString); Assert.IsNotNull(engineInterface.DamProjectData); engineInterface.DamProjectData.ProjectPath = @"MultiCore\"; string result = engineInterface.Validate(); Assert.IsTrue(result == null, "Validation must succeed but does not, see output xml in debugger"); string outputString = engineInterface.Run(); File.WriteAllText("Output.xml", outputString); Output output = DamXmlSerialization.LoadOutputFromXmlString(outputString); int errorCount = GeneralHelper.DetermineNumberOfCalculationErrors(engineInterface.DamProjectData.CalculationMessages); Assert.AreEqual(0, errorCount, "There should be no errors during the calculation."); Assert.AreEqual(output.Results.CalculationMessages.Length, engineInterface.DamProjectData.CalculationMessages.Count); if (engineInterface.DamProjectData.DamProjectType == DamProjectType.Design) { Assert.IsNotNull(output.Results.CalculationResults); } else { Assert.AreEqual(8, output.Results.OperationalOutputTimeSeries.Length); int numberOfResults = 0; int numberOfRealResults = 0; foreach (TimeSerie resultSerie in output.Results.OperationalOutputTimeSeries) { numberOfResults += resultSerie.Entries.TimeSerieEntry.Length; foreach (TimeSerieEntriesTimeSerieEntry timeSerieEntriesTimeSerieEntry in resultSerie.Entries.TimeSerieEntry) { if (!Double.IsNaN(timeSerieEntriesTimeSerieEntry.Value) && (timeSerieEntriesTimeSerieEntry.Value > 0) && (timeSerieEntriesTimeSerieEntry.Value < 100000)) { numberOfRealResults++; } } } Assert.AreEqual(16, numberOfResults); Assert.AreEqual(16, numberOfRealResults); } } [Test, Category("MultiCore")] [TestCase(1)] [TestCase(10)] [TestCase(24)] public void OperationalBeeSwarmMultiCoreWithXmlInputFile(int maxCores) { const string inputFilename = "InputForDebuggingBeeSwarm.xml"; string fullInputFilename = Path.Combine(mapTestFiles, inputFilename); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string inputString = File.ReadAllText(fullInputFilename); var engineInterface = new EngineInterface(inputString); Assert.IsNotNull(engineInterface.DamProjectData); engineInterface.DamProjectData.MaxCalculationCores = maxCores; string result = engineInterface.Validate(); Assert.IsTrue(result == null, "Validation must succeed but does not, see output xml in debugger"); string outputString = engineInterface.Run(); string outputName = "Output" + maxCores + ".xml"; File.WriteAllText(outputName, outputString); //Output output = DamXmlSerialization.LoadOutputFromXmlString(outputString); //TimeSerieCollection outputTimeSeriesCollection = new TimeSerieCollection(); //outputTimeSeriesCollection.Series.AddRange(engineInterface.DamProjectData.OutputTimeSerieCollection.Series); List series = engineInterface.DamProjectData.OutputTimeSerieCollection.Series; int errorCount = GeneralHelper.DetermineNumberOfCalculationErrors(engineInterface.DamProjectData.CalculationMessages); Assert.AreEqual(0, errorCount, "There should be no errors during the calculation."); var seriesCount = 0; var resultsCount = 0; const double cTolerance = 0.0005; foreach (Deltares.DamEngine.Data.General.TimeSeries.TimeSerie timeSeries in series) { //Assert.IsTrue(validParameterIDs.Any(n => n == timeSeries.ParameterId)); //Assert.IsTrue(locations.Any(l => l.Name == timeSeries.LocationId)); // StabilityInside check if (timeSeries.ParameterId == TimeSerieParameters.StabilityInsideFactor.ToString()) { if (timeSeries.LocationId == "Purmer_PU0042+00_K") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(1.442, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(1.579, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } if (timeSeries.LocationId == "Purmer_PU0042+00_K_V") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(1.365, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(1.481, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } if (timeSeries.LocationId == "Purmer_PU0042+00_R") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(1.239, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(1.355, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } if (timeSeries.LocationId == "Purmer_PU0042+00_R_V") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(1.168, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(1.272, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } if (timeSeries.LocationId == "Purmer_PU0110+20_K") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(Double.NaN, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(Double.NaN, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } if (timeSeries.LocationId == "Purmer_PU0110+20_K_V") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(Double.NaN, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(Double.NaN, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } if (timeSeries.LocationId == "Purmer_PU0110+20_R") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(Double.NaN, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(Double.NaN, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } if (timeSeries.LocationId == "Purmer_PU0110+20_R_V") { TimeSerieEntry firstEntry = timeSeries.Entries.First(); Assert.AreEqual(Double.NaN, firstEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; TimeSerieEntry lastEntry = timeSeries.Entries.Last(); Assert.AreEqual(Double.NaN, lastEntry.Value, cTolerance, "The computed safety factory is not correct"); resultsCount++; } } seriesCount++; } Assert.IsTrue(seriesCount > 0, "No output time series"); Assert.AreEqual(16, resultsCount, "Incorrect number of results"); } [Test] [TestCase(1)] [TestCase(4)] [TestCase(16)] public void DesignBishopWithScenariosForHeadPL3CalculatesCorrect(int maxCores) { const string inputFilename = "InputFileMultiCoreTestForScenario.xml"; string fullInputFilename = Path.Combine(mapTestFiles, inputFilename); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string inputString = File.ReadAllText(fullInputFilename); var engineInterface = new EngineInterface(inputString); engineInterface.DamProjectData.MaxCalculationCores = maxCores; var calcDir = engineInterface.DamProjectData.CalculationMap + "_Cores_" + maxCores; engineInterface.DamProjectData.CalculationMap = calcDir; Assert.IsNotNull(engineInterface.DamProjectData); calcDir = Directory.GetCurrentDirectory() + "\\" + calcDir; if (Directory.Exists(calcDir)) { Directory.Delete(calcDir, true); // delete previous results } string result = engineInterface.Validate(); Assert.IsTrue(result == null, "Validation must succeed but does not, see output xml in debugger"); string outputString = engineInterface.Run(); File.WriteAllText("Results_Cores_" + maxCores + ".xml", outputString); Output output = DamXmlSerialization.LoadOutputFromXmlString(outputString); Assert.AreEqual(18, output.Results.CalculationResults.Length); Assert.AreEqual(24,output.Results.CalculationMessages.Length); foreach (var designResult in output.Results.CalculationResults) { if (designResult.BaseFileName.Equals("Loc(KR093_0013)_Sce(3)_Pro(segment_627_1D1-KR093_0013-1)")) { Assert.AreEqual(9.300, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-0.94, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0013)_Sce(4)_Pro(segment_627_1D1-KR093_0013-1)")) { Assert.AreEqual(7.888, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0013)_Sce(3)_Pro(segment_627_1D2-KR093_0013-2)")) { Assert.AreEqual(7.023, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-0.94, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0013)_Sce(4)_Pro(segment_627_1D2-KR093_0013-2)")) { Assert.AreEqual(5.968, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0013)_Sce(3)_Pro(segment_627_1D3-KR093_0013-3)")) { Assert.AreEqual(7.555, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-0.94, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0013)_Sce(4)_Pro(segment_627_1D3-KR093_0013-3)")) { Assert.AreEqual(6.477, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0018)_Sce(3)_Pro(segment_629_1D1-KR093_0018-1)")) { Assert.AreEqual(7.353, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-1.00, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0018)_Sce(4)_Pro(segment_629_1D1-KR093_0018-1)")) { Assert.AreEqual(6.278, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.61, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0018)_Sce(3)_Pro(segment_629_1D2-KR093_0018-2)")) { Assert.AreEqual(5.945, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-1.00, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0018)_Sce(4)_Pro(segment_629_1D2-KR093_0018-2)")) { Assert.AreEqual(1.225, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0018)_Sce(3)_Pro(segment_629_1D3-KR093_0018-3)")) { Assert.AreEqual(1.608, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-1.00, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0018)_Sce(4)_Pro(segment_629_1D3-KR093_0018-3)")) { Assert.AreEqual(1.397, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0019)_Sce(3)_Pro(segment_629_1D1-KR093_0019-1)")) { Assert.AreEqual(4.557, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-1.03, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0019)_Sce(4)_Pro(segment_629_1D1-KR093_0019-1)")) { Assert.AreEqual(3.985, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.57, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0019)_Sce(3)_Pro(segment_629_1D2-KR093_0019-2)")) { Assert.AreEqual(4.087, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-1.03, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0019)_Sce(4)_Pro(segment_629_1D2-KR093_0019-2)")) { Assert.AreEqual(3.418, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0019)_Sce(3)_Pro(segment_629_1D3-KR093_0019-3)")) { Assert.AreEqual(4.432, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("3", designResult.ScenarioName); Assert.AreEqual(-1.03, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } if (designResult.BaseFileName.Equals("Loc(KR093_0019)_Sce(4)_Pro(segment_629_1D3-KR093_0019-3)")) { Assert.AreEqual(3.745, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } } } private static void RemoveTestWorkingDirectory(string testWorkingFolder) { if (Directory.Exists(testWorkingFolder)) { const bool recursive = true; Directory.Delete(testWorkingFolder, recursive); } } }