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; } } } }