Index: Riskeer/Piping/src/Riskeer.Piping.Service/Probabilistic/ProbabilisticPipingCalculationService.cs =================================================================== diff -u -re2b60a183f95fefe71686ac319c22bb7ad644bca -r71c3adcd5c30cb64e6a1b804e6841558e8d2d712 --- Riskeer/Piping/src/Riskeer.Piping.Service/Probabilistic/ProbabilisticPipingCalculationService.cs (.../ProbabilisticPipingCalculationService.cs) (revision e2b60a183f95fefe71686ac319c22bb7ad644bca) +++ Riskeer/Piping/src/Riskeer.Piping.Service/Probabilistic/ProbabilisticPipingCalculationService.cs (.../ProbabilisticPipingCalculationService.cs) (revision 71c3adcd5c30cb64e6a1b804e6841558e8d2d712) @@ -21,14 +21,29 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using Core.Common.Base.Geometry; +using Core.Common.Base.IO; +using log4net; using Riskeer.Common.Data.AssessmentSection; +using Riskeer.Common.Data.Exceptions; +using Riskeer.Common.Data.FailureMechanism; using Riskeer.Common.Data.Hydraulics; +using Riskeer.Common.Data.IllustrationPoints; +using Riskeer.Common.Data.Probabilistics; using Riskeer.Common.IO.HydraRing; using Riskeer.Common.Service; +using Riskeer.Common.Service.IllustrationPoints; +using Riskeer.HydraRing.Calculation.Calculator; +using Riskeer.HydraRing.Calculation.Calculator.Factory; +using Riskeer.HydraRing.Calculation.Data.Input.Piping; +using Riskeer.HydraRing.Calculation.Exceptions; using Riskeer.Piping.Data; using Riskeer.Piping.Data.Probabilistic; +using Riskeer.Piping.Service.Properties; using RiskeerCommonServiceResources = Riskeer.Common.Service.Properties.Resources; +using HydraRingGeneralResult = Riskeer.HydraRing.Calculation.Data.Output.IllustrationPoints.GeneralResult; namespace Riskeer.Piping.Service.Probabilistic { @@ -37,7 +52,19 @@ /// public class ProbabilisticPipingCalculationService { + private const int numberOfCalculators = 2; + private static readonly ILog log = LogManager.GetLogger(typeof(ProbabilisticPipingCalculationService)); + + private IPipingCalculator profileSpecificCalculator; + private IPipingCalculator sectionSpecificCalculator; + private bool canceled; + /// + /// Fired when the calculation progress changed. + /// + public event OnProgressChanged OnProgressChanged; + + /// /// Performs validation over the values on the given . Error and status information is logged during /// the execution of the operation. /// @@ -82,6 +109,297 @@ return !messages.Any(); } + /// + /// Performs a structures calculation based on the supplied and sets + /// if the calculation was successful. Error and status information is logged during the execution of the operation. + /// + /// The that holds all the information required to perform the calculation. + /// The which the belongs to. + /// The with the + /// hydraulic boundary calculation settings. + /// Preprocessing is disabled when the preprocessor directory equals . + /// Thrown when any parameter is null. + /// Thrown when the hydraulic boundary database file path + /// contains invalid characters. + /// Thrown when an unexpected + /// enum value is encountered. + /// Thrown when: + /// + /// No settings database file could be found at the location of the hydraulic boundary database file path + /// with the same name. + /// Unable to open settings database file. + /// Unable to read required data from database file. + /// + /// Thrown when an error occurs while performing the calculation. + public void Calculate(ProbabilisticPipingCalculation calculation, PipingFailureMechanism failureMechanism, + HydraulicBoundaryCalculationSettings calculationSettings) + { + if (calculation == null) + { + throw new ArgumentNullException(nameof(calculation)); + } + + if (failureMechanism == null) + { + throw new ArgumentNullException(nameof(failureMechanism)); + } + + if (calculationSettings == null) + { + throw new ArgumentNullException(nameof(calculationSettings)); + } + + string hydraulicBoundaryDatabaseFilePath = calculationSettings.HydraulicBoundaryDatabaseFilePath; + bool usePreprocessor = !string.IsNullOrEmpty(calculationSettings.PreprocessorDirectory); + + profileSpecificCalculator = HydraRingCalculatorFactory.Instance.CreatePipingCalculator( + HydraRingCalculationSettingsFactory.CreateSettings(calculationSettings)); + + sectionSpecificCalculator = HydraRingCalculatorFactory.Instance.CreatePipingCalculator( + HydraRingCalculationSettingsFactory.CreateSettings(calculationSettings)); + + CalculationServiceHelper.LogCalculationBegin(); + + try + { + PartialProbabilisticPipingOutput profileSpecificOutput = CalculateProfileSpecific( + calculation, failureMechanism, hydraulicBoundaryDatabaseFilePath, usePreprocessor); + + if (canceled) + { + return; + } + + PartialProbabilisticPipingOutput sectionSpecificOutput = CalculateSectionSpecific( + calculation, failureMechanism, hydraulicBoundaryDatabaseFilePath, usePreprocessor); + + if (canceled) + { + return; + } + + calculation.Output = new ProbabilisticPipingOutput(sectionSpecificOutput, profileSpecificOutput); + } + finally + { + CalculationServiceHelper.LogCalculationEnd(); + + profileSpecificCalculator = null; + sectionSpecificCalculator = null; + } + } + + /// + /// Cancels any currently running grass cover erosion inwards calculation. + /// + public void Cancel() + { + profileSpecificCalculator?.Cancel(); + sectionSpecificCalculator?.Cancel(); + canceled = true; + } + + private PartialProbabilisticPipingOutput CalculateProfileSpecific(ProbabilisticPipingCalculation calculation, PipingFailureMechanism failureMechanism, string hydraulicBoundaryDatabaseFilePath, bool usePreprocessor) + { + NotifyProgress(string.Format(Resources.ProbabilisticPipingCalculationService_Calculate_Executing_calculation_of_type_0, + Resources.ProbabilisticPipingCalculationService_ProfileSpecific), + 1, numberOfCalculators); + + PipingCalculationInput profileSpecificCalculationInput = CreateInput( + calculation, failureMechanism.GeneralInput, 0, + hydraulicBoundaryDatabaseFilePath, usePreprocessor); + + PerformCalculation(() => profileSpecificCalculator.Calculate(profileSpecificCalculationInput), + () => profileSpecificCalculator.LastErrorFileContent, + () => profileSpecificCalculator.OutputDirectory, + calculation.Name, + Resources.ProbabilisticPipingCalculationService_ProfileSpecific); + + GeneralResult generalResult = null; + try + { + generalResult = calculation.InputParameters.ShouldIllustrationPointsBeCalculated + ? ConvertIllustrationPointsResult(profileSpecificCalculator.IllustrationPointsResult, + profileSpecificCalculator.IllustrationPointsParserErrorMessage) + : null; + } + catch (ArgumentException e) + { + log.WarnFormat(Resources.PipingProbabailisticCalculationService_Calculate_Error_in_reading_illustrationPoints_for_CalculationName_0_CalculationType_1_overtopping_with_ErrorMessage_2, + calculation.Name, Resources.ProbabilisticPipingCalculationService_ProfileSpecific, e.Message); + } + + return new PartialProbabilisticPipingOutput(profileSpecificCalculator.ExceedanceProbabilityBeta, + generalResult); + } + + private PartialProbabilisticPipingOutput CalculateSectionSpecific(ProbabilisticPipingCalculation calculation, PipingFailureMechanism failureMechanism, string hydraulicBoundaryDatabaseFilePath, bool usePreprocessor) + { + NotifyProgress(string.Format(Resources.ProbabilisticPipingCalculationService_Calculate_Executing_calculation_of_type_0, + Resources.ProbabilisticPipingCalculationService_SectionSpecific), + 2, numberOfCalculators); + + FailureMechanismSection section = failureMechanism.Sections.First(s => calculation.IsSurfaceLineIntersectionWithReferenceLineInSection(Math2D.ConvertPointsToLineSegments(s.Points))); + + PipingCalculationInput sectionSpecificCalculationInput = CreateInput( + calculation, failureMechanism.GeneralInput, section.Length, + hydraulicBoundaryDatabaseFilePath, usePreprocessor); + + PerformCalculation(() => sectionSpecificCalculator.Calculate(sectionSpecificCalculationInput), + () => sectionSpecificCalculator.LastErrorFileContent, + () => sectionSpecificCalculator.OutputDirectory, + calculation.Name, + Resources.ProbabilisticPipingCalculationService_SectionSpecific); + + GeneralResult generalResult = null; + try + { + generalResult = calculation.InputParameters.ShouldIllustrationPointsBeCalculated + ? ConvertIllustrationPointsResult(sectionSpecificCalculator.IllustrationPointsResult, + sectionSpecificCalculator.IllustrationPointsParserErrorMessage) + : null; + } + catch (ArgumentException e) + { + log.WarnFormat(Resources.PipingProbabailisticCalculationService_Calculate_Error_in_reading_illustrationPoints_for_CalculationName_0_CalculationType_1_overtopping_with_ErrorMessage_2, + calculation.Name, Resources.ProbabilisticPipingCalculationService_SectionSpecific, e.Message); + } + + return new PartialProbabilisticPipingOutput(sectionSpecificCalculator.ExceedanceProbabilityBeta, + generalResult); + } + + /// + /// Performs a grass cover erosion inwards calculation. + /// + /// The action that performs the calculation. + /// The function for obtaining the last error file content. + /// The function for obtaining the output directory. + /// The name of the calculation to perform. + /// The name of the step to perform. + /// Thrown when an error occurs while performing the calculation. + private void PerformCalculation(Action performCalculation, + Func getLastErrorFileContent, + Func getOutputDirectory, + string calculationName, + string stepName) + { + var exceptionThrown = false; + + try + { + performCalculation(); + } + catch (HydraRingCalculationException) + { + if (!canceled) + { + string lastErrorFileContent = getLastErrorFileContent(); + if (string.IsNullOrEmpty(lastErrorFileContent)) + { + log.ErrorFormat( + Resources.ProbabilisticPipingCalculationService_Calculate_Error_in_calculation_of_type_0_for_calculation_with_name_1_no_error_report, + stepName, + calculationName); + } + else + { + log.ErrorFormat( + Resources.ProbabilisticPipingCalculationService_Calculate_Error_in_calculation_of_type_0_for_calculation_with_name_1_click_details_for_last_error_report_2, + stepName, + calculationName, + lastErrorFileContent); + } + + exceptionThrown = true; + throw; + } + } + finally + { + string lastErrorFileContent = getLastErrorFileContent(); + bool errorOccurred = CalculationServiceHelper.HasErrorOccurred(canceled, exceptionThrown, lastErrorFileContent); + if (errorOccurred) + { + log.ErrorFormat( + Resources.ProbabilisticPipingCalculationService_Calculate_Error_in_calculation_of_type_0_for_calculation_with_name_1_click_details_for_last_error_report_2, + stepName, + calculationName, + lastErrorFileContent); + } + + log.InfoFormat( + Resources.ProbabilisticPipingCalculationService_Calculate_Calculation_of_type_0_performed_in_temporary_directory_1, + stepName, + getOutputDirectory()); + + if (errorOccurred) + { + throw new HydraRingCalculationException(lastErrorFileContent); + } + } + } + + private PipingCalculationInput CreateInput(ProbabilisticPipingCalculation calculation, GeneralPipingInput generalInput, double sectionLength, string hydraulicBoundaryDatabaseFilePath, bool usePreprocessor) + { + ProbabilisticPipingInput pipingInput = calculation.InputParameters; + + LogNormalDistribution effectiveThicknessCoverageLayer = DerivedPipingInput.GetEffectiveThicknessCoverageLayer(pipingInput, generalInput); + LogNormalDistribution saturatedVolumicWeightOfCoverageLayer = DerivedPipingInput.GetSaturatedVolumicWeightOfCoverageLayer(pipingInput); + VariationCoefficientLogNormalDistribution seepageLength = DerivedPipingInput.GetSeepageLength(pipingInput); + LogNormalDistribution thicknessAquiferLayer = DerivedPipingInput.GetThicknessAquiferLayer(pipingInput); + VariationCoefficientLogNormalDistribution darcyPermeability = DerivedPipingInput.GetDarcyPermeability(pipingInput); + VariationCoefficientLogNormalDistribution diameterD70 = DerivedPipingInput.GetDiameterD70(pipingInput); + + var input = new PipingCalculationInput( + pipingInput.HydraulicBoundaryLocation.Id, + sectionLength, + generalInput.WaterVolumetricWeight, + pipingInput.PhreaticLevelExit.Mean, pipingInput.PhreaticLevelExit.StandardDeviation, + generalInput.WaterVolumetricWeight, + effectiveThicknessCoverageLayer.Mean, effectiveThicknessCoverageLayer.StandardDeviation, + saturatedVolumicWeightOfCoverageLayer.Mean, saturatedVolumicWeightOfCoverageLayer.StandardDeviation, + saturatedVolumicWeightOfCoverageLayer.Shift, + generalInput.UpliftModelFactor.Mean, generalInput.UpliftModelFactor.StandardDeviation, + pipingInput.DampingFactorExit.Mean, pipingInput.DampingFactorExit.StandardDeviation, + seepageLength.Mean, seepageLength.CoefficientOfVariation, + thicknessAquiferLayer.Mean, thicknessAquiferLayer.StandardDeviation, + generalInput.SandParticlesVolumicWeight, + generalInput.SellmeijerModelFactor.Mean, generalInput.SellmeijerModelFactor.StandardDeviation, + generalInput.BeddingAngle, + generalInput.WhitesDragCoefficient, + darcyPermeability.Mean, darcyPermeability.CoefficientOfVariation, + diameterD70.Mean, diameterD70.CoefficientOfVariation, + generalInput.Gravity, + generalInput.CriticalHeaveGradient.Mean, generalInput.CriticalHeaveGradient.StandardDeviation); + + HydraRingSettingsDatabaseHelper.AssignSettingsFromDatabase(input, hydraulicBoundaryDatabaseFilePath, usePreprocessor); + + return input; + } + + private static GeneralResult ConvertIllustrationPointsResult(HydraRingGeneralResult result, string errorMessage) + { + if (result == null) + { + log.Warn(errorMessage); + return null; + } + + try + { + GeneralResult generalResult = + GeneralResultConverter.ConvertToGeneralResultTopLevelFaultTreeIllustrationPoint(result); + return generalResult; + } + catch (IllustrationPointConversionException e) + { + log.Warn(RiskeerCommonServiceResources.SetGeneralResult_Converting_IllustrationPointResult_Failed, e); + } + + return null; + } + private static IEnumerable ValidateHydraulicBoundaryDatabase(IAssessmentSection assessmentSection) { string preprocessorDirectory = assessmentSection.HydraulicBoundaryDatabase.EffectivePreprocessorDirectory(); @@ -111,5 +429,10 @@ return validationResults; } + + private void NotifyProgress(string stepName, int currentStepNumber, int totalStepNumber) + { + OnProgressChanged?.Invoke(stepName, currentStepNumber, totalStepNumber); + } } } \ No newline at end of file Index: Riskeer/Piping/src/Riskeer.Piping.Service/Properties/Resources.Designer.cs =================================================================== diff -u -r106eeb3a0608bd85eb1fcc8fff72256fd9c3ac5f -r71c3adcd5c30cb64e6a1b804e6841558e8d2d712 --- Riskeer/Piping/src/Riskeer.Piping.Service/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 106eeb3a0608bd85eb1fcc8fff72256fd9c3ac5f) +++ Riskeer/Piping/src/Riskeer.Piping.Service/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 71c3adcd5c30cb64e6a1b804e6841558e8d2d712) @@ -1,4 +1,4 @@ -// Copyright (C) Stichting Deltares 2019. All rights reserved. +// Copyright (C) Stichting Deltares 2019. All rights reserved. // // This file is part of Riskeer. // @@ -40,7 +40,7 @@ // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -230,5 +230,73 @@ "e_larger_than_WaterVolumetricWeight", resourceCulture); } } + + /// + /// Looks up a localized string similar to Fout bij het uitlezen van de illustratiepunten voor berekening {0} ({1}): {2} Het uitlezen van illustratiepunten wordt overgeslagen.. + /// + internal static string PipingProbabailisticCalculationService_Calculate_Error_in_reading_illustrationPoints_for_CalculationName_0_CalculationType_1_overtopping_with_ErrorMessage_2 { + get { + return ResourceManager.GetString("PipingProbabailisticCalculationService_Calculate_Error_in_reading_illustrationPoi" + + "nts_for_CalculationName_0_CalculationType_1_overtopping_with_ErrorMessage_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to De {0} berekening is uitgevoerd op de tijdelijke locatie '{1}'. Gedetailleerde invoer en uitvoer kan in de bestanden op deze locatie worden gevonden.. + /// + internal static string ProbabilisticPipingCalculationService_Calculate_Calculation_of_type_0_performed_in_temporary_directory_1 { + get { + return ResourceManager.GetString("ProbabilisticPipingCalculationService_Calculate_Calculation_of_type_0_performed_i" + + "n_temporary_directory_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to De {0} berekening voor piping '{1}' is mislukt. Bekijk het foutrapport door op details te klikken. + ///{2}. + /// + internal static string ProbabilisticPipingCalculationService_Calculate_Error_in_calculation_of_type_0_for_calculation_with_name_1_click_details_for_last_error_report_2 { + get { + return ResourceManager.GetString("ProbabilisticPipingCalculationService_Calculate_Error_in_calculation_of_type_0_fo" + + "r_calculation_with_name_1_click_details_for_last_error_report_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to De {0} berekening voor piping '{1}' is mislukt. Er is geen foutrapport beschikbaar.. + /// + internal static string ProbabilisticPipingCalculationService_Calculate_Error_in_calculation_of_type_0_for_calculation_with_name_1_no_error_report { + get { + return ResourceManager.GetString("ProbabilisticPipingCalculationService_Calculate_Error_in_calculation_of_type_0_fo" + + "r_calculation_with_name_1_no_error_report", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Uitvoeren piping berekening voor {0}. + /// + internal static string ProbabilisticPipingCalculationService_Calculate_Executing_calculation_of_type_0 { + get { + return ResourceManager.GetString("ProbabilisticPipingCalculationService_Calculate_Executing_calculation_of_type_0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to doorsnede. + /// + internal static string ProbabilisticPipingCalculationService_ProfileSpecific { + get { + return ResourceManager.GetString("ProbabilisticPipingCalculationService_ProfileSpecific", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to vak. + /// + internal static string ProbabilisticPipingCalculationService_SectionSpecific { + get { + return ResourceManager.GetString("ProbabilisticPipingCalculationService_SectionSpecific", resourceCulture); + } + } } } Index: Riskeer/Piping/src/Riskeer.Piping.Service/Properties/Resources.resx =================================================================== diff -u -rbf1fde9d2147a6eeaecebbb371be2c4856759159 -r71c3adcd5c30cb64e6a1b804e6841558e8d2d712 --- Riskeer/Piping/src/Riskeer.Piping.Service/Properties/Resources.resx (.../Resources.resx) (revision bf1fde9d2147a6eeaecebbb371be2c4856759159) +++ Riskeer/Piping/src/Riskeer.Piping.Service/Properties/Resources.resx (.../Resources.resx) (revision 71c3adcd5c30cb64e6a1b804e6841558e8d2d712) @@ -165,4 +165,26 @@ Het verzadigd volumetrisch gewicht van de deklaag moet groter zijn dan het volumetrisch gewicht van water. + + Uitvoeren piping berekening voor {0} + + + De {0} berekening voor piping '{1}' is mislukt. Er is geen foutrapport beschikbaar. + + + De {0} berekening voor piping '{1}' is mislukt. Bekijk het foutrapport door op details te klikken. +{2} + + + De {0} berekening is uitgevoerd op de tijdelijke locatie '{1}'. Gedetailleerde invoer en uitvoer kan in de bestanden op deze locatie worden gevonden. + + + Fout bij het uitlezen van de illustratiepunten voor berekening {0} ({1}): {2} Het uitlezen van illustratiepunten wordt overgeslagen. + + + doorsnede + + + vak + \ No newline at end of file Index: Riskeer/Piping/src/Riskeer.Piping.Service/Riskeer.Piping.Service.csproj =================================================================== diff -u -ra4047c0251a066635676fb6a1927836a6310d720 -r71c3adcd5c30cb64e6a1b804e6841558e8d2d712 --- Riskeer/Piping/src/Riskeer.Piping.Service/Riskeer.Piping.Service.csproj (.../Riskeer.Piping.Service.csproj) (revision a4047c0251a066635676fb6a1927836a6310d720) +++ Riskeer/Piping/src/Riskeer.Piping.Service/Riskeer.Piping.Service.csproj (.../Riskeer.Piping.Service.csproj) (revision 71c3adcd5c30cb64e6a1b804e6841558e8d2d712) @@ -1,4 +1,4 @@ - + @@ -10,6 +10,7 @@ + @@ -32,4 +33,14 @@ Copying.licenseheader + + + 2.0.8 + true + all + + + + + \ No newline at end of file