// Copyright (C) Stichting Deltares 2024. 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.Runtime.Serialization; using Deltares.DamEngine.Data.Geotechnics; namespace Deltares.DamEngine.Calculators.Uplift; [Serializable] public class UpliftCalculatorException : ApplicationException { // // For guidelines regarding the creation of new exception types, see // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp // and // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp // public UpliftCalculatorException() {} public UpliftCalculatorException(string message) : base(message) {} public UpliftCalculatorException(string message, ApplicationException inner) : base(message, inner) {} protected UpliftCalculatorException( SerializationInfo info, StreamingContext context) : base(info, context) {} } public class UpliftCalculator { public UpliftCalculator() { VolumicWeightOfWater = 9.81; UnitWeightSoilEmbankment = null; } public double VolumicWeightOfWater { get; set; } public SoilProfile1D SoilProfile { get; set; } public double TopOfLayerToBeEvaluated { get; set; } public double SurfaceLevel { get; set; } public double PhreaticLevel { get; set; } public double UpLiftTopLevel { get; set; } public double? UnitWeightSoilEmbankment { get; set; } /// /// /// /// /// public double CalculateUpliftFactor(double headOfPlLine) { ThrowWhenSoilProfileIsNull(); SoilVolumicMassCalculator massCalculator = CreateSoilVolumeMassCalculator(); double mass = massCalculator.CalculateTotalMass(); double height = headOfPlLine - TopOfLayerToBeEvaluated; double phreaticPressure = VolumicWeightOfWater * height; if (phreaticPressure > 0) { return mass / phreaticPressure; } return double.MaxValue; } /// /// Calculate soil extra height to be added to obtain the specified upliftFactor with a given head of PLline /// /// /// /// Required extra height public double CalculateExtraHeight(double headOfPlLine, double upliftFactor) { ThrowWhenSoilProfileIsNull(); SoilVolumicMassCalculator massCalculator = CreateSoilVolumeMassCalculator(); double mass = massCalculator.CalculateTotalMass(); double toplevel = Math.Min(SurfaceLevel, TopOfLayerToBeEvaluated); double height = headOfPlLine - toplevel; double phreaticPressure = VolumicWeightOfWater * height; double requiredExtraMass = upliftFactor * phreaticPressure - mass; double unitWeightSoil = SoilProfile.Layers[0].Soil.AbovePhreaticLevel; if (UnitWeightSoilEmbankment != null) { unitWeightSoil = UnitWeightSoilEmbankment.Value; } if (requiredExtraMass > 0) { return requiredExtraMass / unitWeightSoil; } return 0.0; } /// /// /// /// /// public double CalculateHeadOfPlLine(double upliftFactor) { ThrowWhenSoilProfileIsNull(); SoilVolumicMassCalculator massCalculator = CreateSoilVolumeMassCalculator(); double massSoils = massCalculator.CalculateTotalMass(); double massWater = massSoils / (upliftFactor * VolumicWeightOfWater); return massWater + TopOfLayerToBeEvaluated; } /// /// /// /// private SoilVolumicMassCalculator CreateSoilVolumeMassCalculator() { SoilProfile1D updatedSoilProfile = AddTopLayerIfSurfaceLevelHigherThenToplevelSoilProfile(SoilProfile); return new SoilVolumicMassCalculator { PhreaticLevel = PhreaticLevel, SoilProfile = updatedSoilProfile, TopOfLayerToBeEvaluated = TopOfLayerToBeEvaluated, SurfaceLevel = SurfaceLevel, VolumicWeightOfWater = VolumicWeightOfWater }; } /// /// Adds an extra top layer if surface level is higher than toplevel soil profile. /// /// The updated soil profile. /// private SoilProfile1D AddTopLayerIfSurfaceLevelHigherThenToplevelSoilProfile(SoilProfile1D updatedSoilProfile) { if ((SurfaceLevel > SoilProfile.TopLevel) && (UnitWeightSoilEmbankment != null)) { updatedSoilProfile = new SoilProfile1D(); updatedSoilProfile.Assign(SoilProfile); updatedSoilProfile.Layers.Insert(0, new SoilLayer1D(new Soil { AbovePhreaticLevel = UnitWeightSoilEmbankment.Value, BelowPhreaticLevel = UnitWeightSoilEmbankment.Value }, SurfaceLevel)); } return updatedSoilProfile; } /// /// Check precondition /// private void ThrowWhenSoilProfileIsNull() { if (SoilProfile == null) { throw new UpliftCalculatorException("The soilprofile is not defined"); } } }