// Copyright (C) Stichting Deltares 2018. All rights reserved.
//
// This file is part of the application DAM - Live.
//
// DAM - UI is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU 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.IO;
using System.Linq;
using Deltares.Dam.Application.Live;
using Deltares.Dam.Data;
using Deltares.Dam.Data.Sensors;
using Deltares.DamLive.TestHelper;
using Deltares.Standard.IO;
using NUnit.Framework;
namespace Deltares.DamLive.Tests
{
[TestFixture]
[Category("Integration")]
public class DamLiveIntegrationTest
{
#region Test Setup
const string TestWorkingFolder = "LiveDikeIntegrationTestWorkingFolder";
private const string TestDataFolder = @"TestData\DamLive\Set2";
private List locations;
private string inputFile;
private string outputFile;
private string projectFile;
private string parameterFile;
private DamEngineRunner runner;
private DamProjectData damProjectData;
[TestFixtureSetUp]
public void SetupFixture()
{
IoHelper.RemoveTestWorkingDirectory(TestWorkingFolder); // to be sure no test directory exist from previous tests
Directory.CreateDirectory(TestWorkingFolder);
}
[TestFixtureTearDown]
public void TearDownFixture()
{
IoHelper.RemoveTestWorkingDirectory(TestWorkingFolder);
}
[TearDown]
public void TearDownTest()
{
damProjectData.Dispose();
AssertNoErrors();
}
[SetUp]
public void SetupTest()
{
// create a random unique test directory name in the
// test working folder
var actualTestPath = Guid.NewGuid().ToString().Replace("-", "");
actualTestPath = Path.Combine(TestWorkingFolder, actualTestPath);
Directory.CreateDirectory(actualTestPath);
DirectoryHelper.CopyRecursive(actualTestPath, TestDataFolder);
inputFile = Path.Combine(actualTestPath, "live.FEWS.InputFile.1Step.xml");
outputFile = Path.Combine(actualTestPath, "live.FEWS.OutputFile.xml");
parameterFile = Path.Combine(actualTestPath, "live.Parameters.xml");
projectFile = Path.Combine(actualTestPath, "output.damx");
var soilDatabasFile = Path.Combine(actualTestPath, "output0.soilmaterials.mdb");
damProjectData = DamProject.LoadData(projectFile);
locations = damProjectData.Locations;
#region Sensor data setup
var sensor1 = new Sensor
{
ID = 1,
Name = "Sensor 1 bws",
RelativeLocation = 50,
Depth = -0.25,
//1 255364,05597700000 598646,53034800000
XRd = 255364.05597700000,
YRd = 598646.53034800000,
PLLineMappings = new[] {PLLineType.PL1},
Type = SensorType.WaterLevel
};
var sensor2 = new Sensor
{
ID = 2,
Name = "Sensor 2 p31,5 fr kr",
RelativeLocation = 90,
Depth = -1.4,
//2 255314,98052600000 598610,92683800000
XRd = 255314.98052600000,
YRd = 598610.92683800000,
PLLineMappings = new[] { PLLineType.PL1 }
};
var sensor3 = new Sensor
{
ID = 3,
Name = "Sensor 3 p31,5 fr bita",
RelativeLocation = 104,
Depth = -1.4,
//3 255297,41641600000 598607,82723500000
XRd = 255297.41641600000,
YRd = 598607.82723500000,
PLLineMappings = new[] { PLLineType.PL1 }
};
var sensor4 = new Sensor
{
ID = 4,
Name = "Sensor 4 p31,5 fr bite",
RelativeLocation = 123.3,
Depth = -1.4,
//4 255281,75318400000 598605,06308600000
XRd = 255281.75318400000,
YRd = 598605.06308600000,
PLLineMappings = new[] { PLLineType.PL1 }
};
var sensor5 = new Sensor
{
ID = 5,
Name = "Sensor 5 p31,5 wv kr",
RelativeLocation = 90,
Depth = -8,
//5 255315,30724200000 598609,45483400000
XRd = 255315.30724200000,
YRd = 598609.45483400000,
PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4 }
};
var sensor6 = new Sensor
{
ID = 6,
Name = "Sensor 6 p31,5 wv bite",
RelativeLocation = 123.3,
Depth = -8,
//6 255282,10125300000 598603,60443900000
XRd = 255282.10125300000,
YRd = 598603.60443900000,
PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4 }
};
var sensor7 = new Sensor
{
ID = 7,
Name = "Sensor 7 p31,5 wv al",
RelativeLocation = 180,
Depth = -8,
//7 255258,88456900000 598601,02737800000
YRd = 255258.88456900000,
XRd = 598601.02737800000,
PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4 }
};
var sensor8 = new Sensor
{
ID = 8,
Name = "Sensor 8 p34,0 fr bita",
RelativeLocation = 111.6,
Depth = -1.4,
//8 254903,30399000000 600985,77819300000
YRd = 254903.30399000000,
XRd = 600985.77819300000,
PLLineMappings = new[] { PLLineType.PL1 }
};
var sensor9 = new Sensor
{
ID = 9,
Name = "Sensor 9 p34,0 fr bite",
RelativeLocation = 133,
Depth = -1.4,
//9 254880,03131200000 600990,83641800000
XRd = 254880.03131200000,
YRd = 600990.83641800000,
PLLineMappings = new[] { PLLineType.PL1 }
};
var sensor10 = new Sensor
{
ID = 10,
Name = "Sensor 10 p34,0 wv bite",
RelativeLocation = 150,
Depth = -11,
//10 254868,38462700000 600993,36777900000
XRd = 254868.38462700000,
YRd = 600993.36777900000,
PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4 }
};
var sensor11 = new Sensor
{
ID = 11,
Name = "Sensor 11 p37,0 fr bite",
RelativeLocation = 90,
Depth = -1.4,
//11 253891,83608800000 603326,50840000000
XRd = 253891.83608800000,
YRd = 603326.50840000000,
PLLineMappings = new[] { PLLineType.PL1 }
};
var sensor12 = new Sensor
{
ID = 12,
Name = "Sensor 12 p37,0 pp",
RelativeLocation = 106.9,
Depth = 0,
//12 253879,41142700000 603312,09339600000
XRd = 253879.41142700000,
YRd = 603312.09339600000,
PLLineMappings = new[] { PLLineType.PL1 }
};
var sensor13 = new Sensor
{
ID = 13,
Name = "Sensor 13 p37,0 wv bute",
RelativeLocation = 10,
Depth = -14,
//13 253946,28533900000 603389,68003600000
XRd = 253946.28533900000,
YRd = 603389.68003600000,
PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4, }
};
var sensor14 = new Sensor
{
ID = 14,
Name = "Sensor 14 p37,0 wv kr",
RelativeLocation = 73.3,
Depth = -14,
//14 253902,12906700000 603338,45024200000
XRd = 253902.12906700000,
YRd = 603338.45024200000,
PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4, }
};
var sensor15 = new Sensor
{
ID = 15,
Name = "Sensor 15 p37,0 wv bite",
RelativeLocation = 102.3,
Depth = -14,
//15 253882,90332500000 603316,14467200000
XRd = 253882.90332500000,
YRd = 603316.14467200000,
PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4, }
};
#endregion
#region Sensor location coupling
var location0 = locations[0];
var repository = new SensorRepository(location0);
repository.Add(new[] { sensor1, sensor2, sensor3, sensor4, sensor5, sensor6, sensor7 });
var sensorData = location0.SensorData;
sensorData.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.Sensor;
sensorData.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.LocationData;
sensorData.SourceTypePl3 = DataSourceTypeSensors.Sensor;
sensorData.SourceTypePl4 = DataSourceTypeSensors.Sensor;
//location0.Name = "dwp 31,5";
var location1 = locations[1];
repository = new SensorRepository(location1);
repository.Add(new[] { sensor1, sensor8, sensor9, sensor10 });
sensorData = location1.SensorData;
sensorData.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.Sensor;
sensorData.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.LocationData;
sensorData.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.LocationData;
sensorData.SourceTypePl3 = DataSourceTypeSensors.Sensor;
sensorData.SourceTypePl4 = DataSourceTypeSensors.Sensor;
//location1.Name = "dwp 34,0";
var location2 = locations[2];
repository = new SensorRepository(location2);
repository.Add(new[] { sensor1, sensor11, sensor12, sensor13, sensor14, sensor15 });
sensorData = location2.SensorData;
sensorData.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.Sensor;
sensorData.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.LocationData;
sensorData.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.Ignore;
sensorData.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.Sensor;
sensorData.SourceTypePl3 = DataSourceTypeSensors.Sensor;
sensorData.SourceTypePl4 = DataSourceTypeSensors.Sensor;
//location2.Name = "dwp 37,0";
#endregion
// Load the sensor time serie data (see input file for details)
var inputTimeSeries = TimeSerieCollection.LoadFromFile(inputFile);
runner = new DamEngineRunner()
{
WorkingPath = Path.ChangeExtension(projectFile, ".Calc"),
StabilityWorkingPath = "stability",
PipingWorkingPath = "piping",
WaterLevelOffset = 0,
CalculationParameters = new CalculationParameters
{
MStabParameters = new MStabParameters
{
Model = MStabModelType.Bishop,
ShearStrength = MStabShearStrength.CPhi,
IsProbabilistic = false,
SoilDatabaseName = Path.Combine(@".\", soilDatabasFile),
SearchMethod = MStabSearchMethod.Grid,
GridPosition = MStabGridPosition.Right,
CalculationOptions = new MStabCalculationOptions{ },
},
CalculationModules = new CalculationModules
{
Overtopping = false,
PipingBligh = false,
PipingIJkdijk = false,
PipingSellmeijer = false,
PipingSellmeijerProbabilistic = false,
Stability = true
}
},
DamProjectData = damProjectData,
FewsOutputFile = new FileInfo(outputFile),
InputTimeSeriesCollection = inputTimeSeries
};
}
#endregion
#region Helper methods
///
/// Asserts that there are no errors in the runner
///
private void AssertNoErrors()
{
if (runner.HasErrors)
{
Assert.Fail("The test failed. See the error log in the test output console for more info");
}
}
#endregion
///
/// This test calls the runner's Run method.
/// This test is an integration test.
///
/// Required files are:
/// - the DAMX file which contains the dike models
/// - FEWS input file containing the water level time series for the locations
/// or monitoring points
/// - FEWS output file containing the time series results for each node
/// (location/monitoring point)
///
/// See setup method
///
[Test, Ignore("Under construction")]
public void Run_UsingTestFiles_HasExpectedResultsInOutputFile()
{
runner.Run();
AssertNoErrors();
const double expectedSafetyFactor = 1.226;
const double cTolerance = 0.0005;
var series = runner.OutputTimeSeriesCollection.Series;
int seriesCount = 0;
var validParameterIDs = Enum.GetNames(typeof (TimeSerieParameters));
foreach (var timeSeries in series)
{
Assert.IsTrue(validParameterIDs.Any(n => n == timeSeries.ParameterId));
Assert.IsTrue(locations.Any(l => l.Name == timeSeries.LocationId));
if (timeSeries.LocationId == locations[0].Name)
{
var firstEntry = timeSeries.Entries.First();
Assert.AreEqual(expectedSafetyFactor, firstEntry.Value, cTolerance, "The computed safety factory is not correct");
}
seriesCount++;
}
Assert.AreEqual(locations.Count, seriesCount);
Assert.IsTrue(seriesCount > 0, "No output time series");
}
}
}