// Copyright (C) Stichting Deltares 2017. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets is free software: you can redistribute it and/or modify // it under the terms of the GNU 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 General Public License for more details. // // You should have received a copy of the GNU 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.Globalization; using System.Linq; using Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Base.Geometry; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.Hydraulics; using Ringtoets.Common.Data.Probabilistics; using Ringtoets.MacroStabilityInwards.Data.Properties; using Ringtoets.MacroStabilityInwards.Primitives; namespace Ringtoets.MacroStabilityInwards.Data { /// /// Class that holds all piping calculation specific input parameters, i.e.. the values /// that can differ across various calculations. /// public class MacroStabilityInwardsInput : Observable, ICalculationInput { private readonly GeneralMacroStabilityInwardsInput generalInputParameters; private readonly NormalDistribution phreaticLevelExit; private readonly LogNormalDistribution dampingFactorExit; private RoundedDouble exitPointL; private RoundedDouble entryPointL; private RingtoetsMacroStabilityInwardsSurfaceLine surfaceLine; private RoundedDouble assessmentLevel; private bool useAssessmentLevelManualInput; /// /// Initializes a new instance of the class. /// /// General piping calculation parameters that /// are the same across all piping calculations. /// Thrown when /// is null. public MacroStabilityInwardsInput(GeneralMacroStabilityInwardsInput generalInputParameters) { if (generalInputParameters == null) { throw new ArgumentNullException(nameof(generalInputParameters)); } this.generalInputParameters = generalInputParameters; exitPointL = new RoundedDouble(2, double.NaN); entryPointL = new RoundedDouble(2, double.NaN); phreaticLevelExit = new NormalDistribution(3) { StandardDeviation = (RoundedDouble) 0.1 }; dampingFactorExit = new LogNormalDistribution(3) { Mean = (RoundedDouble) 0.7, StandardDeviation = (RoundedDouble) 0.1 }; assessmentLevel = new RoundedDouble(2, double.NaN); useAssessmentLevelManualInput = false; } /// /// Gets or sets the l-coordinate of the entry point, which, together with /// the l-coordinate of the exit point, is used to determine the seepage /// length of . /// [m] /// /// Thrown when either: /// /// is smaller or equal to . /// does not fall within the local X-coordinate range of /// /// public RoundedDouble EntryPointL { get { return entryPointL; } set { RoundedDouble newEntryPointL = value.ToPrecision(entryPointL.NumberOfDecimalPlaces); if (!double.IsNaN(newEntryPointL)) { if (!double.IsNaN(exitPointL)) { ValidateEntryExitPoint(newEntryPointL, exitPointL); } if (surfaceLine != null) { ValidatePointOnSurfaceLine(newEntryPointL); } } entryPointL = newEntryPointL; } } /// /// Gets or sets the l-coordinate of the exit point, which, together with /// the l-coordinate of the entry point, is used to determine the seepage /// length of . /// [m] /// /// Thrown when either: /// /// is smaller or equal to . /// does not fall within the local X-coordinate range of /// /// public RoundedDouble ExitPointL { get { return exitPointL; } set { RoundedDouble newExitPointL = value.ToPrecision(exitPointL.NumberOfDecimalPlaces); if (!double.IsNaN(newExitPointL)) { if (!double.IsNaN(entryPointL)) { ValidateEntryExitPoint(entryPointL, newExitPointL); } if (surfaceLine != null) { ValidatePointOnSurfaceLine(newExitPointL); } } exitPointL = newExitPointL; } } /// /// Gets or sets the surface line. /// public RingtoetsMacroStabilityInwardsSurfaceLine SurfaceLine { get { return surfaceLine; } set { surfaceLine = value; SynchronizeEntryAndExitPointInput(); } } /// /// Gets or sets the stochastic soil model which is linked to the . /// public StochasticSoilModel StochasticSoilModel { get; set; } /// /// Gets or sets the profile which contains a 1 dimensional definition of soil layers with properties. /// public StochasticSoilProfile StochasticSoilProfile { get; set; } /// /// Gets or sets the hydraulic boundary location from which to use the assessment level. /// public HydraulicBoundaryLocation HydraulicBoundaryLocation { get; set; } /// /// Gets or sets whether the assessment level is manual input for the calculation. /// public bool UseAssessmentLevelManualInput { get { return useAssessmentLevelManualInput; } set { useAssessmentLevelManualInput = value; if (useAssessmentLevelManualInput) { HydraulicBoundaryLocation = null; } } } /// /// Gets the value true if the entry point and exit point of the /// instance of match the entry point and /// exit point of ; or false if this is /// not the case, or if there is no assigned. /// public bool IsEntryAndExitPointInputSynchronized { get { if (SurfaceLine == null) { return false; } double newEntryPointL; double newExitPointL; GetEntryExitPointFromSurfaceLine(out newEntryPointL, out newExitPointL); return Math.Abs(newEntryPointL - EntryPointL) < 1e-6 && Math.Abs(newExitPointL - ExitPointL) < 1e-6; } } /// /// Applies the entry point and exit point of the to the /// parameters of the instance of . /// /// When no surface line is present, the entry and exit point are set to . public void SynchronizeEntryAndExitPointInput() { if (SurfaceLine == null) { EntryPointL = RoundedDouble.NaN; ExitPointL = RoundedDouble.NaN; } else { double tempEntryPointL; double tempExitPointL; GetEntryExitPointFromSurfaceLine(out tempEntryPointL, out tempExitPointL); if (tempExitPointL <= ExitPointL) { EntryPointL = (RoundedDouble) tempEntryPointL; ExitPointL = (RoundedDouble) tempExitPointL; } else { ExitPointL = (RoundedDouble) tempExitPointL; EntryPointL = (RoundedDouble) tempEntryPointL; } } } private void GetEntryExitPointFromSurfaceLine(out double tempEntryPointL, out double tempExitPointL) { int entryPointIndex = Array.IndexOf(SurfaceLine.Points, SurfaceLine.DikeToeAtRiver); int exitPointIndex = Array.IndexOf(SurfaceLine.Points, SurfaceLine.DikeToeAtPolder); Point2D[] localGeometry = SurfaceLine.ProjectGeometryToLZ().ToArray(); tempEntryPointL = localGeometry[0].X; tempExitPointL = localGeometry[localGeometry.Length - 1].X; bool isDifferentPoints = entryPointIndex < 0 || exitPointIndex < 0 || entryPointIndex < exitPointIndex; if (isDifferentPoints && exitPointIndex > 0) { tempExitPointL = localGeometry.ElementAt(exitPointIndex).X; } if (isDifferentPoints && entryPointIndex > -1) { tempEntryPointL = localGeometry.ElementAt(entryPointIndex).X; } } private void ValidateEntryExitPoint(RoundedDouble entryPointLocalXCoordinate, RoundedDouble exitPointLocalXCoordinate) { if (entryPointLocalXCoordinate >= exitPointLocalXCoordinate) { throw new ArgumentOutOfRangeException(null, Resources.PipingInput_EntryPointL_greater_or_equal_to_ExitPointL); } } private void ValidatePointOnSurfaceLine(RoundedDouble newLocalXCoordinate) { if (!surfaceLine.ValidateInRange(newLocalXCoordinate)) { var validityRange = new Range(surfaceLine.LocalGeometry.First().X, surfaceLine.LocalGeometry.Last().X); string outOfRangeMessage = string.Format(Resources.PipingInput_ValidatePointOnSurfaceLine_Length_must_be_in_Range_0_, validityRange.ToString(FormattableConstants.ShowAtLeastOneDecimal, CultureInfo.CurrentCulture)); throw new ArgumentOutOfRangeException(null, outOfRangeMessage); } } #region Derived input /// /// Gets or sets the outside high water level. /// [m] /// /// Thrown when the user attempts to set the /// assessment level while is false public RoundedDouble AssessmentLevel { get { if (!UseAssessmentLevelManualInput) { return HydraulicBoundaryLocation?.DesignWaterLevel ?? new RoundedDouble(2, double.NaN); } return assessmentLevel; } set { if (!UseAssessmentLevelManualInput) { throw new InvalidOperationException("UseAssessmentLevelManualInput is false"); } assessmentLevel = value.ToPrecision(assessmentLevel.NumberOfDecimalPlaces); } } /// /// Gets the piezometric head at the exit point. /// [m] /// public RoundedDouble PiezometricHeadExit { get { return new DerivedMacroStabilityInwardsInput(this).PiezometricHeadExit; } } #endregion #region General input parameters /// /// Gets the reduction factor Sellmeijer. /// public double SellmeijerReductionFactor { get { return generalInputParameters.SellmeijerReductionFactor; } } /// /// Gets the volumetric weight of water. /// [kN/m³] /// public double WaterVolumetricWeight { get { return generalInputParameters.WaterVolumetricWeight; } } /// /// Gets the (lowerbound) volumic weight of sand grain material of a sand layer under water. /// [kN/m³] /// public double SandParticlesVolumicWeight { get { return generalInputParameters.SandParticlesVolumicWeight; } } /// /// Gets the White's drag coefficient. /// public double WhitesDragCoefficient { get { return generalInputParameters.WhitesDragCoefficient; } } /// /// Gets the kinematic viscosity of water at 10 °C. /// [m²/s] /// public double WaterKinematicViscosity { get { return generalInputParameters.WaterKinematicViscosity; } } /// /// Gets the gravitational acceleration. /// [m/s²] /// public double Gravity { get { return generalInputParameters.Gravity; } } /// /// Gets the mean diameter of small scale tests applied to different kinds of sand, on which the formula of Sellmeijer has been fit. /// [m] /// public double MeanDiameter70 { get { return generalInputParameters.MeanDiameter70; } } /// /// Gets the angle of the force balance representing the amount in which sand grains resist rolling. /// [°] /// public double BeddingAngle { get { return generalInputParameters.BeddingAngle; } } /// /// Gets the calculation value used to account for uncertainty in the model for uplift. /// public double UpliftModelFactor { get { return generalInputParameters.UpliftModelFactor; } } /// /// Gets the calculation value used to account for uncertainty in the model for Sellmeijer. /// public double SellmeijerModelFactor { get { return generalInputParameters.SellmeijerModelFactor; } } /// /// Gets the critical exit gradient for heave. /// public double CriticalHeaveGradient { get { return generalInputParameters.CriticalHeaveGradient; } } #endregion #region Probabilistic parameters /// /// Gets or sets the phreatic level at the exit point. /// [m] /// public NormalDistribution PhreaticLevelExit { get { return phreaticLevelExit; } set { phreaticLevelExit.Mean = value.Mean; phreaticLevelExit.StandardDeviation = value.StandardDeviation; } } /// /// Gets the horizontal distance between entry and exit point. /// [m] /// public VariationCoefficientLogNormalDistribution SeepageLength { get { return new DerivedMacroStabilityInwardsInput(this).SeepageLength; } } /// /// Gets the sieve size through which 70% of the grains of the top part of the aquifer pass. /// [m] /// public VariationCoefficientLogNormalDistribution Diameter70 { get { return new DerivedMacroStabilityInwardsInput(this).DiameterD70; } } /// /// Gets the Darcy-speed with which water flows through the aquifer layer. /// [m/s] /// public VariationCoefficientLogNormalDistribution DarcyPermeability { get { return new DerivedMacroStabilityInwardsInput(this).DarcyPermeability; } } /// /// Gets the total thickness of the aquifer layers at the exit point. /// [m] /// public LogNormalDistribution ThicknessAquiferLayer { get { return new DerivedMacroStabilityInwardsInput(this).ThicknessAquiferLayer; } } /// /// Gets the total thickness of the coverage layer at the exit point. /// [m] /// public LogNormalDistribution ThicknessCoverageLayer { get { return new DerivedMacroStabilityInwardsInput(this).ThicknessCoverageLayer; } } /// /// Gets the effective thickness of the coverage layer at the exit point. /// [m] /// public LogNormalDistribution EffectiveThicknessCoverageLayer { get { return new DerivedMacroStabilityInwardsInput(this).EffectiveThicknessCoverageLayer; } } /// /// Gets or sets the damping factor at the exit point. /// public LogNormalDistribution DampingFactorExit { get { return dampingFactorExit; } set { dampingFactorExit.Mean = value.Mean; dampingFactorExit.StandardDeviation = value.StandardDeviation; } } /// /// Gets the volumic weight of the saturated coverage layer. /// public LogNormalDistribution SaturatedVolumicWeightOfCoverageLayer { get { return new DerivedMacroStabilityInwardsInput(this).SaturatedVolumicWeightOfCoverageLayer; } } #endregion } }