// 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 RingtoetsPipingSurfaceLine 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 RingtoetsPipingSurfaceLine 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
}
}