Index: Ringtoets/Common/src/Ringtoets.Common.Data/Structures/StructuresInputBase.cs =================================================================== diff -u -r8614a64110c5bc1e1b91950a7308b77322709c91 -r0afc6984f0b40aa96f1929cb20e0be7402dd7fed --- Ringtoets/Common/src/Ringtoets.Common.Data/Structures/StructuresInputBase.cs (.../StructuresInputBase.cs) (revision 8614a64110c5bc1e1b91950a7308b77322709c91) +++ Ringtoets/Common/src/Ringtoets.Common.Data/Structures/StructuresInputBase.cs (.../StructuresInputBase.cs) (revision 0afc6984f0b40aa96f1929cb20e0be7402dd7fed) @@ -19,12 +19,15 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; using System.Linq; using Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Base.Geometry; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.DikeProfiles; +using Ringtoets.Common.Data.Probabilistics; +using Ringtoets.Common.Data.Properties; using Ringtoets.HydraRing.Data; namespace Ringtoets.Common.Data.Structures @@ -35,20 +38,259 @@ public abstract class StructuresInputBase : Observable, ICalculationInput, IUseBreakWater, IUseForeshore where T : StructureBase { + private readonly NormalDistribution modelFactorSuperCriticalFlow; + private readonly LogNormalDistribution allowedLevelIncreaseStorage; + private readonly VariationCoefficientLogNormalDistribution storageStructureArea; + private readonly LogNormalDistribution flowWidthAtBottomProtection; + private readonly VariationCoefficientLogNormalDistribution criticalOvertoppingDischarge; + private readonly VariationCoefficientNormalDistribution widthFlowApertures; + private readonly VariationCoefficientLogNormalDistribution stormDuration; + private T structure; + + private RoundedDouble structureNormalOrientation; + private double failureProbabilityStructureWithErosion; + private ForeshoreProfile foreshoreProfile; protected StructuresInputBase() { + structureNormalOrientation = new RoundedDouble(2, double.NaN); + + modelFactorSuperCriticalFlow = new NormalDistribution(2) + { + Mean = (RoundedDouble) 1.1, + StandardDeviation = (RoundedDouble) 0.03 + }; + + allowedLevelIncreaseStorage = new LogNormalDistribution(2) + { + Mean = (RoundedDouble) double.NaN, + StandardDeviation = (RoundedDouble) 0.1 + }; + + storageStructureArea = new VariationCoefficientLogNormalDistribution(2) + { + Mean = (RoundedDouble) double.NaN, + CoefficientOfVariation = (RoundedDouble) 0.1 + }; + + flowWidthAtBottomProtection = new LogNormalDistribution(2) + { + Mean = (RoundedDouble) double.NaN, + StandardDeviation = (RoundedDouble) 0.05 + }; + + criticalOvertoppingDischarge = new VariationCoefficientLogNormalDistribution(2) + { + Mean = (RoundedDouble) double.NaN, + CoefficientOfVariation = (RoundedDouble) 0.15 + }; + + failureProbabilityStructureWithErosion = double.NaN; + + widthFlowApertures = new VariationCoefficientNormalDistribution(2) + { + Mean = (RoundedDouble)double.NaN, + CoefficientOfVariation = (RoundedDouble)0.05 + }; + + stormDuration = new VariationCoefficientLogNormalDistribution(2) + { + Mean = (RoundedDouble)6.0, + CoefficientOfVariation = (RoundedDouble)0.25 + }; + UpdateForeshoreProperties(); } + private static bool ValidProbabilityValue(double probability) + { + return !double.IsNaN(probability) && probability <= 1 && probability >= 0; + } + #region Hydraulic data public HydraulicBoundaryLocation HydraulicBoundaryLocation { get; set; } + /// + /// Gets or sets the storm duration. + /// [hrs] + /// + /// Only sets the mean. + public VariationCoefficientLogNormalDistribution StormDuration + { + get + { + return stormDuration; + } + set + { + stormDuration.Mean = value.Mean; + } + } + + #region Schematization + + /// + /// Gets or sets the orientation of the normal of the structure. + /// [degrees] + /// + ///Thown when the value for the orientation is not between [0,360] degrees. + public RoundedDouble StructureNormalOrientation + { + get + { + return structureNormalOrientation; + } + set + { + if (double.IsNaN(value)) + { + structureNormalOrientation = value.ToPrecision(structureNormalOrientation.NumberOfDecimalPlaces); + return; + } + + RoundedDouble newOrientationValue = value.ToPrecision(structureNormalOrientation.NumberOfDecimalPlaces); + if (newOrientationValue < 0 || newOrientationValue > 360) + { + throw new ArgumentOutOfRangeException("value", Resources.Orientation_Value_needs_to_be_between_0_and_360); + } + structureNormalOrientation = newOrientationValue; + } + } + + /// + /// Gets or sets the allowed increase of level for storage. + /// [m] + /// + public LogNormalDistribution AllowedLevelIncreaseStorage + { + get + { + return allowedLevelIncreaseStorage; + } + set + { + allowedLevelIncreaseStorage.Mean = value.Mean; + allowedLevelIncreaseStorage.StandardDeviation = value.StandardDeviation; + } + } + + /// + /// Gets or sets the storage structure area. + /// [m^2] + /// + public VariationCoefficientLogNormalDistribution StorageStructureArea + { + get + { + return storageStructureArea; + } + set + { + storageStructureArea.Mean = value.Mean; + storageStructureArea.CoefficientOfVariation = value.CoefficientOfVariation; + } + } + + /// + /// Gets or sets the flow width at the bottom protection. + /// [m] + /// + public LogNormalDistribution FlowWidthAtBottomProtection + { + get + { + return flowWidthAtBottomProtection; + } + set + { + flowWidthAtBottomProtection.Mean = value.Mean; + flowWidthAtBottomProtection.StandardDeviation = value.StandardDeviation; + } + } + + /// + /// Gets or sets the critical overtopping discharge. + /// [m^3/s/m] + /// + public VariationCoefficientLogNormalDistribution CriticalOvertoppingDischarge + { + get + { + return criticalOvertoppingDischarge; + } + set + { + criticalOvertoppingDischarge.Mean = value.Mean; + criticalOvertoppingDischarge.CoefficientOfVariation = value.CoefficientOfVariation; + } + } + + /// + /// Gets or sets the failure probability of structure given erosion. + /// [1/year] + /// + /// Thrown when the value of the probability + /// is not between [0, 1]. + public double FailureProbabilityStructureWithErosion + { + get + { + return failureProbabilityStructureWithErosion; + } + set + { + if (!ValidProbabilityValue(value)) + { + throw new ArgumentOutOfRangeException("value", Resources.FailureProbability_Value_needs_to_be_between_0_and_1); + } + failureProbabilityStructureWithErosion = value; + } + } + + /// + /// Gets or sets the width of flow apertures. + /// [m] + /// + public VariationCoefficientNormalDistribution WidthFlowApertures + { + get + { + return widthFlowApertures; + } + set + { + widthFlowApertures.Mean = value.Mean; + widthFlowApertures.CoefficientOfVariation = value.CoefficientOfVariation; + } + } + #endregion + #endregion + + #region Model factors + + /// + /// Gets or sets the model factor for the super critical flow. + /// + /// Only sets the mean. + public NormalDistribution ModelFactorSuperCriticalFlow + { + get + { + return modelFactorSuperCriticalFlow; + } + set + { + modelFactorSuperCriticalFlow.Mean = value.Mean; + } + } + + #endregion + #region Foreshore Profile /// Index: Ringtoets/Common/test/Ringtoets.Common.Data.Test/Structures/StructuresInputBaseTest.cs =================================================================== diff -u -r8614a64110c5bc1e1b91950a7308b77322709c91 -r0afc6984f0b40aa96f1929cb20e0be7402dd7fed --- Ringtoets/Common/test/Ringtoets.Common.Data.Test/Structures/StructuresInputBaseTest.cs (.../StructuresInputBaseTest.cs) (revision 8614a64110c5bc1e1b91950a7308b77322709c91) +++ Ringtoets/Common/test/Ringtoets.Common.Data.Test/Structures/StructuresInputBaseTest.cs (.../StructuresInputBaseTest.cs) (revision 0afc6984f0b40aa96f1929cb20e0be7402dd7fed) @@ -19,14 +19,18 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; using System.Collections.Generic; using Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Base.Geometry; +using Core.Common.TestUtil; using NUnit.Framework; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.DikeProfiles; +using Ringtoets.Common.Data.Probabilistics; using Ringtoets.Common.Data.Structures; +using Ringtoets.Common.Data.TestUtil; using Ringtoets.HydraRing.Data; namespace Ringtoets.Common.Data.Test.Structures @@ -37,6 +41,49 @@ [Test] public void Constructor_ExpectedValues() { + // Setup + var modelFactorSuperCriticalFlow = new NormalDistribution(2) + { + Mean = (RoundedDouble)1.1, + StandardDeviation = (RoundedDouble)0.03 + }; + + var allowedLevelIncreaseStorage = new LogNormalDistribution(2) + { + Mean = (RoundedDouble)double.NaN, + StandardDeviation = (RoundedDouble)0.1 + }; + + var storageStructureArea = new VariationCoefficientLogNormalDistribution(2) + { + Mean = (RoundedDouble)double.NaN, + CoefficientOfVariation = (RoundedDouble)0.1 + }; + + var flowWidthAtBottomProtection = new LogNormalDistribution(2) + { + Mean = (RoundedDouble)double.NaN, + StandardDeviation = (RoundedDouble)0.05 + }; + + var criticalOvertoppingDischarge = new VariationCoefficientLogNormalDistribution(2) + { + Mean = (RoundedDouble)double.NaN, + CoefficientOfVariation = (RoundedDouble)0.15 + }; + + var widthFlowApertures = new VariationCoefficientNormalDistribution(2) + { + Mean = (RoundedDouble)double.NaN, + CoefficientOfVariation = (RoundedDouble)0.05 + }; + + var stormDuration = new VariationCoefficientLogNormalDistribution(2) + { + Mean = (RoundedDouble)6.0, + CoefficientOfVariation = (RoundedDouble)0.25 + }; + // Call var input = new SimpleStructuresInput(); @@ -45,7 +92,29 @@ Assert.IsInstanceOf(input); Assert.IsInstanceOf(input); Assert.IsInstanceOf(input); + Assert.IsNull(input.HydraulicBoundaryLocation); + + AssertEqualValue(double.NaN, input.StructureNormalOrientation); + Assert.AreEqual(2, input.StructureNormalOrientation.NumberOfDecimalPlaces); + + Assert.IsNull(input.ForeshoreProfile); + Assert.IsFalse(input.UseBreakWater); + Assert.AreEqual(BreakWaterType.Dam, input.BreakWater.Type); + Assert.AreEqual(0, input.BreakWater.Height.Value); + Assert.AreEqual(2, input.BreakWater.Height.NumberOfDecimalPlaces); + Assert.IsFalse(input.UseForeshore); + CollectionAssert.IsEmpty(input.ForeshoreGeometry); + + DistributionAssert.AreEqual(modelFactorSuperCriticalFlow, input.ModelFactorSuperCriticalFlow); + DistributionAssert.AreEqual(allowedLevelIncreaseStorage, input.AllowedLevelIncreaseStorage); + DistributionAssert.AreEqual(storageStructureArea, input.StorageStructureArea); + DistributionAssert.AreEqual(flowWidthAtBottomProtection, input.FlowWidthAtBottomProtection); + DistributionAssert.AreEqual(criticalOvertoppingDischarge, input.CriticalOvertoppingDischarge); + DistributionAssert.AreEqual(widthFlowApertures, input.WidthFlowApertures); + DistributionAssert.AreEqual(stormDuration, input.StormDuration); + + Assert.IsNaN(input.FailureProbabilityStructureWithErosion); } [Test] @@ -163,9 +232,273 @@ Assert.AreEqual(originalHydraulicBoundaryLocation, input.HydraulicBoundaryLocation); } - private class SimpleStructuresInput : StructuresInputBase + [Test] + [TestCase(360.004)] + [TestCase(300)] + [TestCase(0)] + [TestCase(-0.004)] + [TestCase(double.NaN)] + public void Properties_StructureNormalOrientationValidValues_NewValueSet(double orientation) { - + // Setup + var input = new SimpleStructuresInput(); + + // Call + input.StructureNormalOrientation = (RoundedDouble) orientation; + + // Assert + Assert.AreEqual(2, input.StructureNormalOrientation.NumberOfDecimalPlaces); + AssertEqualValue(orientation, input.StructureNormalOrientation); } + + [Test] + [TestCase(400)] + [TestCase(360.05)] + [TestCase(-0.005)] + [TestCase(-23)] + [TestCase(double.PositiveInfinity)] + [TestCase(double.NegativeInfinity)] + public void Properties_StructureNormalOrientationInValidValues_ThrowsArgumentOutOfRangeException(double invalidValue) + { + // Setup + var input = new SimpleStructuresInput(); + + // Call + TestDelegate call = () => input.StructureNormalOrientation = (RoundedDouble) invalidValue; + + // Assert + TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, "De waarde voor de oriƫntatie moet in het bereik tussen [0, 360] graden liggen."); + } + + [Test] + public void Properties_ModelFactorSuperCriticalFlow_ExpectedValues() + { + // Setup + var random = new Random(22); + var input = new SimpleStructuresInput(); + var mean = (RoundedDouble)(0.01 + random.NextDouble()); + var expectedDistribution = new NormalDistribution(2) + { + Mean = mean, + StandardDeviation = input.ModelFactorSuperCriticalFlow.StandardDeviation + }; + var distributionToSet = new NormalDistribution(5) + { + Mean = mean, + StandardDeviation = (RoundedDouble)random.NextDouble() + }; + + // Call + input.ModelFactorSuperCriticalFlow = distributionToSet; + + // Assert + AssertDistributionCorrectlySet(input.ModelFactorSuperCriticalFlow, distributionToSet, expectedDistribution); + } + + [Test] + public void Properties_AllowedLevelIncreaseStorage_ExpectedValues() + { + // Setup + var random = new Random(22); + var input = new SimpleStructuresInput(); + var mean = (RoundedDouble)(0.01 + random.NextDouble()); + var standardDeviation = (RoundedDouble)(0.01 + random.NextDouble()); + var expectedDistribution = new LogNormalDistribution(2) + { + Mean = mean, + StandardDeviation = standardDeviation + }; + var distributionToSet = new LogNormalDistribution(5) + { + Mean = mean, + StandardDeviation = standardDeviation + }; + + // Call + input.AllowedLevelIncreaseStorage = distributionToSet; + + // Assert + AssertDistributionCorrectlySet(input.AllowedLevelIncreaseStorage, distributionToSet, expectedDistribution); + } + + [Test] + public void Properties_StorageStructureArea_ExpectedValues() + { + // Setup + var random = new Random(22); + var input = new SimpleStructuresInput(); + var mean = (RoundedDouble)(0.01 + random.NextDouble()); + var variation = (RoundedDouble)(0.01 + random.NextDouble()); + var expectedDistribution = new VariationCoefficientLogNormalDistribution(2) + { + Mean = mean, + CoefficientOfVariation = variation + }; + var distributionToSet = new VariationCoefficientLogNormalDistribution(5) + { + Mean = mean, + CoefficientOfVariation = variation + }; + + // Call + input.StorageStructureArea = distributionToSet; + + // Assert + AssertDistributionCorrectlySet(input.StorageStructureArea, distributionToSet, expectedDistribution); + } + + [Test] + public void Properties_FlowWidthAtBottomProtection_ExpectedValues() + { + // Setup + var random = new Random(22); + var input = new SimpleStructuresInput(); + var mean = (RoundedDouble)(0.01 + random.NextDouble()); + var standardDeviation = (RoundedDouble)(0.01 + random.NextDouble()); + var expectedDistribution = new LogNormalDistribution(2) + { + Mean = mean, + StandardDeviation = standardDeviation + }; + var distributionToSet = new LogNormalDistribution(5) + { + Mean = mean, + StandardDeviation = standardDeviation + }; + + // Call + input.FlowWidthAtBottomProtection = distributionToSet; + + // Assert + AssertDistributionCorrectlySet(input.FlowWidthAtBottomProtection, distributionToSet, expectedDistribution); + } + + [Test] + public void Properties_CriticalOvertoppingDischarge_ExpectedValues() + { + // Setup + var random = new Random(22); + var input = new SimpleStructuresInput(); + var mean = (RoundedDouble)(0.01 + random.NextDouble()); + var variation = (RoundedDouble)(0.01 + random.NextDouble()); + var expectedDistribution = new VariationCoefficientLogNormalDistribution(2) + { + Mean = mean, + CoefficientOfVariation = variation + }; + var distributionToSet = new VariationCoefficientLogNormalDistribution(5) + { + Mean = mean, + CoefficientOfVariation = variation + }; + + // Call + input.CriticalOvertoppingDischarge = distributionToSet; + + // Assert + AssertDistributionCorrectlySet(input.CriticalOvertoppingDischarge, distributionToSet, expectedDistribution); + } + + [Test] + [TestCase(0)] + [TestCase(0.5)] + [TestCase(1)] + public void Properties_ValidFailureProbabilityStructureWithErosion_ExpectedValues(double failureProbabilityStructureWithErosion) + { + // Setup + var input = new SimpleStructuresInput(); + + // Call + input.FailureProbabilityStructureWithErosion = failureProbabilityStructureWithErosion; + + // Assert + Assert.AreEqual(failureProbabilityStructureWithErosion, input.FailureProbabilityStructureWithErosion); + } + + [Test] + [TestCase(-0.1)] + [TestCase(1.1)] + [TestCase(double.NaN)] + public void Properties_InvalidFailureProbabilityStructureWithErosion_ThrowArgumentOutOfRangeException(double failureProbabilityStructureWithErosion) + { + // Setup + var input = new SimpleStructuresInput(); + + // Call + TestDelegate call = () => input.FailureProbabilityStructureWithErosion = (RoundedDouble)failureProbabilityStructureWithErosion; + + // Assert + TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, "De waarde voor de faalkans moet in het bereik tussen [0, 1] liggen."); + } + + [Test] + public void Properties_WidthFlowApertures_ExpectedValues() + { + // Setup + var random = new Random(22); + var input = new SimpleStructuresInput(); + var mean = (RoundedDouble)(0.01 + random.NextDouble()); + var variation = (RoundedDouble)(0.01 + random.NextDouble()); + var expectedDistribution = new VariationCoefficientNormalDistribution(2) + { + Mean = mean, + CoefficientOfVariation = variation + }; + var distributionToSet = new VariationCoefficientNormalDistribution(5) + { + Mean = mean, + CoefficientOfVariation = variation + }; + + // Call + input.WidthFlowApertures = distributionToSet; + + // Assert + AssertDistributionCorrectlySet(input.WidthFlowApertures, distributionToSet, expectedDistribution); + } + + [Test] + public void Properties_StormDuration_ExpectedValues() + { + // Setup + var random = new Random(22); + var input = new SimpleStructuresInput(); + var mean = (RoundedDouble)(0.01 + random.NextDouble()); + var expectedDistribution = new VariationCoefficientLogNormalDistribution(2) + { + Mean = mean, + CoefficientOfVariation = input.StormDuration.CoefficientOfVariation + }; + var distributionToSet = new VariationCoefficientLogNormalDistribution(5) + { + Mean = mean, + CoefficientOfVariation = (RoundedDouble)random.NextDouble() + }; + + // Call + input.StormDuration = distributionToSet; + + // Assert + AssertDistributionCorrectlySet(input.StormDuration, distributionToSet, expectedDistribution); + } + + private static void AssertEqualValue(double expectedValue, RoundedDouble actualValue) + { + Assert.AreEqual(expectedValue, actualValue, actualValue.GetAccuracy()); + } + + private static void AssertDistributionCorrectlySet(IDistribution distributionToAssert, IDistribution setDistribution, IDistribution expectedDistribution) + { + Assert.AreNotSame(setDistribution, distributionToAssert); + DistributionAssert.AreEqual(expectedDistribution, distributionToAssert); + } + + private static void AssertDistributionCorrectlySet(IVariationCoefficientDistribution distributionToAssert, IVariationCoefficientDistribution setDistribution, IVariationCoefficientDistribution expectedDistribution) + { + Assert.AreNotSame(setDistribution, distributionToAssert); + DistributionAssert.AreEqual(expectedDistribution, distributionToAssert); + } + + private class SimpleStructuresInput : StructuresInputBase {} } } \ No newline at end of file Index: Ringtoets/HeightStructures/src/Ringtoets.HeightStructures.Data/HeightStructuresInput.cs =================================================================== diff -u -r5e9769061c2802f1182ed502e2a32581cfb68196 -r0afc6984f0b40aa96f1929cb20e0be7402dd7fed --- Ringtoets/HeightStructures/src/Ringtoets.HeightStructures.Data/HeightStructuresInput.cs (.../HeightStructuresInput.cs) (revision 5e9769061c2802f1182ed502e2a32581cfb68196) +++ Ringtoets/HeightStructures/src/Ringtoets.HeightStructures.Data/HeightStructuresInput.cs (.../HeightStructuresInput.cs) (revision 0afc6984f0b40aa96f1929cb20e0be7402dd7fed) @@ -181,7 +181,7 @@ #endregion - #region Schematisation + #region Schematization /// /// Gets or sets the crest level of the structure.