// Copyright (C) Stichting Deltares 2016. 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 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.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 stations /// /// /// 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 string ringId; private readonly HydraRingUncertaintiesType uncertaintiesType; 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 id of the ring to perform Hydra-Ring calculations for. /// The to use while performing Hydra-Ring calculations. public HydraRingConfigurationService(string ringId, HydraRingUncertaintiesType uncertaintiesType) { this.ringId = ringId; this.uncertaintiesType = uncertaintiesType; } /// /// Gets the id of the ring to perform Hydra-Ring calculations for. /// public string RingId { get { return ringId; } } /// /// Gets the to use while performing Hydra-Ring calculations. /// public HydraRingUncertaintiesType UncertaintiesType { get { return uncertaintiesType; } } /// /// 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. public void AddHydraRingCalculationInput(HydraRingCalculationInput input) { if (hydraRingInputs.Any(h => h.Section.SectionId == input.Section.SectionId)) { throw new ArgumentException(@"Section id is not unique", "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); } /// /// Generates the database creation script necessary for performing Hydra-Ring calculations. /// /// The database creation script. public void WriteDataBaseCreationScript(string databaseFilePath) { var configurationDictionary = new Dictionary>(); configurationDictionary["HydraulicModels"] = GetHydraulicModelsConfiguration(); configurationDictionary["Sections"] = GetSectionsConfiguration(); configurationDictionary["SectionCalculationSchemes"] = GetSectionCalculationSchemesConfiguration(); configurationDictionary["DesignTables"] = GetDesignTablesConfiguration(); 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 station 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 stations }, { "Relative", 100.0 // Fixed: no support for coupling two stations }, { "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 GetNumericsConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); foreach (int subMechanismId in failureMechanismDefaults.SubMechanismIds) { var numericsSetting = hydraRingCalculationInput.NumericsSettings[subMechanismId]; 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 }, { "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", 1 // Fixed: not relevant }, { "DsMinNumberOfIterations", numericsSetting.DsMinNumberOfIterations }, { "DsMaxNumberOfIterations", numericsSetting.DsMaxNumberOfIterations }, { "DsVarCoefficient", GetHydraRingValue(numericsSetting.DsVarCoefficient) }, { "NiUMin", GetHydraRingValue(numericsSetting.NiUMin) }, { "NiUMax", GetHydraRingValue(numericsSetting.NiUMax) }, { "NiNumberSteps", numericsSetting.NiNumberSteps } }); } } return orderDictionaries; } private IList GetVariableDatasConfiguration() { var orderDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); foreach (HydraRingVariable hydraRingVariable in hydraRingCalculationInput.Variables) { var 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", hydraRingVariable.DistributionType != HydraRingDistributionType.Deterministic ? GetHydraRingValue(hydraRingVariable.Mean) : defaultHydraRingValue }, { "Parameter2", hydraRingVariable.DistributionType != HydraRingDistributionType.Deterministic && hydraRingVariable.DeviationType == HydraRingDeviationType.Standard ? GetHydraRingNullableValue(hydraRingVariable.Variability) : defaultHydraRingNullValue }, { "Parameter3", hydraRingVariable.DistributionType == HydraRingDistributionType.LogNormal ? GetHydraRingNullableValue(hydraRingVariable.Shift) : defaultHydraRingNullValue }, { "Parameter4", defaultHydraRingNullValue // Fixed: Not relevant }, { "DeviationType", (int?) hydraRingVariable.DeviationType }, { "CoefficientOfVariation", hydraRingVariable.DistributionType != HydraRingDistributionType.Deterministic && hydraRingVariable.DeviationType == HydraRingDeviationType.Variation ? GetHydraRingValue(hydraRingVariable.Variability) : defaultHydraRingValue }, { "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())) { 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++) { var 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(new OrderedDictionary { { "SectionId", hydraRingCalculationInput.Section.SectionId }, { "MechanismId", failureMechanismDefaults.MechanismId }, { "LayerId", defaultLayerId // Fixed: no support for revetments }, { "AlternativeId", defaultAlternativeId // Fixed: no support for piping }, { "FaultTreeModelId", failureMechanismDefaults.FaultTreeModelId } }); } return orderedDictionaries; } private IList GetSectionSubMechanismModelsConfiguration() { var orderedDictionaries = new List(); foreach (HydraRingCalculationInput hydraRingCalculationInput in hydraRingInputs) { FailureMechanismDefaults failureMechanismDefaults = failureMechanismDefaultsProvider.GetFailureMechanismDefaults(hydraRingCalculationInput.FailureMechanismType); foreach (var subMechanismId in failureMechanismDefaults.SubMechanismIds) { var 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 (var tableName in configurationDictionary.Keys) { lines.Add("DELETE FROM [" + tableName + "];"); if (configurationDictionary[tableName].Count <= 0) { lines.Add(""); continue; } foreach (var orderedDictionary in configurationDictionary[tableName]) { var valueStrings = new List(); foreach (var 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()); } var 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; } } }