// 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.Collections.Specialized; using System.Globalization; using System.IO; using System.Linq; using System.Security; using Ringtoets.HydraRing.Calculation.Data; using Ringtoets.HydraRing.Calculation.Data.Defaults; using Ringtoets.HydraRing.Calculation.Data.Input; using Ringtoets.HydraRing.Calculation.Data.Settings; using Ringtoets.HydraRing.Calculation.Data.Variables; using Ringtoets.HydraRing.Calculation.Providers; namespace Ringtoets.HydraRing.Calculation.Services { /// /// Service for generating the database creation script that is necessary for performing Hydra-Ring calculations. /// The following Hydra-Ring features are not exposed (yet): /// /// /// Combination of multiple sections /// /// /// Coupling two hydraulic boundary locations /// /// /// Performing revetment calculations (DesignTables > LayerId) /// /// /// Performing piping calculations (DesignTables > AlternativeId) /// /// /// Type III calculations (DesignTables > Method) /// /// /// In the end, the configuration can be used to generate a Hydra-Ring database creation script. /// internal class HydraRingConfigurationService { private const double defaultLayerId = 1; private const double defaultAlternativeId = 1; private const double defaultHydraRingValue = 0.0; private readonly double? defaultHydraRingNullValue = null; private readonly IList hydraRingInputs = new List(); private readonly FailureMechanismDefaultsProvider failureMechanismDefaultsProvider = new FailureMechanismDefaultsProvider(); private readonly VariableDefaultsProvider variableDefaultsProvider = new VariableDefaultsProvider(); /// /// Creates a new instance of the class. /// /// The to use while performing Hydra-Ring calculations. public HydraRingConfigurationService(HydraRingUncertaintiesType uncertaintiesType) { UncertaintiesType = uncertaintiesType; } /// /// Gets the to use while performing Hydra-Ring calculations. /// public HydraRingUncertaintiesType UncertaintiesType { get; } /// /// Adds Hydra-Ring calculation input to the configuration. /// /// The calculation input to add to the configuration. /// Thrown when with /// the same has already been added. /// Thrown when is not unique. /// Thrown when /// is not the same with already added input. public void AddHydraRingCalculationInput(HydraRingCalculationInput input) { if (hydraRingInputs.Any(h => h.Section.SectionId == input.Section.SectionId)) { throw new ArgumentException(@"Section id is not unique", nameof(input)); } if (hydraRingInputs.Count > 0 && hydraRingInputs.First().FailureMechanismType != input.FailureMechanismType) { throw new NotSupportedException("Running calculations for multiple failure mechanism types is not supported."); } hydraRingInputs.Add(input); } /// /// Writes the database creation script necessary for performing Hydra-Ring calculations. /// /// The file path to write the database creation script to. /// Thrown when an I/O error occurred while opening the file. /// Thrown when the path can't be accessed due to missing permissions. /// Thrown when the path can't be accessed due to missing permissions. public void WriteDatabaseCreationScript(string databaseFilePath) { var configurationDictionary = new Dictionary>(); configurationDictionary["HydraulicModels"] = GetHydraulicModelsConfiguration(); configurationDictionary["Sections"] = GetSectionsConfiguration(); configurationDictionary["SectionCalculationSchemes"] = GetSectionCalculationSchemesConfiguration(); configurationDictionary["DesignTables"] = GetDesignTablesConfiguration(); configurationDictionary["PreprocessorSettings"] = GetPreprocessorSettingsConfiguration(); configurationDictionary["Numerics"] = GetNumericsConfiguration(); configurationDictionary["VariableDatas"] = GetVariableDatasConfiguration(); configurationDictionary["CalculationProfiles"] = GetCalculationProfilesConfiguration(); configurationDictionary["SectionFaultTreeModels"] = GetSectionFaultTreeModelsConfiguration(); configurationDictionary["SectionSubMechanismModels"] = GetSectionSubMechanismModelsConfiguration(); configurationDictionary["Fetches"] = new List(); configurationDictionary["AreaPoints"] = new List(); configurationDictionary["PresentationSections"] = new List(); configurationDictionary["Profiles"] = GetProfilesConfiguration(); configurationDictionary["ForelandModels"] = GetForlandModelsConfiguration(); configurationDictionary["Forelands"] = GetForelandsConfiguration(); configurationDictionary["ProbabilityAlternatives"] = new List(); configurationDictionary["SetUpHeights"] = new List(); configurationDictionary["CalcWindDirections"] = new List(); configurationDictionary["Swells"] = new List(); configurationDictionary["WaveReductions"] = new List(); configurationDictionary["Areas"] = GetAreasConfiguration(); configurationDictionary["Projects"] = GetProjectsConfiguration(); configurationDictionary["Breakwaters"] = GetBreakWatersConfiguration(); File.WriteAllText(databaseFilePath, GenerateDatabaseCreationScript(configurationDictionary)); } private IList GetHydraulicModelsConfiguration() { return new List { new OrderedDictionary { { "TimeIntegrationSchemeID", 1 }, { "UncertaintiesID", (int) UncertaintiesType }, { "DataSetName", "WTI 2017" // Fixed: use the WTI 2017 set of hydraulic boundary locations } } }; } private IList GetSectionsConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { HydraRingSection hydraRingSection = hydraRingCalculationInput.Section; orderedDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingSection.SectionId }, { "PresentationId", 1 // Fixed: no support for combination of multiple sections }, { "MainMechanismId", 1 // Fixed: no support for combination of multiple sections }, { "Name", hydraRingSection.SectionId // Just use the section id }, { "Description", hydraRingSection.SectionId // Just use the section id }, { "RingCoordinateBegin", defaultHydraRingValue // No support for coordinates }, { "RingCoordinateEnd", defaultHydraRingValue // No support for coordinates }, { "XCoordinate", defaultHydraRingValue // No support for coordinates }, { "YCoordinate", defaultHydraRingValue // No support for coordinates }, { "StationId1", hydraRingCalculationInput.HydraulicBoundaryLocationId }, { "StationId2", hydraRingCalculationInput.HydraulicBoundaryLocationId // Same as "StationId1": no support for coupling two hydraulic boundary locations }, { "Relative", 100.0 // Fixed: no support for coupling two hydraulic boundary locations }, { "Normal", GetHydraRingValue(hydraRingSection.CrossSectionNormal) }, { "Length", GetHydraRingValue(hydraRingSection.SectionLength) } }); } return orderedDictionaries; } private IList GetSectionCalculationSchemesConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); TimeIntegrationSetting timeIntegrationSetting = hydraRingCalculationInput.TimeIntegrationSetting; orderedDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "MechanismId", failureMechanismDefaults.MechanismId }, { "TimeIntegrationSchemeID", timeIntegrationSetting.TimeIntegrationSchemeId } }); } return orderedDictionaries; } private IList GetDesignTablesConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); DesignTablesSetting designTablesSetting = hydraRingCalculationInput.DesignTablesSetting; orderedDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "MechanismId", failureMechanismDefaults.MechanismId }, { "LayerId", defaultLayerId // Fixed: no support for revetments }, { "AlternativeId", defaultAlternativeId // Fixed: no support for piping }, { "Method", hydraRingCalculationInput.CalculationTypeId }, { "VariableId", hydraRingCalculationInput.VariableId }, { "LoadVariableId", defaultHydraRingValue // Fixed: not relevant }, { "TableMin", defaultHydraRingValue // Fixed: no support for type III calculations (see "Method") }, { "TableMax", defaultHydraRingValue // Fixed: no support for type III calculations (see "Method") }, { "TableStepSize", defaultHydraRingValue // Fixed: no support for type III calculations (see "Method") }, { "ValueMin", GetHydraRingValue(designTablesSetting.ValueMin) }, { "ValueMax", GetHydraRingValue(designTablesSetting.ValueMax) }, { "Beta", GetHydraRingValue(hydraRingCalculationInput.Beta) } }); } return orderedDictionaries; } private IList GetPreprocessorSettingsConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { PreprocessorSetting preprocessorSetting = hydraRingCalculationInput.PreprocessorSetting; if (preprocessorSetting.RunPreprocessor) { orderedDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "MinValueRunPreprocessor", preprocessorSetting.ValueMin }, { "MaxValueRunPreprocessor", preprocessorSetting.ValueMax } }); } } return orderedDictionaries; } private IList GetNumericsConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); foreach (int subMechanismId in failureMechanismDefaults.SubMechanismIds) { NumericsSetting numericsSetting = hydraRingCalculationInput.NumericsSettings[subMechanismId]; orderDictionaries.Add(CreateNumericsRecord(hydraRingCalculationInput.Section.SectionId, failureMechanismDefaults.MechanismId, subMechanismId, numericsSetting)); } if (hydraRingCalculationInput.PreprocessorSetting.RunPreprocessor) { orderDictionaries.Add(CreateNumericsRecord(hydraRingCalculationInput.Section.SectionId, failureMechanismDefaults.MechanismId, failureMechanismDefaults.PreprocessorSubMechanismId, hydraRingCalculationInput.PreprocessorSetting.NumericsSetting)); } } return orderDictionaries; } private static OrderedDictionary CreateNumericsRecord(int sectionId, int mechanismId, int subMechanismId, NumericsSetting numericsSetting) { return new OrderedDictionary { { "SectionId", sectionId }, { "MechanismId", mechanismId }, { "LayerId", defaultLayerId // Fixed: no support for revetments }, { "AlternativeId", defaultAlternativeId // Fixed: no support for piping }, { "SubMechanismId", subMechanismId }, { "Method", numericsSetting.CalculationTechniqueId }, { "FormStartMethod", numericsSetting.FormStartMethod }, { "FormNumberOfIterations", numericsSetting.FormNumberOfIterations }, { "FormRelaxationFactor", GetHydraRingValue(numericsSetting.FormRelaxationFactor) }, { "FormEpsBeta", GetHydraRingValue(numericsSetting.FormEpsBeta) }, { "FormEpsHOH", GetHydraRingValue(numericsSetting.FormEpsHoh) }, { "FormEpsZFunc", GetHydraRingValue(numericsSetting.FormEpsZFunc) }, { "DsStartMethod", numericsSetting.DsStartMethod }, { "DsIterationmethod", 3 // Fixed: not relevant }, { "DsMinNumberOfIterations", numericsSetting.DsMinNumberOfIterations }, { "DsMaxNumberOfIterations", numericsSetting.DsMaxNumberOfIterations }, { "DsVarCoefficient", GetHydraRingValue(numericsSetting.DsVarCoefficient) }, { "NiUMin", GetHydraRingValue(numericsSetting.NiUMin) }, { "NiUMax", GetHydraRingValue(numericsSetting.NiUMax) }, { "NiNumberSteps", numericsSetting.NiNumberSteps } }; } private IList GetVariableDatasConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); foreach (HydraRingVariable hydraRingVariable in hydraRingCalculationInput.Variables) { VariableDefaults variableDefaults = variableDefaultsProvider.GetVariableDefaults(hydraRingCalculationInput.FailureMechanismType, hydraRingVariable.VariableId); orderDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "MechanismId", failureMechanismDefaults.MechanismId }, { "LayerId", defaultLayerId // Fixed: no support for revetments }, { "AlternativeId", defaultAlternativeId // Fixed: no support for piping }, { "VariableId", hydraRingVariable.VariableId }, { "Value", GetHydraRingValue(hydraRingVariable.Value) }, { "DistributionType", (int?) hydraRingVariable.DistributionType }, { "Parameter1", GetHydraRingValue(hydraRingVariable.Parameter1) }, { "Parameter2", GetHydraRingNullableValue(hydraRingVariable.Parameter2) }, { "Parameter3", GetHydraRingNullableValue(hydraRingVariable.Parameter3) }, { "Parameter4", GetHydraRingNullableValue(hydraRingVariable.Parameter4) }, { "DeviationType", (int?) hydraRingVariable.DeviationType }, { "CoefficientOfVariation", GetHydraRingValue(hydraRingVariable.CoefficientOfVariation) }, { "CorrelationLength", GetHydraRingValue(variableDefaults.CorrelationLength) } }); } } return orderDictionaries; } private IList GetProfilesConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { for (var i = 0; i < hydraRingCalculationInput.ProfilePoints.Count(); i++) { HydraRingProfilePoint hydraRingProfilePoint = hydraRingCalculationInput.ProfilePoints.ElementAt(i); orderDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "SequenceNumber", i + 1 }, { "XCoordinate", GetHydraRingValue(hydraRingProfilePoint.X) }, { "ZCoordinate", GetHydraRingValue(hydraRingProfilePoint.Z) } }); } } return orderDictionaries; } private IList GetCalculationProfilesConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { for (var i = 0; i < hydraRingCalculationInput.ProfilePoints.Count(); i++) { HydraRingProfilePoint hydraRingProfilePoint = hydraRingCalculationInput.ProfilePoints.ElementAt(i); orderDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "SequenceNumber", i + 1 }, { "XCoordinate", GetHydraRingValue(hydraRingProfilePoint.X) }, { "ZCoordinate", GetHydraRingValue(hydraRingProfilePoint.Z) }, { "Roughness", GetHydraRingValue(hydraRingProfilePoint.Roughness) } }); } } return orderDictionaries; } private IList GetForlandModelsConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput input in hydraRingInputs.Where(i => i.ForelandsPoints.Any() || i.BreakWater != null)) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(input.FailureMechanismType); orderDictionaries.Add(new OrderedDictionary { { "SectionId", input.Section.SectionId }, { "MechanismId", failureMechanismDefaults.MechanismId }, { "Model", 3 } }); } return orderDictionaries; } private IList GetForelandsConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { for (var i = 0; i < hydraRingCalculationInput.ForelandsPoints.Count(); i++) { HydraRingForelandPoint forelandPoint = hydraRingCalculationInput.ForelandsPoints.ElementAt(i); orderDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "SequenceNumber", i + 1 }, { "XCoordinate", GetHydraRingValue(forelandPoint.X) }, { "ZCoordinate", GetHydraRingValue(forelandPoint.Z) } }); } } return orderDictionaries; } private IList GetBreakWatersConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { if (hydraRingCalculationInput.BreakWater != null) { orderedDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "Type", hydraRingCalculationInput.BreakWater.Type }, { "Height", GetHydraRingValue(hydraRingCalculationInput.BreakWater.Height) } }); } } return orderedDictionaries; } private IList GetSectionFaultTreeModelsConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); orderedDictionaries.Add(CreateFaultTreeModelsRecord(hydraRingCalculationInput.Section.SectionId, failureMechanismDefaults.MechanismId, failureMechanismDefaults.FaultTreeModelId)); if (hydraRingCalculationInput.PreprocessorSetting.RunPreprocessor) { orderedDictionaries.Add(CreateFaultTreeModelsRecord(hydraRingCalculationInput.Section.SectionId, failureMechanismDefaults.MechanismId, failureMechanismDefaults.PreprocessorFaultTreeModelId)); } } return orderedDictionaries; } private static OrderedDictionary CreateFaultTreeModelsRecord(int sectionId, int mechanismId, int faultTreeModelId) { return new OrderedDictionary { { "SectionId", sectionId }, { "MechanismId", mechanismId }, { "LayerId", defaultLayerId // Fixed: no support for revetments }, { "AlternativeId", defaultAlternativeId // Fixed: no support for piping }, { "FaultTreeModelId", faultTreeModelId } }; } private IList GetSectionSubMechanismModelsConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); foreach (int subMechanismId in failureMechanismDefaults.SubMechanismIds) { int? subMechanismModelId = hydraRingCalculationInput.GetSubMechanismModelId(subMechanismId); if (subMechanismModelId != null) { orderedDictionaries.Add(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "LayerId", defaultLayerId // Fixed: no support for revetments }, { "AlternativeId", defaultAlternativeId // Fixed: no support for piping }, { "SubMechanismId", subMechanismId }, { "SubMechanismModelId", subMechanismModelId } }); } } } return orderedDictionaries; } private static IList GetAreasConfiguration() { return new List { new OrderedDictionary { { "aDefault", 1 // Fixed: not relevant }, { "bDefault", "1" // Fixed: not relevant }, { "cDefault", "Nederland" // Fixed: not relevant } } }; } private static IList GetProjectsConfiguration() { return new List { new OrderedDictionary { { "aDefault", 1 // Fixed: not relevant }, { "bDefault", "WTI 2017" // Fixed: not relevant }, { "cDefault", "Ringtoets calculation" // Fixed: not relevant } } }; } private static string GenerateDatabaseCreationScript(Dictionary> configurationDictionary) { var lines = new List(); foreach (string tableName in configurationDictionary.Keys) { lines.Add("DELETE FROM [" + tableName + "];"); if (configurationDictionary[tableName].Count <= 0) { lines.Add(""); continue; } foreach (OrderedDictionary orderedDictionary in configurationDictionary[tableName]) { var valueStrings = new List(); foreach (object val in orderedDictionary.Values) { if (val == null) { valueStrings.Add("NULL"); continue; } if (val is string) { valueStrings.Add("'" + val + "'"); continue; } if (val is double) { valueStrings.Add(((double) val).ToString(CultureInfo.InvariantCulture)); continue; } valueStrings.Add(val.ToString()); } string valuesString = string.Join(", ", valueStrings); lines.Add("INSERT INTO [" + tableName + "] VALUES (" + valuesString + ");"); } lines.Add(""); } return string.Join(Environment.NewLine, lines); } private static double GetHydraRingValue(double value) { return !double.IsNaN(value) ? value : defaultHydraRingValue; } private double? GetHydraRingNullableValue(double value) { return !double.IsNaN(value) ? value : defaultHydraRingNullValue; } } }