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