// Copyright (C) Stichting Deltares 2018. All rights reserved.
//
// This file is part of the Dam Engine.
//
// The Dam Engine 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 System;
using System.Collections.Generic;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.PlLines;
namespace Deltares.DamEngine.Data.RWScenarios
{
public class HydraulicShortcutRWEvaluator : RWEvaluator
{
private const double cMinUpliftFactor = 1.2;
private const double cMinAquitardThickness = 2.0; // meter
private const double cMinHeadGradient = 1.0; // meter
private const double cMinAquitardThicknessIfDrySensitive = 5.0; // meter
private const double cMinClayThickness = 2.0; // meter
private DikeDrySensitivity dikeDrySensitivity = DikeDrySensitivity.None;
private LoadSituation loadSituation = LoadSituation.Wet;
public HydraulicShortcutRWEvaluator()
{
}
public override Enum Evaluate(Location location, SoilGeometry soilGeometry, params Enum[] previousChoices)
{
base.Evaluate(location, soilGeometry, previousChoices);
HydraulicShortcutType hydraulicShortcutType = HydraulicShortcutType.NoHydraulicShortcut;
// Determine dikeDrySensitivity and loadsituation
Dictionary choices = new Dictionary();
foreach (Enum enumValue in previousChoices)
{
if (enumValue != null)
{
choices[enumValue.GetType()] = enumValue;
}
}
dikeDrySensitivity = (DikeDrySensitivity)choices[typeof(DikeDrySensitivity)];
loadSituation = (LoadSituation)choices[typeof(LoadSituation)];
System.Diagnostics.Debug.Print(String.Format("==== Hydraulic shortcut evaluation of '{0}'", location.Name));
// determine hydraulic shortcut
// evaluate boezempeil (step 1)
if (EvaluateBoezemLevelBelowHeadAquifer())
{
hydraulicShortcutType = HydraulicShortcutType.NoHydraulicShortcut;
}
else
{
// Evaluate thickness of aquitard (step 2)
if (!EvaluateAquitardHasEnoughThickness())
{
hydraulicShortcutType = HydraulicShortcutType.HydraulicShortcut;
}
else
{
// Evaluate drysensitive dike (step 3)
if (!EvaluateDikeIsDrySensitive())
{
hydraulicShortcutType = HydraulicShortcutType.NoHydraulicShortcut;
}
else
{
// Evaluate thickness clay in aquitard and sheetpile (step 4)
if (EvaluateClayInAquitardTooThin())
{
if (loadSituation == LoadSituation.Dry)
{
hydraulicShortcutType = HydraulicShortcutType.HydraulicShortcut;
}
else
{
hydraulicShortcutType = HydraulicShortcutType.NoHydraulicShortcut;
}
}
else
{
hydraulicShortcutType = HydraulicShortcutType.NoHydraulicShortcut;
}
}
}
}
System.Diagnostics.Debug.Print(String.Format("==== End of Hydraulic shortcut evalution of '{0}'", location.Name));
return hydraulicShortcutType;
}
///
/// Condition: Dikte waterremmende laag minstens 2 meter
///
///
private bool EvaluateAquitardHasEnoughThickness()
{
var aquitardEvaluator = new AquitardEvaluator(soilGeometry.SoilProfile);
double aquitardTichkness = aquitardEvaluator.DetermineAquitardThicknessWithMinimalWeight(location.DredgingDepth, this.location.GetDikeEmbankmentSoil()); // Note: do not evaluate sheetpile here
bool aquitardHasEnoughThickness = (aquitardTichkness >= cMinAquitardThickness);
System.Diagnostics.Debug.Print(String.Format("Aquitard thickness ({0}) sufficient is {1}; it should be more than {2} meter",
aquitardTichkness, aquitardHasEnoughThickness , cMinAquitardThickness));
return aquitardHasEnoughThickness;
}
///
/// Condition: Droogtegevoeilige kade
///
///
private bool EvaluateDikeIsDrySensitive()
{
// Evaluate dry sensivity of dike
// with uplift calculation the pl-lines will be created different when dikematerial is of type peat
bool isDrySensitive = (dikeDrySensitivity == DikeDrySensitivity.Dry);
System.Diagnostics.Debug.Print(String.Format("Is dry sensitive dike is {0} (check on material)", isDrySensitive));
if (isDrySensitive)
{
double gradient = (GetBoezemLevel() - location.PolderLevelLow);
isDrySensitive = gradient > cMinHeadGradient;
System.Diagnostics.Debug.Print(String.Format("Is dry sensitive dike is {0} because Gradient in dike ({1}) more than {2} meter", isDrySensitive, gradient, cMinHeadGradient));
}
if (isDrySensitive)
{
double? upliftFactor = 0.0;
// upliftFactor = GetLowestUpliftFactor(); ## Bka
if (upliftFactor != null)
{
isDrySensitive = (upliftFactor.Value < cMinUpliftFactor);
System.Diagnostics.Debug.Print(String.Format("Is dry sensitive dike is {0} because upliftfactor ({1}) more than {2}", isDrySensitive, upliftFactor.Value, cMinUpliftFactor));
}
else
{
isDrySensitive = false;
}
}
return isDrySensitive;
}
///
/// Condition: Dikte kleilaag in waterremmende laag kleiner 2 meter of dikte waterremmende kleiner 5 meter
///
///
private bool EvaluateClayInAquitardTooThin()
{
var aquitardEvaluator = new AquitardEvaluator(soilGeometry.SoilProfile);
double aquitardThicknessWithoutMinimalWeight = aquitardEvaluator.DetermineAquitardThicknessWithoutMinimalWeight(GetBoezemBottomOrSheetPileBottom(), this.location.GetDikeEmbankmentSoil());
double claythickness = aquitardEvaluator.DetermineAquitardClayThickness(GetBoezemBottomOrSheetPileBottom());
bool clayInAquitardTooThin = (aquitardThicknessWithoutMinimalWeight < cMinAquitardThicknessIfDrySensitive);
clayInAquitardTooThin = clayInAquitardTooThin || (claythickness < cMinClayThickness);
System.Diagnostics.Debug.Print(String.Format("For dry sensitive dike aquitard thickness ({0} < {1}) or clay thickness ({2} < {3}) evaluate to {4}",
aquitardThicknessWithoutMinimalWeight, cMinAquitardThicknessIfDrySensitive, claythickness, cMinClayThickness, clayInAquitardTooThin));
return clayInAquitardTooThin;
}
///
/// Condition: Boezempeil kleiner of gelijk aan stijghoogte eerste WVP
///
///
private bool EvaluateBoezemLevelBelowHeadAquifer()
{
double boezemLevel = GetBoezemLevel();
bool boezemLevelBelowHeadAquifer = boezemLevel <= location.HeadPl3;
System.Diagnostics.Debug.Print(String.Format("Storage basin level ({0}) below head Aquifer WVP ({1}) is {2}", boezemLevel, location.HeadPl3, boezemLevelBelowHeadAquifer));
return boezemLevelBelowHeadAquifer;
}
private double GetBoezemBottomOrSheetPileBottom()
{
double boezemBottom = location.DredgingDepth;
if (location.SheetPileLength > 0)
{
double rwBankProtectionBottomLevel = location.RwBankProtectionBottomLevel;
boezemBottom = Math.Min(boezemBottom, rwBankProtectionBottomLevel);
//// sheetpile is available
//if (location.LocalXZSheetPilePoint.X < location.LocalXZSurfaceLine.CharacteristicPoints[CharacteristicPointType.DikeTopAtRiver].X)
//{
// double sheetpilePointLevel = location.LocalXZSheetPilePoint.Z - location.SheetPileLength;
// boezemBottom = Math.Min(boezemBottom, sheetpilePointLevel);
//}
//else
//{
// System.Diagnostics.Debug.Print(String.Format("Ignored sheetpile because X sheetpile ({0}) is larger than X dike crest at river ({1})",
// location.LocalXZSheetPilePoint.X, location.LocalXZSurfaceLine.CharacteristicPoints[CharacteristicPointType.DikeTopAtRiver].X));
//}
}
return boezemBottom;
}
///
/// Determine boezemlevel according to loadsituation
///
///
private double GetBoezemLevel()
{
double boezemLevel = 0.0;
switch (loadSituation)
{
case LoadSituation.Wet:
boezemLevel = location.BoezemLevelTp;
break;
case LoadSituation.Dry:
boezemLevel = location.BoezemLevelHbp;
break;
}
return boezemLevel;
}
///
/// Create PL-lines
///
///
// private PLLines CreatePLLines()
// {
// PLLinesCreator plLinesCreator = new PLLinesCreator();
// plLinesCreator.WaterLevelRiverHigh = GetBoezemLevel();
// plLinesCreator.HeadInPLLine2 = location.HeadPL2;
// plLinesCreator.HeadInPLLine3 = location.HeadPl3;
// plLinesCreator.HeadInPLLine4 = location.HeadPl4;
//
// plLinesCreator.SurfaceLine = location.LocalXZSurfaceLine2;
// plLinesCreator.WaterLevelPolder = location.PolderLevel;
// plLinesCreator.ModelParametersForPLLines = location.CreateModelParametersForPLLines();
// plLinesCreator.SoilProfile1D = soilGeometry.SoilProfile1D;
// plLinesCreator.StiFileName = null;
// plLinesCreator.SoilProfileType = SoilProfileType.ProfileType1D;
// plLinesCreator.GaugePLLines = null;
// plLinesCreator.Gauges = null;
// plLinesCreator.GaugeMissVal = 0.0;
// plLinesCreator.IsAdjustPL3AndPL4SoNoUpliftWillOccurEnabled = true; // for stability this must set to true
// plLinesCreator.PlLineOffsetBelowDikeTopAtRiver = location.PlLineOffsetBelowDikeTopAtRiver;
// plLinesCreator.PlLineOffsetBelowDikeTopAtPolder = location.PlLineOffsetBelowDikeTopAtPolder;
// plLinesCreator.SoilBaseDB = null; // soilbase;
// plLinesCreator.DikeEmbankmentMaterial = null; // soilbase.GetSoil(location.DikeEmbankmentMaterial);
// plLinesCreator.IsUseOvenDryUnitWeight = (dikeDrySensitivity == DikeDrySensitivity.Dry);
// plLinesCreator.IsHydraulicShortcut = false; // in this evaluation obviously no hydraulic shortcut
// plLinesCreator.XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin;
//
// PLLines plLines = plLinesCreator.CreateAllPLLines(location);
// return plLines;
// }
///
/// Determine where lowest uplift factor occurs and the value of that factor
///
///
// private double? GetLowestUpliftFactor()
// {
//
// UpliftLocationDeterminator upliftLocationDeterminator = new UpliftLocationDeterminator()
// {
// SurfaceLine = location.SurfaceLine2,
// SoilProfile1D = soilGeometry.SoilProfile1D,
// StiFileName = null,
// SoilBaseDB = null, //soilbase,
// DikeEmbankmentMaterial = location.GetDikeEmbankmentSoil(),
// PLLines = CreatePLLines(),
// IsUseOvenDryUnitWeight = (dikeDrySensitivity == DikeDrySensitivity.Dry),
// XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin
// };
// UpliftLocationAndResult upliftLocationAndResult = upliftLocationDeterminator.GetLocationAtWithLowestUpliftFactor();
// if (upliftLocationAndResult != null)
// return upliftLocationAndResult.UpliftFactor;
// else
// return null;
// }
}
}