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