// 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.Collections.Generic;
using System.Data;
using Deltares.DamEngine.Calculators.DikesDesign;
using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces;
using Deltares.DamEngine.Calculators.Properties;
using Deltares.DamEngine.Calculators.Uplift;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.PlLines;
using Deltares.DamEngine.Data.General.Results;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.DamEngine.Data.Standard.Logging;
using Deltares.WTIPiping;
using UpliftLocationAndResult = Deltares.DamEngine.Calculators.Uplift.UpliftLocationAndResult;
namespace Deltares.DamEngine.Calculators.KernelWrappers.WtiPipingSellmeijerRevised;
///
/// Wrapper for Wti Piping SellmeijerRevised kernel
///
public class WtiPipingSellmeijerRevisedKernelWrapper : IKernelWrapper
{
private const double defaultMaxReturnValue = 90.0;
private const double defaultFailedValue = 0.0;
private const double defaultFluidisationGradient = 0.3;
///
/// Prepares the failure mechanism input based on general dam kernel input.
///
/// The dam kernel input.
/// The number of the current iteration
/// The kernel data input.
/// The kernel data output.
///
/// Result of the prepare
///
public PrepareResult Prepare(DamKernelInput damKernelInput, int iterationIndex, out IKernelDataInput kernelDataInput, out IKernelDataOutput kernelDataOutput)
{
var damPipingOutput = new WtiPipingSellmeijerRevisedOutput
{
FoSbe = defaultMaxReturnValue,
FoSu = defaultMaxReturnValue,
FoSh = defaultMaxReturnValue
};
kernelDataOutput = damPipingOutput;
if (damKernelInput.SubSoilScenario != null)
{
if (damKernelInput.SubSoilScenario.SegmentFailureMechanismType.Value.In(
SegmentFailureMechanismType.Piping, SegmentFailureMechanismType.All))
{
SoilProfile1D soilProfile1D = damKernelInput.SubSoilScenario.SoilProfile1D;
Location location = damKernelInput.Location;
double waterLevel = damKernelInput.RiverLevelHigh;
if (double.IsNaN(waterLevel))
{
waterLevel = location.CurrentScenario.RiverLevel;
}
PlLines plLines =
PlLinesHelper.CreatePlLinesForPiping(damKernelInput.TimeStepDateTime, location, soilProfile1D, waterLevel);
if (EvaluateUpliftSituation(damKernelInput, out kernelDataInput, plLines, waterLevel, damPipingOutput))
{
return PrepareResult.Successful;
}
}
}
kernelDataInput = null;
return PrepareResult.NotRelevant;
}
///
/// Validates the kernel data input.
///
/// The kernel data input.
/// The kernel data output.
/// The messages.
///
/// Number of errors that prevent a calculation
///
public int Validate(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out List messages)
{
var wtiPipingSellmeijerRevisedOutput = (WtiPipingSellmeijerRevisedOutput) kernelDataOutput;
messages = new List();
// Validate the WTI Heave calculator
HeaveCalculator calculatorWtiHeave = CreateWtiHeaveCalculator(kernelDataInput);
List kernelMessages = calculatorWtiHeave.Validate();
foreach (string stringMessage in kernelMessages)
{
messages.Add(new LogMessage
{
Message = stringMessage,
MessageType = LogMessageType.Error
});
}
// Validate the WTI Uplift calculator
WTIUpliftCalculator calculatorWtiUplift = CreateWtiUpliftCalculator(kernelDataInput);
kernelMessages.Clear();
kernelMessages = calculatorWtiUplift.Validate();
foreach (string stringMessage in kernelMessages)
{
messages.Add(new LogMessage
{
Message = stringMessage,
MessageType = LogMessageType.Error
});
}
// Validate the WTI Piping calculator
Sellmeijer2011Calculator calculatorWtiSellmeijerRevised = CreatePipingCalculatorWtiSellmeijerRevised(kernelDataInput);
kernelMessages.Clear();
kernelMessages = calculatorWtiSellmeijerRevised.Validate();
foreach (string stringMessage in kernelMessages)
{
messages.Add(new LogMessage
{
Message = stringMessage,
MessageType = LogMessageType.Error
});
}
if (messages.Count > 0)
{
wtiPipingSellmeijerRevisedOutput.CalculationResult = CalculationResult.InvalidInputData;
}
return messages.Count;
}
///
/// Performs a failure mechanism calculation based on the input.
///
/// The kernel data input.
/// The kernel data output.
/// The messages.
public void Execute(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput,
out List messages)
{
var wtiPipingSellmeijerRevisedInput = kernelDataInput as WtiPipingSellmeijerRevisedInput;
var wtiPipingSellmeijerRevisedOutput = (WtiPipingSellmeijerRevisedOutput) kernelDataOutput;
ThrowWhenKernelInputNull(wtiPipingSellmeijerRevisedInput);
ThrowWhenKernelOutputNull(wtiPipingSellmeijerRevisedOutput);
// Initialize result as no run.
wtiPipingSellmeijerRevisedOutput.CalculationResult = CalculationResult.NoRun;
messages = new List();
List upliftMessages;
PerformSingleCalculationWtiUplift(out upliftMessages, wtiPipingSellmeijerRevisedOutput,
wtiPipingSellmeijerRevisedInput);
messages.AddRange(upliftMessages);
if (wtiPipingSellmeijerRevisedOutput.CalculationResult == CalculationResult.Succeeded)
{
List heaveMessages;
PerformSingleCalculationWtiHeave(out heaveMessages, wtiPipingSellmeijerRevisedOutput,
wtiPipingSellmeijerRevisedInput);
messages.AddRange(heaveMessages);
if (wtiPipingSellmeijerRevisedOutput.CalculationResult == CalculationResult.Succeeded)
{
List pipingMessages;
PerformSingleCalculationWtiSellmeijerRevised(out pipingMessages, wtiPipingSellmeijerRevisedOutput,
wtiPipingSellmeijerRevisedInput);
messages.AddRange(pipingMessages);
}
else
{
AssignFailedValuesWtiSellmeijerRevised(wtiPipingSellmeijerRevisedOutput);
}
}
else
{
AssignFailedValuesWtiHeave(wtiPipingSellmeijerRevisedOutput);
AssignFailedValuesWtiSellmeijerRevised(wtiPipingSellmeijerRevisedOutput);
}
if (wtiPipingSellmeijerRevisedOutput.CalculationResult != CalculationResult.Succeeded)
{
if (wtiPipingSellmeijerRevisedOutput.CalculationResult == CalculationResult.InvalidInputStructure ||
wtiPipingSellmeijerRevisedOutput.CalculationResult == CalculationResult.InvalidInputData ||
wtiPipingSellmeijerRevisedOutput.CalculationResult == CalculationResult.UnexpectedError)
{
wtiPipingSellmeijerRevisedOutput.CalculationResult = CalculationResult.RunFailed;
}
var totalMessage = "";
for (var i = 0; i < messages.Count; i++)
{
totalMessage = totalMessage + messages[i].Message + Environment.NewLine;
}
throw new WtiPipingSellmeijerRevisedException(totalMessage);
}
}
///
/// Fills the dam result based on the kernel output.
///
/// The dam kernel input.
/// The kernel data output.
/// The design scenario.
/// The result message.
/// The design results
public void PostProcess(DamKernelInput damKernelInput, IKernelDataOutput kernelDataOutput, DesignScenario designScenario, string resultMessage, out List designResults)
{
var damPipingOutput = kernelDataOutput as WtiPipingSellmeijerRevisedOutput;
ThrowWhenDamKernelInputNull(damKernelInput);
ThrowWhenKernelOutputNull(damPipingOutput);
designResults = new List();
var designResult = new DesignResult(damKernelInput.DamFailureMechanismeCalculationSpecification,
designScenario, damKernelInput.SubSoilScenario.SoilProfile1D, null)
{
CalculationResult = damPipingOutput.CalculationResult
};
var pipingDesignResults = new PipingDesignResults(PipingModelType.Wti2017);
designResult.PipingDesignResults = pipingDesignResults;
pipingDesignResults.ResultMessage = resultMessage;
pipingDesignResults.RedesignedSurfaceLine = damKernelInput.Location.SurfaceLine;
// Make sure defaultMaxReturnValue is limit.
pipingDesignResults.Wti2017BackwardErosionSafetyFactor = Math.Min(damPipingOutput.FoSbe, defaultMaxReturnValue);
pipingDesignResults.Wti2017BackwardErosionHcritical = damPipingOutput.Hcbe;
pipingDesignResults.Wti2017BackwardErosionDeltaPhiC = damPipingOutput.DeltaPhiCbe;
pipingDesignResults.LocalExitPointX = damPipingOutput.ExitPointX;
pipingDesignResults.UpliftFactor = damPipingOutput.UpliftFactor;
pipingDesignResults.UpliftSituation = damPipingOutput.UpliftSituation;
// Add results of the wti-uplift calculation
pipingDesignResults.Wti2017UpliftSafetyFactor = Math.Min(damPipingOutput.FoSu, defaultMaxReturnValue);
pipingDesignResults.Wti2017UpliftHcritical = damPipingOutput.Hcu;
pipingDesignResults.Wti2017UpliftDeltaPhiC = damPipingOutput.DeltaPhiCu;
// Add results of the wti-heave calculation
pipingDesignResults.Wti2017HeaveSafetyFactor = Math.Min(damPipingOutput.FoSh, defaultMaxReturnValue);
pipingDesignResults.Wti2017HeaveHcritical = damPipingOutput.Hch;
pipingDesignResults.Wti2017Gradient = damPipingOutput.Gradient;
pipingDesignResults.EffectiveStress = damPipingOutput.EffectiveStress;
// Add the overall results for WTI piping kernel (FoS = highest value of FoSh, FoSu and FoSbe; HcO is Hcbe belonging to FoS), see MWDAM-1370
double maxFoS = damPipingOutput.FoSbe;
double overallHc = damPipingOutput.Hcbe;
if (damPipingOutput.FoSu > maxFoS)
{
maxFoS = damPipingOutput.FoSu;
overallHc = damPipingOutput.Hcu;
}
if (damPipingOutput.FoSh > maxFoS)
{
maxFoS = damPipingOutput.FoSh;
overallHc = damPipingOutput.Hch;
}
// Make sure defaultMaxReturnValue is limit.
maxFoS = Math.Min(maxFoS, defaultMaxReturnValue);
pipingDesignResults.Wti2017SafetyFactorOverall = maxFoS;
pipingDesignResults.Wti2017HcriticalOverall = overallHc;
// Determine the values for the additional output parameters as requested in MWDAM-1370
pipingDesignResults.Wti2017BackwardErosionDeltaPhiReduced = damPipingOutput.DeltaPhibe;
pipingDesignResults.CCreep = damPipingOutput.SeepageLength / damPipingOutput.DeltaPhiCbe;
designResults.Add(designResult);
}
///
/// Calculates the design at point.
///
/// The dam kernel input.
/// The kernel data input.
/// The kernel data output.
/// The point.
/// The messages.
///
public ShoulderDesign CalculateDesignAtPoint(DamKernelInput damKernelInput, IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, Point2D point, out List messages)
{
messages = new List();
var damPipingInput = kernelDataInput as WtiPipingSellmeijerRevisedInput;
var damPipingOutput = (WtiPipingSellmeijerRevisedOutput) kernelDataOutput;
ThrowWhenDamKernelInputNull(damKernelInput);
ThrowWhenKernelOutputNull(damPipingOutput);
Location location = damKernelInput.Location;
SoilProfile1D soilProfile = damKernelInput.SubSoilScenario.SoilProfile1D;
SurfaceLine2 surfaceLine = damKernelInput.Location.SurfaceLine;
PlLines plLines;
UpliftLocationAndResult upliftLocationAndResult;
DamPipingHelper.DeterminePlLinesAndUpliftLocation(damKernelInput, point, out plLines, out upliftLocationAndResult);
double requiredFoS = location.ModelFactors.RequiredSafetyFactorPiping;
double upliftCriterion = location.UpliftCriterionPiping;
// if there is no uplift, then there is no piping so return null
if (upliftLocationAndResult != null)
{
double xEntry = surfaceLine.CharacteristicPoints.GetPoint2D(CharacteristicPointType.DikeToeAtRiver).X;
double xExit = upliftLocationAndResult.X;
damPipingInput.SeepageLength = (xExit - xEntry) + damKernelInput.Location.DistanceToEntryPoint;
damPipingOutput.SeepageLength = damPipingInput.SeepageLength;
double topLevelAquifer = soilProfile.GetLayerWithName(upliftLocationAndResult.LayerWhereUpliftOccuresId).TopLevel;
// The following 2 parameters are dependent on the position of the point and have to be recalculated for the current point
double dCoverLayer = DamPipingHelper.DetermineHeightCoverLayer(topLevelAquifer, point.Z); // point.Z is surfacelevel
damPipingInput.DTotal = dCoverLayer;
double referenceLevel = Math.Max(location.CurrentScenario.PolderLevel, point.Z); // point.Z is surfacelevel
damPipingInput.HExit = referenceLevel;
// Initialize result as no run.
damPipingOutput.CalculationResult = CalculationResult.NoRun;
// Calculate the piping safety factor using the level of the given point
List upliftMessages;
PerformSingleCalculationWtiUplift(out upliftMessages, damPipingOutput, damPipingInput);
messages.AddRange(upliftMessages);
List heaveMessages;
PerformSingleCalculationWtiHeave(out heaveMessages, damPipingOutput, damPipingInput);
messages.AddRange(heaveMessages);
List pipingMessages;
PerformSingleCalculationWtiSellmeijerRevised(out pipingMessages, damPipingOutput, damPipingInput);
messages.AddRange(pipingMessages);
// If too low, then determine required height and length (from uplift)
if (damPipingOutput.FoSbe < requiredFoS)
{
// Finally, determine the required shoulderheight
double currentShoulderHeight = upliftLocationAndResult.Z -
surfaceLine.CharacteristicPoints.GetPoint2D(CharacteristicPointType.DikeToeAtPolder).Z;
var shoulderDesign = new ShoulderDesign(upliftLocationAndResult.X - surfaceLine.GetDikeToeInward().X,
currentShoulderHeight + ShoulderDesignHelper.CalculateExtraShoulderHeight(soilProfile, plLines, upliftLocationAndResult,
upliftCriterion));
return shoulderDesign;
}
}
return null;
}
///
/// Evaluates the design (current factor greater than desired factor)
///
/// The dam kernel input.
/// The kernel data input.
/// The kernel data output.
/// The design advise.
/// The evaluation message.
///
/// if the design was succesful
///
public bool EvaluateDesign(DamKernelInput damKernelInput, IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out DesignAdvise designAdvise, out string evaluationMessage)
{
var damPipingInput = kernelDataInput as WtiPipingSellmeijerRevisedInput;
var damPipingOutput = (WtiPipingSellmeijerRevisedOutput) kernelDataOutput;
ThrowWhenKernelInputNull(damPipingInput);
ThrowWhenDamKernelInputNull(damKernelInput);
ThrowWhenKernelOutputNull(damPipingOutput);
double fosRequired = damKernelInput.Location.ModelFactors.RequiredSafetyFactorPiping;
double fosAchieved = damPipingOutput.FoSbe;
evaluationMessage = String.Format(Resources.FactorAchievedVsFactorRequired, fosAchieved, fosRequired);
designAdvise = DesignAdvise.None;
return (fosAchieved >= fosRequired);
}
///
/// Prepares the design.
///
/// The kernel data input.
/// The kernel data output.
/// The dam kernel input.
/// Index of the iteration.
/// The embankment design parameters.
///
public void PrepareDesign(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, DamKernelInput damKernelInput, int iterationIndex, out EmbankmentDesignParameters embankmentDesignParameters)
{
throw new NotImplementedException();
}
///
/// Gets the design strategy
///
///
///
public DesignStrategy GetDesignStrategy(DamKernelInput damKernelInput)
{
return DesignStrategy.ShoulderPerPoint;
}
///
/// Converts the CharacteristicPointType to PipingCharacteristicPointType.
///
/// Type of the characteristic point.
/// the PipingCharacteristicPointType
internal PipingCharacteristicPointType ConvertToPipingPointType(CharacteristicPointType characteristicPointType)
{
switch (characteristicPointType)
{
case CharacteristicPointType.BottomDitchDikeSide: return PipingCharacteristicPointType.BottomDitchDikeSide;
case CharacteristicPointType.BottomDitchPolderSide: return PipingCharacteristicPointType.BottomDitchPolderSide;
case CharacteristicPointType.DikeToeAtPolder: return PipingCharacteristicPointType.DikeToeAtPolder;
case CharacteristicPointType.DitchDikeSide: return PipingCharacteristicPointType.DitchDikeSide;
case CharacteristicPointType.DitchPolderSide: return PipingCharacteristicPointType.DitchPolderSide;
case CharacteristicPointType.ShoulderBaseInside: return PipingCharacteristicPointType.ShoulderBaseInside;
default: return PipingCharacteristicPointType.None;
}
}
///
/// Converts a SurfaceLine2 to piping surface line.
///
/// The surface line.
/// the PipingSurfaceLine
internal PipingSurfaceLine ConvertToPipingSurfaceLine(SurfaceLine2 surfaceLine)
{
var pipingSurfaceLine = new PipingSurfaceLine();
foreach (CharacteristicPoint surfaceLineCharacteristicPoint in surfaceLine.CharacteristicPoints)
{
var pipingPoint = new PipingPoint
{
X = surfaceLineCharacteristicPoint.Point.X,
Z = surfaceLineCharacteristicPoint.Point.Z,
Type = ConvertToPipingPointType(surfaceLineCharacteristicPoint.CharacteristicPointType)
};
pipingSurfaceLine.Points.Add(pipingPoint);
}
return pipingSurfaceLine;
}
///
/// Converts a SoilProfile1D to piping profile.
///
/// The soil profile1 d.
/// the PipingProfile
internal PipingProfile ConvertToPipingProfile(SoilProfile1D soilProfile1D)
{
var pipingProfile = new PipingProfile();
foreach (SoilLayer1D soilLayer1D in soilProfile1D.Layers)
{
var pipingLayer = new PipingLayer
{
AbovePhreaticLevel = soilLayer1D.Soil.AbovePhreaticLevel,
BelowPhreaticLevel = soilLayer1D.Soil.BelowPhreaticLevel,
DryUnitWeight = soilLayer1D.Soil.DryUnitWeight,
IsAquifer = soilLayer1D.IsAquifer,
TopLevel = soilLayer1D.TopLevel,
Name = soilLayer1D.Name
};
pipingProfile.Layers.Add(pipingLayer);
}
pipingProfile.BottomLevel = soilProfile1D.BottomLevel;
return pipingProfile;
}
internal void AssignFailedValuesWtiUplift(WtiPipingSellmeijerRevisedOutput wtiPipingOutput)
{
wtiPipingOutput.FoSu = defaultFailedValue;
wtiPipingOutput.Hcu = defaultFailedValue;
wtiPipingOutput.DeltaPhiCu = defaultFailedValue;
}
internal void AssignFailedValuesWtiHeave(WtiPipingSellmeijerRevisedOutput wtiPipingOutput)
{
wtiPipingOutput.FoSh = defaultFailedValue;
wtiPipingOutput.Hch = defaultFailedValue;
wtiPipingOutput.Gradient = defaultFailedValue;
}
internal void AssignFailedValuesWtiSellmeijerRevised(WtiPipingSellmeijerRevisedOutput wtiPipingOutput)
{
wtiPipingOutput.FoSbe = defaultFailedValue;
wtiPipingOutput.Hcbe = defaultFailedValue;
wtiPipingOutput.DeltaPhiCbe = defaultFailedValue;
}
///
/// Evaluates the uplift situation and prepares the input for the wti-piping and the wti-uplift calculation.
///
/// The dam kernel input.
/// The kernel data input.
/// The pl lines.
/// The water level.
/// The dam piping output.
private bool EvaluateUpliftSituation(DamKernelInput damKernelInput, out IKernelDataInput kernelDataInput,
PlLines plLines, double waterLevel,
WtiPipingSellmeijerRevisedOutput damPipingOutput)
{
const double upliftCriterionTolerance = 0.000000001;
SoilProfile1D soilProfile1D = damKernelInput.SubSoilScenario.SoilProfile1D;
SurfaceLine2 surfaceLine = damKernelInput.Location.SurfaceLine;
Location location = damKernelInput.Location;
var upliftSituation = new UpliftSituation();
var upliftLocationDeterminator = new UpliftLocationDeterminator
{
PlLines = plLines,
SoilProfile = soilProfile1D,
SurfaceLine = surfaceLine,
DikeEmbankmentMaterial = location.GetDikeEmbankmentSoil()
};
// The tolerance is built in because after design it could be that the value that is designed to, is not reached by this margin
double upliftCriterion = location.UpliftCriterionPiping - upliftCriterionTolerance;
UpliftLocationAndResult upliftLocationAndResult = upliftLocationDeterminator.GetLocationAndResult(upliftCriterion);
upliftSituation.IsUplift = (upliftLocationAndResult != null);
double xEntry = surfaceLine.CharacteristicPoints.GetPoint2D(CharacteristicPointType.DikeToeAtRiver).X;
if (upliftLocationAndResult != null)
{
double xExit = upliftLocationAndResult.X;
double surfaceLevel = surfaceLine.Geometry.GetZatX(upliftLocationAndResult.X);
double topLevelAquifer = soilProfile1D.GetLayerWithName(upliftLocationAndResult.LayerWhereUpliftOccuresId).TopLevel;
double dCoverLayer = DamPipingHelper.DetermineHeightCoverLayer(topLevelAquifer, surfaceLevel);
SoilProfile1DAquiferLayerCombiner.AquiferLayerProperties aquiferLayer = SoilProfile1DAquiferLayerCombiner.CombineLayers(soilProfile1D, upliftLocationAndResult.LayerWhereUpliftOccuresId);
double d70 = aquiferLayer.D70;
double aquiferHeight = aquiferLayer.Height;
double permeabilityKx = aquiferLayer.PermeabilityKx;
double? upliftFactor = upliftLocationAndResult.UpliftFactor;
double seepageLength = (xExit - xEntry) + damKernelInput.Location.DistanceToEntryPoint;
seepageLength = Math.Max(0, seepageLength);
// Reference level is highest value of surfaceLevel or PolderLevel
// Uit TR Zandmeevoerende wellen (1999): "Het verval dH is gelijk aan het verschil tussen buitenwaterstand (het ontwerppeil(OP))
// bij zeedijken en de maatgevende hoogwaterstand (MHW bij rivierdijken) en de waterstand binnendijks ter plaatse van het uittredepunt,
// rekening houdend met zeespiegelrijzing etc.(zie paragraaf 3.7.2). In dien ter plaatse van het uittreepunt of de opbarstlocatie
// geen vrije waterstand heerst kan gerekend worden met het maaiveldniveau, rekening houdend met eventuele maaiveld daling (zie paragraaf 3.7.2)."
double referenceLevel = Math.Max(location.CurrentScenario.PolderLevel, surfaceLevel);
// Additional parameters for Uplift
double phiPolder = referenceLevel;
double rExit = 1 - location.ModelParametersForPlLines.DampingFactorPl3;
if (soilProfile1D.InBetweenAquiferLayer != null)
{
rExit = 1 - location.ModelParametersForPlLines.DampingFactorPl4;
}
EffectiveThicknessCalculator effectiveThicknessCalculator = CreateEffectiveThicknessCalculator(soilProfile1D,
surfaceLine, location.CurrentScenario.PolderLevel, Physics.UnitWeightOfwater, xExit);
effectiveThicknessCalculator.Calculate();
double effectiveStress = effectiveThicknessCalculator.EffectiveStress;
// Fill the input for the wti-uplift calculation as well as the wti-piping SellmeijerRevised calculation.
kernelDataInput = new WtiPipingSellmeijerRevisedInput
{
HRiver = waterLevel,
HExit = referenceLevel,
Rc = defaultFluidisationGradient,
DTotal = dCoverLayer,
SeepageLength = seepageLength,
// specific Sellmeijer 4 Forces
KinematicViscosityWater = Physics.WaterViscosity,
VolumetricWeightOfWater = Physics.UnitWeightOfwater,
D70 = d70,
DAquifer = aquiferHeight,
DarcyPermeability = permeabilityKx,
ModelFactorUplift = 1.0,
EffectiveStress = effectiveStress,
PhiExit = phiPolder + rExit * (waterLevel - phiPolder),
RExit = rExit,
PhiPolder = phiPolder
};
damPipingOutput.EffectiveStress = effectiveStress;
damPipingOutput.ExitPointX = xExit;
damPipingOutput.UpliftFactor = upliftFactor;
damPipingOutput.UpliftSituation = upliftSituation;
damPipingOutput.DeltaPhibe = waterLevel - referenceLevel - defaultFluidisationGradient * dCoverLayer;
damPipingOutput.SeepageLength = seepageLength;
return true;
}
kernelDataInput = new WtiPipingSellmeijerRevisedInput();
return false;
}
///
/// Creates the piping calculator wti sellmeijer revised.
///
/// The kernel data input.
/// the Sellmeijer2011Calculator
private Sellmeijer2011Calculator CreatePipingCalculatorWtiSellmeijerRevised(IKernelDataInput kernelDataInput)
{
var wtiPipingSellmeijerRevisedInput = kernelDataInput as WtiPipingSellmeijerRevisedInput;
ThrowWhenKernelInputNull(wtiPipingSellmeijerRevisedInput);
var calculator = new Sellmeijer2011Calculator
{
HRiver = wtiPipingSellmeijerRevisedInput.HRiver,
HExit = wtiPipingSellmeijerRevisedInput.HExit,
Rc = wtiPipingSellmeijerRevisedInput.Rc,
DTotal = wtiPipingSellmeijerRevisedInput.DTotal,
DAquifer = wtiPipingSellmeijerRevisedInput.DAquifer,
SeepageLength = wtiPipingSellmeijerRevisedInput.SeepageLength,
D70 = wtiPipingSellmeijerRevisedInput.D70,
D70Mean = wtiPipingSellmeijerRevisedInput.D70Mean,
WhitesDragCoefficient = wtiPipingSellmeijerRevisedInput.WhitesDragCoefficient,
BeddingAngle = wtiPipingSellmeijerRevisedInput.BeddingAngle,
DarcyPermeability = wtiPipingSellmeijerRevisedInput.DarcyPermeability,
KinematicViscosityWater = wtiPipingSellmeijerRevisedInput.KinematicViscosityWater,
VolumetricWeightOfWater = wtiPipingSellmeijerRevisedInput.VolumetricWeightOfWater,
GammaSubParticles = wtiPipingSellmeijerRevisedInput.GammaSubParticles,
Gravity = wtiPipingSellmeijerRevisedInput.Gravity,
BottomLevelAquitardAboveExitPointZ = wtiPipingSellmeijerRevisedInput.BottomLevelAquitardAboveExitPointZ,
ModelFactorPiping = wtiPipingSellmeijerRevisedInput.ModelFactorPiping
};
return calculator;
}
///
/// Creates the wti uplift calculator.
///
/// The kernel data input.
///
private WTIUpliftCalculator CreateWtiUpliftCalculator(IKernelDataInput kernelDataInput)
{
var wtiPipingSellmeijerRevisedInput = kernelDataInput as WtiPipingSellmeijerRevisedInput;
ThrowWhenKernelInputNull(wtiPipingSellmeijerRevisedInput);
var calculator = new WTIUpliftCalculator
{
VolumetricWeightOfWater = wtiPipingSellmeijerRevisedInput.VolumetricWeightOfWater,
ModelFactorUplift = wtiPipingSellmeijerRevisedInput.ModelFactorUplift,
EffectiveStress = wtiPipingSellmeijerRevisedInput.EffectiveStress,
RExit = wtiPipingSellmeijerRevisedInput.RExit,
HRiver = wtiPipingSellmeijerRevisedInput.HRiver,
HExit = wtiPipingSellmeijerRevisedInput.HExit,
PhiPolder = wtiPipingSellmeijerRevisedInput.PhiPolder,
PhiExit = wtiPipingSellmeijerRevisedInput.PhiExit
};
return calculator;
}
///
/// Creates the wti heave calculator.
///
/// The kernel data input.
///
private HeaveCalculator CreateWtiHeaveCalculator(IKernelDataInput kernelDataInput)
{
var wtiPipingSellmeijerRevisedInput = kernelDataInput as WtiPipingSellmeijerRevisedInput;
ThrowWhenKernelInputNull(wtiPipingSellmeijerRevisedInput);
var calculator = new HeaveCalculator
{
Ich = wtiPipingSellmeijerRevisedInput.Ich,
DTotal = wtiPipingSellmeijerRevisedInput.DTotal,
PhiExit = wtiPipingSellmeijerRevisedInput.PhiExit,
RExit = wtiPipingSellmeijerRevisedInput.RExit,
HExit = wtiPipingSellmeijerRevisedInput.HExit
};
return calculator;
}
///
/// Creates the effective thickness calculator.
///
/// The soil profile.
/// The surface line.
/// The phreatic level.
/// The volumetric weight of water.
/// The x exit.
/// the EffectiveThicknessCalculator
private EffectiveThicknessCalculator CreateEffectiveThicknessCalculator(SoilProfile1D soilProfile, SurfaceLine2 surfaceLine,
double phreaticLevel, double volumicWeightOfWater, double xExit)
{
var calculator = new EffectiveThicknessCalculator
{
SurfaceLine = ConvertToPipingSurfaceLine(surfaceLine),
SoilProfile = ConvertToPipingProfile(soilProfile),
PhreaticLevel = phreaticLevel,
VolumicWeightOfWater = volumicWeightOfWater,
ExitPointXCoordinate = xExit
};
return calculator;
}
///
/// Performs the single calculation wti sellmeijer revised.
///
/// The messages.
/// The wti piping output.
/// The wti piping input.
private void PerformSingleCalculationWtiSellmeijerRevised(out List messages, WtiPipingSellmeijerRevisedOutput wtiPipingOutput,
WtiPipingSellmeijerRevisedInput wtiPipingInput)
{
wtiPipingOutput.FoSbe = defaultMaxReturnValue;
messages = new List();
try
{
Sellmeijer2011Calculator calculator = CreatePipingCalculatorWtiSellmeijerRevised(wtiPipingInput);
calculator.Calculate();
wtiPipingOutput.FoSbe = calculator.FoSp;
wtiPipingOutput.Hcbe = calculator.Hcp;
wtiPipingOutput.DeltaPhiCbe = calculator.Hc;
wtiPipingOutput.CalculationResult = CalculationResult.Succeeded;
}
catch (Exception e)
{
AssignFailedValuesWtiSellmeijerRevised(wtiPipingOutput);
wtiPipingOutput.CalculationResult = CalculationResult.UnexpectedError;
messages.Add(new LogMessage(LogMessageType.Error, null, e.Message));
}
}
///
/// Performs the single calculation wti uplift.
///
/// The messages.
/// The wti piping output.
/// The wti piping input.
private void PerformSingleCalculationWtiUplift(out List messages, WtiPipingSellmeijerRevisedOutput wtiPipingOutput,
WtiPipingSellmeijerRevisedInput wtiPipingInput)
{
wtiPipingOutput.FoSu = defaultMaxReturnValue;
messages = new List();
try
{
WTIUpliftCalculator calculator = CreateWtiUpliftCalculator(wtiPipingInput);
calculator.Calculate();
wtiPipingOutput.FoSu = calculator.FoSu;
wtiPipingOutput.Hcu = calculator.Hcu;
wtiPipingOutput.DeltaPhiCu = calculator.DeltaPhiCu;
wtiPipingOutput.CalculationResult = CalculationResult.Succeeded;
}
catch (Exception e)
{
AssignFailedValuesWtiUplift(wtiPipingOutput);
wtiPipingOutput.CalculationResult = CalculationResult.UnexpectedError;
messages.Add(new LogMessage(LogMessageType.Error, null, e.Message));
}
}
private void PerformSingleCalculationWtiHeave(out List messages, WtiPipingSellmeijerRevisedOutput wtiPipingOutput,
WtiPipingSellmeijerRevisedInput wtiPipingInput)
{
wtiPipingOutput.FoSh = defaultMaxReturnValue;
messages = new List();
try
{
HeaveCalculator calculator = CreateWtiHeaveCalculator(wtiPipingInput);
calculator.Calculate();
wtiPipingOutput.FoSh = calculator.FoSh;
wtiPipingOutput.Hch = calculator.Hch;
wtiPipingOutput.Gradient = calculator.Gradient;
wtiPipingOutput.CalculationResult = CalculationResult.Succeeded;
}
catch (Exception e)
{
AssignFailedValuesWtiHeave(wtiPipingOutput);
wtiPipingOutput.CalculationResult = CalculationResult.UnexpectedError;
messages.Add(new LogMessage(LogMessageType.Error, null, e.Message));
}
}
private void ThrowWhenKernelInputNull(WtiPipingSellmeijerRevisedInput wtiPipingInput)
{
if (wtiPipingInput == null)
{
throw new NoNullAllowedException(Resources.WtiPipingSellmeijerRevisedKernelWrapper_NoInputObjectDefined);
}
}
private void ThrowWhenKernelOutputNull(WtiPipingSellmeijerRevisedOutput wtiPipingOutput)
{
if (wtiPipingOutput == null)
{
throw new NoNullAllowedException(Resources.WtiPipingSellmeijerRevisedKernelWrapper_NoOutputObjectDefined);
}
}
private void ThrowWhenDamKernelInputNull(DamKernelInput damKernelInput)
{
if (damKernelInput == null)
{
throw new NoNullAllowedException(Resources.WtiPipingSellmeijerRevisedKernelWrapper_NoInputObjectDefined);
}
}
}