// Copyright (C) Stichting Deltares 2018. 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.IO; using Deltares.DamEngine.Data.Design; using Deltares.DamEngine.Data.General; using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; using Deltares.DamEngine.Io; using Deltares.DamEngine.Io.XmlInput; using KellermanSoftware.CompareNetObjects; using NUnit.Framework; using Segment = Deltares.DamEngine.Data.General.Segment; using Soil = Deltares.DamEngine.Data.Geotechnics.Soil; using SoilProfile1D = Deltares.DamEngine.Data.Geotechnics.SoilProfile1D; using SoilProfile2D = Deltares.DamEngine.Data.Geotechnics.SoilProfile2D; namespace Deltares.DamEngine.Interface.Tests { [TestFixture] public class FillDamFromXmlInputTests { const AnalysisType expectedAnalysisType = AnalysisType.AdaptGeometry; const AnalysisType notExpectedAnalysisType = AnalysisType.NoAdaption; [Test] public void CanWriteAndReadDamProjectDataToXml() { const string inputFilename = "InputFile.xml"; DamProjectData expectedDamProjectData = CreateExampleDamProjectData(); // Write input file Input input = FillXmlInputFromDam.CreateInput(expectedDamProjectData); DamXmlSerialization.SaveInputAsXmlFile(inputFilename, input); // Init static that is to be loaded with not expected value DamProjectCalculationSpecification.SelectedAnalysisType = notExpectedAnalysisType; // Load input file input = DamXmlSerialization.LoadInputFromXmlFile(inputFilename); DamProjectData actualDamProjectData = FillDamFromXmlInput.CreateDamProjectData(input); CompareDamProjectData(actualDamProjectData, expectedDamProjectData); } [Test] public void CanWriteAndReadDamProjectDataToXmlString() { DamProjectData expectedDamProjectData = CreateExampleDamProjectData(); // Write input string string xmlString; Input input = FillXmlInputFromDam.CreateInput(expectedDamProjectData); xmlString = DamXmlSerialization.SaveInputAsXmlString(input); // Init static that is to be loaded with not expected value DamProjectCalculationSpecification.SelectedAnalysisType = notExpectedAnalysisType; // Load input string input = DamXmlSerialization.LoadInputFromXmlString(xmlString); DamProjectData actualDamProjectData = FillDamFromXmlInput.CreateDamProjectData(input); CompareDamProjectData(actualDamProjectData, expectedDamProjectData); } private void AddPointToSurfaceLine(SurfaceLine2 surfaceLine, double xCoordinate, double zCoordinate, CharacteristicPointType characteristicPointType) { var geometryPoint = new GeometryPoint() { X = xCoordinate, Y = 0.0, Z = zCoordinate, }; surfaceLine.AddCharacteristicPoint(geometryPoint, characteristicPointType); } private DamProjectData CreateExampleDamProjectData() { var damProjectData = new DamProjectData(); damProjectData.ProjectPath = @"D:\TestDir"; damProjectData.CalculationMap = @"Sub\Calc"; damProjectData.MaxCalculationCores = 3; FillAnalysisSpecification(damProjectData); FillStabilityParameters(damProjectData); damProjectData.Dike = new Dike(); Dike dike = damProjectData.Dike; FillSurfaceLines(dike); FillSoils(dike); FillSoilProfiles1D(dike); FillSoilProfiles2D(dike); FillSegments(damProjectData); FillLocations(dike, damProjectData.Segments, damProjectData.ProjectPath); return damProjectData; } private static void FillAnalysisSpecification(DamProjectData damProjectData) { damProjectData.DamProjectType = DamProjectType.Design; damProjectData.DamProjectCalculationSpecification = new DamProjectCalculationSpecification(); DamProjectCalculationSpecification.SelectedAnalysisType = expectedAnalysisType; var calculationSpecification = new DamFailureMechanismeCalculationSpecification(); calculationSpecification.FailureMechanismSystemType = FailureMechanismSystemType.Piping; calculationSpecification.CalculationModel = PipingModelType.Bligh; damProjectData.DamProjectCalculationSpecification.DamCalculationSpecifications.Add(calculationSpecification); } private static void FillStabilityParameters(DamProjectData damProjectData) { // Note: DamProjectCalculationSpecification created and filled by FillAnalysisSpecification var curspec = damProjectData.DamProjectCalculationSpecification.CurrentSpecification; curspec.FailureMechanismParametersMStab = new FailureMechanismParametersMStab { MStabParameters = new MStabParameters { SearchMethod = MStabSearchMethod.Grid, SlipCircleDefinition = new SlipCircleDefinition { GridSizeDetermination = GridSizeDetermination.Specified, BishopGridHorizontalPointCount = 4, BishopGridHorizontalPointDistance = 1.2, BishopGridVerticalPointCount = 5, BishopGridVerticalPointDistance = 1.1, BishopTangentLinesDefinition = TangentLinesDefinition.Specified, BishopTangentLinesDistance = 0.25, UpliftVanLeftGridHorizontalPointCount = 6, UpliftVanLeftGridHorizontalPointDistance = 0.7, UpliftVanLeftGridVerticalPointCount = 3, UpliftVanLeftGridVerticalPointDistance = 1.3, UpliftVanRightGridHorizontalPointCount = 8, UpliftVanRightGridHorizontalPointDistance = 1.76, UpliftVanRightGridVerticalPointCount = 11, UpliftVanRightGridVerticalPointDistance = 0.14, UpliftVanTangentLinesDefinition = TangentLinesDefinition.OnBoundaryLines, UpliftVanTangentLinesDistance = 0.01 } } }; } private void FillSoils(Dike dike) { const int soilCount = 3; dike.SoilList = new SoilList(); for (int i = 0; i < soilCount; i++) { Soil soil = new Soil() {Name = String.Format("Soil {0}", i)}; //soil.SoilType = SoilType.Loam; soil.AbovePhreaticLevel = 7 + 0.1 * i; soil.BelowPhreaticLevel = 8 + 0.1 * i; soil.DryUnitWeight = 9 + 0.1 * i; soil.ShearStrengthModel = ShearStrengthModel.SuMeasured; soil.UseDefaultShearStrengthModel = false; soil.Cohesion = 10 + 0.1 * i; soil.FrictionAngle = 13 + 0.1 * i; soil.Ocr = 14 + 0.1 * i; soil.SlopeRestProfile = 15 + 0.1 * i; soil.DilatancyType = DilatancyType.Zero; //soil.CuBottom = 11 + 0.1 * i; //soil.CuTop = 12 + 0.1 * i; //soil.PoP = 15 + 0.1 * i; //soil.RatioCuPc = 16 + 0.1 * i; //soil.StrengthIncreaseExponent = 17 + 0.1 * i; //soil.UsePop = true; soil.BeddingAngle = 18 + 0.1 * i; soil.DiameterD70 = 19 + 0.1 * i; soil.DiameterD90 = 20 + 0.1 * i; soil.PermeabKx = 21 + 0.1 * i; soil.WhitesConstant = 22 + 0.1 * i; dike.SoilList.Add(soil); } var dikemat = new Soil { Name = "DikeMat", AbovePhreaticLevel = 7, BelowPhreaticLevel = 8, DryUnitWeight = 9, BeddingAngle = 18, DiameterD70 = 19, DiameterD90 = 20, PermeabKx = 21, WhitesConstant = 22 }; dike.SoilList.Add(dikemat); } private void FillSurfaceLines(Dike dike) { const int surfaceLineCount = 3; for (int i = 0; i < surfaceLineCount; i++) { var surfaceLine = new SurfaceLine2(); surfaceLine.Name = String.Format("SurfaceLine {0}", i); surfaceLine.CharacteristicPoints.Geometry = surfaceLine.Geometry; AddPointsToSurfaceLines(surfaceLine); surfaceLine.Geometry.SyncCalcPoints(); dike.SurfaceLines2.Add(surfaceLine); } } private void AddPointsToSurfaceLines(SurfaceLine2 surfaceLine) { AddPointToSurfaceLine(surfaceLine, 0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside); AddPointToSurfaceLine(surfaceLine, 2.0, 0.5, CharacteristicPointType.None); AddPointToSurfaceLine(surfaceLine, 4.0, 0.0, CharacteristicPointType.DikeToeAtRiver); AddPointToSurfaceLine(surfaceLine, 9.0, 5.0, CharacteristicPointType.DikeTopAtRiver); AddPointToSurfaceLine(surfaceLine, 10.0, 5.2, CharacteristicPointType.None); AddPointToSurfaceLine(surfaceLine, 13.0, 5.4, CharacteristicPointType.DikeTopAtPolder); AddPointToSurfaceLine(surfaceLine, 18.0, 1.0, CharacteristicPointType.DikeToeAtPolder); AddPointToSurfaceLine(surfaceLine, 24.0, 1.0, CharacteristicPointType.SurfaceLevelInside); } private static void FillLocations(Dike dike, IList segments, string projectPath) { const int locationCount = 3; for (int i = 0; i < locationCount; i++) { var location = new Data.General.Location(); location.Name = "Location " + (i + 1).ToString(); location.XSoilGeometry2DOrigin = 1.23; location.ModelParametersForPLLines.PlLineCreationMethod = (PlLineCreationMethod) i; location.IntrusionVerticalWaterPressure = (IntrusionVerticalWaterPressureType) i; location.PolderLevel = 1.0 * i + 0.11; location.ModelParametersForPLLines.DampingFactorPL4 = 1.0 * i + 0.12; location.ModelParametersForPLLines.DampingFactorPL3 = 1.0 * i + 0.13; location.ModelParametersForPLLines.PenetrationLength = 1.0 * i + 0.14; location.PlLineOffsetBelowDikeCrestMiddle = 1.0 * i + 0.15; location.UsePlLineOffsetFactorBelowShoulderCrest = true; location.PlLineOffsetFactorBelowShoulderCrest = 1.0 * i + 0.16; location.PlLineOffsetDryBelowDikeCrestMiddle = 1.0 * i + 0.17; location.UsePlLineOffsetDryFactorBelowShoulderCrest = true; location.PlLineOffsetDryFactorBelowShoulderCrest = 1.0 * i + 0.18; location.SlopeDampingPiezometricHeightPolderSide = 1.0 * i + 0.19; location.PlLineOffsetBelowDikeTopAtRiver = 1.0 * i + 0.20; location.PlLineOffsetBelowDikeTopAtPolder = 1.0 * i + 0.21; location.PlLineOffsetBelowShoulderBaseInside = 1.0 * i + 0.22; location.PlLineOffsetBelowDikeToeAtPolder = 1.0 * i + 0.23; location.HeadPl2 = 1.0 * i + 0.24; location.HeadPl3 = 1.0 * i + 0.25; location.HeadPl4 = 1.0 * i + 0.21; location.SurfaceLine = dike.SurfaceLines2[i]; location.Segment = segments[i % 2]; // alternate between the 2 available segments for (int j = 0; j < 3; j++) { var designScenario = FillDesignScenario(i, j); designScenario.Location = location; location.Scenarios.Add(designScenario); } location.DikeEmbankmentMaterial = "DikeMat"; location.StabilityOptions = new StabilityOptions { SoilGeometries2DPath = Path.Combine(projectPath, @"Sub\TestMap"), StabilityZoneType = MStabZonesType.ZoneAreas, ForbiddenZoneFactor = 1.23, ZoneAreaRestSlopeCrestWidth = 8.23, TrafficLoad = 11.11, MinimalCircleDepth = 1.21, SoilDatabaseName = "test.mdb", }; location.RedesignDikeHeight = false; location.RedesignDikeShoulder = false; location.ShoulderEmbankmentMaterial = "ShoulderMat" + (i + 1).ToString(); ; location.StabilityShoulderGrowSlope = 10.0 * i + 0.10; location.StabilityShoulderGrowDeltaX = 10.0 * i + 0.11; location.StabilitySlopeAdaptionDeltaX = 10.0 * i + 0.12; location.SlopeAdaptionStartCotangent = 10.0 * i + 0.13; location.SlopeAdaptionEndCotangent = 10.0 * i + 0.14; location.SlopeAdaptionStepCotangent = 10.0 * i + 0.15; location.UseNewDikeTopWidth = true; location.UseNewDikeSlopeInside = true; location.UseNewDikeSlopeOutside = true; location.UseNewShoulderTopSlope = true; location.UseNewShoulderBaseSlope = true; location.UseNewMaxHeightShoulderAsFraction = true; location.UseNewMinDistanceDikeToeStartDitch = true; location.UseNewDitchDefinition = true; location.NewDikeTopWidth = 10.0 * i + 0.16; location.NewDikeSlopeInside = 10.0 * i + 0.17; location.NewDikeSlopeOutside = 10.0 * i + 0.18; location.NewShoulderTopSlope = 10.0 * i + 0.19; location.NewShoulderBaseSlope = 10.0 * i + 0.20; location.NewMaxHeightShoulderAsFraction = 10.0 * i + 0.21; location.NewMinDistanceDikeToeStartDitch = 10.0 * i + 0.22; location.UseNewDitchDefinition = true; location.NewWidthDitchBottom = 10.0 * i + 0.23; location.NewSlopeAngleDitch = 10.0 * i + 0.24; location.NewDepthDitch = 10.0 * i + 0.25; location.StabilityDesignMethod = StabilityDesignMethod.SlopeAdaptionBeforeShoulderAdaption; location.SoilList = dike.SoilList; dike.Locations.Add(location); } } private static void FillSoilProfiles1D(Dike dike) { dike.SoilProfiles = new List(); const int profilesCount = 2; for (int i = 0; i < profilesCount; i++) { var profile = new SoilProfile1D(); profile.Name = "Profile1D " + (i + 1).ToString(); profile.BottomLevel = -21.12 * (i + 1); const int layerCount = 3; for (int j = 0; j < layerCount; j++) { var layer = new SoilLayer1D { Name = "Layer" + (j + 1).ToString(), Soil = dike.SoilList.Soils[j], TopLevel = 1 * -j }; if (j < 2) { layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Automatic; layer.IsAquifer = false; } else { layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Hydrostatic; layer.IsAquifer = true; } profile.Layers.Add(layer); } dike.SoilProfiles.Add(profile); } } private static DesignScenario FillDesignScenario(int locationIndex, int scenarioIndex) { // The parameter factor is used to create unique data for the design scenario int factor = (locationIndex + 1) * (scenarioIndex + 1); var designScenario = new DesignScenario(); designScenario.LocationScenarioID = scenarioIndex.ToString(); designScenario.RiverLevel = 1.0 * factor + 0.51; designScenario.RiverLevelLow = 1.0 * factor + 0.52; designScenario.DikeTableHeight = 1.0 * factor + 0.53; designScenario.PlLineOffsetBelowDikeTopAtRiver = 1.0 * factor + 0.54; designScenario.PlLineOffsetBelowDikeTopAtPolder = 1.0 * factor + 0.55; designScenario.PlLineOffsetBelowShoulderBaseInside = 1.0 * factor + 0.56; designScenario.PlLineOffsetBelowDikeToeAtPolder = 1.0 * factor + 0.57; designScenario.PlLineOffsetBelowDikeCrestMiddle = 1.0 * factor + 0.58; designScenario.UsePlLineOffsetBelowDikeCrestMiddle = true; designScenario.PlLineOffsetFactorBelowShoulderCrest = 1.0 * factor + 0.59; designScenario.UsePlLineOffsetFactorBelowShoulderCrest = true; designScenario.HeadPl3 = 1.0 * factor + 0.60; designScenario.HeadPl4 = 1.0 * factor + 0.61; designScenario.UpliftCriterionStability = 1.0 * factor + 0.62; designScenario.UpliftCriterionPiping = 1.0 * factor + 0.63; designScenario.RequiredSafetyFactorStabilityInnerSlope = 1.0 * factor + 0.64; designScenario.RequiredSafetyFactorStabilityOuterSlope = 1.0 * factor + 0.65; designScenario.RequiredSafetyFactorPiping = 1.0 * factor + 0.66; return designScenario; } private static void FillSoilProfiles2D(Dike dike) { dike.SoilProfiles2D = new List(); const int profilesCount = 2; for (int i = 0; i < profilesCount; i++) { var profile = new SoilProfile2D { Name = "Profile2D " + (i + 1).ToString() }; const int preConCount = 2; for (int j = 0; j < preConCount; j++) { var preCon = new PreConsolidationStress { Name = "Precon " + (j + 1).ToString(), StressValue = 3.33 * (i + 1) * (j + 1), X = 12.3 * (i + 1) * (j + 1), Z = 0.3 * (-i - 1) * (j + 1) }; profile.PreconsolidationStresses.Add(preCon); } const int layerCount = 3; for (int j = 0; j < layerCount; j++) { var layer = new SoilLayer2D { Name = "Layer" + (j + 1).ToString(), Soil = dike.SoilList.Soils[j] }; if (j < 2) { layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Automatic; layer.IsAquifer = false; } else { layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Hydrostatic; layer.IsAquifer = true; } layer.GeometrySurface = new GeometrySurface(); var outerLoop = new GeometryLoop(); outerLoop.Points.Add((new GeometryPoint(0, 0))); outerLoop.Points.Add((new GeometryPoint(0, 10))); outerLoop.Points.Add((new GeometryPoint(10, 10))); layer.GeometrySurface.OuterLoop = outerLoop; var innerloop = new GeometryLoop(); innerloop.Points.Add((new GeometryPoint(1, 1))); innerloop.Points.Add((new GeometryPoint(1, 9))); innerloop.Points.Add((new GeometryPoint(9, 9))); layer.GeometrySurface.InnerLoops.Add(innerloop); profile.Surfaces.Add(layer); } dike.SoilProfiles2D.Add(profile); } } private static void FillSegments(DamProjectData damProjectData) { var segmentCount = 2; for (int i = 0; i < segmentCount; i++) { var segment = new Segment(); segment.Name = "Segment " + i.ToString(); var soilProfileProbability = new SoilGeometryProbability(); if (i == 0) { soilProfileProbability.SegmentFailureMechanismType = FailureMechanismSystemType.StabilityInside; soilProfileProbability.SoilProfile2DName = "Profile2D " + (i + 1).ToString(); soilProfileProbability.SoilProfile2D = FillDamFromXmlInput.FindSoilProfile2DByName(damProjectData.Dike.SoilProfiles2D, soilProfileProbability.SoilProfile2DName); if (soilProfileProbability.SoilProfile2D != null) { soilProfileProbability.SoilProfileType = SoilProfileType.ProfileType2D; } else { soilProfileProbability.SoilProfileType = SoilProfileType.ProfileTypeStiFile; } } else { soilProfileProbability.SegmentFailureMechanismType = FailureMechanismSystemType.Piping; soilProfileProbability.SoilProfile1DName = "Profile1D " + (i + 1).ToString(); soilProfileProbability.SoilProfile1D = FillDamFromXmlInput.FindSoilProfile1DByName(damProjectData.Dike.SoilProfiles, soilProfileProbability.SoilProfile1DName); soilProfileProbability.SoilProfileType = SoilProfileType.ProfileType1D; } soilProfileProbability.Probability = 0.003 * (i + 1); segment.SoilProfileProbabilities.Add(soilProfileProbability); damProjectData.Segments.Add(segment); } } private void CompareDamProjectData(DamProjectData actual, DamProjectData expected) { Assert.AreEqual(expectedAnalysisType, DamProjectCalculationSpecification.SelectedAnalysisType); var compare = new CompareLogic { Config = { MaxDifferences = 100 } }; var result = compare.Compare(expected, actual); Assert.AreEqual(0, result.Differences.Count, "Differences found read/write Input object"); } } }