Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/RegionalAssessment/HydraulicShortcut/HydraulicShortcutEvaluatorTests.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/RegionalAssessment/HydraulicShortcut/HydraulicShortcutEvaluatorTests.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/RegionalAssessment/HydraulicShortcut/HydraulicShortcutEvaluatorTests.cs (revision 1046) @@ -0,0 +1,178 @@ +// 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 Deltares.DamEngine.Calculators.RegionalAssessment.HydraulicShortcut; +using Deltares.DamEngine.Data.General; +using Deltares.DamEngine.Data.Geotechnics; +using Deltares.DamEngine.TestHelpers.Factories; +using NUnit.Framework; + +namespace Deltares.DamEngine.Calculators.Tests.RegionalAssessment.HydraulicShortcut +{ + [TestFixture] + public class HydraulicShortcutEvaluatorTests + { + [Test] + public void CanEvaluateTo_HydraulicShortcut() + { + var hydraulicShortcutEvaluator = new HydraulicShortcutEvaluator(); + var lineTutorial1 = FactoryForSurfaceLines.CreateSurfaceLineTutorial1(); + var location = CreateLocation(lineTutorial1); + var soilProfile = FactoryForSoilProfiles.CreateClaySandProfile(); + var previousChoices = CreateChoices(); + + var hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + // Top of aquifer is -5.0 + // DredgingDepth (boezembodem) = -4.0 + // Aquitard = 1, so < 2.0 m, so HydraulicShortcut + Assert.AreEqual(HydraulicShortcutType.HydraulicShortcut, hydraulicShortcut); + } + + [Test] + [Ignore("Failing test because of change in SVN rev. 8773; test should be improved")] + public void SheetPileIsAppliedInBoezemBottomDetermination() + { + var hydraulicShortcutEvaluator = new HydraulicShortcutEvaluator(); + var surfaceLineTutorial1 = FactoryForSurfaceLines.CreateSurfaceLineTutorial1(); + var location = CreateLocation(surfaceLineTutorial1); + var previousChoices = CreateChoices(); + location.DikeMaterialType = SoilType.Clay; + previousChoices[1] = DikeDrySensitivity.Dry; + var soilProfile = FactoryForSoilProfiles.CreateClaySandProfile(); + location.DredgingDepth = -2; + + var hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + // Top of aquifer is -5.0 + // DredgingDepth (boezembodem) = -2.0 + // Aquitard = 3, so > 2.0 m, so next check + // Dikematerial = clay so next check + Assert.AreEqual(HydraulicShortcutType.NoHydraulicShortcut, hydraulicShortcut); + + location.SheetPileLength = location.LocalXZSheetPilePoint.Z + 4.0; + location.RwBankProtectionBottomLevel = -4; + + // Top of aquifer is -5.0 + // level of sheetpile point = -4.0 + // Aquitard = 1, so < 2.0 m, so HydarulicShortcut + hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + Assert.AreEqual(HydraulicShortcutType.HydraulicShortcut, hydraulicShortcut); + } + + [Test] + public void CanEvaluateTo_NoHydraulicShortcut_IfBoezemLevelLowerThanHeadAquifer() + { + var hydraulicShortcutEvaluator = new HydraulicShortcutEvaluator(); + var surfaceLineTutorial1 = FactoryForSurfaceLines.CreateSurfaceLineTutorial1(); + var location = CreateLocation(surfaceLineTutorial1); + var previousChoices = CreateChoices(); + var soilProfile = FactoryForSoilProfiles.CreateClaySandProfile(); + + // Dry situation + location.HeadPl3 = location.BoezemLevelHbp + 0.1; + var hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + Assert.AreEqual(HydraulicShortcutType.NoHydraulicShortcut, hydraulicShortcut); + + // Wet situation + previousChoices[0] = LoadSituation.Wet; + location.HeadPl3 = location.BoezemLevelTp + 0.1; + hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + Assert.AreEqual(HydraulicShortcutType.NoHydraulicShortcut, hydraulicShortcut); + } + + [Test] + public void CanEvaluateTo_NoHydraulicShortcut_IfNotDrySensitive() + { + var hydraulicShortcutEvaluator = new HydraulicShortcutEvaluator(); + var surfaceLineTutorial1 = FactoryForSurfaceLines.CreateSurfaceLineTutorial1(); + var location = CreateLocation(surfaceLineTutorial1); + var previousChoices = CreateChoices(); + var soilProfile = FactoryForSoilProfiles.CreateHeavyClaySandProfileForHydraulicShortcutEvaluator(); + + // Dry situation + previousChoices[0] = LoadSituation.Dry; + previousChoices[1] = DikeDrySensitivity.None; + location.DredgingDepth = -2.0; + location.DikeMaterialType = SoilType.Clay; + previousChoices[1] = DikeDrySensitivity.None; + var hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + // Top of aquifer is -5.0 + // DredgingDepth (boezembodem) = -2.0 + // Aquitard = 3, so > 2.0 m, so so check next condition + // Dike is clay, so no HydraulicShortcut + Assert.AreEqual(HydraulicShortcutType.NoHydraulicShortcut, hydraulicShortcut); + + location.PolderLevelLow = location.BoezemLevelHbp - 0.5; + location.DikeMaterialType = SoilType.Peat; + previousChoices[1] = DikeDrySensitivity.Dry; + // Dike is peat, so check next condition + // Gradient is 0.5 meter, so less than 1 meter, so NoHydraulicShortcut + hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + Assert.AreEqual(HydraulicShortcutType.NoHydraulicShortcut, hydraulicShortcut); + + location.PolderLevelLow = location.BoezemLevelHbp - 1.5; + // Dike is peat, so check next condition + // Gradient is 1.5 meter, so more than 1 meter, so check next condition + // UpliftFactor more than 1.2 so NoHydraulicShortcut + hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + Assert.AreEqual(HydraulicShortcutType.NoHydraulicShortcut, hydraulicShortcut); + + soilProfile.Layers[0].Soil.AbovePhreaticLevel = 10.0; + soilProfile.Layers[0].Soil.BelowPhreaticLevel = 12.0; + location.DredgingDepth = 1.0; + // Dike is peat, so check next condition + // Gradient is 1.5 meter, so more than 1 meter, so check next condition + // UpliftFactor less than 1.2 so check next condition + // Top of aquifer is -5.0 + // DredgingDepth = 1 + // Aquitard = 6, so > 5.0 m, so NoHydraulicShortcut + hydraulicShortcut = (HydraulicShortcutType)hydraulicShortcutEvaluator.Evaluate(location, new SoilGeometry(soilProfile, null), previousChoices); + Assert.AreEqual(HydraulicShortcutType.NoHydraulicShortcut, hydraulicShortcut); + } + + + private Enum[] CreateChoices() + { + Enum[] choices = new Enum[2]; + choices[0] = LoadSituation.Dry; + choices[1] = DikeDrySensitivity.None; + return choices; + } + + private Location CreateLocation(SurfaceLine2 surfaceline) + { + var location = new Location + { + Name = "Test location", + DredgingDepth = -4.0, + BoezemLevelTp = 2.0, + BoezemLevelHbp = 1.8 + }; + location.HeadPl3 = location.BoezemLevelHbp - 0.1; + location.HeadPl4 = location.BoezemLevelHbp - 0.1; + location.SurfaceLine = surfaceline; + location.LocalXZSheetPilePoint = location.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver); + location.SheetPileLength = 0.0; + + return location; + } + } +} Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj =================================================================== diff -u -r1040 -r1046 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj (.../Deltares.DamEngine.Calculators.csproj) (revision 1040) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Deltares.DamEngine.Calculators.csproj (.../Deltares.DamEngine.Calculators.csproj) (revision 1046) @@ -62,6 +62,8 @@ + + Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/RegionalAssessment/HydraulicShortcut/HydraulicShortcutEvaluator.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/RegionalAssessment/HydraulicShortcut/HydraulicShortcutEvaluator.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/RegionalAssessment/HydraulicShortcut/HydraulicShortcutEvaluator.cs (revision 1046) @@ -0,0 +1,284 @@ +// 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.Calculators.PlLinesCreator; +using Deltares.DamEngine.Calculators.Uplift; +using Deltares.DamEngine.Data.General; +using Deltares.DamEngine.Data.General.PlLines; +using Deltares.DamEngine.Data.RWScenarios; + +namespace Deltares.DamEngine.Calculators.RegionalAssessment.HydraulicShortcut +{ + /// + /// Class which determines whether there is hydraulic shortcut or not. + /// + /// + public class HydraulicShortcutEvaluator: Evaluator.Evaluator + { + 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; + + /// + /// Evaluates the specified location. + /// + /// The location. + /// The soil geometry. + /// The previous choices. + /// + public override Enum Evaluate(Location aLocation, SoilGeometry aSoilGeometry, params Enum[] aPreviousChoices) + { + base.Evaluate(aLocation, aSoilGeometry, aPreviousChoices); + HydraulicShortcutType hydraulicShortcutType; + + // Determine dikeDrySensitivity and loadsituation + Dictionary choices = new Dictionary(); + foreach (Enum enumValue in aPreviousChoices) + { + if (enumValue != null) + { + choices[enumValue.GetType()] = enumValue; + } + } + dikeDrySensitivity = (DikeDrySensitivity)choices[typeof(DikeDrySensitivity)]; + loadSituation = (LoadSituation)choices[typeof(LoadSituation)]; + // 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; + } + } + } + } + return hydraulicShortcutType; + } + + /// + /// Condition: Dikte waterremmende laag minstens 2 meter + /// + /// + private bool EvaluateAquitardHasEnoughThickness() + { + var aquitardEvaluator = new AquitardEvaluator(soilGeometry.SoilProfile); + double aquitardTichkness = aquitardEvaluator.DetermineAquitardThicknessWithMinimalWeight(location.DredgingDepth, location.GetDikeEmbankmentSoil()); // Note: do not evaluate sheetpile here + bool aquitardHasEnoughThickness = (aquitardTichkness >= 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); + if (isDrySensitive) + { + double gradient = (GetBoezemLevel() - location.PolderLevelLow); + isDrySensitive = gradient > cMinHeadGradient; + } + if (isDrySensitive) + { + var upliftFactor = GetLowestUpliftFactor(); + if (upliftFactor != null) + { + 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(), location.GetDikeEmbankmentSoil()); + double claythickness = aquitardEvaluator.DetermineAquitardClayThickness(GetBoezemBottomOrSheetPileBottom()); + + bool clayInAquitardTooThin = (aquitardThicknessWithoutMinimalWeight < cMinAquitardThicknessIfDrySensitive); + clayInAquitardTooThin = clayInAquitardTooThin || (claythickness < cMinClayThickness); + + return clayInAquitardTooThin; + } + + /// + /// Condition: Boezempeil kleiner of gelijk aan stijghoogte eerste WVP + /// + /// + private bool EvaluateBoezemLevelBelowHeadAquifer() + { + double boezemLevel = GetBoezemLevel(); + bool boezemLevelBelowHeadAquifer = boezemLevel <= location.HeadPl3; + 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 + { + WaterLevelRiverHigh = GetBoezemLevel(), + HeadInPLLine2 = location.HeadPl2, + HeadInPLLine3 = location.HeadPl3, + HeadInPLLine4 = location.HeadPl4, + SurfaceLine = location.SurfaceLine, + WaterLevelPolder = location.PolderLevel, + ModelParametersForPLLines = location.ModelParametersForPLLines, + SoilProfile = soilGeometry.SoilProfile, + SoilGeometry2DName = null, + SoilProfileType = SoilProfileType.ProfileType1D, + GaugePLLines = null, + Gauges = null, + GaugeMissVal = 0.0, + IsAdjustPL3AndPL4SoNoUpliftWillOccurEnabled = true, + PlLineOffsetBelowDikeTopAtRiver = location.PlLineOffsetBelowDikeTopAtRiver, + PlLineOffsetBelowDikeTopAtPolder = location.PlLineOffsetBelowDikeTopAtPolder, + DikeEmbankmentMaterial = null, + IsUseOvenDryUnitWeight = (dikeDrySensitivity == DikeDrySensitivity.Dry), + IsHydraulicShortcut = false, + XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin + }; + + // for stability this must set to true + // soilbase.GetSoil(location.DikeEmbankmentMaterial); + // in this evaluation obviously no hydraulic shortcut + + 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.SurfaceLine, + SoilProfile = soilGeometry.SoilProfile, + SoilGeometry2DName = null, + 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; + } + } +} Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/Deltares.DamEngine.Calculators.Tests.csproj =================================================================== diff -u -r1036 -r1046 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/Deltares.DamEngine.Calculators.Tests.csproj (.../Deltares.DamEngine.Calculators.Tests.csproj) (revision 1036) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/Deltares.DamEngine.Calculators.Tests.csproj (.../Deltares.DamEngine.Calculators.Tests.csproj) (revision 1046) @@ -49,6 +49,7 @@ + Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/RegionalAssessment/Evaluator/Evaluator.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/RegionalAssessment/Evaluator/Evaluator.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/RegionalAssessment/Evaluator/Evaluator.cs (revision 1046) @@ -0,0 +1,56 @@ +// 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 System.Linq; +using System.Text; +using System.Threading.Tasks; +using Deltares.DamEngine.Data.General; + +namespace Deltares.DamEngine.Calculators.RegionalAssessment.Evaluator +{ + /// + /// Base class for all evaluators used in the Regional Assessment. + /// + public class Evaluator + { + protected Location location; + protected SoilGeometry soilGeometry; + private Enum[] previousChoices; + + /// + /// Evaluates the specified a location. + /// + /// a location. + /// a soil geometry. + /// a previous choices. + /// + public virtual Enum Evaluate(Location aLocation, SoilGeometry aSoilGeometry, params Enum[] aPreviousChoices) + { + this.location = aLocation; + this.soilGeometry = aSoilGeometry; + this.previousChoices = aPreviousChoices; + + return null; + } + } +}