using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Deltares.DamEngine.Calculators.DikesDesign;
using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStabilityCommon;
using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces;
using Deltares.DamEngine.Calculators.Properties;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.Results;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.DamEngine.Data.Standard.Logging;
using Deltares.WTIStability.Calculation.Wrapper;
namespace Deltares.DamEngine.Calculators.KernelWrappers.WtiMacroStabilityInwards
{
public class WtiMacroStabilityInwardsKernelWrapper : IKernelWrapper
{
private WTIStabilityCalculation wtiMacroStabilityCalculator = null;
private int lastIterationIndex = 0;
///
/// Gets or sets the failure mechanisme paramaters for mstab.
///
///
/// The failure mechanisme paramaters mstab.
///
public FailureMechanismParametersMStab FailureMechanismParametersMStab { get; set; } //ToDo MWDAM-? Use same as for DGeoStability or create new one for WTI?
public bool tmpPresumePrepareSucceeds; //ToDo MWDAM-1356
public bool tmpPresumeInputValid; //ToDo MWDAM-1367
public bool tmpPresumeRunSucceeds; //ToDo MWDAM-1356, MWDAM-1367, MWDAM-1357
///
/// Prepares the specified 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 macroStabilityInput = new WtiMacroStabilityInput();
kernelDataInput = macroStabilityInput;
var macroStabilityOutput = new WtiMacroStabilityOutput
{
CalculationResult = CalculationResult.NoRun
};
try
{
// Determine whether there is uplift
var upliftSituation = UpliftHelper.DetermineStabilityUplift(damKernelInput, false);
macroStabilityOutput.UpliftSituation = upliftSituation;
kernelDataOutput = macroStabilityOutput;
if (upliftSituation.IsUplift)
{
// ToDo MWDAM-1356: Not clear yet what parts are required for input.
var xmlInput = CreateXmlInput(macroStabilityInput, FailureMechanismParametersMStab.EmbankmentDesignParameters);
return PrepareKernel(xmlInput);
}
else
{
return PrepareResult.NotRelevant;
}
}
catch
{
kernelDataOutput = macroStabilityOutput;
return PrepareResult.Failed;
}
}
private PrepareResult PrepareKernel(string xmlInput)
{
ThrowWhenWtiMacroStabilityCalculatorNull(wtiMacroStabilityCalculator);
try
{
// ToDo MWDAM-1356: Not clear yet what parts are required for input. Temporary test code added.
//wtiMacroStabilityCalculator.InitializeForDeterministic(xmlInput); //ToDo: uncomment when input is set
//return PrepareResult.Successful; //ToDo: uncomment when input is set
if (tmpPresumePrepareSucceeds) //ToDo: remove the temporary test code when input is set
{
return PrepareResult.Successful;
}
else
{
return PrepareResult.Failed;
}
}
catch
{
return PrepareResult.Failed;
}
}
private string CreateXmlInput(WtiMacroStabilityInput macroStabilityInput, EmbankmentDesignParameters embankmentDesignParameters)
{
string xmlInput = "";
//ToDo in MWDAM-1356
return xmlInput;
}
///
/// Validates the specified kernel data input.
///
/// The kernel data input.
/// The kernel data output.
/// The return messages.
///
/// Zero when there are no errors, one when there are errors that prevent a calculation
///
public int Validate(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out List messages)
{
ThrowWhenWtiMacroStabilityCalculatorNull(wtiMacroStabilityCalculator);
if (tmpPresumeInputValid)
{
messages = new List();
return 0;
}
else
{
messages = new List();
messages.Add(new LogMessage(LogMessageType.Error, null, "Not implemented yet"));
// Todo MWDAM-1356 : make valid XML, only then following lines can be enabled
// string kernelMessage = wtiMacroStabilityCalculator.Validate();
// ParseValidationResult(kernelMessage, out messages);
WtiMacroStabilityOutput macroStabilityOutput = (WtiMacroStabilityOutput)kernelDataOutput;
var numberOfErrors = messages.Count(mt => mt.MessageType == LogMessageType.Error);
if (numberOfErrors > 0)
{
macroStabilityOutput.CalculationResult = CalculationResult.InvalidInputData;
}
return numberOfErrors;
}
}
internal void ParseValidationResult(string xmlValidationResult, out List messages)
{
messages = new List();
// ToDo MWDAM-1367: Parse the xml from the kernel and add message with type Error, Info or Warning
// start of temporary test code
if (tmpPresumeInputValid)
{
// only an info/warning message, presumed input valid for test
messages.Add(new LogMessage()
{
Message = "test info message",
MessageType = LogMessageType.Info
});
}
else
{
// add an error message, presumed input not valid for test
messages.Add(new LogMessage()
{
Message = "test error message",
MessageType = LogMessageType.Error
});
}
// end of temporary test code. next code must be enough, presumed that the kernel does all the validation
}
///
/// Executes the kernel.
///
/// The kernel data input.
/// The kernel data output.
/// The return messages.
public void Execute(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out List messages)
{
WtiMacroStabilityInput macroStabilityInput = (WtiMacroStabilityInput)kernelDataInput;
WtiMacroStabilityOutput macroStabilityOutput = (WtiMacroStabilityOutput)kernelDataOutput;
ThrowWhenWtiMacroStabilityKernelInputNull(macroStabilityInput);
ThrowWhenWtiMacroStabilityKernelOutputNull(macroStabilityOutput);
messages = new List();
PerformWtiStabilityCalculation(out messages, macroStabilityOutput, macroStabilityInput);
}
private void PerformWtiStabilityCalculation(out List messages, WtiMacroStabilityOutput macroStabilityOutput,
WtiMacroStabilityInput macroStabilityInput)
{
ThrowWhenWtiMacroStabilityCalculatorNull(wtiMacroStabilityCalculator);
macroStabilityOutput.CalculationResult = CalculationResult.NoRun;
messages = new List();
macroStabilityOutput.StabilityOutputItems = new List();
//this must be code when prepare is done
// try
// {
// string kernelMessage = wtiMacroStabilityCalculator.Run();
// ParseRunResult(kernelMessage, macroStabilityOutput, messages);
// macroStabilityOutput.CalculationResult = CalculationResult.Succeeded;
// }
// catch (Exception e)
// {
// macroStabilityOutput.CalculationResult = CalculationResult.UnexpectedError;
// messages.Add(new LogMessage(LogMessageType.Error, null, e.Message));
// }
// ToDo MWDAM-1356: setting input is not done yet. Temporary test code added.
// start of temporary test code
if (tmpPresumeRunSucceeds)
{
//presume run succeeded
macroStabilityOutput.CalculationResult = CalculationResult.Succeeded;
ParseRunResult("", macroStabilityOutput, messages);
}
else
{
//presume run failed
macroStabilityOutput.CalculationResult = CalculationResult.UnexpectedError;
messages.Add(new LogMessage(LogMessageType.Error, null, "run failed"));
}
// end of temporary test code
}
private void ParseRunResult(string xmlRunResult, WtiMacroStabilityOutput macroStabilityOutput, List messages)
{
// ToDo MWDAM-1357: Parse the xml from the kernel, fill results and add message with type Error, Info or Warning
var macroStabilityOutputItem = new WtiMacroStabilityOutputItem();
// start of temporary test code
macroStabilityOutputItem.SafetyFactor = 1.357;
// end of temporary test code
macroStabilityOutput.StabilityOutputItems.Add(macroStabilityOutputItem);
}
///
/// Creates the calculator for WTI stability based on kernel input.
///
public void CreateWtiStabilityCalculator()
{
wtiMacroStabilityCalculator = new WTIStabilityCalculation();
}
///
/// Fills the design results with 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)
{
ThrowWhenWtiMacroStabilityDamKernelInputNull(damKernelInput);
WtiMacroStabilityOutput macroStabilityOutput = kernelDataOutput as WtiMacroStabilityOutput;
ThrowWhenWtiMacroStabilityKernelOutputNull(macroStabilityOutput);
designResults = new List();
if (macroStabilityOutput.StabilityOutputItems.Count > 0)
{
var macroStabilityOutputItem = macroStabilityOutput.StabilityOutputItems[0];
if (macroStabilityOutputItem != null)
{
var designResult = NewDesignResult(damKernelInput, designScenario, macroStabilityOutputItem);
FillDesignResult(macroStabilityOutputItem, designResult);
designResult.StabilityDesignResults.NumberOfIterations = lastIterationIndex;
designResult.StabilityDesignResults.UpliftSituation = macroStabilityOutput.UpliftSituation;
designResults.Add(designResult);
}
}
}
private DesignResult NewDesignResult(DamKernelInput damKernelInput, DesignScenario designScenario,
WtiMacroStabilityOutputItem macroStabilityOutputItem)
{
string soilProfile2DName = damKernelInput.SubSoilScenario.ToString();
var designResult = new DesignResult(damKernelInput.DamFailureMechanismeCalculationSpecification,
designScenario, damKernelInput.SubSoilScenario.SoilProfile1D, soilProfile2DName)
{
// initialize as failed
CalculationResult = CalculationResult.RunFailed
};
designResult.StabilityDesignResults = new StabilityDesignResults();
var stabilityDesignResults = new StabilityDesignResults();
stabilityDesignResults.RedesignedSurfaceLine = damKernelInput.Location.SurfaceLine;
designResult.ProfileName = soilProfile2DName;
designResult.StabilityDesignResults = stabilityDesignResults;
return designResult;
}
private static void FillDesignResult(WtiMacroStabilityOutputItem macroStabilityOutputItem, DesignResult designResult)
{
designResult.CalculationResult = macroStabilityOutputItem.CalculationResult;
designResult.StabilityDesignResults.StabilityModelType = macroStabilityOutputItem.StabilityModelType;
if (designResult.CalculationResult == CalculationResult.Succeeded)
{
designResult.StabilityDesignResults.SafetyFactor = macroStabilityOutputItem.SafetyFactor;
}
}
///
/// Throws the when WTI macro stability kernel input is not assigned.
///
/// The dam WTI macro stability input.
///
public static void ThrowWhenWtiMacroStabilityKernelInputNull(WtiMacroStabilityInput wtiMacroStabilityInput)
{
if (wtiMacroStabilityInput == null)
{
throw new NoNullAllowedException(Resources.WtiMacroStabilityKernelWrapper_NoWtiMacroStabilityInputObjectDefined);
}
}
///
/// Throws the when WTI macro stability kernel output is not assigned.
///
/// The dam WTI macro stability output.
///
public static void ThrowWhenWtiMacroStabilityKernelOutputNull(WtiMacroStabilityOutput wtiMacroStabilityOutput)
{
if (wtiMacroStabilityOutput == null)
{
throw new NoNullAllowedException(Resources.WtiMacroStabilityKernelWrapper_NoWtiMacroStabilityOutputObjectDefined);
}
}
///
/// Throws the when WTI macro stability dam kernel input is not assigned.
///
/// The dam kernel input.
///
public static void ThrowWhenWtiMacroStabilityDamKernelInputNull(DamKernelInput damKernelInput)
{
if (damKernelInput == null)
{
throw new NoNullAllowedException(Resources.WtiMacroStabilityKernelWrapper_NoDamInputObjectDefinedForWtiMacroStability);
}
}
///
/// Throws the when WTI macro stability calculator is not assigned.
///
/// The WTI macro stability calculator.
///
public static void ThrowWhenWtiMacroStabilityCalculatorNull(WTIStabilityCalculation wtiMacroStabilityCalculator)
{
if (wtiMacroStabilityCalculator == null)
{
throw new NoNullAllowedException(Resources.WtiMacroStabilityKernelWrapper_NoDamKernelObjectDefinedForWtiMacroStability);
}
}
///
/// 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, GeometryPoint point, out List messages)
{
// ToDo: Not clear yet if this must be done or how
throw new NotImplementedException();
}
///
/// 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)
{
WtiMacroStabilityInput macroStabilityInput = kernelDataInput as WtiMacroStabilityInput;
WtiMacroStabilityOutput macroStabilityOutput = kernelDataOutput as WtiMacroStabilityOutput;
ThrowWhenWtiMacroStabilityKernelInputNull(macroStabilityInput);
ThrowWhenWtiMacroStabilityKernelOutputNull(macroStabilityOutput);
ThrowWhenWtiMacroStabilityDamKernelInputNull(damKernelInput);
double fosRequired = damKernelInput.Location.ModelFactors.RequiredSafetyFactorStabilityInnerSlope.Value;
double fosAchieved = macroStabilityOutput.StabilityOutputItems[0].SafetyFactor;
//ToDo MWDAM-1357: not clear where the exitPointXCoordinate must come from
//double exitPointXCoordinate = macroStabilityOutput.StabilityOutputItems[0].CircleSurfacePointRightXCoordinate;
double exitPointXCoordinate = 1.123; // ToDo replace by value above. set a value for test.
GeometryPoint limitPointForShoulderDesign = damKernelInput.Location.SurfaceLine.GetLimitPointForShoulderDesign();
evaluationMessage = String.Format(Resources.FactorAchievedVsFactorRequired, fosAchieved, fosRequired);
if (exitPointXCoordinate > limitPointForShoulderDesign.X)
{
designAdvise = DesignAdvise.ShoulderInwards;
}
else
{
designAdvise = DesignAdvise.SlopeInwards;
}
bool isDesignReady = fosAchieved >= fosRequired;
if (isDesignReady)
{
designAdvise = DesignAdvise.None;
}
return isDesignReady;
}
///
/// 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)
{
WtiMacroStabilityInput macroStabilityInput = kernelDataInput as WtiMacroStabilityInput;
ThrowWhenWtiMacroStabilityKernelInputNull(macroStabilityInput);
lastIterationIndex = iterationIndex;
var location = damKernelInput.Location;
//ToDo MWDAM-1356: Not clear yet what parts are required for input. subSoilScenario, riverLevel and others might be necessary for CreateXmlInput
//MStabModelType model = MStabModelType.UpliftVan;
//var subSoilScenario = damKernelInput.SubSoilScenario;
//double riverLevel = damKernelInput.RiverLevelHigh;
EmbankmentDesignParameters embankmentDesignParametersForKernelInput;
if (iterationIndex < 1)
{
// This is the first (initial) call to prepareDesign.
// The embankment material is set to DikeEmbankmentMaterial, because the next iteration (Index = 1) will be height adaption
embankmentDesignParameters = new EmbankmentDesignParameters()
{
EmbankmentMaterialname = location.DikeEmbankmentMaterial,
};
//ToDo MWDAM-? Use FailureMechanismParametersMStab or create new one for WTI?
FailureMechanismParametersMStab.EmbankmentDesignParameters = embankmentDesignParameters;
embankmentDesignParametersForKernelInput = null;
}
else
{
// Calculation iterations start with IterationIndex = 1.
// When IterationIndex = 1: height adaption.
// When Iteration > 1: Slope/Shoulder adaption.
// Starting from IterationIndex 2 the following parameters should be used:
// - The embankment material is set to ShoulderEmbankmentMaterial.
// - The previous geometry is set to the height adapted geometry (name is constructed with iteration index 1).
if (iterationIndex == 2)
{
FailureMechanismParametersMStab.EmbankmentDesignParameters.EmbankmentMaterialname = location.ShoulderEmbankmentMaterial;
}
// In the following prepareDesign calls just return the stored embankmentDesignParameters
embankmentDesignParameters = FailureMechanismParametersMStab.EmbankmentDesignParameters;
embankmentDesignParametersForKernelInput = embankmentDesignParameters;
}
var xmlInput = CreateXmlInput(macroStabilityInput, embankmentDesignParametersForKernelInput);
var prepareResult = PrepareKernel(xmlInput);
if (prepareResult != PrepareResult.Successful)
{
throw new MacroStabilityException(Resources.WtiMacroStabilityKernelWrapper_PrepareForWtiMacroStabilityDidNotSucceed);
}
}
///
/// Gets the design strategy
///
///
///
public DesignStrategy GetDesignStrategy(DamKernelInput damKernelInput)
{
switch (damKernelInput.Location.StabilityDesignMethod)
{
case StabilityDesignMethod.OptimizedSlopeAndShoulderAdaption:
return DesignStrategy.OptimizedSlopeAndShoulderAdaption;
case StabilityDesignMethod.SlopeAdaptionBeforeShoulderAdaption:
return DesignStrategy.SlopeAdaptionBeforeShoulderAdaption;
default:
return DesignStrategy.NoDesignPossible;
}
}
}
}