// 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\";
[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")]
[Category(Categories.WorkInProgress)]
[TestCase("OperationalBishopGrid1Core.xml")]
[TestCase("OperationalBishopGrid2Cores.xml")]
[TestCase("OperationalBishopGrid4Cores.xml")]
[TestCase("OperationalBishopGrid8Cores.xml")]
[TestCase("OperationalBishopGrid18Cores.xml")]
public void OperationalBishopGridTestsWithXmlInputFile(string aFileName)
{
//const string inputFilename = "InputForDebugging.xml"; // or put your own name here;
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 nor 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 nor 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]//, Ignore("This test is only used for debugging XML files generated by Dam UI")]
[TestCase(10)]
[TestCase(24)]
public void OperationalBeeSwarmMultiCoreWithXmlInputFile(int maxCores)
{
const string inputFilename = "InputForDebuggingBeeSwarm.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);
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 nor 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");
}
private static void RemoveTestWorkingDirectory(string testWorkingFolder)
{
if (Directory.Exists(testWorkingFolder))
{
const bool recursive = true;
Directory.Delete(testWorkingFolder, recursive);
}
}
}