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