// 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 Core.Common.Base.Data;
using Ringtoets.Common.Service;
using Ringtoets.Common.Service.ValidationRules;
using Ringtoets.MacroStabilityInwards.Data;
using Ringtoets.MacroStabilityInwards.KernelWrapper;
using Ringtoets.MacroStabilityInwards.KernelWrapper.SubCalculator;
using Ringtoets.MacroStabilityInwards.Primitives;
using Ringtoets.MacroStabilityInwards.Service.Properties;
using RingtoetsCommonServiceResources = Ringtoets.Common.Service.Properties.Resources;
using RingtoetsCommonFormsResources = Ringtoets.Common.Forms.Properties.Resources;
namespace Ringtoets.MacroStabilityInwards.Service
{
///
/// This class is responsible for invoking operations on the . Error and status information is
/// logged during the execution of the operation.
///
public static class MacroStabilityInwardsCalculationService
{
///
/// Performs validation over the values on the given . Error and status information is logged during
/// the execution of the operation.
///
/// The for which to validate the values.
/// False if contains validation errors; True otherwise.
/// Thrown when is null.
public static bool Validate(MacroStabilityInwardsCalculation calculation)
{
if (calculation == null)
{
throw new ArgumentNullException(nameof(calculation));
}
CalculationServiceHelper.LogValidationBeginTime(calculation.Name);
CalculationServiceHelper.LogMessagesAsWarning(GetInputWarnings(calculation.InputParameters).ToArray());
string[] inputValidationResults = ValidateInput(calculation.InputParameters).ToArray();
if (inputValidationResults.Length > 0)
{
CalculationServiceHelper.LogMessagesAsError(RingtoetsCommonServiceResources.Error_in_validation_0, inputValidationResults);
CalculationServiceHelper.LogValidationEndTime(calculation.Name);
return false;
}
List validationResults = new MacroStabilityInwardsCalculator(CreateInputFromData(calculation.InputParameters), MacroStabilityInwardsSubCalculatorFactory.Instance).Validate();
CalculationServiceHelper.LogMessagesAsError(RingtoetsCommonServiceResources.Error_in_validation_0, validationResults.ToArray());
CalculationServiceHelper.LogValidationEndTime(calculation.Name);
return validationResults.Count == 0;
}
///
/// Performs a macro stability inwards calculation based on the supplied and sets
/// based on the result if the calculation was successful. Error and status information is logged during
/// the execution of the operation.
///
/// The to base the input for the calculation upon.
/// Thrown when is null.
/// Consider calling first to see if calculation is possible.
public static void Calculate(MacroStabilityInwardsCalculation calculation)
{
if (calculation == null)
{
throw new ArgumentNullException(nameof(calculation));
}
CalculationServiceHelper.LogCalculationBeginTime(calculation.Name);
try
{
MacroStabilityInwardsCalculatorResult macroStabilityInwardsResult = new MacroStabilityInwardsCalculator(CreateInputFromData(calculation.InputParameters), MacroStabilityInwardsSubCalculatorFactory.Instance).Calculate();
calculation.Output = new MacroStabilityInwardsOutput(new MacroStabilityInwardsOutput.ConstructionProperties
{
UpliftZValue = macroStabilityInwardsResult.UpliftZValue,
UpliftFactorOfSafety = macroStabilityInwardsResult.UpliftFactorOfSafety,
HeaveZValue = macroStabilityInwardsResult.HeaveZValue,
HeaveFactorOfSafety = macroStabilityInwardsResult.HeaveFactorOfSafety,
SellmeijerZValue = macroStabilityInwardsResult.SellmeijerZValue,
SellmeijerFactorOfSafety = macroStabilityInwardsResult.SellmeijerFactorOfSafety,
UpliftEffectiveStress = macroStabilityInwardsResult.UpliftEffectiveStress,
HeaveGradient = macroStabilityInwardsResult.HeaveGradient,
SellmeijerCreepCoefficient = macroStabilityInwardsResult.SellmeijerCreepCoefficient,
SellmeijerCriticalFall = macroStabilityInwardsResult.SellmeijerCriticalFall,
SellmeijerReducedFall = macroStabilityInwardsResult.SellmeijerReducedFall
});
}
catch (MacroStabilityInwardsCalculatorException e)
{
CalculationServiceHelper.LogMessagesAsError(Resources.Error_in_piping_calculation_0, e.Message);
}
finally
{
CalculationServiceHelper.LogCalculationEndTime(calculation.Name);
}
}
private static List ValidateInput(MacroStabilityInwardsInput inputParameters)
{
var validationResults = new List();
validationResults.AddRange(ValidateHydraulics(inputParameters));
IEnumerable coreValidationError = ValidateCoreSurfaceLineAndSoilProfileProperties(inputParameters);
validationResults.AddRange(coreValidationError);
if (double.IsNaN(inputParameters.EntryPointL))
{
validationResults.Add(Resources.PipingCalculationService_ValidateInput_No_value_for_EntryPointL);
}
if (!coreValidationError.Any())
{
validationResults.AddRange(ValidateSoilLayers(inputParameters));
}
return validationResults;
}
private static IEnumerable ValidateHydraulics(MacroStabilityInwardsInput inputParameters)
{
var validationResults = new List();
if (!inputParameters.UseAssessmentLevelManualInput && inputParameters.HydraulicBoundaryLocation == null)
{
validationResults.Add(Resources.PipingCalculationService_ValidateInput_No_HydraulicBoundaryLocation_selected);
}
else
{
validationResults.AddRange(ValidateAssessmentLevel(inputParameters));
if (double.IsNaN(inputParameters.PiezometricHeadExit) || double.IsInfinity(inputParameters.PiezometricHeadExit))
{
validationResults.Add(Resources.PipingCalculationService_ValidateInput_Cannot_determine_PiezometricHeadExit);
}
}
return validationResults;
}
private static IEnumerable ValidateAssessmentLevel(MacroStabilityInwardsInput inputParameters)
{
var validationResult = new List();
if (inputParameters.UseAssessmentLevelManualInput)
{
validationResult.AddRange(new NumericInputRule(inputParameters.AssessmentLevel, ParameterNameExtractor.GetFromDisplayName(RingtoetsCommonFormsResources.AssessmentLevel_DisplayName)).Validate());
}
else
{
if (double.IsNaN(inputParameters.AssessmentLevel))
{
validationResult.Add(Resources.PipingCalculationService_ValidateInput_Cannot_determine_AssessmentLevel);
}
}
return validationResult;
}
private static IEnumerable ValidateCoreSurfaceLineAndSoilProfileProperties(MacroStabilityInwardsInput inputParameters)
{
var validationResults = new List();
if (inputParameters.SurfaceLine == null)
{
validationResults.Add(Resources.PipingCalculationService_ValidateInput_No_SurfaceLine_selected);
}
if (inputParameters.StochasticSoilProfile == null)
{
validationResults.Add(Resources.PipingCalculationService_ValidateInput_No_StochasticSoilProfile_selected);
}
if (double.IsNaN(inputParameters.ExitPointL))
{
validationResults.Add(Resources.PipingCalculationService_ValidateInput_No_value_for_ExitPointL);
}
return validationResults;
}
private static IEnumerable ValidateSoilLayers(MacroStabilityInwardsInput inputParameters)
{
var validationResults = new List();
if (double.IsNaN(inputParameters.ThicknessAquiferLayer.Mean))
{
validationResults.Add(Resources.PipingCalculationService_ValidateInput_Cannot_determine_thickness_aquifer_layer);
}
MacroStabilityInwardsSoilProfile macroStabilityInwardsSoilProfile = inputParameters.StochasticSoilProfile.SoilProfile;
double surfaceLevel = inputParameters.SurfaceLine.GetZAtL(inputParameters.ExitPointL);
validationResults.AddRange(ValidateAquiferLayers(inputParameters, macroStabilityInwardsSoilProfile, surfaceLevel));
validationResults.AddRange(ValidateCoverageLayers(inputParameters, macroStabilityInwardsSoilProfile, surfaceLevel));
return validationResults;
}
private static IEnumerable ValidateAquiferLayers(MacroStabilityInwardsInput inputParameters, MacroStabilityInwardsSoilProfile macroStabilityInwardsSoilProfile, double surfaceLevel)
{
var validationResult = new List();
bool hasConsecutiveAquiferLayers = macroStabilityInwardsSoilProfile.GetConsecutiveAquiferLayersBelowLevel(surfaceLevel).Any();
if (!hasConsecutiveAquiferLayers)
{
validationResult.Add(Resources.PipingCalculationService_ValidateInput_No_aquifer_layer_at_ExitPointL_under_SurfaceLine);
}
else
{
if (double.IsNaN(MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetDarcyPermeability(inputParameters).GetDesignValue()))
{
validationResult.Add(Resources.PipingCalculationService_ValidateInput_Cannot_derive_DarcyPermeability);
}
if (double.IsNaN(MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetDiameter70(inputParameters).GetDesignValue()))
{
validationResult.Add(Resources.PipingCalculationService_ValidateInput_Cannot_derive_Diameter70);
}
}
return validationResult;
}
private static IEnumerable ValidateCoverageLayers(MacroStabilityInwardsInput inputParameters, MacroStabilityInwardsSoilProfile macroStabilityInwardsSoilProfile, double surfaceLevel)
{
var validationResult = new List();
bool hasConsecutiveCoverageLayers = macroStabilityInwardsSoilProfile.GetConsecutiveCoverageLayersBelowLevel(surfaceLevel).Any();
if (hasConsecutiveCoverageLayers)
{
RoundedDouble saturatedVolumicWeightOfCoverageLayer =
MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetSaturatedVolumicWeightOfCoverageLayer(inputParameters).GetDesignValue();
if (double.IsNaN(saturatedVolumicWeightOfCoverageLayer))
{
validationResult.Add(Resources.PipingCalculationService_ValidateInput_Cannot_derive_SaturatedVolumicWeight);
}
else if (saturatedVolumicWeightOfCoverageLayer < inputParameters.WaterVolumetricWeight)
{
validationResult.Add(Resources.PipingCalculationService_ValidateInput_SaturatedVolumicWeightCoverageLayer_must_be_larger_than_WaterVolumetricWeight);
}
}
return validationResult;
}
private static List GetInputWarnings(MacroStabilityInwardsInput inputParameters)
{
var warnings = new List();
if (IsSurfaceLineProfileDefinitionComplete(inputParameters))
{
double surfaceLineLevel = inputParameters.SurfaceLine.GetZAtL(inputParameters.ExitPointL);
warnings.AddRange(GetMultipleAquiferLayersWarning(inputParameters, surfaceLineLevel));
warnings.AddRange(GetMultipleCoverageLayersWarning(inputParameters, surfaceLineLevel));
warnings.AddRange(GetDiameter70Warnings(inputParameters));
warnings.AddRange(GetThicknessCoverageLayerWarnings(inputParameters));
}
return warnings;
}
private static IEnumerable GetThicknessCoverageLayerWarnings(MacroStabilityInwardsInput inputParameters)
{
var warnings = new List();
MacroStabilityInwardsSoilProfile macroStabilityInwardsSoilProfile = inputParameters.StochasticSoilProfile.SoilProfile;
double surfaceLevel = inputParameters.SurfaceLine.GetZAtL(inputParameters.ExitPointL);
bool hasConsecutiveCoverageLayers = macroStabilityInwardsSoilProfile.GetConsecutiveCoverageLayersBelowLevel(surfaceLevel).Any();
if (!hasConsecutiveCoverageLayers)
{
warnings.Add(Resources.PipingCalculationService_ValidateInput_No_coverage_layer_at_ExitPointL_under_SurfaceLine);
}
if (double.IsNaN(inputParameters.ThicknessCoverageLayer.Mean))
{
warnings.Add(Resources.PipingCalculationService_ValidateInput_Cannot_determine_thickness_coverage_layer);
}
return warnings;
}
private static IEnumerable GetDiameter70Warnings(MacroStabilityInwardsInput inputParameters)
{
var warnings = new List();
RoundedDouble diameter70Value = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetDiameter70(inputParameters).GetDesignValue();
if (!double.IsNaN(diameter70Value) && (diameter70Value < 6.3e-5 || diameter70Value > 0.5e-3))
{
warnings.Add(string.Format(Resources.PipingCalculationService_GetInputWarnings_Specified_DiameterD70_value_0_not_in_valid_range_of_model, diameter70Value));
}
return warnings;
}
private static IEnumerable GetMultipleCoverageLayersWarning(MacroStabilityInwardsInput inputParameters, double surfaceLineLevel)
{
var warnings = new List();
bool hasMoreThanOneCoverageLayer = inputParameters.StochasticSoilProfile.SoilProfile.GetConsecutiveCoverageLayersBelowLevel(surfaceLineLevel).Count() > 1;
if (hasMoreThanOneCoverageLayer)
{
warnings.Add(Resources.PipingCalculationService_GetInputWarnings_Multiple_coverage_layers_Attempt_to_determine_value_from_combination);
}
return warnings;
}
private static IEnumerable GetMultipleAquiferLayersWarning(MacroStabilityInwardsInput inputParameters, double surfaceLineLevel)
{
var warnings = new List();
bool hasMoreThanOneAquiferLayer = inputParameters.StochasticSoilProfile.SoilProfile.GetConsecutiveAquiferLayersBelowLevel(surfaceLineLevel).Count() > 1;
if (hasMoreThanOneAquiferLayer)
{
warnings.Add(Resources.PipingCalculationService_GetInputWarnings_Multiple_aquifer_layers_Attempt_to_determine_values_for_DiameterD70_and_DarcyPermeability_from_top_layer);
}
return warnings;
}
private static bool IsSurfaceLineProfileDefinitionComplete(MacroStabilityInwardsInput surfaceLineMissing)
{
return surfaceLineMissing.SurfaceLine != null &&
surfaceLineMissing.StochasticSoilProfile != null &&
!double.IsNaN(surfaceLineMissing.ExitPointL);
}
private static MacroStabilityInwardsCalculatorInput CreateInputFromData(MacroStabilityInwardsInput inputParameters)
{
return new MacroStabilityInwardsCalculatorInput(
new MacroStabilityInwardsCalculatorInput.ConstructionProperties
{
WaterVolumetricWeight = inputParameters.WaterVolumetricWeight,
SaturatedVolumicWeightOfCoverageLayer = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetSaturatedVolumicWeightOfCoverageLayer(inputParameters).GetDesignValue(),
UpliftModelFactor = inputParameters.UpliftModelFactor,
AssessmentLevel = inputParameters.AssessmentLevel,
PiezometricHeadExit = inputParameters.PiezometricHeadExit,
DampingFactorExit = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetDampingFactorExit(inputParameters).GetDesignValue(),
PhreaticLevelExit = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetPhreaticLevelExit(inputParameters).GetDesignValue(),
CriticalHeaveGradient = inputParameters.CriticalHeaveGradient,
ThicknessCoverageLayer = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetThicknessCoverageLayer(inputParameters).GetDesignValue(),
EffectiveThicknessCoverageLayer = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetEffectiveThicknessCoverageLayer(inputParameters).GetDesignValue(),
SellmeijerModelFactor = inputParameters.SellmeijerModelFactor,
SellmeijerReductionFactor = inputParameters.SellmeijerReductionFactor,
SeepageLength = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetSeepageLength(inputParameters).GetDesignValue(),
SandParticlesVolumicWeight = inputParameters.SandParticlesVolumicWeight,
WhitesDragCoefficient = inputParameters.WhitesDragCoefficient,
Diameter70 = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetDiameter70(inputParameters).GetDesignValue(),
DarcyPermeability = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetDarcyPermeability(inputParameters).GetDesignValue(),
WaterKinematicViscosity = inputParameters.WaterKinematicViscosity,
Gravity = inputParameters.Gravity,
ThicknessAquiferLayer = MacroStabilityInwardsSemiProbabilisticDesignValueFactory.GetThicknessAquiferLayer(inputParameters).GetDesignValue(),
MeanDiameter70 = inputParameters.MeanDiameter70,
BeddingAngle = inputParameters.BeddingAngle,
ExitPointXCoordinate = inputParameters.ExitPointL,
SurfaceLine = inputParameters.SurfaceLine,
SoilProfile = inputParameters.StochasticSoilProfile?.SoilProfile
});
}
}
}