// Copyright (C) Stichting Deltares 2017. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets is free software: you can redistribute it and/or modify // it under the terms of the GNU 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 General Public License for more details. // // You should have received a copy of the GNU 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 Ringtoets.MacroStabilityInwards.Primitives; namespace Ringtoets.MacroStabilityInwards.Data { /// /// Defines extension methods dealing with instances. /// public static class MacroStabilityInwardsSoilProfileExtensions { /// /// Retrieves the thickness of the consecutive aquifer layers (if any) which are (partly) under a certain . /// Only the thickness of the part of the aquifer layer under the level is determined. /// /// The soil profile containing to consider. /// The level under which the aquifer layers are sought. /// The thickness of the part of the consecutive aquifer layer(s) (partly) under the . public static double GetTopmostConsecutiveAquiferLayerThicknessBelowLevel(this PipingSoilProfile soilProfile, double level) { return TotalThicknessOfConsecutiveLayersBelowLevel( soilProfile, level, soilProfile.GetConsecutiveAquiferLayersBelowLevel(level).ToArray()); } /// /// Retrieves the thickness of the consecutive coverage layers (if any) which are (partly) under a certain . /// Only the thickness of the part of the coverage layer under the level is determined. /// /// The soil profile containing to consider. /// The level under which the coverage layers are sought. /// The thickness of the part of the consecutive coverage layer(s) (partly) under the . public static double GetConsecutiveCoverageLayerThicknessBelowLevel(this PipingSoilProfile soilProfile, double level) { return TotalThicknessOfConsecutiveLayersBelowLevel( soilProfile, level, soilProfile.GetConsecutiveCoverageLayersBelowLevel(level).ToArray()); } /// /// Retrieves the collection of aquifer layers below a certain . /// /// The soil profile containing to consider. /// The level under which the aquifer layers are sought. /// The collection of consecutive aquifer layer(s) (partly) under the . public static IEnumerable GetConsecutiveAquiferLayersBelowLevel(this PipingSoilProfile soilProfile, double level) { return GetConsecutiveLayers(soilProfile, level, true); } /// /// Retrieves the collection of aquitard layers below a certain . /// /// The soil profile containing to consider. /// The level under which the aquitard layers are sought. /// The collection of consecutive aquitard layer(s) (partly) under the . public static IEnumerable GetConsecutiveCoverageLayersBelowLevel(this PipingSoilProfile soilProfile, double level) { PipingSoilLayer topAquiferLayer = soilProfile.GetConsecutiveAquiferLayersBelowLevel(level).FirstOrDefault(); if (topAquiferLayer != null) { PipingSoilLayer[] aquitardLayers = GetConsecutiveLayers(soilProfile, level, false).ToArray(); if (aquitardLayers.Any() && topAquiferLayer.Top < aquitardLayers.First().Top) { return aquitardLayers; } } return Enumerable.Empty(); } /// /// Calculates the thickness of a collection of consecutive . /// /// The containing the . /// The level under which to calculate the total thickness. /// Collection of consecutive , ordered by /// which are part of . /// The total thickness of the consecutive layers below the given . /// Thrown when either or /// is null. /// Thrown when the bottommost is not part of /// . private static double TotalThicknessOfConsecutiveLayersBelowLevel(PipingSoilProfile soilProfile, double level, PipingSoilLayer[] layers) { if (soilProfile == null) { throw new ArgumentNullException(nameof(soilProfile)); } if (layers == null) { throw new ArgumentNullException(nameof(layers)); } if (layers.Length == 0) { return double.NaN; } PipingSoilLayer bottomLayer = layers.Last(); PipingSoilLayer topLayer = layers.First(); return Math.Min(topLayer.Top, level) - (bottomLayer.Top - soilProfile.GetLayerThickness(bottomLayer)); } /// /// Gets consecutive layers in the which have an aquifer property of . /// /// The soil profile containing to consider. /// The level under which the aquitard layers are sought. /// Value indicating whether the consecutive layers should be aquifer or aquitard. /// The collection of consecutive layer(s) with an aquifer property equal to /// under the . private static IEnumerable GetConsecutiveLayers(PipingSoilProfile soilProfile, double level, bool isAquifer) { if (level < soilProfile.Bottom) { yield break; } var yielding = false; foreach (PipingSoilLayer soilLayer in soilProfile.Layers) { if (soilLayer.IsAquifer == isAquifer && IsSoilLayerPartlyBelowLevel(soilProfile, soilLayer, level)) { yielding = true; yield return soilLayer; } if (yielding && soilLayer.IsAquifer != isAquifer) { yield break; } } } private static bool IsSoilLayerPartlyBelowLevel(PipingSoilProfile soilProfile, PipingSoilLayer soilLayer, double level) { return soilLayer.Top < level || soilLayer.Top - soilProfile.GetLayerThickness(soilLayer) < level; } } }