// Copyright (C) Stichting Deltares 2025. 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.Linq;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard;
using Deltares.MacroStability.CSharpWrapper.Input;
using Deltares.MacroStability.CSharpWrapper.Water;
using HeadLine = Deltares.DamEngine.Data.Geometry.HeadLine;
using KernelWaternet = Deltares.MacroStability.CSharpWrapper.Water.Waternet;
using KernelHeadLine = Deltares.MacroStability.CSharpWrapper.Water.HeadLine;
using KernelWaternetLine = Deltares.MacroStability.CSharpWrapper.Water.WaternetLine;
using KernelUpliftVanCalculationGrid = Deltares.MacroStability.CSharpWrapper.UpliftVanCalculationGrid;
using Soil = Deltares.DamEngine.Data.Geotechnics.Soil;
using SoilProfile = Deltares.MacroStability.CSharpWrapper.Input.SoilProfile;
using Waternet = Deltares.DamEngine.Data.Geometry.Waternet;
using WaternetLine = Deltares.DamEngine.Data.Geometry.WaternetLine;
namespace Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon.MacroStabilityIo;
/// Fill DamEngine data objects from the kernel data model
public class FillEngineFromMacroStabilityWrapperInput
{
private readonly Dictionary soilDictionary = new Dictionary();
/// Gets or sets the SoilList DamEngine object
/// The soil list.
public SoilList SoilList { get; set; }
/// Gets or sets the TrafficLoadDegreeOfConsolidation DamEngine object.
/// The list of traffic load degree of consolidation.
public IList TrafficLoadDegreeOfConsolidations { get; set; }
/// Gets or sets the SoilProfile2D DamEngine object.
/// The soil profile2 d.
public SoilProfile2D SoilProfile2D { get; set; }
/// Gets or sets the SurfaceLine2 DamEngine object.
/// The surface line2.
public SurfaceLine2 SurfaceLine2 { get; set; }
/// Gets or sets the waternet.
/// The waternet.
public Waternet Waternet { get; set; }
/// Gets or sets the UpliftVan calculation grid.
/// The uplift van calculation grid.
public UpliftVanCalculationGrid UpliftVanCalculationGrid { get; set; }
///
/// Gets or sets the slip circle definition.
///
///
/// The slip circle definition.
///
public SlipCircleDefinition SlipCircleDefinition { get; private set; }
/// Gets or sets the traffic load.
/// The traffic load.
public TrafficLoad TrafficLoad { get; set; }
/// Gets or sets the failure mechanism parameters m stab.
/// The failure mechanism parameters for macrostability DamEngine object.
public FailureMechanismParametersMStab FailureMechanismParametersMStab { get; set; }
/// Creates the dam project data from the kernel model.
/// The kernel model.
/// The DamProjectData object filled with Wti data
public void FillDamProjectDataFromKernelModel(MacroStabilityInput macroStabilityInput)
{
soilDictionary.Clear();
TransferStabilityModel(macroStabilityInput.StabilityModel);
ConstructionStage lastStage = macroStabilityInput.StabilityModel.ConstructionStages.Last();
TransferSoils(macroStabilityInput.StabilityModel.Soils, lastStage.FixedSoilStresses);
TransferSoilProfile2D(lastStage.SoilProfile, lastStage.PreconsolidationStresses);
PreConstructionStage lastPreConStage = macroStabilityInput.PreprocessingInput.PreConstructionStages.Last();
TransferSurfaceLine(lastPreConStage.SurfaceLine);
TransferWaternet(macroStabilityInput.StabilityModel.ConstructionStages.Last().Waternet);
SearchAreaConditions preprocessingSearchAreaConditions = macroStabilityInput.PreprocessingInput.SearchAreaConditions;
TransferUpliftVanCalculationGridSettings(preprocessingSearchAreaConditions);
TransferUpliftVanCalculationGrid(macroStabilityInput.StabilityModel.UpliftVanCalculationGrid, preprocessingSearchAreaConditions);
TransferTrafficLoad(macroStabilityInput.StabilityModel.ConstructionStages.Last().UniformLoads);
TransferTrafficLoadDegreeOfConsolidation(macroStabilityInput.StabilityModel.ConstructionStages.Last().ConsolidationValues);
}
private void TransferTrafficLoad(ICollection kernelUniformLoads)
{
TrafficLoad = null;
if ((kernelUniformLoads != null) && (kernelUniformLoads.Count > 0))
{
if (kernelUniformLoads.Count > 1)
{
throw new ArgumentException($"Trafficload cannot be constructed because there are too many uniform loads defined ({kernelUniformLoads.Count}");
}
UniformLoad kernelUniformLoad = kernelUniformLoads.First();
TrafficLoad = new TrafficLoad
{
XStart = kernelUniformLoad.XStart,
XEnd = kernelUniformLoad.XEnd,
Pressure = kernelUniformLoad.Pressure
};
}
}
private void TransferTrafficLoadDegreeOfConsolidation(ICollection kernelConsolidationValues)
{
if (kernelConsolidationValues != null)
{
TrafficLoadDegreeOfConsolidations = new List();
foreach (Soil soil in SoilList.Soils.Where(soil => kernelConsolidationValues.Any(c => c.Consolidated.ToType().Soil.Name == soil.Name)))
{
TrafficLoadDegreeOfConsolidations.Add(new TrafficLoadDegreeOfConsolidation
{
SoilName = soil.Name,
DegreeOfConsolidation = kernelConsolidationValues.First(c => c.Consolidated.ToType().Soil.Name == soil.Name).Value
});
}
}
}
private void TransferUpliftVanCalculationGrid(KernelUpliftVanCalculationGrid kernelSlipPlaneUpliftVan,
SearchAreaConditions kernelSearchAreaConditions)
{
UpliftVanCalculationGrid = new UpliftVanCalculationGrid
{
LeftGridXCount = kernelSlipPlaneUpliftVan.LeftGrid.GridXNumber,
LeftGridXLeft = kernelSlipPlaneUpliftVan.LeftGrid.GridXLeft,
LeftGridXRight = kernelSlipPlaneUpliftVan.LeftGrid.GridXRight,
LeftGridZCount = kernelSlipPlaneUpliftVan.LeftGrid.GridZNumber,
LeftGridZTop = kernelSlipPlaneUpliftVan.LeftGrid.GridZTop,
LeftGridZBottom = kernelSlipPlaneUpliftVan.LeftGrid.GridZBottom,
RightGridXCount = kernelSlipPlaneUpliftVan.RightGrid.GridXNumber,
RightGridXLeft = kernelSlipPlaneUpliftVan.RightGrid.GridXLeft,
RightGridXRight = kernelSlipPlaneUpliftVan.RightGrid.GridXRight,
RightGridZCount = kernelSlipPlaneUpliftVan.RightGrid.GridZNumber,
RightGridZTop = kernelSlipPlaneUpliftVan.RightGrid.GridZTop,
RightGridZBottom = kernelSlipPlaneUpliftVan.RightGrid.GridZBottom
};
if (kernelSlipPlaneUpliftVan.TangentLines != null && !kernelSearchAreaConditions.AutoTangentLines)
{
UpliftVanCalculationGrid.TangentLineLevels = kernelSlipPlaneUpliftVan.TangentLines.ToList();
}
}
private void TransferUpliftVanCalculationGridSettings(SearchAreaConditions kernelSearchAreaConditions)
{
SlipCircleDefinition = new SlipCircleDefinition
{
UpliftVanGridSizeDetermination = kernelSearchAreaConditions.AutoSearchArea
? GridSizeDetermination.Automatic
: GridSizeDetermination.Specified
};
if (kernelSearchAreaConditions.AutoTangentLines)
{
SlipCircleDefinition.UpliftVanTangentLinesDefinition = kernelSearchAreaConditions.OnlyAbovePleistoceen ? TangentLinesDefinition.Automatic : TangentLinesDefinition.OnBoundaryLines;
}
else
{
SlipCircleDefinition.UpliftVanTangentLinesDefinition = TangentLinesDefinition.Specified;
SlipCircleDefinition.UpliftVanTangentLinesDistance =
(kernelSearchAreaConditions.TangentLineZTop - kernelSearchAreaConditions.TangentLineZBottom) /
(kernelSearchAreaConditions.TangentLineNumber - 1);
}
}
private void TransferWaternet(KernelWaternet kernelWaternet)
{
var headLineMapping = new Dictionary();
Waternet = new Waternet
{
Name = kernelWaternet.Name
};
// Phreatic line
var phreaticLine = CreateLine(kernelWaternet.PhreaticLine);
Waternet.PhreaticLine = phreaticLine;
headLineMapping.Add(kernelWaternet.PhreaticLine, phreaticLine);
// Head Lines
foreach (KernelHeadLine kernelHeadLine in kernelWaternet.HeadLines)
{
var headLine = CreateLine(kernelHeadLine);
Waternet.HeadLineList.Add(headLine);
headLineMapping.Add(kernelHeadLine, headLine);
}
// Waternet Lines
foreach (ReferenceLine kernelWaternetLine in kernelWaternet.ReferenceLines)
{
var waternetLine = CreateLine(kernelWaternetLine);
waternetLine.HeadLine = headLineMapping[kernelWaternetLine.AssociatedHeadLine];
Waternet.WaternetLineList.Add(waternetLine);
}
}
private static TLineType CreateLine(KernelWaternetLine waternetLine)
where TLineType : GeometryPointString, new()
{
var lineType = new TLineType
{
Name = waternetLine.Name
};
Point2D[] coordinates = waternetLine.Points.Select(p => new Point2D(p.X, p.Z)).ToArray();
lineType.Points.AddRange(coordinates);
return lineType;
}
private void TransferSurfaceLine(SurfaceLine kernelSurfaceLine)
{
SurfaceLine2 = new SurfaceLine2();
foreach (SurfaceLineCharacteristicPoint kernelCharPoint in kernelSurfaceLine.CharacteristicPoints)
{
var damCharPoint = new CharacteristicPoint
{
CharacteristicPointType = ConversionHelper.ConvertToDamCharacteristicPointType(kernelCharPoint.CharacteristicPointType),
Point = new Point2D
{
X = kernelCharPoint.GeometryPoint.X,
Z = kernelCharPoint.GeometryPoint.Z
}
};
SurfaceLine2.CharacteristicPoints.Add(damCharPoint);
}
}
private void TransferSoils(ICollection stabilityModelSoils, ICollection stabilityModelFixedSoilStresses)
{
SoilList = new SoilList();
foreach (MacroStability.CSharpWrapper.Input.Soil kernelSoil in stabilityModelSoils)
{
Soil damSoil = ConversionHelper.ConvertToDamSoil(kernelSoil);
// fill the dictionary to reset the soils for the surfaces in the SoilProfile2D
soilDictionary.Add(kernelSoil.Name, damSoil);
SoilList.Add(damSoil);
damSoil.PoP = stabilityModelFixedSoilStresses.First(s => s.Soil.Name.Equals(damSoil.Name))!.POP;
}
}
private void TransferStabilityModel(StabilityInput kernelModelStabilityModel)
{
FailureMechanismParametersMStab = new FailureMechanismParametersMStab();
//kernelModelStabilityModel.MoveGrid is not in DamEngine datamodel
//kernelModelStabilityModel.MaximumSliceWidth is not in DamEngine datamodel
FailureMechanismParametersMStab.MStabParameters.SearchMethod =
ConversionHelper.ConvertToDamSearchMethod(kernelModelStabilityModel.SearchAlgorithm);
FailureMechanismParametersMStab.MStabParameters.Model =
ConversionHelper.ConvertToMStabModelType(kernelModelStabilityModel.ModelOption);
FailureMechanismParametersMStab.MStabParameters.GridPosition =
ConversionHelper.ConvertToMStabGridPosition(kernelModelStabilityModel.Orientation);
}
private void TransferSoilProfile2D(SoilProfile kernelSoilProfile2D,
ICollection preconsolidationStresses)
{
SoilProfile2D = new SoilProfile2D();
// Add points
var pointsDictionary = new Dictionary();
foreach (MacroStability.CSharpWrapper.Point2D kernelPoint in kernelSoilProfile2D.Geometry.Points)
{
var damPoint = new Point2D
{
X = kernelPoint.X,
Z = kernelPoint.Z
};
pointsDictionary.Add(kernelPoint, damPoint);
SoilProfile2D.Geometry.Points.Add(damPoint);
}
// Add curves
var curvesDictionary = new Dictionary();
foreach (Curve kernelCurve in kernelSoilProfile2D.Geometry.Curves)
{
Point2D damHeadPoint = pointsDictionary[kernelCurve.HeadPoint];
Point2D damEndPoint = pointsDictionary[kernelCurve.EndPoint];
var damCurve = new GeometryCurve
{
HeadPoint = damHeadPoint,
EndPoint = damEndPoint
};
curvesDictionary.Add(kernelCurve, damCurve);
SoilProfile2D.Geometry.Curves.Add(damCurve);
}
// Add loops
var loopsDictionary = new Dictionary();
foreach (Loop kernelLoop in kernelSoilProfile2D.Geometry.Loops)
{
var damLoop = new GeometryLoop();
foreach (Curve damCurve in kernelLoop.Curves)
{
damLoop.CurveList.Add(curvesDictionary[damCurve]);
}
loopsDictionary.Add(kernelLoop, damLoop);
SoilProfile2D.Geometry.Loops.Add(damLoop);
}
// Add surfaces
var geometrySurfacesDictionary = new Dictionary();
foreach (Surface kernelSurface in kernelSoilProfile2D.Geometry.Surfaces)
{
var damSurface = new GeometrySurface();
damSurface.OuterLoop = loopsDictionary[kernelSurface.OuterLoop];
foreach (Loop damInnerLoop in kernelSurface.InnerLoops)
{
damSurface.InnerLoops.Add(loopsDictionary[damInnerLoop]);
}
geometrySurfacesDictionary.Add(kernelSurface, damSurface);
SoilProfile2D.Geometry.Surfaces.Add(damSurface);
}
// Add soil surfaces
foreach (SoilProfileSurface kernelSoilLayer2D in kernelSoilProfile2D.SoilSurfaces)
{
var damSoilLayer2D = new SoilLayer2D();
damSoilLayer2D.GeometrySurface = geometrySurfacesDictionary[kernelSoilLayer2D.Surface];
damSoilLayer2D.Soil = soilDictionary[kernelSoilLayer2D.Soil.Name];
damSoilLayer2D.IsAquifer = kernelSoilLayer2D.IsAquifer;
damSoilLayer2D.WaterpressureInterpolationModel = ConversionHelper.ConvertToDamWaterpressureInterpolationModel(kernelSoilLayer2D.WaterPressureInterpolationModel);
SoilProfile2D.Surfaces.Add(damSoilLayer2D);
}
// Add the preconsolidation stresses
foreach (PreconsolidationStress preconsolidationStress in preconsolidationStresses)
{
var damPreConsolidationStress = new PreConsolidationStress
{
X = preconsolidationStress.Point.X,
Z = preconsolidationStress.Point.Z,
StressValue = preconsolidationStress.StressValue
};
SoilProfile2D.PreconsolidationStresses.Add(damPreConsolidationStress);
}
}
}