using System;
using System.Linq;
using Deltares.Geometry;
using Deltares.Geotechnics;
using Deltares.Geotechnics.Soils;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Geotechnics.WaternetCreator;
using Deltares.MStab;
using Deltares.Stability;
using Deltares.Standard;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.Extensions;
using Deltares.Standard.Language;
namespace Deltares.Dam.Data
{
public class StabilityProjectObjectCreator
{
internal MStabProject CreateMacroStabilityProject(Scenario scenario, SoilProfile soilProfile, FailureMechanismeParamatersMStab failureMechanismeParamatersMStab, double riverLevel,StabilityProjectParameterValues parameterValues)
{
MStabProject mStabProject = null;
DataEventPublisher.InvokeWithoutPublishingEvents(() =>
{
mStabProject = new MStabProject();
//get soil data
GetMstabProjectSoilData(scenario, soilProfile, mStabProject);
//geometry
CreateMstabProjectGeometry(scenario, soilProfile, mStabProject);
//modeloptions
mStabProject.Stability.ModelOption = GetModelOption(failureMechanismeParamatersMStab.MStabParameters.Model);
if (mStabProject.Stability.ModelOption == ModelOptions.Spencer)
{
mStabProject.Stability.AutoGenerateGeneticSpencer = true;
mStabProject.Stability.IsHighSlipPlanes = failureMechanismeParamatersMStab.MStabParameters.Model ==
MStabModelType.SpencerHigh; // #Bka added SpencerHigh/SpencerLow as quick fix. Should be replaced by new Spencer options
mStabProject.Stability.IsLowSlipPlanes = failureMechanismeParamatersMStab.MStabParameters.Model ==
MStabModelType.SpencerLow;
}
GridOrientation gridOrientation;
gridOrientation = (failureMechanismeParamatersMStab.MStabParameters.GridPosition == MStabGridPosition.Left)
? GridOrientation.Outwards
: GridOrientation.Inwards;
mStabProject.Stability.GridOrientation = gridOrientation;
mStabProject.Stability.SlipPlaneConstraints.SlipPlaneMinDepth = parameterValues.MinimalCircleDepth;
//waternet
CreateMstabProjectWaternet(scenario, riverLevel, mStabProject, parameterValues.PhreaticAdaptionType, parameterValues.PenetrationLength, parameterValues.PLlineCreationMethod);
//create stability calculation grid (For Uplift, the waternet data needs to be available so do this after the waternet.
CreateStabilityCalculationGrid(mStabProject.Stability, failureMechanismeParamatersMStab);
//loads
var trafficLoad = GetUniformLoad(scenario, failureMechanismeParamatersMStab, parameterValues);
if (trafficLoad != null)
{
mStabProject.Stability.UniformLoads.Add(trafficLoad);
}
});
return mStabProject;
}
private UniformLoad GetUniformLoad(Scenario scenario,FailureMechanismeParamatersMStab fmParamsMstab,StabilityProjectParameterValues parameterValues)
{
double load;
if (parameterValues.TrafficLoad > 0)
{
load = parameterValues.TrafficLoad;
}
else if (scenario.Location.TrafficLoad > 0)
{
load = scenario.Location.TrafficLoad;
}
else
{
load = fmParamsMstab.TrafficLoad;
}
return CreateUniformLoad(scenario.Location.SurfaceLine2, load);
}
private void GetMstabProjectSoilData(Scenario scenario, SoilProfile soilProfile,
MStabProject mStabProject)
{
var profile1D = soilProfile as SoilProfile1D;
if (profile1D != null)
{
foreach (var soil in profile1D.Soils)
{
var newSoil = new Soil();
newSoil.Assign(soil);
mStabProject.Stability.SoilModel.Create(newSoil);
}
}
else
{
SoilProfile2D profile2D = soilProfile as SoilProfile2D;
if (profile2D != null)
foreach (SoilLayer2D soilLayer2D in profile2D.Surfaces)
{
if (soilLayer2D.Soil != null)
{
var newSoil = new Soil();
newSoil.Assign(soilLayer2D.Soil);
mStabProject.Stability.SoilModel.Create(newSoil);
}
else
{
var oldStiLayerHasNoSoilError = LocalizationManager.GetTranslatedText(this.GetType(), "OldStiLayerHasNoSoilError");
throw new Exception(oldStiLayerHasNoSoilError);
}
}
}
}
private void CreateStabilityCalculationGrid(StabilityModel stability, FailureMechanismeParamatersMStab failureMechanismeParamatersMStab)
{
// As this is only used when for the rto-option, and that option can not handle non auto grids,
// checking the setting of the grid for automatic is useless.
// create grid according RTOCalculationgrid
stability.SlipCircle.Auto = true;
RTOCalculationgrid rtoCalculationGrid = new RTOCalculationgrid(stability);
rtoCalculationGrid.CreateGrid(stability);
}
private ModelOptions GetModelOption(MStabModelType model)
{
switch (model)
{
case MStabModelType.Bishop:
return ModelOptions.Bishop;
case MStabModelType.BishopRandomField:
return ModelOptions.BishopProbabilityRandomField;
case MStabModelType.Fellenius:
return ModelOptions.Fellenius;
case MStabModelType.HorizontalBalance:
return ModelOptions.HorizontalBalance;
case MStabModelType.Spencer:
case MStabModelType.SpencerHigh: // #Bka added SpencerHigh/SpencerLow as quick fix. Should be replaced by new spencer options
case MStabModelType.SpencerLow:
return ModelOptions.Spencer;
case MStabModelType.UpliftSpencer:
return ModelOptions.UpliftSpencer;
case MStabModelType.UpliftVan:
return ModelOptions.UpliftVan;
default:
return ModelOptions.Bishop;
}
}
private UniformLoad CreateUniformLoad(SurfaceLine2 surfaceLine,double trafficLoad)
{
GeometryPoint trafficLoadInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadInside);
GeometryPoint trafficLoadOutside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadOutside);
if (trafficLoadInside != null && trafficLoadOutside != null && !Double.IsNaN(trafficLoadInside.X) &&
!Double.IsNaN(trafficLoadOutside.X))
{
UniformLoad uniformLoad = new UniformLoad();
uniformLoad.XStart = Math.Min(trafficLoadInside.X, trafficLoadOutside.X);
uniformLoad.XEnd = Math.Max(trafficLoadInside.X, trafficLoadOutside.X);
uniformLoad.Magnitude = trafficLoad;
uniformLoad.LoadType = UniformLoad.LoadTypeEnum.Temporary;
return uniformLoad;
}
return null;
}
private void CreateMstabProjectGeometry(Scenario scenario, SoilProfile soilProfile,
MStabProject mStabProject)
{
StabilityModel model = new StabilityModel() {CalculationModel = CalculationModel.RTO};
mStabProject.Stability = model;
var surfaceLine = scenario.Location.SurfaceLine2; // # Bka: is this correct for design or use scenario.GetMostRecentSurfaceLine
var dikeEmbankmentMaterial = scenario.Location.GetDikeEmbankmentSoil();
var newSoil = new Soil();
newSoil.Assign(dikeEmbankmentMaterial);
mStabProject.Stability.SoilModel.Create(newSoil);
SoilSurfaceProfile soilSurfaceProfile = new SoilSurfaceProfile();
if (soilProfile.GetType() == typeof(SoilProfile1D))
{
DataEventPublisher.InvokeAndPublish(() =>
{
//soilSurfaceProfile = new SoilSurfaceProfile();
soilSurfaceProfile.SoilProfile = (SoilProfile1D)soilProfile;
soilSurfaceProfile.SurfaceLine2 = surfaceLine;
soilSurfaceProfile.DikeEmbankmentMaterial = dikeEmbankmentMaterial;
});
model.SoilProfile = soilSurfaceProfile;
}
else if (soilProfile.GetType() == typeof (SoilProfile2D))
{
var soilSurfaceProfile2D = new SoilSurfaceProfile2D();
soilSurfaceProfile2D.DikeEmbankmentMaterial = dikeEmbankmentMaterial;
soilSurfaceProfile2D.SoilProfile2D = (SoilProfile2D) soilProfile;
soilSurfaceProfile2D.SurfaceLine = surfaceLine.Geometry;
model.SoilProfile = soilSurfaceProfile2D;
}
model.SurfaceLine2.Dispose();
model.SurfaceLine2 = surfaceLine;
}
private void CreateMstabProjectWaternet(Scenario scenario, double riverLevel, MStabProject mStabProject,PhreaticAdaptionType phreaticAdaptionType, double penetrationLength,PLLineCreationMethod plLineCreationMethod)
{
double? riverLevelLow = (mStabProject.Stability.GridOrientation == GridOrientation.Outwards)
? scenario.RiverLevelLow
: null;
if (riverLevelLow != null)
{
mStabProject.Stability.Location.WaterLevelRiverLow = (double)riverLevelLow;
}
mStabProject.Stability.Location.WaterLevelRiver = riverLevel;
mStabProject.Stability.Location.SoilProfile2D = mStabProject.Stability.SoilProfile;
mStabProject.Stability.Location.Surfaceline.Dispose();
mStabProject.Stability.Location.Surfaceline = scenario.Location.SurfaceLine2;
DataEventPublisher.InvokeWithoutPublishingEvents(() =>
{
Waternet waternet = CreateWaternetUsingWaternetCreator(scenario.Location, mStabProject.Stability.Location, phreaticAdaptionType, penetrationLength, plLineCreationMethod);
//mStabProject.Stability.GeotechnicsData.Create(waternet);
mStabProject.Stability.GeotechnicsData.Waternets.Clear();
mStabProject.Stability.GeotechnicsData.Waternets.Add(waternet);
mStabProject.Geotechnics.CurrentWaternet = waternet;
});
}
internal Waternet CreateWaternetUsingWaternetCreator(Location location,
Geotechnics.WaternetCreator.Location wLocation, PhreaticAdaptionType adaptionType, double penetrationLength, PLLineCreationMethod plLineCreationMethod)
{
WaternetCreator waternetCreator = new WaternetCreator();
wLocation.WaterLevelPolder = location.PolderLevel;
if (location.HeadPL2 != null)
{
wLocation.HeadInPLLine2Inwards = (double)location.HeadPL2;
wLocation.HeadInPLLine2Outwards = (double)location.HeadPL2;
}
//head 3 and 4 are equal to waterlevel river
/*if (location.HeadPl3 != null)
{
waternetLocation.HeadInPLLine3 = (double) location.HeadPl3;
}
if (location.HeadPl4 != null)
{
waternetLocation.HeadInPLLine4 = (double) location.HeadPl4;
}*/
wLocation.PlLineCreationMethod = GetPlLineCreationMethod(plLineCreationMethod);
wLocation.PenetrationLength = penetrationLength;
//TODO lourens: get valid leakage length values
GetLeakageLengthValues(wLocation);
wLocation.AdjustPl3And4ForUplift = true; // for stability this must be set to true
wLocation.PlLineOffsetBelowDikeTopAtRiver = location.PlLineOffsetBelowDikeTopAtRiver;
wLocation.PlLineOffsetBelowDikeTopAtPolder = location.PlLineOffsetBelowDikeTopAtPolder;
wLocation.PlLineOffsetBelowShoulderBaseInside = location.PlLineOffsetBelowShoulderBaseInside;
wLocation.PlLineOffsetBelowDikeToeAtPolder = location.PlLineOffsetBelowDikeToeAtPolder;
wLocation.NWOPhreaticAdaption = GetNwoPhreaticAdaption(adaptionType);
wLocation.Inwards = double.IsNaN(wLocation.WaterLevelRiverLow);
var waternet = new Waternet();
//waterlevelLow == nan means GridOrientation.Inwards
waternetCreator.UpdateWaternet(waternet, wLocation);
return waternet;
}
internal PLLines CreateAllPlLinesUsingWaternetCreator(Location location, SurfaceLine2 surfaceLine,
SoilProfile soilProfile, PhreaticAdaptionType phreaticAdaptionType, double penatrationLength, double waterlevel, PLLineCreationMethod plLineCreationMethod, double waterlevelLow)
{
using (var wlocation = new Geotechnics.WaternetCreator.Location())
{
wlocation.Surfaceline = surfaceLine;
wlocation.WaterLevelRiver = waterlevel;
wlocation.WaterLevelRiverLow = waterlevelLow;
var profile1D = soilProfile as SoilProfile1D;
if (profile1D != null)
{
wlocation.SoilProfile1D = profile1D;
}
else
{
wlocation.SoilProfile2D = (SoilProfile2D) soilProfile;
}
Waternet waternet = CreateWaternetUsingWaternetCreator(location, wlocation, phreaticAdaptionType, penatrationLength, plLineCreationMethod);
var plLines = new PLLines();
//assign phreatic Line
var plLine = CreateAndFillPlLine(waternet.PhreaticLine);
plLine.IsPhreatic = true;
plLines.Lines[PLLineType.PL1] = plLine;
//assign waternet lines
AssignWaternetHeadLinesToPlLines(waternet, plLines);
return plLines;
}
}
private void AssignWaternetHeadLinesToPlLines(Waternet waternet, PLLines plLines)
{
var headLineNames = waternet.HeadLineList.Select(h => h.Name);
foreach (var headLineName in headLineNames)
{
var plLine = AssignHeadLineToPlLine(waternet, headLineName);
if (plLine == null) return;
if (headLineName.Contains("2"))
{
plLines.Lines[PLLineType.PL2] = plLine;
}
if (headLineName.Contains("3"))
{
plLines.Lines[PLLineType.PL3] = plLine;
}
if (headLineName.Contains("4"))
{
plLines.Lines[PLLineType.PL4] = plLine;
}
}
}
private PLLine AssignHeadLineToPlLine(Waternet waternet, string headLineName)
{
var headLine = waternet.HeadLineList.First(h => h.Name == headLineName);
if (headLine != null)
{
return CreateAndFillPlLine(headLine);
}
return null;
}
private PLLine CreateAndFillPlLine(GeometryPointString headLine)
{
PLLine line = new PLLine();
foreach (var point in headLine.Points)
{
line.Points.Add(new PLLinePoint(point.X, point.Z));
}
return line;
}
///
/// map DAM enum PhreaticAdaptionType to Geotechnics enum PhreaticAdaptionType
///
///
private Geotechnics.WaternetCreator.PhreaticAdaptionType GetNwoPhreaticAdaption(PhreaticAdaptionType adaptionType)
{
switch (adaptionType)
{
case PhreaticAdaptionType.Fill:
return Geotechnics.WaternetCreator.PhreaticAdaptionType.Fill;
case PhreaticAdaptionType.MakeEmpty:
return Geotechnics.WaternetCreator.PhreaticAdaptionType.MakeEmpty;
case PhreaticAdaptionType.None:
return Geotechnics.WaternetCreator.PhreaticAdaptionType.None;
default:
return Geotechnics.WaternetCreator.PhreaticAdaptionType.None;
}
}
///
/// get leakage length values, to replace use of damping
///
///
private void GetLeakageLengthValues(Geotechnics.WaternetCreator.Location waternetLocation)
{
waternetLocation.LeakageLengthInwardsPl3 = 1000;
waternetLocation.LeakageLengthOutwardsPl3 = 1000;
waternetLocation.LeakageLengthInwardsPl4 = 1000;
waternetLocation.LeakageLengthOutwardsPl4 = 1000;
}
///
/// map DAM enum PlLineCreationMethod to Geotechnics enum PlLineCreationMethod
///
///
private PlLineCreationMethod GetPlLineCreationMethod(PLLineCreationMethod plLineCreationMethod)
{
switch (plLineCreationMethod)
{
case PLLineCreationMethod.ExpertKnowledgeLinearInDike:
return PlLineCreationMethod.ExpertKnowledgeLinearInDike;
case PLLineCreationMethod.ExpertKnowledgeRRD:
return PlLineCreationMethod.ExpertKnowledgeRrd;
case PLLineCreationMethod.DupuitDynamic:
return PlLineCreationMethod.DupuitDynamic;
case PLLineCreationMethod.DupuitStatic:
return PlLineCreationMethod.DupuitStatic;
case PLLineCreationMethod.None:
return PlLineCreationMethod.None;
case PLLineCreationMethod.Sensors:
return PlLineCreationMethod.Sensors;
default:
return PlLineCreationMethod.ExpertKnowledgeRrd;
}
}
}
}