// 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.Linq; using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon; using Deltares.DamEngine.Data.General; using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; namespace Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityInwards; public class UpliftVanGridCreator { /// Determines the UpliftVan grid from settings. /// the slip circle definition /// The surface line. /// public static UpliftVanCalculationGrid DetermineGridsFromSettings( SlipCircleDefinition slipCircleDefinition, SurfaceLine2 surfaceLine) { var upliftVanCalculationGrid = new UpliftVanCalculationGrid { IsGridsAutomatic = false, IsTangentLinesAutomatic = false }; if (slipCircleDefinition.GridSizeDetermination == GridSizeDetermination.Specified) { // Define specified active (left) grid if (surfaceLine != null) { // Use middle of the dike for X-coordinate GeometryPoint dikeTopAtRiverPoint = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); GeometryPoint dikeTopAtPolderPoint = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); double gridXCoordinate = (dikeTopAtRiverPoint.X + dikeTopAtPolderPoint.X) * 0.5; double gridYCoordinate = surfaceLine.Geometry.GetZatX(gridXCoordinate); double gridWidth = slipCircleDefinition.UpliftVanLeftGridHorizontalPointDistance * (slipCircleDefinition.UpliftVanLeftGridHorizontalPointCount - 1); double gridHeight = slipCircleDefinition.UpliftVanLeftGridVerticalPointDistance * (slipCircleDefinition.UpliftVanLeftGridVerticalPointCount - 1); upliftVanCalculationGrid.LeftGridXLeft = gridXCoordinate; upliftVanCalculationGrid.LeftGridXRight = gridXCoordinate + gridWidth; upliftVanCalculationGrid.LeftGridXCount = slipCircleDefinition.UpliftVanLeftGridHorizontalPointCount; upliftVanCalculationGrid.LeftGridZBottom = gridYCoordinate; upliftVanCalculationGrid.LeftGridZTop = gridYCoordinate + gridHeight; upliftVanCalculationGrid.LeftGridZCount = slipCircleDefinition.UpliftVanLeftGridVerticalPointCount; } // Define specified passive (right) grid if (surfaceLine != null) { const double gridOffset = 0.2; GeometryPoint dikeToeAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); // X-coordinates settings of the grid double gridWidth = slipCircleDefinition.UpliftVanRightGridHorizontalPointDistance * (slipCircleDefinition.UpliftVanRightGridHorizontalPointCount - 1); // The grid starts at either last uplift point X-coordinate - gridWidth or dike toe at polder X-coordinate, whichever is largest double gridXCoordinate = Math.Max(slipCircleDefinition.XCoordinateLastUpliftPoint - gridWidth, dikeToeAtPolder.X); upliftVanCalculationGrid.RightGridXLeft = gridXCoordinate; // The grid is limited to the right boundary of the surfaceline double boundaryRight = surfaceLine.CharacteristicPoints.Geometry.GetGeometryBounds().Right; upliftVanCalculationGrid.RightGridXRight = Math.Min(gridXCoordinate + gridWidth, boundaryRight); upliftVanCalculationGrid.RightGridXCount = slipCircleDefinition.UpliftVanRightGridHorizontalPointCount; // Z-coordinates settings of the grid double gridHeight = slipCircleDefinition.UpliftVanRightGridVerticalPointDistance * (slipCircleDefinition.UpliftVanRightGridVerticalPointCount - 1); upliftVanCalculationGrid.RightGridZBottom = dikeToeAtPolder.Z + gridOffset; upliftVanCalculationGrid.RightGridZTop = upliftVanCalculationGrid.RightGridZBottom + gridHeight; upliftVanCalculationGrid.RightGridZCount = slipCircleDefinition.UpliftVanRightGridVerticalPointCount; } // Tangent lines are defined in another method } else { // code for slipCircleDefinition.GridSizeDetermination == GridSizeDetermination.Automatic upliftVanCalculationGrid.IsGridsAutomatic = true; } return upliftVanCalculationGrid; } /// Determines the tangent lines. /// The uplift van calculation grid. /// The slip circle definition. /// The soil profile1 d. public static void DetermineTangentLines(UpliftVanCalculationGrid upliftVanCalculationGrid, SlipCircleDefinition slipCircleDefinition, SoilProfile1D soilProfile1D) { switch (slipCircleDefinition.UpliftVanTangentLinesDefinition) { case TangentLinesDefinition.OnBoundaryLines: // In the kernel, the tangent lines are set to the boundaries, no need to do anything here. upliftVanCalculationGrid.IsTangentLinesAutomatic = false; break; case TangentLinesDefinition.Specified: DetermineTangentLinesSpecified(upliftVanCalculationGrid, soilProfile1D, slipCircleDefinition.UpliftVanTangentLinesDistance); break; } } private static void DetermineTangentLinesSpecified(UpliftVanCalculationGrid upliftVanCalculationGrid, SoilProfile1D soilProfile1D, double distance) { if (!(distance > 0)) { throw new ArgumentException($"Vertical distance should be > 0 but is {distance}"); } double topOfBottomLayer = soilProfile1D.Layers.Last().TopLevel; if (soilProfile1D.LayerCount == 1) { topOfBottomLayer = 0.5 * (soilProfile1D.Layers.Last().TopLevel + soilProfile1D.Layers.Last().BottomLevel); } double surfaceLevel = soilProfile1D.Layers.First().TopLevel; double bottomTangentLines = topOfBottomLayer - distance; bottomTangentLines = Math.Min(bottomTangentLines, surfaceLevel); double topTangentLines = bottomTangentLines; var tangentLinesCount = 1; upliftVanCalculationGrid.TangentLineLevels.Add(topTangentLines); while (topTangentLines < surfaceLevel) { topTangentLines += distance; upliftVanCalculationGrid.TangentLineLevels.Add(topTangentLines); tangentLinesCount++; } upliftVanCalculationGrid.TangentLineLevels.Reverse(); upliftVanCalculationGrid.TangentLineCount = tangentLinesCount; upliftVanCalculationGrid.TangentLineZTop = topTangentLines; upliftVanCalculationGrid.TangentLineZBottom = bottomTangentLines; } }