using System; using System.Collections.Generic; using System.Data; using Deltares.DamEngine.Calculators.KernelWrappers.Common; using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces; using Deltares.DamEngine.Calculators.PlLinesCreator; using Deltares.DamEngine.Calculators.Uplift; using Deltares.DamEngine.Data.Design; using Deltares.DamEngine.Data.General; using Deltares.DamEngine.Data.General.PlLines; using Deltares.DamEngine.Data.General.Results; using Deltares.DamEngine.Data.Geotechnics; using Deltares.DamEngine.Data.Standard.Logging; using Deltares.DamPiping.BlighCalculator; namespace Deltares.DamEngine.Calculators.KernelWrappers.DamPipingBligh { /// /// Wrapper around Bligh piping kernel /// /// public class DamPipingBlighKernelWrapper : IKernelWrapper { private const double defaultFluidisationGradient = 0.3; public const double defaultMaxReturnValue = 90.0; /// /// Create the kernel input. /// /// The dam kernel input. /// public IKernelDataInput Prepare(DamKernelInput damKernelInput) { var damPipingBlighInput = new DamPipingBlighInput(); var soilProfile1D = damKernelInput.SubSoilScenario.SoilProfile1D; var surfaceLine = damKernelInput.Location.LocalXZSurfaceLine2; var location = damKernelInput.Location; double riverLevel = damKernelInput.DesignScenario.RiverLevel; var plLines = CreatePlLines(location, soilProfile1D, riverLevel); UpliftLocationDeterminator upliftLocationDeterminator = new UpliftLocationDeterminator { PLLines = plLines, SoilProfile = soilProfile1D, SurfaceLine = surfaceLine, DikeEmbankmentMaterial = location.GetDikeEmbankmentSoil(), XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin }; var upliftLocationAndResult = upliftLocationDeterminator.GetLocationAndResult(damKernelInput.DesignScenario.GetUpliftCriterionPiping(null)); bool isUplift = (upliftLocationAndResult != null); double xEntry = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X; double xExit = 0.0; double surfaceLevel = 0.0; double d70 = 0.0; double dCoverLayer = 0.0; if (upliftLocationAndResult != null) { xExit = upliftLocationAndResult.X; surfaceLevel = surfaceLine.Geometry.GetZatX(upliftLocationAndResult.X); SoilLayer1D heaveLayer = soilProfile1D.GetLayerWithName(upliftLocationAndResult.LayerWhereUpliftOccuresId); d70 = heaveLayer.Soil.DiameterD70; var topLevelAquifer = soilProfile1D.GetLayerWithName(upliftLocationAndResult.LayerWhereUpliftOccuresId).TopLevel; dCoverLayer = DetermineHeightCoverLayer(topLevelAquifer, surfaceLevel); } double seepageLength = xExit - xEntry; damPipingBlighInput.HRiver = riverLevel; // Reference level is highest value of surfaceLevel or PolderLevel // Uit TR Zandmeevoerende wellen (1999): "Het verval dH is gelijk aan het verschil tussen buitenwaterstand (het ontwerppeil(OP)) // bij zeedijken en de maatgevende hoogwaterstand (MHW bij rivierdijken) en de waterstand binnendijks ter plaatse van het uittredepunt, // rekening houdend met zeespiegelrijzing etc.(zie paragraaf 3.7.2). In dien ter plaatse van het uittreepunt of de opbarstlocatie // geen vrije waterstand heerst kan gerekend worden met het maaiveldniveau, rekening houdend met eventuele maaiveld daling (zie paragraaf 3.7.2)." var referenceLevel = Math.Max(location.PolderLevel, surfaceLevel); return new DamPipingBlighInput() { HRiver = riverLevel, HExit = referenceLevel, Rc = defaultFluidisationGradient, DTotal = dCoverLayer, SeepageLength = seepageLength, D70 = d70, IsUplift = isUplift }; } /// /// Validates the kernel data input. /// /// The kernel data input. /// The messages. /// public int Validate(IKernelDataInput kernelDataInput, out List messages) { var calculatorBligh = CreatePipingCalculatorBligh(kernelDataInput); List kernelMessages = calculatorBligh.Validate(); messages = new List(); foreach (string stringMessage in kernelMessages) { messages.Add(new LogMessage() { Message = stringMessage, MessageType = LogMessageType.Error }); } return messages.Count; } /// /// Executes the kernel. /// /// The kernel data input. /// The messages. /// public IKernelDataOutput Execute(IKernelDataInput kernelDataInput, out List messages) { DamPipingBlighInput damPipingBlighInput = kernelDataInput as DamPipingBlighInput; if (damPipingBlighInput == null) { throw new NoNullAllowedException("No input object defined for Bligh"); } messages = new List(); var damPipingBlighOutput = new DamPipingBlighOutput() { FoSp = defaultMaxReturnValue }; if (damPipingBlighInput.IsUplift) { var calculatorBligh = CreatePipingCalculatorBligh(kernelDataInput); calculatorBligh.Calculate(); damPipingBlighOutput.FoSp = calculatorBligh.FoSp; damPipingBlighOutput.Hc = calculatorBligh.Hc; } return damPipingBlighOutput; } /// /// Creates the piping calculator bligh based on kernel input. /// /// The kernel data input. /// /// No input object defined for Bligh private static PipingCalculatorBligh CreatePipingCalculatorBligh(IKernelDataInput kernelDataInput) { DamPipingBlighInput damPipingBlighInput = kernelDataInput as DamPipingBlighInput; if (damPipingBlighInput == null) { throw new NoNullAllowedException("No input object defined for Bligh"); } var calculator = new PipingCalculatorBligh { HRiver = damPipingBlighInput.HRiver, HExit = damPipingBlighInput.HExit, Rc = damPipingBlighInput.Rc, DTotal = damPipingBlighInput.DTotal, SeepageLength = damPipingBlighInput.SeepageLength, D70 = damPipingBlighInput.D70 }; return calculator; } /// /// Fills the design results with the kernel output. /// /// The dam kernel input. /// The kernel data output. /// The design result. /// No output object defined for Bligh public void PostProcess(DamKernelInput damKernelInput, IKernelDataOutput kernelDataOutput, out DesignResult designResult) { DamPipingBlighOutput damPipingBlighOutput = kernelDataOutput as DamPipingBlighOutput; if (damPipingBlighOutput == null) { throw new NoNullAllowedException("No output object defined for Bligh"); } string id = "id"; string soilProfile2DName = "soilProfile2DName"; var d = new DamFailureMechanismeCalculationSpecification(); var s = new DesignScenario(); var p = new SoilProfile1D(); designResult = new DesignResult(d, s, p, soilProfile2DName, AnalysisType.NoAdaption,0); var pipingDesignResults = new PipingDesignResults(PipingModelType.Bligh); pipingDesignResults.BlighFactor = damPipingBlighOutput.FoSp; pipingDesignResults.BlighHcritical = damPipingBlighOutput.Hc; designResult.PipingDesignResults = pipingDesignResults; } /// /// Creates the pl lines. /// /// The location. /// The soil profile. /// The water level. /// private PLLines CreatePlLines(Location location, SoilProfile1D soilProfile, double waterLevel) { var plLineCreator = new PLLinesCreator { WaterLevelRiverHigh = waterLevel, SurfaceLine = location.SurfaceLine2, WaterLevelPolder = location.PolderLevel, HeadInPLLine2 = location.HeadPl2, HeadInPLLine3 = location.HeadPl3, HeadInPLLine4 = location.HeadPl4, ModelParametersForPLLines = location.ModelParametersForPLLines, SoilProfile = soilProfile, GaugePLLines = null, // TODO: Operational Gauges = null, // TODO: Operational IsAdjustPL3AndPL4SoNoUpliftWillOccurEnabled = false, // for piping this must be set to false PlLineOffsetBelowDikeTopAtRiver = location.PlLineOffsetBelowDikeTopAtRiver, PlLineOffsetBelowDikeTopAtPolder = location.PlLineOffsetBelowDikeTopAtPolder, DikeEmbankmentMaterial = location.GetDikeEmbankmentSoil(), IsHydraulicShortcut = false, // TODO: Regional XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin }; return plLineCreator.CreateAllPLLines(location); } /// /// Determines the total thickness of the cover layer. /// /// The top level aquifer. /// The surface level. /// private double DetermineHeightCoverLayer(double topLevelAquifer, double surfaceLevel) { topLevelAquifer = Math.Min(topLevelAquifer, surfaceLevel); var d = surfaceLevel - topLevelAquifer; // if d negative is negative then top of aquifer is higher then surface layer. // This means that the aquifer is exposed on the surface. // In this case d = 0 d = Math.Max(0, d); return d; } } }