Index: Riskeer/GrassCoverErosionInwards/src/Riskeer.GrassCoverErosionInwards.Data/GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs =================================================================== diff -u -rafa2eda2dd59089149cf23c5dfc38f4d2965c1df -r9b2442a3a0450b110d587f6d3cdf4664a09fac1d --- Riskeer/GrassCoverErosionInwards/src/Riskeer.GrassCoverErosionInwards.Data/GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision afa2eda2dd59089149cf23c5dfc38f4d2965c1df) +++ Riskeer/GrassCoverErosionInwards/src/Riskeer.GrassCoverErosionInwards.Data/GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision 9b2442a3a0450b110d587f6d3cdf4664a09fac1d) @@ -21,7 +21,11 @@ using System; using System.Collections.Generic; +using System.Linq; +using Core.Common.Base.Data; +using Core.Common.Base.Geometry; using Riskeer.Common.Data.AssessmentSection; +using Riskeer.Common.Data.Calculation; using Riskeer.Common.Data.Probability; namespace Riskeer.GrassCoverErosionInwards.Data @@ -67,15 +71,75 @@ throw new ArgumentNullException(nameof(assessmentSection)); } - if (sectionResult.Calculation == null || !sectionResult.Calculation.HasOutput) + GrassCoverErosionInwardsCalculationScenario[] relevantScenarios = sectionResult.GetCalculationScenarios(calculationScenarios).ToArray(); + + if (relevantScenarios.Length == 0 || !relevantScenarios.All(s => s.HasOutput) || Math.Abs(sectionResult.GetTotalContribution(relevantScenarios) - 1.0) > 1e-6) { return double.NaN; } - ProbabilityAssessmentOutput derivedOutput = GrassCoverErosionInwardsProbabilityAssessmentOutputFactory.Create(sectionResult.Calculation.Output.OvertoppingOutput, - failureMechanism, assessmentSection); + double totalDetailedAssessmentProbability = 0; + foreach (GrassCoverErosionInwardsCalculationScenario scenario in relevantScenarios) + { + ProbabilityAssessmentOutput derivedOutput = GrassCoverErosionInwardsProbabilityAssessmentOutputFactory.Create(scenario.Output.OvertoppingOutput, + failureMechanism, assessmentSection); - return derivedOutput.Probability; + totalDetailedAssessmentProbability += derivedOutput.Probability * (double) scenario.Contribution; + } + + return totalDetailedAssessmentProbability; } + + /// + /// Gets the total contribution of all relevant calculation scenarios. + /// + /// The section result to get the total contribution for. + /// The calculation scenarios to get the total contribution for. + /// The total contribution of all relevant calculation scenarios. + /// Thrown when any parameter is null. + public static RoundedDouble GetTotalContribution(this GrassCoverErosionInwardsFailureMechanismSectionResult sectionResult, + IEnumerable calculationScenarios) + { + if (sectionResult == null) + { + throw new ArgumentNullException(nameof(sectionResult)); + } + + if (calculationScenarios == null) + { + throw new ArgumentNullException(nameof(calculationScenarios)); + } + + return (RoundedDouble) sectionResult + .GetCalculationScenarios(calculationScenarios) + .Aggregate(0, (current, calculationScenario) => current + calculationScenario.Contribution); + } + + /// + /// Gets a collection of the relevant . + /// + /// The section result to get the relevant scenarios for. + /// The calculation scenarios to get the relevant scenarios from. + /// A collection of relevant calculation scenarios. + /// Thrown when any parameter is null. + public static IEnumerable GetCalculationScenarios( + this GrassCoverErosionInwardsFailureMechanismSectionResult sectionResult, + IEnumerable calculationScenarios) + { + if (sectionResult == null) + { + throw new ArgumentNullException(nameof(sectionResult)); + } + + if (calculationScenarios == null) + { + throw new ArgumentNullException(nameof(calculationScenarios)); + } + + IEnumerable lineSegments = Math2D.ConvertPointsToLineSegments(sectionResult.Section.Points); + + return calculationScenarios + .Where(cs => cs.IsRelevant && cs.IsDikeProfileIntersectionWithReferenceLineInSection(lineSegments)); + } } } \ No newline at end of file Index: Riskeer/GrassCoverErosionInwards/test/Riskeer.GrassCoverErosionInwards.Data.Test/GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs =================================================================== diff -u -rafa2eda2dd59089149cf23c5dfc38f4d2965c1df -r9b2442a3a0450b110d587f6d3cdf4664a09fac1d --- Riskeer/GrassCoverErosionInwards/test/Riskeer.GrassCoverErosionInwards.Data.Test/GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs (.../GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs) (revision afa2eda2dd59089149cf23c5dfc38f4d2965c1df) +++ Riskeer/GrassCoverErosionInwards/test/Riskeer.GrassCoverErosionInwards.Data.Test/GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs (.../GrassCoverErosionInwardsFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs) (revision 9b2442a3a0450b110d587f6d3cdf4664a09fac1d) @@ -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. // @@ -20,8 +20,10 @@ // All rights reserved. using System; +using System.Collections.Generic; using System.Linq; using Core.Common.Base.Data; +using Core.Common.Base.Geometry; using NUnit.Framework; using Rhino.Mocks; using Riskeer.Common.Data.AssessmentSection; @@ -111,6 +113,48 @@ } [Test] + public void GetDetailedAssessmentProbability_MultipleScenarios_ReturnsValueBasedOnRelevantScenarios() + { + // Setup + var failureMechanism = new GrassCoverErosionInwardsFailureMechanism(); + + var mocks = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionTestHelper.CreateAssessmentSectionStub(failureMechanism, mocks); + mocks.ReplayAll(); + + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var failureMechanismSectionResult = new GrassCoverErosionInwardsFailureMechanismSectionResult(section); + + GrassCoverErosionInwardsCalculationScenario calculationScenario1 = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateGrassCoverErosionInwardsCalculationScenario(section); + GrassCoverErosionInwardsCalculationScenario calculationScenario2 = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateGrassCoverErosionInwardsCalculationScenario(section); + GrassCoverErosionInwardsCalculationScenario calculationScenario3 = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateGrassCoverErosionInwardsCalculationScenario(section); + + calculationScenario1.IsRelevant = true; + calculationScenario1.Contribution = (RoundedDouble) 0.2111; + calculationScenario1.Output = new GrassCoverErosionInwardsOutput(new TestOvertoppingOutput(1.1), null, null); + + calculationScenario2.IsRelevant = true; + calculationScenario2.Contribution = (RoundedDouble) 0.7889; + calculationScenario1.Output = new GrassCoverErosionInwardsOutput(new TestOvertoppingOutput(2.2), null, null); + + calculationScenario3.IsRelevant = false; + + GrassCoverErosionInwardsCalculationScenario[] calculations = + { + calculationScenario1, + calculationScenario2, + calculationScenario3 + }; + + // Call + double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(calculations, failureMechanism, assessmentSection); + + // Assert + Assert.AreEqual(0.3973850177700996, detailedAssessmentProbability); + mocks.VerifyAll(); + } + + [Test] public void GetDetailedAssessmentProbability_NoScenarios_ReturnsNaN() { // Setup @@ -209,10 +253,10 @@ GrassCoverErosionInwardsCalculationScenario calculationScenario2 = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); calculationScenario1.IsRelevant = true; - calculationScenario1.Contribution = (RoundedDouble)contribution1; + calculationScenario1.Contribution = (RoundedDouble) contribution1; calculationScenario2.IsRelevant = true; - calculationScenario2.Contribution = (RoundedDouble)contribution2; + calculationScenario2.Contribution = (RoundedDouble) contribution2; calculationScenario2.Output = new GrassCoverErosionInwardsOutput(new TestOvertoppingOutput(double.NaN), null, null); GrassCoverErosionInwardsCalculationScenario[] calculations = @@ -246,8 +290,8 @@ FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); GrassCoverErosionInwardsCalculationScenario scenarioA = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); GrassCoverErosionInwardsCalculationScenario scenarioB = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); - scenarioA.Contribution = (RoundedDouble)contributionA; - scenarioB.Contribution = (RoundedDouble)contributionB; + scenarioA.Contribution = (RoundedDouble) contributionA; + scenarioB.Contribution = (RoundedDouble) contributionB; var result = new GrassCoverErosionInwardsFailureMechanismSectionResult(section); @@ -262,5 +306,131 @@ Assert.IsNaN(detailedAssessmentProbability); mocks.VerifyAll(); } + + [Test] + public void GetTotalContribution_SectionResultNull_ThrowsArgumentNullException() + { + // Call + void Call() => ((GrassCoverErosionInwardsFailureMechanismSectionResult) null).GetTotalContribution(Enumerable.Empty()); + + // Assert + var exception = Assert.Throws(Call); + Assert.AreEqual("sectionResult", exception.ParamName); + } + + [Test] + public void GetTotalContribution_CalculationScenariosNull_ThrowsArgumentNullException() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var sectionResult = new GrassCoverErosionInwardsFailureMechanismSectionResult(section); + + // Call + void Call() => sectionResult.GetTotalContribution(null); + + // Assert + var exception = Assert.Throws(Call); + Assert.AreEqual("calculationScenarios", exception.ParamName); + } + + [Test] + public void GetTotalContribution_WithScenarios_ReturnsTotalRelevantScenarioContribution() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var failureMechanismSectionResult = new GrassCoverErosionInwardsFailureMechanismSectionResult(section); + + GrassCoverErosionInwardsCalculationScenario calculationScenario = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); + calculationScenario.Contribution = (RoundedDouble) 0.3211; + + GrassCoverErosionInwardsCalculationScenario calculationScenario2 = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); + calculationScenario2.Contribution = (RoundedDouble) 0.5435; + + GrassCoverErosionInwardsCalculationScenario calculationScenario3 = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); + calculationScenario3.IsRelevant = false; + + GrassCoverErosionInwardsCalculationScenario[] calculationScenarios = + { + calculationScenario, + calculationScenario2, + calculationScenario3 + }; + + // Call + RoundedDouble totalContribution = failureMechanismSectionResult.GetTotalContribution(calculationScenarios); + + // Assert + Assert.AreEqual((RoundedDouble) 0.8646, totalContribution); + } + + [Test] + public void GetCalculationScenarios_SectionResultNull_ThrowsArgumentNullException() + { + // Call + void Call() => ((GrassCoverErosionInwardsFailureMechanismSectionResult) null).GetCalculationScenarios(Enumerable.Empty()); + + // Assert + var exception = Assert.Throws(Call); + Assert.AreEqual("sectionResult", exception.ParamName); + } + + [Test] + public void GetCalculationScenarios_CalculationScenariosNull_ThrowsArgumentNullException() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var sectionResult = new GrassCoverErosionInwardsFailureMechanismSectionResult(section); + + // Call + void Call() => sectionResult.GetCalculationScenarios(null); + + // Assert + var exception = Assert.Throws(Call); + Assert.AreEqual("calculationScenarios", exception.ParamName); + } + + [Test] + public void GetCalculationScenarios_WithRelevantAndIrrelevantScenarios_ReturnsRelevantCalculationScenarios() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var sectionResult = new GrassCoverErosionInwardsFailureMechanismSectionResult(section); + GrassCoverErosionInwardsCalculationScenario calculationScenario = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); + GrassCoverErosionInwardsCalculationScenario calculationScenario2 = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario(section); + calculationScenario2.IsRelevant = false; + + // Call + IEnumerable relevantScenarios = sectionResult.GetCalculationScenarios(new[] + { + calculationScenario, + calculationScenario2 + }); + + // Assert + Assert.AreEqual(calculationScenario, relevantScenarios.Single()); + } + + [Test] + public void GetCalculationScenarios_WithoutScenarioIntersectingSection_ReturnsNoCalculationScenarios() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(new[] + { + new Point2D(999, 999), + new Point2D(998, 998) + }); + var sectionResult = new GrassCoverErosionInwardsFailureMechanismSectionResult(section); + GrassCoverErosionInwardsCalculationScenario calculationScenario = GrassCoverErosionInwardsCalculationScenarioTestFactory.CreateNotCalculatedGrassCoverErosionInwardsCalculationScenario( + FailureMechanismSectionTestFactory.CreateFailureMechanismSection()); + + // Call + IEnumerable relevantScenarios = sectionResult.GetCalculationScenarios(new[] + { + calculationScenario + }); + + // Assert + CollectionAssert.IsEmpty(relevantScenarios); + } } } \ No newline at end of file Index: Riskeer/MacroStabilityInwards/src/Riskeer.MacroStabilityInwards.Data/MacroStabilityInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs =================================================================== diff -u -rafa2eda2dd59089149cf23c5dfc38f4d2965c1df -r9b2442a3a0450b110d587f6d3cdf4664a09fac1d --- Riskeer/MacroStabilityInwards/src/Riskeer.MacroStabilityInwards.Data/MacroStabilityInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../MacroStabilityInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision afa2eda2dd59089149cf23c5dfc38f4d2965c1df) +++ Riskeer/MacroStabilityInwards/src/Riskeer.MacroStabilityInwards.Data/MacroStabilityInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../MacroStabilityInwardsFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision 9b2442a3a0450b110d587f6d3cdf4664a09fac1d) @@ -71,9 +71,8 @@ } MacroStabilityInwardsCalculationScenario[] relevantScenarios = sectionResult.GetCalculationScenarios(calculationScenarios).ToArray(); - bool relevantScenarioAvailable = relevantScenarios.Length != 0; - - if (!relevantScenarioAvailable || !relevantScenarios.All(s => s.HasOutput) || Math.Abs(sectionResult.GetTotalContribution(relevantScenarios) - 1.0) > 1e-6) + + if (relevantScenarios.Length == 0 || !relevantScenarios.All(s => s.HasOutput) || Math.Abs(sectionResult.GetTotalContribution(relevantScenarios) - 1.0) > 1e-6) { return double.NaN; } Index: Riskeer/Piping/src/Riskeer.Piping.Data/PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs =================================================================== diff -u -rafa2eda2dd59089149cf23c5dfc38f4d2965c1df -r9b2442a3a0450b110d587f6d3cdf4664a09fac1d --- Riskeer/Piping/src/Riskeer.Piping.Data/PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision afa2eda2dd59089149cf23c5dfc38f4d2965c1df) +++ Riskeer/Piping/src/Riskeer.Piping.Data/PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision 9b2442a3a0450b110d587f6d3cdf4664a09fac1d) @@ -70,9 +70,8 @@ } PipingCalculationScenario[] relevantScenarios = sectionResult.GetCalculationScenarios(calculationScenarios).ToArray(); - bool relevantScenarioAvailable = relevantScenarios.Length != 0; - if (!relevantScenarioAvailable || !relevantScenarios.All(s => s.HasOutput) || Math.Abs(sectionResult.GetTotalContribution(relevantScenarios) - 1.0) > 1e-6) + if (relevantScenarios.Length == 0 || !relevantScenarios.All(s => s.HasOutput) || Math.Abs(sectionResult.GetTotalContribution(relevantScenarios) - 1.0) > 1e-6) { return double.NaN; }