// Copyright (C) Stichting Deltares 2017. 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 Deltares.DamEngine.Data.General; using Deltares.DamEngine.Data.General.PlLines; using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; namespace Deltares.DamEngine.Calculators.Uplift { /// /// Exception for UpliftLocationDeterminator class /// public class UpliftLocationDeterminatorException : 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 UpliftLocationDeterminatorException() { } public UpliftLocationDeterminatorException(string message) : base(message) { } } /// /// Data class containing information about uplift location and uplift factor /// public class UpliftLocationAndResult : GeometryPoint { public UpliftLocationAndResult() { UpliftFactor = 0; LayerWhereUpliftOccuresId = ""; } public UpliftLocationAndResult(double upliftFactor, string layerWhereUpliftOccuresId) { UpliftFactor = upliftFactor; LayerWhereUpliftOccuresId = layerWhereUpliftOccuresId; } public UpliftLocationAndResult(GeometryPoint point, double upliftFactor, string layerWhereUpliftOccuresId) { X = point.X; Y = point.Y; Z = point.Z; UpliftFactor = upliftFactor; LayerWhereUpliftOccuresId = layerWhereUpliftOccuresId; } public double? UpliftFactor { get; set; } public string LayerWhereUpliftOccuresId { get; set; } } /// /// Determie uplift location and uplift factor /// public class UpliftLocationDeterminator { public bool IsUseOvenDryUnitWeight { get; set; } public PLLines PLLines { get; set; } public SurfaceLine2 SurfaceLine { get; set; } public SoilProfile1D SoilProfile { get; set; } public SoilProfile2D SoilProfile2D { get; set; } public string SoilGeometry2DName { get; set; } public Soil DikeEmbankmentMaterial { get; set; } // public SoilbaseDB SoilBaseDB { get; set; } public SoilList SoilList { get; set; } public double XSoilGeometry2DOrigin { get; set; } /// /// Constructor /// public UpliftLocationDeterminator() { IsUseOvenDryUnitWeight = false; } /// /// Get location nearest dike with and upliftfactor lower than required /// /// location and upliftfactor public UpliftLocationAndResult GetLocationAndResult(double upliftCriterion) { ThrowIfNoPLLinesDefined(); ThrowIfNoSurfaceLinDefined(); ThrowIfNoSoilProfileDefined(); return GetLocationInPolderNearestDikeWithUpliftFactorLowerThanRequired(upliftCriterion); } /// /// Get location nearest dike with and upliftfactor lower than required /// /// location and upliftfactor public UpliftLocationAndResult GetLocationInPolderNearestDikeWithUpliftFactorLowerThanRequired(double upliftCriterion) { ThrowIfNoPLLinesDefined(); ThrowIfNoSurfaceLinDefined(); ThrowIfNoSoilProfileDefined(); GeometryPoint startSurfacePoint = SurfaceLine.GetDikeToeInward(); IEnumerable relevantSurfacePointsList = from GeometryPoint point in SurfaceLine.Geometry.Points where point.X >= startSurfacePoint.X orderby point.X ascending select point; bool foundUpliftFactor = false; UpliftLocationAndResult upliftLocationAndResult = null; foreach (GeometryPoint surfacePoint in relevantSurfacePointsList) { upliftLocationAndResult = GetUpliftFactorAtPoint(surfacePoint); if ((upliftLocationAndResult != null) && (upliftLocationAndResult.UpliftFactor < upliftCriterion)) { foundUpliftFactor = true; upliftLocationAndResult.X = surfacePoint.X; upliftLocationAndResult.Z = surfacePoint.Z; break; } } return (foundUpliftFactor == true) ? upliftLocationAndResult : null; } /// /// Create upliftcalculator at given point /// /// GeometryPoint for which to calculate upliftfactor /// Top of layer where uplift occurs /// location and upliftfactor private UpliftCalculator CreateUpliftCalculator(GeometryPoint point, double topOfLayer, SoilProfile1D soilProfile) { PLLine phreaticLine = PLLines.Lines[PLLineType.PL1]; return new UpliftCalculator { PhreaticLevel = phreaticLine.ZFromX(point.X), SoilProfile = soilProfile, TopOfLayerToBeEvaluated = topOfLayer, SurfaceLevel = point.Z, UnitWeightSoilEmbankment = (this.DikeEmbankmentMaterial == null) ? (double?) null : this.DikeEmbankmentMaterial.AbovePhreaticLevel, IsUseOvenDryUnitWeight = this.IsUseOvenDryUnitWeight }; } /// /// Calculate upliftfactor for given point /// /// /// location and upliftfactor public UpliftLocationAndResult GetUpliftFactorAtPoint(GeometryPoint point) { SoilProfile1D soilProfileInCurrentPoint = GetSoilProfileBelowPoint(point.X); double upliftFactorForInBetweenSandLayer = double.MaxValue; if (soilProfileInCurrentPoint.InBetweenAquiferLayer != null) { // Check if inbetween sandlayer below surface double topInBetweenSandLayer = soilProfileInCurrentPoint.InBetweenAquiferLayer.TopLevel; if (topInBetweenSandLayer < point.Z) { // There is an aquitard above the aquifer, for which we can determine the uplift factor UpliftCalculator upliftCalculatorForInBetweenSandLayer = CreateUpliftCalculator(point, topInBetweenSandLayer, soilProfileInCurrentPoint); if ( (PLLines.Lines[PLLineType.PL4] != null) && (PLLines.Lines[PLLineType.PL4].Points.Count > 0 )) upliftFactorForInBetweenSandLayer = upliftCalculatorForInBetweenSandLayer.CalculateUpliftFactor(PLLines.Lines[PLLineType.PL4].ZFromX(point.X)); } else { if (soilProfileInCurrentPoint.GetBottomLevel(soilProfileInCurrentPoint.InBetweenAquiferLayer) < point.Z) { // The surface cuts into the aquifer so the level to be evaluated is at surfacelevel UpliftCalculator upliftCalculatorForInBetweenSandLayer = CreateUpliftCalculator(point, point.Z, soilProfileInCurrentPoint); if ((PLLines.Lines[PLLineType.PL4] != null) && (PLLines.Lines[PLLineType.PL4].Points.Count > 0)) upliftFactorForInBetweenSandLayer = upliftCalculatorForInBetweenSandLayer.CalculateUpliftFactor(PLLines.Lines[PLLineType.PL4].ZFromX(point.X)); } } } double upliftFactorForBottomSandLayer = double.MaxValue; if (soilProfileInCurrentPoint.BottomAquiferLayer != null) { // Check if bottom sandlayer below surface double topBottomSandLayer = soilProfileInCurrentPoint.BottomAquiferLayer.TopLevel; if (topBottomSandLayer < point.Z) { UpliftCalculator upliftCalculatorForBottomSandLayer = CreateUpliftCalculator(point, soilProfileInCurrentPoint.BottomAquiferLayer.TopLevel, soilProfileInCurrentPoint); if ((PLLines.Lines[PLLineType.PL3] != null) && (PLLines.Lines[PLLineType.PL3].Points.Count > 0)) upliftFactorForBottomSandLayer = upliftCalculatorForBottomSandLayer.CalculateUpliftFactor(PLLines.Lines[PLLineType.PL3].ZFromX(point.X)); } else { if (soilProfileInCurrentPoint.GetBottomLevel(soilProfileInCurrentPoint.BottomAquiferLayer) < point.Z) { // The surface cuts into the aquifer so the level to be evaluated is at surfacelevel UpliftCalculator upliftCalculatorForInBetweenSandLayer = CreateUpliftCalculator(point, point.Z, soilProfileInCurrentPoint); if ((PLLines.Lines[PLLineType.PL3] != null) && (PLLines.Lines[PLLineType.PL3].Points.Count > 0)) upliftFactorForBottomSandLayer = upliftCalculatorForInBetweenSandLayer.CalculateUpliftFactor(PLLines.Lines[PLLineType.PL3].ZFromX(point.X)); } } } if((upliftFactorForBottomSandLayer == double.MaxValue) && (upliftFactorForInBetweenSandLayer == double.MaxValue)) return null; if (upliftFactorForBottomSandLayer < upliftFactorForInBetweenSandLayer) { return new UpliftLocationAndResult(point, upliftFactorForBottomSandLayer, soilProfileInCurrentPoint.BottomAquiferLayer.Name); } else { return new UpliftLocationAndResult(point, upliftFactorForInBetweenSandLayer, soilProfileInCurrentPoint.InBetweenAquiferLayer.Name); } } /// /// Determine location with lowest upliftfactor /// /// location and upliftfactor public UpliftLocationAndResult GetLocationAtWithLowestUpliftFactor() { double? lowestUpliftFactor = null; ThrowIfNoPLLinesDefined(); ThrowIfNoSurfaceLinDefined(); ThrowIfNoSoilProfileDefined(); GeometryPoint startSurfacePoint = SurfaceLine.GetDikeToeInward(); IEnumerable relevantSurfacePointsList = from GeometryPoint point in SurfaceLine.Geometry.Points where point.X >= startSurfacePoint.X orderby point.X ascending select point; UpliftLocationAndResult upliftLocationAndResult = null; UpliftLocationAndResult lowestUpliftLocationAndResult = null; foreach (GeometryPoint surfacePoint in relevantSurfacePointsList) { upliftLocationAndResult = GetUpliftFactorAtPoint(surfacePoint); if (upliftLocationAndResult != null) { if (!lowestUpliftFactor.HasValue || upliftLocationAndResult.UpliftFactor < lowestUpliftFactor) { lowestUpliftFactor = upliftLocationAndResult.UpliftFactor; lowestUpliftLocationAndResult = upliftLocationAndResult; } } } return lowestUpliftLocationAndResult; } /// /// /// /// /// private SoilProfile1D GetSoilProfileBelowPoint(double xCoordinate) { if (this.SoilProfile != null) { return this.SoilProfile; } if (SoilProfile2D != null) { return SoilProfile2D.GetSoilProfile1D(xCoordinate); } // Geometry2DTo1DConverter geometry2DTo1DConverter = new Geometry2DTo1DConverter(this.SoilGeometry2DName, this.SurfaceLine, this.DikeEmbankmentMaterial, this.SoilBaseDB, this.SoilList, -this.XSoilGeometry2DOrigin); ##BKA Replace with Conversion as used in DSM // return geometry2DTo1DConverter.Convert(xCoordinate); return null; } /// /// Check on precondition /// private void ThrowIfNoPLLinesDefined() { if (PLLines == null) throw new UpliftLocationDeterminatorException("Required pllines not found"); } /// /// Check on precondition /// private void ThrowIfNoSurfaceLinDefined() { if (SurfaceLine == null) throw new UpliftLocationDeterminatorException("Required surfaceLine line not found"); } /// /// Check on precondition /// private void ThrowIfNoSoilProfileDefined() { if (SoilProfile == null && (SoilGeometry2DName == null || SoilGeometry2DName == "") && SoilProfile2D == null) throw new UpliftLocationDeterminatorException("Required soilProfile not found"); } } }