using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using Deltares.Geometry; using Deltares.Geotechnics; using Deltares.Geotechnics.Soils; using Deltares.Geotechnics.SurfaceLines; using Deltares.MStab.IO.Classic; using Deltares.Standard; using Deltares.WTIPiping; namespace Deltares.Dam.Data { public class PipingCalculatorWti2017 : PipingCalculator { private const double defaultLeakageLength = 1e12; public double ModelFactorUplift { get; set; } public double RExit { get; set; } List upliftFactorForLocations; private bool isPipingFactorCalculated = false; public PipingCalculatorWti2017(ModelParametersForPLLines modelParametersForPLLines, double requiredSafetyFactor, IList gaugePLLines, IList gauges, double upliftCriterion) : base(modelParametersForPLLines, requiredSafetyFactor, gaugePLLines, gauges, null, upliftCriterion) { ModelFactorUplift = 1.0; RExit = WTIPipingConstants.RExitDefault; } [global::System.Serializable] public class PipingCalculatorWti2017Exception : Exception { // // For guidelines regarding the creation of new exception types, see // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp // and // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp // public PipingCalculatorWti2017Exception() { } public PipingCalculatorWti2017Exception(string message) : base(message) { } public PipingCalculatorWti2017Exception(string message, Exception inner) : base(message, inner) { } protected PipingCalculatorWti2017Exception( SerializationInfo info, StreamingContext context) : base(info, context) { } } public double? CalculatePipingFactor(Location location, SurfaceLine2 surfaceLine, SoilProfile1D soilProfile, PLLines plLines) { this.PLLines = plLines; double waterLevel = plLines.Lines[PLLineType.PL1].Points[0].Z; MakeSoilProfile1DWtiPipingCompliant(soilProfile); this.SoilProfile = soilProfile; entryPoint = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver); DetermineUpliftAtAllPoints(location, surfaceLine, soilProfile, waterLevel); try { if (UpliftLocationAndResult != null) { double surfaceLevel = surfaceLine.Geometry.GetZAtX(UpliftLocationAndResult.X); this.HeaveFactor = CalculateHeaveFactor(location, surfaceLevel); return CalculatePipingFactorAtLevel(location, waterLevel, surfaceLevel); } return cDefaultMaxReturnValue; } catch (Exception e) { throw new DamFailureMechanismeCalculatorException(String.Format("An unexpected error occurred: {0}", e.Message), e); } } /// /// Calculates piping factor. /// /// /// /// /// /// /// Piping factor. /// /// An unexpected error occurred override public double? CalculatePipingFactor(Location location, SurfaceLine2 surfaceLine, SoilProfile1D soilProfile, double waterLevel) { // The base method is not called, because uplift determination is completely done with the Wti2017 kernel var plLines = CreatePLLines(location, surfaceLine, soilProfile, waterLevel); return CalculatePipingFactor(location, surfaceLine, soilProfile, plLines); } private double? CalculateHeaveFactor(Location location, double surfaceLevel) { var heaveCalculator = new HeaveCalculator(); heaveCalculator.PhiExit = location.PolderLevel; // Todo: Should be determined like it is done in ExitPointDeterminator.DeterminePhiAtX heaveCalculator.RExit = 1.0 - location.SlopeDampingPiezometricHeightPolderSide; // In fact this is the response factor heaveCalculator.DTotal = DetermineHeightCoverLayer(surfaceLevel); ; heaveCalculator.HExit = this.PLLines.Lines[PLLineType.PL1].ZFromX(UpliftLocationAndResult.X); // Phreatic level at this point heaveCalculator.Ich = 0.5; // Todo: is this a value that should be available in DAM? In Ringtoets this is a calculation setting heaveCalculator.PhiPolder = location.PolderLevel; if (heaveCalculator.PhiExit <= heaveCalculator.HExit) { // If no (or negative) headdrop then no heap will occur return cDefaultMaxReturnValue; } else { heaveCalculator.Calculate(); return heaveCalculator.FoSh; } } /// /// Determines the uplift at all points. /// /// The location. /// The surface line. /// The soil profile. /// The water level. private void DetermineUpliftAtAllPoints(Location location, SurfaceLine2 surfaceLine, SoilProfile1D soilProfile, double waterLevel) { // Determine uplift location GeometryPoint dikeToeAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); double xLocation = dikeToeAtPolder.X; double headPl3 = PLLines.Lines[PLLineType.PL3].ZFromX(xLocation); double phiPolder = PLLines.Lines[PLLineType.PL1].ZFromX(xLocation); var exitPointDeterminator = new ExitPointDeterminator(); exitPointDeterminator.SoilProfile = SoilProfile1D2PipingProfile(soilProfile); exitPointDeterminator.SurfaceLine = SurfaceLine2PipingSurfaceLine(new Geotechnics.Adapters.SurfaceLineAdapter(surfaceLine)); exitPointDeterminator.PhiPolder = phiPolder; exitPointDeterminator.HRiver = headPl3; exitPointDeterminator.IsUseOvenDryUnitWeight = false; exitPointDeterminator.LeakageLength = defaultLeakageLength; // TODO: should this be DAM input or always use this default value? exitPointDeterminator.MinimumThicknessCoverLayer = 0.0; exitPointDeterminator.ModelFactorUplift = ModelFactorUplift; // TODO: should this be DAM input or always use this default value? exitPointDeterminator.RToe = 1.0 - location.DampingFactorPL3; // In fact this is the response factor exitPointDeterminator.RExit = 1.0 - location.SlopeDampingPiezometricHeightPolderSide; // In fact this is the response factor exitPointDeterminator.RequiredFactorOfSafety = this.upliftCriterion; exitPointDeterminator.VolumetricWeightOfWater = Physics.UnitWeightOfwater; exitPointDeterminator.Calculate(); upliftFactorForLocations = exitPointDeterminator.GetUpliftLocationAndResultList(); if (exitPointDeterminator.ExitPoint == null) { UpliftLocationAndResult = null; } else { UpliftLocationAndResult = new UpliftLocationAndResult(); UpliftLocationAndResult.UpliftFactor = exitPointDeterminator.UpliftFactor; UpliftLocationAndResult.X = exitPointDeterminator.ExitPoint.X; UpliftLocationAndResult.Z = surfaceLine.Geometry.GetZAtX(UpliftLocationAndResult.X); UpliftLocationAndResult.LayerWhereUpliftOccuresId = exitPointDeterminator.LayerWhereUpliftOccuresId; } } /// /// Makes the soil profile1d wti piping compliant. /// Wti Piping calculation needs unique names /// /// The soil profile. private static void MakeSoilProfile1DWtiPipingCompliant(SoilProfile1D soilProfile) { foreach (var layer in soilProfile.Layers) { layer.Name = layer.Id; } } /// /// Calculates the piping factor at given surfacelevel. /// /// The location. /// The water level. /// The surface level. /// private double CalculatePipingFactorAtLevel(Location location, double waterLevel, double surfaceLevel) { var soilProfile1DAquiferLayerCombiner = new SoilProfile1DAquiferLayerCombiner(SoilProfile); AquiferLayerWithParameters aquiferLayerWithParameters = soilProfile1DAquiferLayerCombiner.CombineLayers(UpliftLocationAndResult.LayerWhereUpliftOccuresId); var sc = new Sellmeijer2011Calculator(); var pipingCalculatorInput = DefinePipingInputFromModel(); sc.WhitesDragCoefficient = pipingCalculatorInput.WhitesConstant; sc.BeddingAngle = pipingCalculatorInput.BeddingAngle; sc.GammaSubParticles = WTIPipingConstants.GammaSubParticles; sc.VolumetricWeightOfWater = Physics.UnitWeightOfwater; sc.D70 = Physics.FactorMicroMeterToMeter * pipingCalculatorInput.D70; sc.SeepageLength = pipingCalculatorInput.Length; sc.DarcyPermeability = aquiferLayerWithParameters.PermeabilityKx; sc.DAquifer = aquiferLayerWithParameters.Height; sc.HRiver = waterLevel; sc.ModelFactorPiping = 1.0;// TODO: should this be DAM input or always use this default value? sc.Calculate(); HCritical = sc.Hcp; return sc.FoSp; } /// /// Determines the required shoulder (height and length as seen from the original dike toe) /// /// /// /// /// /// /// The required dimensions when needed else null public override PipingDesign CalculateDesignAtPoint(Location location, SurfaceLine2 surfaceLine, SoilProfile1D soilProfile, double waterLevel, GeometryPoint point) { MakeSoilProfile1DWtiPipingCompliant(soilProfile); this.SoilProfile = soilProfile; entryPoint = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver); var pipingDesign = new PipingDesign(0.0, 0.0); DetermineUpliftAtAllPoints(location, surfaceLine, soilProfile, waterLevel); var upliftResultAtLocation = GetUpliftFactorAtPoint(point); if ((upliftResultAtLocation != null) && (upliftResultAtLocation.UpliftFactor != null) && (upliftResultAtLocation.UpliftFactor.Value < upliftCriterion)) { // Calculate the piping safety factor at the given point var sp = CalculatePipingFactorAtLevel(location, waterLevel, point.Z); // If too low, then determine required height and length (from uplift) if (sp < requiredSafetyFactor) { // Finally, determine the required shoulderheight double currentShoulderHeight = UpliftLocationAndResult.Z - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).Z; // TODO: Determine shoulderheight with WTI UpliftCalculatior pipingDesign.ShoulderHeightFromToe = currentShoulderHeight + CalculateExtraShoulderHeight(); pipingDesign.PipingLengthFromToe = UpliftLocationAndResult.X - surfaceLine.GetDikeToeInward().X; return pipingDesign; } } return null; } private UpliftLocationAndResult GetUpliftFactorAtPoint(GeometryPoint point) { WTIPiping.UpliftLocationAndResult upliftLocationAndResult = upliftFactorForLocations.FirstOrDefault(ul => PipingPoint2GeometryPoint(ul).LocationEquals(point)); var upliftResultAtLocation = new UpliftLocationAndResult() { UpliftFactor = upliftLocationAndResult.UpliftFactor, X = upliftLocationAndResult.X, Z = upliftLocationAndResult.Z }; return upliftResultAtLocation; //var layerName = ""; //var phi = DeterminePhiAtX(point.X); //var upliftCalculator = PrepareUpliftCalculator(point, phi, out layerName); //upliftCalculator.Calculate(); //var res = new UpliftLocationAndResult(point) //{ // UpliftFactor = upliftCalculator.FoSu, // LayerWhereUpliftOccuresId = layerName, // Zu = upliftCalculator.Zu, // Phicu = upliftCalculator.DeltaPhiCu + upliftCalculator.HExit, // Phi = phi //}; //return res; } private PipingProfile SoilProfile1D2PipingProfile(SoilProfile1D soilProfile1D) { throw new Exception("Method 'SoilProfile1D2PipingProfile' not implemented yet"); } private PipingSurfaceLine SurfaceLine2PipingSurfaceLine(Geotechnics.Adapters.SurfaceLineAdapter surfaceLineAdapter) { throw new Exception("Method 'SurfaceLine2PipingSurfaceLine' not implemented yet"); } private GeometryPoint PipingPoint2GeometryPoint(PipingPoint pipingPoint) { return new GeometryPoint(pipingPoint.X, pipingPoint.Y, pipingPoint.Z); } } }