// 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");
}
}
}