// Copyright (C) Stichting Deltares 2018. All rights reserved.
//
// This file is part of the Dam Piping Kernels.
//
// The Dam Macrostability Kernel is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero 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 Deltares.DamPiping.SellmeijerVNKCalculator.Geo;
using System;
using System.Collections.Generic;
using Deltares.DamPiping.SellmeijerVNKCalculator.Properties;
namespace Deltares.DamPiping.SellmeijerVNKCalculator
{
///
/// Calculates piping according to Sellmeijer VNK
///
public class PipingCalculatorSellmeijerVNK
{
public const double RcDefault = 0.3;
///
/// River level as input
///
public double HRiver { get; set; }
///
/// Phreatic level at exit point as input
///
public double HExit { get; set; }
///
/// Polder level as input
///
public double PolderLevel { get; set; }
///
/// Surface level as input
///
public double SurfaceLevel { get; set; }
///
/// Reduction factor as input
///
public double Rc { get; set; } = RcDefault;
///
/// Total thickness of cover layer as input
///
public double DTotal { get; set; }
///
/// Thickness of the layer in between aquifer as input
///
public double DInBetweenAquiferlayer { get; set; }
///
/// Thickness of the bottom aquifer layer as input
///
public double DBottomAquiferlayer { get; set; }
///
/// The permeability kx of the layer in between aquifer as input
///
public double PermeabilityInBetweenAquiferlayer { get; set; }
///
/// The permeability kx of the bottom aquifer layer as input
///
public double PermeabilityBottomAquiferlayer { get; set; }
///
/// Seepage length (xExit - xEntry) as input
///
public double SeepageLength { get; set; }
///
/// Median grainsize D70 as input
///
public double D70 { get; set; }
///
/// The whites constant as input
///
public double WhitesConstant { get; set; }
///
/// The bedding angle as input
///
public double BeddingAngle { get; set; }
///
/// The water viscosity as input
///
public double WaterViscosity { get; set; }
///
/// Safety factor of piping as result
///
public double FoSp { get; private set; }
///
/// Critical head difference for piping as result.
///
public double Hc { get; private set; }
///
/// Start the calculation of all output parameters.
///
public void Calculate()
{
Hc = CalculateHCritical();
var reducedFall = GetReducedFall();
FoSp = DetermineFactorOfSafety(Hc, reducedFall);
}
internal double CalculateHCritical()
{
PipingModel2Calculation pipingModel2Calculation = CreateAndFillPipingModel2Calculation();
// 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)."
pipingModel2Calculation.CalculateHeadDropPC2();
return pipingModel2Calculation.HeadDrop;
}
internal static double DetermineFactorOfSafety(double hCritical, double headDrop)
{
const double cDefaultMaxReturnValue = 90.0;
const double cDefaultMinReturnValue = 0.0;
const double cEpsilon = 1e-8;
double factor = cDefaultMinReturnValue;
if (Math.Abs(hCritical) > cEpsilon)
{
factor = cDefaultMaxReturnValue;
// If actual headdrop is almost zero or smaller than zero then piping will be no problem
// The pipingfactor will be set to cDefaultMaxReturnValue
if (headDrop > 0 + cEpsilon)
{
factor = hCritical / headDrop;
}
}
return factor;
}
internal double GetReducedFall()
{
// The Leidraad says that 0.3 * d can be substracted from hActual
// In the piping Sellmeijer model (PipingModel2 for VNK) 0.3 * d is added to the hCritical
// So we do not substract 0.3 * d from hActual (written by Tom The and Erik Vastenburg)
return HRiver - HExit;
}
///
/// Create PipingModel2Calculation object and fill with input parameters
///
///
private PipingModel2Calculation CreateAndFillPipingModel2Calculation()
{
var pipingModel2Calculation = new PipingModel2Calculation();
pipingModel2Calculation.IsHeadDropCalculation = true; // Constant
pipingModel2Calculation.SeepageLength = SeepageLength;
pipingModel2Calculation.CrackLength = DTotal;
pipingModel2Calculation.HeadDrop = 0.0;// Not used, to be calculated
pipingModel2Calculation.PipingCommonData.BeddingAngle = BeddingAngle; // From soilmaterials of upper sandlayer
pipingModel2Calculation.PipingCommonData.FluidisationGradient = Rc; //Constant
pipingModel2Calculation.PipingCommonData.WaterUnitWeight = Physics.UnitWeightOfwater; //Constant
pipingModel2Calculation.PipingCommonData.WaterViscosity = WaterViscosity; //Constant
pipingModel2Calculation.PipingCommonData.WhitesConstant = WhitesConstant; // From soilmaterials of upper sandlayer
pipingModel2Calculation.PipingCommonData.SafetyFactor = 1.20; //Constant toetsen/ontwerpen = 1.2 en calamiteit = 1.0
pipingModel2Calculation.PipingCommonData.IsAdjustHeadDrop = true; // Constant
// Soil parameters
pipingModel2Calculation.PipingCommonData.ParticleUnitWeight = 26.50; // Constant
pipingModel2Calculation.Permeability1 = PermeabilityInBetweenAquiferlayer; // Kx From upper sandlayer
pipingModel2Calculation.Permeability2 = PermeabilityBottomAquiferlayer; // Kx From bottom sandlayer
pipingModel2Calculation.Permeability3 = PermeabilityInBetweenAquiferlayer; // Kx From upper sandlayer
pipingModel2Calculation.ParticleDiameter = D70; // D70 D60 From soilmaterials of upper sandlayer
// Geometry parameters
pipingModel2Calculation.Height1 = DInBetweenAquiferlayer; // Thickness upper sandlayer
pipingModel2Calculation.Height2 = DBottomAquiferlayer; // Thickness bottom sandlayer
return pipingModel2Calculation;
//
// particleunitweight = gamma_p can be calculated as follows
// (gamma_sat - gamma_water) = (gamma_p - gamma_water) / (1 - n); for now 26.50 is good enough
//
// limit heights: see TPC2Preprocessing.AdjustParameters()
// CD1MinSeepageLengthFactor = 0.02; = D1 / Length
// CD2MinSeepageLengthFactor = 0.03; = D2 / Length
// CD1MaxSeepageLengthFactor = 1.4;
// CD2MaxSeepageLengthFactor = 1.4;
//
// Kx or Ky: Sel: Use Kx
}
///
/// Validates the input
///
/// a filled list when errors are found else an empty list
public List Validate()
{
var errors = new List();
errors.AddRange(PerformValidate());
return errors;
}
private List PerformValidate()
{
var errors = new List();
if (Math.Abs(GetReducedFall()) < double.Epsilon)
{
errors.Add(Resources.PipingCalculatorSellmeijerVNK_PerformValidate_HRiver_HExit_Zero);
}
if (double.IsNaN(SeepageLength))
{
LogParameterIsNaN(errors, "SeepageLength");
}
if (double.IsNaN(HRiver))
{
LogParameterIsNaN(errors, "HRiver");
}
if (double.IsNaN(PolderLevel))
{
LogParameterIsNaN(errors, "PolderLevel");
}
if (double.IsNaN(SurfaceLevel))
{
LogParameterIsNaN(errors, "SurfaceLevel");
}
if (double.IsNaN(Rc))
{
LogParameterIsNaN(errors, "Rc");
}
if (Rc < 0)
{
errors.Add(Resources.PipingCalculatorSellmeijerVNK_PerformValidate_RcLessThan0);
}
if (double.IsNaN(DTotal))
{
LogParameterIsNaN(errors, "DTotal");
}
if (double.IsNaN(DInBetweenAquiferlayer))
{
LogParameterIsNaN(errors, "DInBetweenAquiferlayer");
}
if (double.IsNaN(DBottomAquiferlayer))
{
LogParameterIsNaN(errors, "DBottomAquiferlayer");
}
if (double.IsNaN(PermeabilityInBetweenAquiferlayer))
{
LogParameterIsNaN(errors, "PermeabilityInBetweenAquiferlayer");
}
if (double.IsNaN(PermeabilityBottomAquiferlayer))
{
LogParameterIsNaN(errors, "PermeabilityBottomAquiferlayer");
}
if (double.IsNaN(HExit))
{
LogParameterIsNaN(errors, "HExit");
}
if (double.IsNaN(D70))
{
LogParameterIsNaN(errors, "D70");
}
if (double.IsNaN(WhitesConstant))
{
LogParameterIsNaN(errors, "WhitesConstant");
}
if (double.IsNaN(BeddingAngle))
{
LogParameterIsNaN(errors, "BeddingAngle");
}
if (double.IsNaN(WaterViscosity))
{
LogParameterIsNaN(errors, "WaterViscosity");
}
return errors;
}
private void LogParameterIsNaN(IList list, string paramName)
{
var msg = string.Format(Resources.PipingCalculatorSellmeijerVNK_LogParameterIsNaN_NaNParameterError, paramName);
list.Add(msg);
}
}
}