// Copyright (C) Stichting Deltares 2024. All rights reserved. // // This file is part of the application DAM - UI. // // 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.Data.Properties; using Deltares.Dam.Data.Sensors; using Deltares.Dam.Data.Geometry2DImporter; using Deltares.DamEngine.Data.Standard; using Deltares.DamEngine.Io; using Deltares.DamEngine.Io.XmlInput; using Deltares.Geotechnics.Soils; using Deltares.Geotechnics.SurfaceLines; using Deltares.Standard.Logging; using Sensor = Deltares.Dam.Data.Sensors.Sensor; using SensorLocation = Deltares.DamEngine.Io.XmlInput.SensorLocation; using Soil = Deltares.Geotechnics.Soils.Soil; using SoilProfile1D = Deltares.Geotechnics.Soils.SoilProfile1D; using SoilProfile2D = Deltares.DamEngine.Io.XmlInput.SoilProfile2D; using SurfaceLine = Deltares.DamEngine.Io.XmlInput.SurfaceLine; namespace Deltares.Dam.Data.DamEngineIo; /// /// Create XML Input object from DAM UI project /// public class FillXmlInputFromDamUi { /// /// Creates the input. /// /// The dam project data. /// public static Input CreateInput(DamProjectData damProjectData) { // First of all, check that there is a dike ThrowHelper.ThrowIfArgumentNull(damProjectData.WaterBoard, nameof(damProjectData.WaterBoard), StringResourceNames.NoDikeDefined); Dike dike = damProjectData.WaterBoard.Dikes[0]; // Process locations string soilProfileDirectory = Path.Combine(damProjectData.ProjectPath, dike.MapForSoilGeometries2D); var soilProfiles2DToSerialize = new List(); List filteredJobs = FilterLocationJobsWithSoilProfiles(damProjectData.SelectedLocationJobs, soilProfileDirectory, dike.SoilList, dike.Aquifers, soilProfiles2DToSerialize).ToList(); List filteredLocations = filteredJobs.Select(loc => loc.Location).ToList(); ValidateDamProjectData(damProjectData, filteredLocations); var input = new Input { ProjectPath = damProjectData.ProjectPath, CalculationMap = damProjectData.CalculationMap, MaxCalculationCoresSpecified = true, MaxCalculationCores = damProjectData.MaxCalculationCores }; TransferAnalysisSpecification(damProjectData, input); TransferStabilityParameters(damProjectData, input); input.Locations = new DamEngine.Io.XmlInput.Location[filteredJobs.Count]; TransferLocations(filteredLocations, input.Locations); // Process segments IList usedSegments = DetermineUsedSegments(filteredLocations); if (usedSegments != null) { input.Segments = new DamEngine.Io.XmlInput.Segment[usedSegments.Count]; TransferSegments(usedSegments, input.Segments); } // Process surface lines List usedSurfaceLines = DetermineUsedSurfaceLines(filteredLocations); input.SurfaceLines = new SurfaceLine[usedSurfaceLines.Count]; TransferSurfaceLines(usedSurfaceLines, input.SurfaceLines); // Process soil profiles 1D List usedSoilProfiles1D = null; if (dike.SoilProfiles != null && dike.SoilProfiles.Count > 0) { usedSoilProfiles1D = DetermineUsedSoilProfiles1D(usedSegments); input.SoilProfiles1D = new DamEngine.Io.XmlInput.SoilProfile1D[usedSoilProfiles1D.Count]; TransferSoilProfiles1D(usedSoilProfiles1D, input.SoilProfiles1D); } input.SoilProfiles2D = soilProfiles2DToSerialize.ToArray(); // Process soils List usedSoils = DetermineUsedSoils(dike.SoilList.Soils, usedSoilProfiles1D, soilProfiles2DToSerialize, filteredLocations); input.Soils = new DamEngine.Io.XmlInput.Soil[dike.SoilList.Soils.Count]; TransferSoils(usedSoils, input.Soils); TransferTrafficLoadDegreeOfConsolidation(dike.TrafficLoadDegreeOfConsolidations, usedSoils, input); if (damProjectData.InputTimeSerieCollection != null) { input.OperationalInputTimeSeries = new DamEngine.Io.XmlInput.TimeSerie[damProjectData.InputTimeSerieCollection.Series.Count]; TransferInputTimeSeries(damProjectData.InputTimeSerieCollection, input.OperationalInputTimeSeries); } if (damProjectData.SensorData != null) { input.SensorData = new InputSensorData(); TransferSensorData(damProjectData.SensorData, input.SensorData); } return input; } private static IList DetermineUsedSegments(List localLocations) { var usedSegments = new List(); foreach (Location location in localLocations) { if (!usedSegments.Any(sl => sl.Name.Equals(location.Segment.Name))) { usedSegments.Add(location.Segment); } } return usedSegments; } private static List DetermineUsedSurfaceLines(IList locations) { var usedSurfaceLines = new List(); foreach (Location location in locations) { SurfaceLine2 crtSurfaceLine = location.LocalXZSurfaceLine2; if (!usedSurfaceLines.Any(sl => sl.Name.Equals(crtSurfaceLine.Name))) { usedSurfaceLines.Add(crtSurfaceLine); } } return usedSurfaceLines; } private static List DetermineUsedSoilProfiles1D(IList segments) { var usedSoilProfiles1D = new List(); foreach (Segment segment in segments) { foreach (SoilGeometryProbability soilProfileProbability in segment.SoilProfileProbabilities.Where(spp => spp.SoilProfileType == SoilProfileType.SoilProfile1D)) { if (!usedSoilProfiles1D.Any(usp => usp.Name.Equals(soilProfileProbability.SoilProfile.Name))) { usedSoilProfiles1D.Add(soilProfileProbability.SoilProfile); } } } return usedSoilProfiles1D; } private static List DetermineUsedSoils(List allSoils, List soilProfile1Ds, List soilProfile2Ds, List locations) { List usedSoils = DetermineUsedSoilsFromSoilProfiles1D(soilProfile1Ds); DetermineUsedSoilsFromSoilProfiles2D(allSoils, soilProfile2Ds, usedSoils); DetermineUsedSoilsFromLocations(allSoils, locations, usedSoils); return usedSoils; } private static void DetermineUsedSoilsFromLocations(List allSoils, List locations, List usedSoils) { foreach (Location location in locations) { // Add the soil materials used as dike embankment material in Locations if (!usedSoils.Any(usedSoil => string.Equals(usedSoil.Name, location.DikeEmbankmentMaterial, StringComparison.OrdinalIgnoreCase))) { usedSoils.Add(allSoils.First(soil => string.Equals(soil.Name, location.DikeEmbankmentMaterial, StringComparison.OrdinalIgnoreCase))); } // Add the soil materials used as shoulder embankment material in Locations if (location.ShoulderEmbankmentMaterial != "" && !usedSoils.Any(usedSoil => string.Equals(usedSoil.Name, location.ShoulderEmbankmentMaterial, StringComparison.OrdinalIgnoreCase))) { usedSoils.Add(allSoils.First(soil => string.Equals(soil.Name, location.ShoulderEmbankmentMaterial, StringComparison.OrdinalIgnoreCase))); } } } private static void DetermineUsedSoilsFromSoilProfiles2D(List allSoils, List soilProfile2Ds, List usedSoils) { if (soilProfile2Ds != null && soilProfile2Ds.Count > 0) { foreach (SoilProfile2D soilProfile2D in soilProfile2Ds) { foreach (SoilProfile2DLayer2D layer2D in soilProfile2D.Layers2D) { if (!usedSoils.Any(usedSoil => string.Equals(usedSoil.Name, layer2D.SoilName, StringComparison.OrdinalIgnoreCase))) { usedSoils.Add(allSoils.First(soil => string.Equals(soil.Name, layer2D.SoilName, StringComparison.OrdinalIgnoreCase))); } } } } } private static List DetermineUsedSoilsFromSoilProfiles1D(List soilProfile1Ds) { var usedSoils = new List(); if (soilProfile1Ds != null) { foreach (SoilProfile1D soilProfile1D in soilProfile1Ds) { foreach (Soil soil in soilProfile1D.Soils) { if (!usedSoils.Any(usp => string.Equals(usp.Name, soil.Name, StringComparison.OrdinalIgnoreCase))) { usedSoils.Add(soil); } } } } return usedSoils; } private static void TransferSensorData(SensorData sensorData, InputSensorData inputSensorData) { // Transfer sensor groups var sensorGroupIndex = 0; inputSensorData.SensorGroups = new SensorGroup[sensorData.SensorGroups.Count]; foreach (Group sensorGroup in sensorData.SensorGroups) { var inputSensorGroup = new SensorGroup(); inputSensorGroup.SensorIds = new SensorGroupSensorIds[sensorGroup.SensorCount]; inputSensorGroup.Id = sensorGroup.ID; var sensorIdIndex = 0; foreach (Sensor sensor in sensorGroup.SensorArray) { inputSensorGroup.SensorIds[sensorIdIndex] = new SensorGroupSensorIds { SensorId = sensor.ID }; sensorIdIndex++; } inputSensorData.SensorGroups[sensorGroupIndex] = inputSensorGroup; sensorGroupIndex++; } // Transfer sensor locations var senserLocationIndex = 0; inputSensorData.SensorLocations = new SensorLocation[sensorData.SensorLocations.Count]; foreach (Sensors.SensorLocation sensorLocation in sensorData.SensorLocations) { var inputSensorLocation = new SensorLocation(); inputSensorLocation.GroupId = sensorLocation.GroupID; inputSensorLocation.LocationId = sensorLocation.LocationName; inputSensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder); inputSensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder); inputSensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver); inputSensorLocation.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl1PlLineOffsetBelowShoulderBaseInside); inputSensorLocation.SourceTypePl1WaterLevelAtRiver = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl1WaterLevelAtRiver); inputSensorLocation.SourceTypePl1WaterLevelAtPolder = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl1WaterLevelAtPolder); inputSensorLocation.SourceTypePl3 = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl3); inputSensorLocation.SourceTypePl4 = ConversionHelper.ConvertToInputDataSourceTypeSensors(sensorLocation.SourceTypePl4); inputSensorData.SensorLocations[senserLocationIndex] = inputSensorLocation; senserLocationIndex++; } // Transfer sensors inputSensorData.Sensors = new DamEngine.Io.XmlInput.Sensor[sensorData.Sensors.Count]; var sensorIndex = 0; foreach (Sensor sensor in sensorData.Sensors) { var inputSensor = new DamEngine.Io.XmlInput.Sensor(); inputSensor.Id = sensor.ID; inputSensor.Name = sensor.Name; inputSensor.RelativeLocation = sensor.RelativeLocation; inputSensor.SensorType = ConversionHelper.ConvertToInputSensorType(sensor.Type); inputSensor.PlLineMapping = new SensorPlLineMapping[sensor.PLLineMappings.Length]; var mappingIndex = 0; foreach (PLLineType plLineMapping in sensor.PLLineMappings) { inputSensor.PlLineMapping[mappingIndex] = new SensorPlLineMapping { PLineType = ConversionHelper.ConvertToInputPlLineType(plLineMapping) }; mappingIndex++; } inputSensorData.Sensors[sensorIndex] = inputSensor; sensorIndex++; } } private static void TransferInputTimeSeries(TimeSerieCollection inputTimeSerieCollection, DamEngine.Io.XmlInput.TimeSerie[] operationalInputTimeSeries) { var timeSerieIndex = 0; foreach (TimeSerie timeSerie in inputTimeSerieCollection.Series) { var inputTimeSerie = new DamEngine.Io.XmlInput.TimeSerie(); inputTimeSerie.Entries = new TimeSerieEntries(); inputTimeSerie.Entries.TimeSerieEntry = new TimeSerieEntriesTimeSerieEntry[timeSerie.Entries.Count]; inputTimeSerie.LocationId = timeSerie.LocationId; inputTimeSerie.ParameterId = timeSerie.ParameterId; inputTimeSerie.ForecastDateTime = timeSerie.ForecastDateTime; inputTimeSerie.StartDateTime = timeSerie.StartDateTime; inputTimeSerie.EndDateTime = timeSerie.EndDateTime; inputTimeSerie.MissVal = timeSerie.MissVal; inputTimeSerie.Units = timeSerie.Units; var timeSerieEntryIndex = 0; foreach (TimeSerieEntry timestepEntry in timeSerie.Entries) { var timeStep = new TimeSerieEntriesTimeSerieEntry { DateTime = timestepEntry.DateTime, Value = timestepEntry.Value }; inputTimeSerie.Entries.TimeSerieEntry[timeSerieEntryIndex] = timeStep; timeSerieEntryIndex++; } operationalInputTimeSeries[timeSerieIndex] = inputTimeSerie; timeSerieIndex++; } } private static void TransferAnalysisSpecification(DamProjectData damProjectData, Input input) { input.DamProjectType = ConversionHelper.ConvertToInputDamProjectType(damProjectData.DamProjectType); if (damProjectData.DamProjectCalculationSpecification.CurrentSpecification != null) { input.FailureMechanismSystemType = ConversionHelper.ConvertToInputFailureMechanismSystemType(damProjectData.DamProjectCalculationSpecification.CurrentSpecification.FailureMechanismSystemType); input.AnalysisTypeSpecified = (input.DamProjectType == InputDamProjectType.Design); if (input.AnalysisTypeSpecified) { input.AnalysisType = ConversionHelper.ConvertToInputAnalysisType(DamProjectCalculationSpecification.SelectedAnalysisType); } input.PipingModelTypeSpecified = input.FailureMechanismSystemType == InputFailureMechanismSystemType.Piping; if (input.PipingModelTypeSpecified) { input.PipingModelType = ConversionHelper.ConvertToInputPipingModelType(damProjectData.DamProjectCalculationSpecification.CurrentSpecification.PipingModelType); } input.StabilityModelTypeSpecified = input.FailureMechanismSystemType == InputFailureMechanismSystemType.StabilityInside || input.FailureMechanismSystemType == InputFailureMechanismSystemType.StabilityOutside; if (input.StabilityModelTypeSpecified) { input.StabilityModelType = ConversionHelper.ConvertToInputStabilityModelType(damProjectData.DamProjectCalculationSpecification.CurrentSpecification.StabilityModelType); } } } private static void TransferStabilityParameters(DamProjectData damProjectData, Input input) { if (damProjectData.DamProjectCalculationSpecification != null && damProjectData.DamProjectCalculationSpecification.CurrentSpecification != null) { DamFailureMechanismeCalculationSpecification curSpec = damProjectData.DamProjectCalculationSpecification.CurrentSpecification; if (curSpec.FailureMechanismeParamatersMStab != null && curSpec.FailureMechanismeParamatersMStab.MStabParameters != null) { input.StabilityParameters = new StabilityParameters(); input.StabilityParameters.SearchMethod = ConversionHelper.ConvertToInputSearchMethod(curSpec.FailureMechanismeParamatersMStab.MStabParameters.SearchMethod); SlipCircleDefinition slipCircleDefinition = curSpec.FailureMechanismeParamatersMStab.MStabParameters.SlipCircleDefinition; if (slipCircleDefinition != null) { input.StabilityParameters.UpliftVanGridDetermination = ConversionHelper.ConvertToInputUpliftVanGridDetermination(slipCircleDefinition.UpliftVanGridSizeDetermination); input.StabilityParameters.BishopSearchAreaDetermination = ConversionHelper.ConvertToInputBishopSearchAreaDetermination(slipCircleDefinition.BishopSearchAreaDetermination); input.StabilityParameters.BishopTangentLinesDistanceSpecified = true; input.StabilityParameters.BishopTangentLinesDistance = slipCircleDefinition.BishopTangentLinesDistance; input.StabilityParameters.BishopGridVerticalPointsCountSpecified = true; input.StabilityParameters.BishopGridVerticalPointsCount = slipCircleDefinition.BishopGridVerticalPointCount; input.StabilityParameters.BishopGridVerticalPointsDistanceSpecified = true; input.StabilityParameters.BishopGridVerticalPointsDistance = slipCircleDefinition.BishopGridVerticalPointDistance; input.StabilityParameters.BishopGridHorizontalPointsCountSpecified = true; input.StabilityParameters.BishopGridHorizontalPointsCount = slipCircleDefinition.BishopGridHorizontalPointCount; input.StabilityParameters.BishopGridHorizontalPointsDistanceSpecified = true; input.StabilityParameters.BishopGridHorizontalPointsDistance = slipCircleDefinition.BishopGridHorizontalPointDistance; input.StabilityParameters.UpliftVanTangentLinesDefinitionSpecified = true; input.StabilityParameters.UpliftVanTangentLinesDefinition = ConversionHelper.ConvertToInputTangentLinesDefinition(slipCircleDefinition.UpliftVanTangentLinesDefinition); input.StabilityParameters.UpliftVanTangentLinesDistanceSpecified = true; input.StabilityParameters.UpliftVanTangentLinesDistance = slipCircleDefinition.UpliftVanTangentLinesDistance; input.StabilityParameters.UpliftVanGridLeftVerticalPointsCountSpecified = true; input.StabilityParameters.UpliftVanGridLeftVerticalPointsCount = slipCircleDefinition.UpliftVanLeftGridVerticalPointCount; input.StabilityParameters.UpliftVanGridLeftVerticalPointsDistanceSpecified = true; input.StabilityParameters.UpliftVanGridLeftVerticalPointsDistance = slipCircleDefinition.UpliftVanLeftGridVerticalPointDistance; input.StabilityParameters.UpliftVanGridLeftHorizontalPointsCountSpecified = true; input.StabilityParameters.UpliftVanGridLeftHorizontalPointsCount = slipCircleDefinition.UpliftVanLeftGridHorizontalPointCount; input.StabilityParameters.UpliftVanGridLeftHorizontalPointsDistanceSpecified = true; input.StabilityParameters.UpliftVanGridLeftHorizontalPointsDistance = slipCircleDefinition.UpliftVanLeftGridHorizontalPointDistance; input.StabilityParameters.UpliftVanGridRightVerticalPointsCountSpecified = true; input.StabilityParameters.UpliftVanGridRightVerticalPointsCount = slipCircleDefinition.UpliftVanRightGridVerticalPointCount; input.StabilityParameters.UpliftVanGridRightVerticalPointsDistanceSpecified = true; input.StabilityParameters.UpliftVanGridRightVerticalPointsDistance = slipCircleDefinition.UpliftVanRightGridVerticalPointDistance; input.StabilityParameters.UpliftVanGridRightHorizontalPointsCountSpecified = true; input.StabilityParameters.UpliftVanGridRightHorizontalPointsCount = slipCircleDefinition.UpliftVanRightGridHorizontalPointCount; input.StabilityParameters.UpliftVanGridRightHorizontalPointsDistanceSpecified = true; input.StabilityParameters.UpliftVanGridRightHorizontalPointsDistance = slipCircleDefinition.UpliftVanRightGridHorizontalPointDistance; } } } } private static void ValidateDamProjectData(DamProjectData damProjectData, List selectedLocations) { if (damProjectData.WaterBoard.Dikes == null || damProjectData.WaterBoard.Dikes.Count != 1) { throw new ArgumentException(Resources.DikeShouldContainExactly1Dike); } Dike dike = damProjectData.WaterBoard.Dikes[0]; ThrowHelper.ThrowIfArgumentNull(dike.Locations, nameof(dike.Locations), StringResourceNames.NoLocationsDefined); // Following situation should never occur in the UI. Tested because of the check on RiverLevelLow in the code below DamFailureMechanismeCalculationSpecification currentSpecification = damProjectData.DamProjectCalculationSpecification.CurrentSpecification; ThrowHelper.ThrowIfArgumentNull(currentSpecification, nameof(currentSpecification), StringResourceNames.NoCalculationTypeSpecified); foreach (Location location in selectedLocations) { ThrowHelper.ThrowIfArgumentNull(location.Scenarios, nameof(location.Scenarios), StringResourceNames.NoScenariosDefinedInLocation); foreach (Scenario scenario in location.Scenarios) { string errorMessage = string.Format(Resources.NoRiverLevel, location.Name, scenario.LocationScenarioID); ThrowHelper.ThrowIfArgumentNull(scenario.RiverLevel, nameof(scenario.RiverLevel), errorMessage); // In code above is tested that CurrentSpecification exists if (currentSpecification.FailureMechanismSystemType == FailureMechanismSystemType.StabilityOutside) { errorMessage = string.Format(Resources.NoRiverLevelLow, location.Name, scenario.LocationScenarioID); ThrowHelper.ThrowIfArgumentNull(scenario.RiverLevelLow, nameof(scenario.RiverLevelLow), errorMessage); } } } ThrowHelper.ThrowIfArgumentNull(dike.SurfaceLines2, nameof(dike.SurfaceLines2), StringResourceNames.NoSurfaceLines); foreach (SurfaceLine2 surfaceLine in dike.SurfaceLines2) { if ((surfaceLine.CharacteristicPoints == null) || (surfaceLine.CharacteristicPoints.Count < 1)) { throw new ArgumentException(string.Format(Resources.SurfaceLineHasNoCharacteristicPoints, surfaceLine.Name)); } if ((surfaceLine.Geometry == null) || (surfaceLine.Geometry.Count < 2)) { throw new ArgumentException(string.Format(Resources.SurfaceLineHasNoPoints, surfaceLine.Name)); } } ThrowHelper.ThrowIfArgumentNull(dike.SoilList, nameof(dike.SoilList), StringResourceNames.NoSoilsDefinedInProject); ThrowHelper.ThrowIfArgumentNull(dike.SoilList.Soils, nameof(dike.SoilList.Soils), StringResourceNames.NoSoilsDefinedInProject); ThrowHelper.ThrowIfArgumentNull(dike.SoilProfiles, nameof(dike.SoilProfiles), StringResourceNames.NoSoilprofiles1DDefinedInProject); // Check for invalid Id names foreach (Location location in selectedLocations) { if (!IdValidator.IsCorrectName(location.Name)) { throw new IdValidatorException(string.Format(Resources.LocationInvalidName, location.Name)); } } foreach (Segment segment in damProjectData.WaterBoard.Segments) { if (!IdValidator.IsCorrectName(segment.Name)) { throw new IdValidatorException(string.Format(Resources.SegmentInvalidName, segment.Name)); } } foreach (SurfaceLine2 surfaceLine2 in dike.SurfaceLines2) { if (!IdValidator.IsCorrectName(surfaceLine2.Name)) { throw new IdValidatorException(string.Format(Resources.SurfaceLineInvalidName, surfaceLine2.Name)); } } foreach (SoilProfile1D soilProfile in dike.SoilProfiles) { if (!IdValidator.IsCorrectName(soilProfile.Name)) { throw new IdValidatorException(string.Format(Resources.SoilProfileInvalidName, soilProfile.Name)); } } foreach (Soil soil in dike.SoilList.Soils) { if (!IdValidator.IsCorrectName(soil.Name)) { throw new IdValidatorException(string.Format(Resources.SoilInvalidName, soil.Name)); } } } private static void TransferSoils(List soils, DamEngine.Io.XmlInput.Soil[] inputSoils) { for (var i = 0; i < soils.Count; i++) { Soil soil = soils[i]; var inputSoil = new DamEngine.Io.XmlInput.Soil(); inputSoil.Name = soil.Name; inputSoil.AbovePhreaticLevelSpecified = !Double.IsNaN(soil.AbovePhreaticLevel); inputSoil.AbovePhreaticLevel = soil.AbovePhreaticLevel; inputSoil.BelowPhreaticLevelSpecified = !Double.IsNaN(soil.BelowPhreaticLevel); inputSoil.BelowPhreaticLevel = soil.BelowPhreaticLevel; inputSoil.DiameterD70Specified = !Double.IsNaN(soil.DiameterD70); inputSoil.DiameterD70 = soil.DiameterD70; inputSoil.PermeabKxSpecified = !Double.IsNaN(soil.PermeabKx); inputSoil.PermeabKx = soil.PermeabKx; inputSoil.ShearStrengthModelSpecified = true; inputSoil.ShearStrengthModel = ConversionHelper.ConvertToSoilShearStrengthModel(soil.ShearStrengthModel); if (soil.ShearStrengthModel == ShearStrengthModel.StressTable) { inputSoil.SigmaTauCurve = new SigmaTauCurveSigmaTauPoint[soil.StressTable.SigmaTaus.Count]; for (var j = 0; j < soil.StressTable.SigmaTaus.Count; j++) { inputSoil.SigmaTauCurve[j] = new SigmaTauCurveSigmaTauPoint { Sigma = soil.StressTable.SigmaTaus[j].Sigma, Tau = soil.StressTable.SigmaTaus[j].Tau }; } } if (soil.ShearStrengthModel == ShearStrengthModel.SuTable) { inputSoil.SuTable = new SuTableSigmaSuPoint[soil.SuTable.SigmaSus.Count]; for (var j = 0; j < soil.SuTable.SigmaSus.Count; j++) { inputSoil.SuTable[j] = new SuTableSigmaSuPoint { Sigma = soil.SuTable.SigmaSus[j].Sigma, Su = soil.SuTable.SigmaSus[j].Su }; } } inputSoil.CohesionSpecified = !Double.IsNaN(soil.Cohesion); inputSoil.Cohesion = soil.Cohesion; inputSoil.FrictionAngleSpecified = !Double.IsNaN(soil.FrictionAngle); inputSoil.FrictionAngle = soil.FrictionAngle; inputSoil.OcrSpecified = !Double.IsNaN(soil.OCR); inputSoil.Ocr = soil.OCR; inputSoil.StrengthIncreaseExponentSpecified = !Double.IsNaN(soil.StrengthIncreaseExponent); inputSoil.StrengthIncreaseExponent = soil.StrengthIncreaseExponent; inputSoil.RatioCuPcSpecified = !Double.IsNaN(soil.RatioCuPc); inputSoil.RatioCuPc = soil.RatioCuPc; inputSoil.PopSpecified = !Double.IsNaN(soil.POP); inputSoil.Pop = soil.POP; inputSoils[i] = inputSoil; } } private static void TransferSurfaceLines(IList dikeSurfaceLines, SurfaceLine[] inputSurfaceLines) { for (var i = 0; i < dikeSurfaceLines.Count; i++) { SurfaceLine2 surfaceLine = dikeSurfaceLines[i]; var inputSurfaceLine = new SurfaceLine(); inputSurfaceLine.Name = surfaceLine.Name; inputSurfaceLine.Points = new SurfaceLinePoint[surfaceLine.CharacteristicPoints.Count]; for (var j = 0; j < surfaceLine.CharacteristicPoints.Count; j++) { CharacteristicPoint characteristicPoint = surfaceLine.CharacteristicPoints[j]; var inputPoint = new SurfaceLinePoint { PointType = ConversionHelper.ConvertToInputPointType(characteristicPoint.CharacteristicPointType), X = characteristicPoint.X, Z = characteristicPoint.Z }; inputSurfaceLine.Points[j] = inputPoint; } inputSurfaceLines[i] = inputSurfaceLine; } } private static void TransferLocations(IList dikeLocations, DamEngine.Io.XmlInput.Location[] inputLocations) { for (var i = 0; i < dikeLocations.Count; i++) { Location location = dikeLocations[i]; var inputLocation = new DamEngine.Io.XmlInput.Location(); inputLocation.Name = location.Name; inputLocation.DistanceToEntryPoint = location.DistanceToEntryPoint; inputLocation.DistanceToEntryPointSpecified = true; inputLocation.SurfaceLineName = location.LocalXZSurfaceLine2.Name; inputLocation.SegmentName = location.Segment.Name; var waternetOptions = new LocationWaternetOptions(); waternetOptions.PhreaticLineCreationMethod = ConversionHelper.ConvertToInputPhreaticLineCreationMethod(location.PLLineCreationMethod); waternetOptions.IntrusionVerticalWaterPressure = ConversionHelper.ConvertToInputIntrusionVerticalWaterPressure(location.IntrusionVerticalWaterPressure ?? IntrusionVerticalWaterPressureType.Standard); waternetOptions.DampingFactorPl3 = location.DampingFactorPL3; waternetOptions.DampingFactorPl4 = location.DampingFactorPL4; waternetOptions.PenetrationLength = location.PenetrationLength; waternetOptions.SlopeDampingFactor = location.SlopeDampingPiezometricHeightPolderSide; inputLocation.WaternetOptions = waternetOptions; inputLocation.DesignScenarios = new LocationDesignScenario[location.Scenarios.Count]; for (var j = 0; j < location.Scenarios.Count; j++) { Scenario designScenario = location.Scenarios[j]; var inputDesignScenario = new LocationDesignScenario(); inputDesignScenario.RiverLevel = designScenario.RiverLevel.Value; inputDesignScenario.Id = designScenario.LocationScenarioID; inputDesignScenario.RiverLevelLowSpecified = designScenario.RiverLevelLow.HasValue; inputDesignScenario.RiverLevelLow = designScenario.RiverLevelLow ?? 0.0; inputDesignScenario.DikeTableHeightSpecified = designScenario.DikeTableHeight.HasValue; inputDesignScenario.DikeTableHeight = designScenario.DikeTableHeight ?? 0.0; inputDesignScenario.PlLineOffsetBelowDikeTopAtRiver = designScenario.PlLineOffsetBelowDikeTopAtRiver; inputDesignScenario.PlLineOffsetBelowDikeTopAtPolder = designScenario.PlLineOffsetBelowDikeTopAtPolder; inputDesignScenario.PlLineOffsetBelowShoulderBaseInside = designScenario.PlLineOffsetBelowShoulderBaseInside; inputDesignScenario.PlLineOffsetBelowDikeToeAtPolder = designScenario.PlLineOffsetBelowDikeToeAtPolder; inputDesignScenario.PlLineOffsetBelowDikeCrestMiddleSpecified = designScenario.UsePlLineOffsetBelowDikeCrestMiddle ?? false; inputDesignScenario.PlLineOffsetBelowDikeCrestMiddle = designScenario.PlLineOffsetBelowDikeCrestMiddle ?? 0.0; inputDesignScenario.PlLineOffsetFactorBelowShoulderCrestSpecified = designScenario.UsePlLineOffsetFactorBelowShoulderCrest ?? false; inputDesignScenario.PlLineOffsetFactorBelowShoulderCrest = designScenario.PlLineOffsetFactorBelowShoulderCrest ?? 0.0; inputDesignScenario.HeadPl3Specified = designScenario.HeadPl3.HasValue; inputDesignScenario.HeadPl3 = designScenario.HeadPl3 ?? 0.0; inputDesignScenario.HeadPl4Specified = designScenario.HeadPl4.HasValue; inputDesignScenario.HeadPl4 = designScenario.HeadPl4 ?? 0.0; inputDesignScenario.UpliftCriterionStability = designScenario.UpliftCriterionStability; inputDesignScenario.UpliftCriterionPiping = designScenario.UpliftCriterionPiping; inputDesignScenario.RequiredSafetyFactorStabilityInnerSlope = designScenario.RequiredSafetyFactorStabilityInnerSlope; inputDesignScenario.RequiredSafetyFactorStabilityOuterSlope = designScenario.RequiredSafetyFactorStabilityOuterSlope; inputDesignScenario.RequiredSafetyFactorPiping = designScenario.RequiredSafetyFactorPiping; inputDesignScenario.PolderLevel = designScenario.PolderLevel; inputDesignScenario.HeadPl2Specified = designScenario.HeadPl2.HasValue; inputDesignScenario.HeadPl2 = designScenario.HeadPl2 ?? 0.0; inputLocation.DesignScenarios[j] = inputDesignScenario; } inputLocation.DikeEmbankmentMaterial = location.DikeEmbankmentMaterial; inputLocation.StabilityOptions = new LocationStabilityOptions { ZoneType = ConversionHelper.ConvertToInputZoneType(location.StabilityZoneType), ForbiddenZoneFactorSpecified = true, ForbiddenZoneFactor = location.ForbiddenZoneFactor, TrafficLoadSpecified = true, TrafficLoad = location.TrafficLoad, TrafficLoadDegreeOfConsolidationSpecified = location.TL_DegreeOfConsolidation.HasValue, TrafficLoadDegreeOfConsolidation = location.TL_DegreeOfConsolidation ?? 0.0, MinimumCircleDepthSpecified = true, MinimumCircleDepth = location.MinimalCircleDepth }; // Design options var designOptions = new LocationDesignOptions(); designOptions.RedesignDikeHeight = location.RedesignDikeHeight; designOptions.RedesignDikeShoulder = location.RedesignDikeShoulder; designOptions.ShoulderEmbankmentMaterial = location.ShoulderEmbankmentMaterial; designOptions.StabilityShoulderGrowSlope = location.StabilityShoulderGrowSlope; designOptions.StabilityShoulderGrowDeltaX = location.StabilityShoulderGrowDeltaX; designOptions.StabilitySlopeAdaptionDeltaX = location.StabilitySlopeAdaptionDeltaX; designOptions.SlopeAdaptionStartCotangent = location.SlopeAdaptionStartCotangent; designOptions.SlopeAdaptionEndCotangent = location.SlopeAdaptionEndCotangent; designOptions.SlopeAdaptionStepCotangent = location.SlopeAdaptionStepCotangent; designOptions.NewDikeTopWidthSpecified = location.UseNewDikeTopWidth; designOptions.NewDikeTopWidth = location.NewDikeTopWidth; designOptions.NewDikeSlopeInsideSpecified = location.UseNewDikeSlopeInside; designOptions.NewDikeSlopeInside = location.NewDikeSlopeInside; designOptions.NewDikeSlopeOutsideSpecified = location.UseNewDikeSlopeOutside; designOptions.NewDikeSlopeOutside = location.NewDikeSlopeOutside; designOptions.NewShoulderTopSlopeSpecified = location.UseNewShoulderTopSlope; designOptions.NewShoulderTopSlope = location.NewShoulderTopSlope; designOptions.NewShoulderBaseSlopeSpecified = location.UseNewShoulderBaseSlope; designOptions.NewShoulderBaseSlope = location.NewShoulderBaseSlope; designOptions.NewMaxHeightShoulderAsFractionSpecified = location.UseNewMaxHeightShoulderAsFraction; designOptions.NewMaxHeightShoulderAsFraction = location.NewMaxHeightShoulderAsFraction; designOptions.NewMinDistanceDikeToeStartDitchSpecified = location.UseNewMinDistanceDikeToeStartDitch; designOptions.NewMinDistanceDikeToeStartDitch = location.NewMinDistanceDikeToeStartDitch; designOptions.UseNewDitchDefinition = location.UseNewDitchDefinition; designOptions.NewWidthDitchBottomSpecified = location.UseNewDitchDefinition; designOptions.NewWidthDitchBottom = location.NewWidthDitchBottom; designOptions.NewSlopeAngleDitchSpecified = location.UseNewDitchDefinition; designOptions.NewSlopeAngleDitch = location.NewSlopeAngleDitch; designOptions.NewDepthDitchSpecified = location.UseNewDitchDefinition; designOptions.NewDepthDitch = location.NewDepthDitch; designOptions.StabilityDesignMethod = ConversionHelper.ConvertToInputStabilityDesignMethod(location.StabilityDesignMethod); inputLocation.DesignOptions = designOptions; inputLocations[i] = inputLocation; } } private static void TransferSoilProfiles1D(IList dikeSoilProfiles, DamEngine.Io.XmlInput.SoilProfile1D[] inputSoilProfiles1D) { int profilesCount = dikeSoilProfiles.Count; for (var i = 0; i < profilesCount; i++) { SoilProfile1D soilProfile1D = dikeSoilProfiles[i]; var inputSoilProfile1D = new DamEngine.Io.XmlInput.SoilProfile1D { Name = soilProfile1D.Name, BottomLevel = soilProfile1D.BottomLevel, Layers1D = new SoilProfile1DLayer1D[soilProfile1D.LayerCount] }; AddLayers1D(soilProfile1D, inputSoilProfile1D); inputSoilProfiles1D[i] = inputSoilProfile1D; } } private static void AddLayers1D(SoilProfile1D soilProfile1D, DamEngine.Io.XmlInput.SoilProfile1D inputSoilProfile1D) { for (var i = 0; i < soilProfile1D.LayerCount; i++) { SoilLayer1D layer = soilProfile1D.Layers[i]; var inputLayer = new SoilProfile1DLayer1D { Name = "L" + i, SoilName = layer.Soil.Name, TopLevel = layer.TopLevel, IsAquifer = layer.IsAquifer, WaterpressureInterpolationModel = ConversionHelper.ConvertToInputWaterpressureInterpolationModel( layer.WaterpressureInterpolationModel) }; inputSoilProfile1D.Layers1D[i] = inputLayer; } } private static void TransferSegments(IList segments, DamEngine.Io.XmlInput.Segment[] inputSegments) { for (var i = 0; i < segments.Count; i++) { Segment segment = segments[i]; var inputSegment = new DamEngine.Io.XmlInput.Segment { Name = segment.Name }; AddSoilProfileProbabilities(segment, inputSegment); inputSegments[i] = inputSegment; } } private static void TransferTrafficLoadDegreeOfConsolidation(IList trafficLoadDegreeOfConsolidations, List usedSoils, Input input) { InputTrafficLoadDegreeOfConsolidation[] inputTrafficLoadDegreeOfConsolidations; if (trafficLoadDegreeOfConsolidations != null && trafficLoadDegreeOfConsolidations.Count > 0) { inputTrafficLoadDegreeOfConsolidations = new InputTrafficLoadDegreeOfConsolidation[usedSoils.Count]; var index = 0; foreach (TrafficLoadDegreeOfConsolidation trafficLoadDegreeOfConsolidation in trafficLoadDegreeOfConsolidations) { if (usedSoils.Any(soil => string.Equals(soil.Name, trafficLoadDegreeOfConsolidation.SoilName, StringComparison.OrdinalIgnoreCase))) { inputTrafficLoadDegreeOfConsolidations[index] = new InputTrafficLoadDegreeOfConsolidation() { SoilName = trafficLoadDegreeOfConsolidation.SoilName, DegreeOfConsolidation = trafficLoadDegreeOfConsolidation.DegreeOfConsolidation }; index += 1; } } } else { inputTrafficLoadDegreeOfConsolidations = null; } input.TrafficLoadDegreeOfConsolidations = inputTrafficLoadDegreeOfConsolidations; } private static void AddSoilProfileProbabilities(Segment segment, DamEngine.Io.XmlInput.Segment inputSegment) { if (segment.SoilProfileProbabilities != null) { int probabilityCount = segment.SoilProfileProbabilities.Count; inputSegment.SoilGeometryProbability = new SegmentSoilGeometryProbability[probabilityCount]; for (var i = 0; i < probabilityCount; i++) { SoilGeometryProbability soilGeometryProbability = segment.SoilProfileProbabilities[i]; var inputSoilGeometryProbability = new SegmentSoilGeometryProbability(); inputSoilGeometryProbability.Probability = soilGeometryProbability.Probability; if (soilGeometryProbability.SegmentFailureMechanismType.HasValue) { inputSoilGeometryProbability.SegmentFailureMechanismType = ConversionHelper.ConvertToInputSegmentFailureMechanismType(soilGeometryProbability.SegmentFailureMechanismType.Value); inputSoilGeometryProbability.SegmentFailureMechanismTypeSpecified = true; } else { inputSoilGeometryProbability.SegmentFailureMechanismTypeSpecified = false; } switch (soilGeometryProbability.SoilProfileType) { case SoilProfileType.SoilProfile1D: case SoilProfileType.SoilProfile2D: inputSoilGeometryProbability.SoilProfileName = soilGeometryProbability.SoilGeometryName; break; default: inputSoilGeometryProbability.SoilProfileName = soilGeometryProbability.SoilGeometry2DName; break; } inputSoilGeometryProbability.SoilProfileType = ConversionHelper.ConvertToInputSoilProfileType(soilGeometryProbability.SoilProfileType); inputSegment.SoilGeometryProbability[i] = inputSoilGeometryProbability; } } } /// /// Filters the collection of on whether they have soil profiles to perform calculations with. /// /// The collection of to filter. /// The directory to retrieve the soil profiles from. /// The containing the available soils. /// The collection of that is imported from csv.> /// The collection of that is contained /// by the . /// A collection of on which calculations can be performed. private static IEnumerable FilterLocationJobsWithSoilProfiles(IEnumerable locationJobs, string soilProfileDirectory, SoilList availableSoils, IEnumerable aquifers, ICollection containedSoilProfiles) { var validJobs = new List(); var uniqueSoilProfileNames = new HashSet(); foreach (LocationJob locationJob in locationJobs) { Location location = locationJob.Location; try { foreach (SoilProfile2D soilProfile in GetSoilProfiles(soilProfileDirectory, location.Segment, availableSoils, aquifers, location.XSoilGeometry2DOrigin)) { string soilProfileName = soilProfile.Name; if (!uniqueSoilProfileNames.Contains(soilProfileName)) { uniqueSoilProfileNames.Add(soilProfileName); containedSoilProfiles.Add(soilProfile); } } validJobs.Add(locationJob); } catch (Exception e) when (e is ConversionException || e is SoilProfileImporterException) { LogInvalidLocationJobErrorMessages(location, e.Message); } } return validJobs; } private static void LogInvalidLocationJobErrorMessages(Location location, string errorMessage) { if (location.Scenarios.Any()) { foreach (Scenario scenario in location.Scenarios) { var message = $"Location '{location.Name}', design scenario '{scenario.LocationScenarioID}': The calculation failed with error message: '{errorMessage}'"; LogManager.Messages.Add(new LogMessage(LogMessageType.Error, null, message)); } } else { var message = $"Location '{location.Name}': The calculation failed with error message: '{errorMessage}'"; LogManager.Messages.Add(new LogMessage(LogMessageType.Error, null, message)); } } /// /// Gets the soil profiles based on the input arguments. /// /// The directory to retrieve the soil profiles from. /// The to retrieve the soil profiles for. /// The containing the available soils. /// The collection of that is imported from csv.> /// /// An array of . /// Thrown when the soil profiles could not be successfully imported. /// Thrown when the soil profiles could not be successfully converted. private static IEnumerable GetSoilProfiles(string soilProfileDirectory, Segment segment, SoilList soils, IEnumerable aquifers, double xSoilGeometry2DOrigin) { IEnumerable importedSoilProfiles = SoilProfile2DImporter.Import(soilProfileDirectory, segment, soils, aquifers, xSoilGeometry2DOrigin); if (importedSoilProfiles == null) { return Enumerable.Empty(); } return importedSoilProfiles.Select(XmlSoilProfile2DConverter.Convert).ToArray(); } }