using System;
using System.Collections.Generic;
using System.Data;
using Deltares.DamEngine.Calculators.General;
using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces;
using Deltares.DamEngine.Calculators.Uplift;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.Results;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.DamEngine.Data.Standard.Logging;
using Deltares.DamPiping.BlighCalculator;
namespace Deltares.DamEngine.Calculators.KernelWrappers.DamPipingBligh
{
///
/// Wrapper around Bligh piping kernel
///
///
public class DamPipingBlighKernelWrapper : IKernelWrapper
{
private const double defaultFluidisationGradient = 0.3;
private const double defaultMaxReturnValue = 90.0;
///
/// Create the kernel input.
///
/// The dam kernel input.
/// The kernel data input.
/// The kernel data output.
///
/// Result of the prepare
///
public PrepareResult Prepare(DamKernelInput damKernelInput, out IKernelDataInput kernelDataInput, out IKernelDataOutput kernelDataOutput)
{
var damPipingBlighOutput = new DamPipingBlighOutput()
{
CalculationResult = CalculationResult.NoRun,
FoSp = defaultMaxReturnValue
};
kernelDataOutput = damPipingBlighOutput;
if (damKernelInput.SubSoilScenario.SegmentFailureMechanismType == FailureMechanismSystemType.Piping)
{
var damPipingBlighInput = new DamPipingBlighInput();
var soilProfile1D = damKernelInput.SubSoilScenario.SoilProfile1D;
var surfaceLine = damKernelInput.Location.SurfaceLine;
var location = damKernelInput.Location;
double riverLevel = damKernelInput.DesignScenario.RiverLevel;
UpliftSituation upliftSituation;
var plLines = PlLinesHelper.CreatePlLines(location, soilProfile1D, riverLevel, out upliftSituation);
UpliftLocationDeterminator upliftLocationDeterminator = new UpliftLocationDeterminator
{
PLLines = plLines,
SoilProfile = soilProfile1D,
SurfaceLine = surfaceLine,
DikeEmbankmentMaterial = location.GetDikeEmbankmentSoil(),
XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin
};
var upliftLocationAndResult = upliftLocationDeterminator.GetLocationAndResult(damKernelInput.DesignScenario.GetUpliftCriterionPiping(null));
upliftSituation.IsUplift = (upliftLocationAndResult != null);
double xEntry = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X;
double xExit = 0.0;
double surfaceLevel = 0.0;
double d70 = 0.0;
double dCoverLayer = 0.0;
double? upliftFactor = null;
if (upliftLocationAndResult != null)
{
xExit = upliftLocationAndResult.X;
surfaceLevel = surfaceLine.Geometry.GetZatX(upliftLocationAndResult.X);
SoilLayer1D heaveLayer = soilProfile1D.GetLayerWithName(upliftLocationAndResult.LayerWhereUpliftOccuresId);
d70 = Physics.FactorMeterToMicroMeter * heaveLayer.Soil.DiameterD70;
var topLevelAquifer = soilProfile1D.GetLayerWithName(upliftLocationAndResult.LayerWhereUpliftOccuresId).TopLevel;
dCoverLayer = DamPipingHelper.DetermineHeightCoverLayer(topLevelAquifer, surfaceLevel);
upliftFactor = upliftLocationAndResult.UpliftFactor;
}
double seepageLength = xExit - xEntry;
damPipingBlighInput.HRiver = riverLevel;
// 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)."
var referenceLevel = Math.Max(location.PolderLevel, surfaceLevel);
kernelDataInput = new DamPipingBlighInput()
{
HRiver = riverLevel,
HExit = referenceLevel,
Rc = defaultFluidisationGradient,
DTotal = dCoverLayer,
SeepageLength = seepageLength,
D70 = d70,
};
damPipingBlighOutput.ExitPointX = xExit;
damPipingBlighOutput.UpliftFactor = upliftFactor;
damPipingBlighOutput.UpliftSituation = upliftSituation;
return PrepareResult.Successful;
}
kernelDataInput = null;
return PrepareResult.NotRelevant;
}
///
/// Validates the kernel data input.
///
/// The kernel data input.
/// The messages.
///
public int Validate(IKernelDataInput kernelDataInput, out List messages)
{
var calculatorBligh = CreatePipingCalculatorBligh(kernelDataInput);
List kernelMessages = calculatorBligh.Validate();
messages = new List();
foreach (string stringMessage in kernelMessages)
{
messages.Add(new LogMessage()
{
Message = stringMessage,
MessageType = LogMessageType.Error
});
}
return messages.Count;
}
///
/// Executes the kernel.
///
/// The kernel data input.
/// The kernel data output.
/// The messages.
/// No input object defined for Bligh
public void Execute(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out List messages)
{
DamPipingBlighOutput damPipingBlighOutput = (DamPipingBlighOutput) kernelDataOutput;
damPipingBlighOutput.CalculationResult = CalculationResult.NoRun;
damPipingBlighOutput.FoSp = defaultMaxReturnValue;
messages = new List();
try
{
DamPipingBlighInput damPipingBlighInput = kernelDataInput as DamPipingBlighInput;
if (damPipingBlighInput == null)
{
throw new NoNullAllowedException("No input object defined for Bligh");
}
if (damPipingBlighOutput.UpliftSituation.IsUplift)
{
var calculatorBligh = CreatePipingCalculatorBligh(kernelDataInput);
calculatorBligh.Calculate();
damPipingBlighOutput.FoSp = calculatorBligh.FoSp;
damPipingBlighOutput.Hc = calculatorBligh.Hc;
damPipingBlighOutput.CalculationResult = CalculationResult.Succeeded;
}
}
catch (Exception e)
{
damPipingBlighOutput.CalculationResult = CalculationResult.UnexpectedError;
messages.Add(new LogMessage(LogMessageType.Error, null, e.Message));
}
}
///
/// Creates the piping calculator bligh based on kernel input.
///
/// The kernel data input.
///
/// No input object defined for Bligh
private static PipingCalculatorBligh CreatePipingCalculatorBligh(IKernelDataInput kernelDataInput)
{
DamPipingBlighInput damPipingBlighInput = kernelDataInput as DamPipingBlighInput;
if (damPipingBlighInput == null)
{
throw new NoNullAllowedException("No input object defined for Bligh");
}
var calculator = new PipingCalculatorBligh
{
HRiver = damPipingBlighInput.HRiver,
HExit = damPipingBlighInput.HExit,
Rc = damPipingBlighInput.Rc,
DTotal = damPipingBlighInput.DTotal,
SeepageLength = damPipingBlighInput.SeepageLength,
D70 = damPipingBlighInput.D70
};
return calculator;
}
///
/// Fills the design results from the kernel output.
///
/// The dam kernel input.
/// The kernel data output.
/// The design result.
/// No output object defined for Bligh
public void PostProcess(DamKernelInput damKernelInput, IKernelDataOutput kernelDataOutput, out DesignResult designResult)
{
DamPipingBlighOutput damPipingBlighOutput = kernelDataOutput as DamPipingBlighOutput;
if (damPipingBlighOutput == null)
{
throw new NoNullAllowedException("No output object defined for Bligh");
}
// TODO: for now this only works for 1D profiles
string soilProfile2DName = "soilProfile2DName";
var damFailureMechanismeCalculationSpecification = new DamFailureMechanismeCalculationSpecification()
{
FailureMechanismSystemType = FailureMechanismSystemType.Piping,
PipingModelType = PipingModelType.Bligh
};
var designScenario = damKernelInput.DesignScenario;
var soilProfile1D = damKernelInput.SubSoilScenario.SoilProfile1D;
designResult = new DesignResult(damFailureMechanismeCalculationSpecification,
designScenario, soilProfile1D, soilProfile2DName,
DamProjectCalculationSpecification.SelectedAnalysisType);
designResult.CalculationResult = damPipingBlighOutput.CalculationResult;
var pipingDesignResults = new PipingDesignResults(PipingModelType.Bligh);
pipingDesignResults.BlighFactor = damPipingBlighOutput.FoSp;
pipingDesignResults.BlighHcritical = damPipingBlighOutput.Hc;
// TODO: for now this only works for NoAdaption of geometry; if adaption is enabled, the real redesigned surfaceline has to be assigned
pipingDesignResults.RedesignedSurfaceLine = damKernelInput.Location.SurfaceLine;
designResult.PipingDesignResults = pipingDesignResults;
designResult.CalculationResult = damPipingBlighOutput.CalculationResult;
pipingDesignResults.UpliftSituation = damPipingBlighOutput.UpliftSituation;
pipingDesignResults.LocalExitPointX = damPipingBlighOutput.ExitPointX;
pipingDesignResults.UpliftFactor = damPipingBlighOutput.UpliftFactor;
}
}
}