// 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.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading; 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; namespace Deltares.DamEngine.IntegrationTests.IntegrationTests { [TestFixture] public class MultiCoreMacroStabilityTests { private const double tol2Digits = 0.005; private const double tolerance = 0.0005; private const string mapTestFiles = @"TestFiles\"; [Test, Category("MultiCore")] [TestCase(MStabModelType.Bishop, AnalysisType.NoAdaption)] [TestCase(MStabModelType.UpliftVan, AnalysisType.NoAdaption)] [TestCase(MStabModelType.BishopUpliftVan, AnalysisType.NoAdaption)] [TestCase(MStabModelType.Bishop, AnalysisType.AdaptGeometry)] [TestCase(MStabModelType.UpliftVan, AnalysisType.AdaptGeometry)] public void CanPerformRunMacroStabilityTutorialDesignMultiCore(MStabModelType mStabModelType, AnalysisType analysisType) { // Based on ".data\DamEngineTestProjects\DAM Tutorial Design\DAM Tutorial Design.damx" // with Dam Classic rev.1059 // Select locations DWP_1 to DWP_12 const int multiCoreCount = 4; const string fileName = @"TestFiles\MacroStabilityTutorialDesignInputFileMultipleLocations.xml"; const string fileNameOutputPrefix = @"TestFiles\MacroStabilityTutorialDesignMultipleLocations"; string inputString = File.ReadAllText(fileName); inputString = XmlAdapter.ChangeValueInXml(inputString, "ProjectPath", ""); // 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, "StabilityModelType", mStabModelType.ToString()); inputString = XmlAdapter.ChangeValueInXml(inputString, "AnalysisType", analysisType.ToString()); // Calculate one core string calcDir = String.Format("TestStabInwards_{0}_{1}_{2}Core", mStabModelType.ToString(), analysisType.ToString(), 1); string outputFilename = DetermineOutputFilename(fileNameOutputPrefix, mStabModelType.ToString(), analysisType.ToString(), 1); string outputString; EngineInterface engineInterface; // Following line to force 1-core calculation to be performed always. // Outcomment it to prevent 1-core calculation to be performed if it as already done in a previous run, to speed up the test. if (File.Exists(outputFilename)) File.Delete(outputFilename); if (File.Exists(outputFilename)) { // This is to speed up local testing; after the first run the file will be read from disk. // If something in the calculation results changes, the file has to be deleted (see line above) // It will then be generated again in the else block of this statement outputString = File.ReadAllText(outputFilename); Debug.WriteLine("Skipping single core calculation Macrostability; results are read from file"); } else { inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used if (Directory.Exists(calcDir)) { Directory.Delete(calcDir, true); // delete previous results } Directory.CreateDirectory(calcDir); Debug.WriteLine("Perform single core calculation Macrostability"); engineInterface = new EngineInterface(inputString); Assert.IsNotNull(engineInterface.DamProjectData); outputString = engineInterface.Run(); Assert.IsNotNull(outputString); File.WriteAllText(outputFilename, outputString, Encoding.Unicode); } var outputOneCore = DamXmlSerialization.LoadOutputFromXmlString(outputString); // Calculate multicore calcDir = String.Format("TestStabInwards_{0}_{1}_{2}Core", mStabModelType.ToString(), analysisType.ToString(), multiCoreCount); outputFilename = DetermineOutputFilename(fileNameOutputPrefix, mStabModelType.ToString(), analysisType.ToString(), multiCoreCount); // Following line to force multicore calculation to be performed always. // Outcomment it to prevent multicore calculation to be performed if it as already done in a previous run, to speed up the test. if (File.Exists(outputFilename)) File.Delete(outputFilename); if (File.Exists(outputFilename)) { // This is to speed up local testing; after the first run the file will be read from disk. // If something in the calculation results changes, the file has to be deleted (see line above) // It will then be generated again in the else block of this statement outputString = File.ReadAllText(outputFilename); Debug.WriteLine("Skipping multicore calculation Macrostability; results are read from file"); } else { inputString = XmlAdapter.ChangeValueInXml(inputString, "CalculationMap", calcDir); // Current directory will be used inputString = XmlAdapter.ChangeValueInXml(inputString, "MaxCalculationCores", multiCoreCount.ToString()); if (Directory.Exists(calcDir)) { Directory.Delete(calcDir, true); // delete previous results } Directory.CreateDirectory(calcDir); Debug.WriteLine("Perform multicore calculation with {0} cores Macrostability", multiCoreCount); engineInterface = new EngineInterface(inputString); Assert.IsNotNull(engineInterface.DamProjectData); outputString = engineInterface.Run(); Assert.IsNotNull(outputString); File.WriteAllText(outputFilename, outputString, Encoding.Unicode); } var outputMultiCore = DamXmlSerialization.LoadOutputFromXmlString(outputString); // Compare the results var differences = new List(); StringBuilder differencesStringBuilder = new StringBuilder(); foreach (DesignResult oneCoreResult in outputOneCore.Results.CalculationResults) { DesignResult multiCoreResult = outputMultiCore.Results.CalculationResults.FirstOrDefault(x => x.LocationName.Equals(oneCoreResult.LocationName) && x.ProfileName.Equals(oneCoreResult.ProfileName) && x.StabilityDesignResults.StabilityModelType == oneCoreResult.StabilityDesignResults.StabilityModelType); if (multiCoreResult == null) { var diffString = String.Format("No multicore result in location '{0}', soilprofile '{1}'", oneCoreResult.LocationName, oneCoreResult.ProfileName); differencesStringBuilder.AppendLine(diffString); differences.Add(diffString); } else { if (Math.Abs(oneCoreResult.StabilityDesignResults.SafetyFactor - multiCoreResult.StabilityDesignResults.SafetyFactor) > tolerance) { var diffString = String.Format("Different result in location '{0}', soilprofile '{1}': 1 core = {2}, multicore = {3}", oneCoreResult.LocationName, oneCoreResult.ProfileName, oneCoreResult.StabilityDesignResults.SafetyFactor, multiCoreResult.StabilityDesignResults.SafetyFactor); differencesStringBuilder.AppendLine(diffString); differences.Add(diffString); } } } Assert.IsTrue(differences.Count == 0, "Differences found" + Environment.NewLine + differencesStringBuilder); } [Test] //, Ignore("This test is only used for debugging XML files generated by Dam UI")] [TestCase(1)] [TestCase(4)] [TestCase(16)] public void ProblemWithScenariosFromWFInputFile(int maxCores) { const string inputFilename = "InputFileMultiCoreTestForScenario.xml"; // or put your own name here; 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 } // C:\Dam\DamEngine\branches\DamEngine 19.3\src\bin\Debug\Bka16CoreDam_Run1NewDGS.Calc_Cores_16 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(0,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(10.182, 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(0.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_1D1-KR093_0013-2)")) { Assert.AreEqual(0.888, 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-2)")) { Assert.AreEqual(0.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_1D1-KR093_0013-3)")) { Assert.AreEqual(0.844, 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-3)")) { Assert.AreEqual(0.844, 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.838, 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(1.160, 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-2)")) { Assert.AreEqual(1.325, 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-2)")) { Assert.AreEqual(1.201, 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-3)")) { Assert.AreEqual(1.381, 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-3)")) { Assert.AreEqual(1.374, 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.948, 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(4.044, 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-2)")) { Assert.AreEqual(4.300, 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-2)")) { Assert.AreEqual(3.648, 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-3)")) { Assert.AreEqual(4.697, 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-3)")) { Assert.AreEqual(4.008, designResult.StabilityDesignResults.SafetyFactor, tolerance); Assert.AreEqual("4", designResult.ScenarioName); Assert.AreEqual(-0.37, designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, tol2Digits); } } } private string DetermineOutputFilename(string prefix, string modelType, string analysisType, int coreCount, string extension = ".xml") { return String.Format("{0}_{1}_{2}_{3}core_OutputFile{4}", prefix, modelType, analysisType, coreCount, extension); } } }