Index: Riskeer/Piping/src/Riskeer.Piping.Data/PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs =================================================================== diff -u -re19e5d4f6f9202bc80b4e4af5456b1192e37a671 -r5c1fa0be4802b9a798b5df51a570735e4a9d15a1 --- Riskeer/Piping/src/Riskeer.Piping.Data/PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision e19e5d4f6f9202bc80b4e4af5456b1192e37a671) +++ Riskeer/Piping/src/Riskeer.Piping.Data/PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs (.../PipingFailureMechanismSectionResultDetailedAssessmentExtensions.cs) (revision 5c1fa0be4802b9a798b5df51a570735e4a9d15a1) @@ -24,7 +24,9 @@ using System.Linq; using Core.Common.Base.Data; using Core.Common.Base.Geometry; +using Core.Common.Util; using Riskeer.Common.Data.Calculation; +using Riskeer.Piping.Data.Probabilistic; using Riskeer.Piping.Data.SemiProbabilistic; namespace Riskeer.Piping.Data @@ -38,7 +40,48 @@ /// Gets the value for the detailed assessment of safety per failure mechanism section as a probability. /// /// The section result to get the detailed assessment probability for. - /// All calculation scenarios in the failure mechanism. + /// All probabilistic calculation scenarios in the failure mechanism. + /// The func to get the output from a calculation scenario. + /// The calculated detailed assessment probability; or when there + /// are no relevant calculations, when not all relevant calculations are performed or when the + /// contribution of the relevant calculations don't add up to 1. + /// Thrown when any parameter is null. + public static double GetInitialFailureMechanismResultProbability(this PipingFailureMechanismSectionResult sectionResult, + IEnumerable calculationScenarios, + Func getOutputFunc) + { + if (sectionResult == null) + { + throw new ArgumentNullException(nameof(sectionResult)); + } + + if (calculationScenarios == null) + { + throw new ArgumentNullException(nameof(calculationScenarios)); + } + + if (getOutputFunc == null) + { + throw new ArgumentNullException(nameof(getOutputFunc)); + } + + ProbabilisticPipingCalculationScenario[] 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; + } + + return relevantScenarios.Sum(scenario => StatisticsConverter.ReliabilityToProbability(getOutputFunc(scenario).Reliability) * (double) scenario.Contribution); + } + + /// + /// Gets the value for the detailed assessment of safety per failure mechanism section as a probability. + /// + /// The section result to get the detailed assessment probability for. + /// All semi probabilistic calculation scenarios in the failure mechanism. /// The norm to assess for. /// The calculated detailed assessment probability; or when there /// are no relevant calculations, when not all relevant calculations are performed or when the @@ -58,7 +101,9 @@ throw new ArgumentNullException(nameof(calculationScenarios)); } - SemiProbabilisticPipingCalculationScenario[] relevantScenarios = sectionResult.GetCalculationScenarios(calculationScenarios).ToArray(); + SemiProbabilisticPipingCalculationScenario[] relevantScenarios = sectionResult.GetCalculationScenarios( + calculationScenarios) + .ToArray(); if (relevantScenarios.Length == 0 || !relevantScenarios.All(s => s.HasOutput) || Math.Abs(sectionResult.GetTotalContribution(relevantScenarios) - 1.0) > 1e-6) { @@ -84,7 +129,7 @@ /// The total contribution of all relevant calculation scenarios. /// Thrown when any parameter is null. public static RoundedDouble GetTotalContribution(this PipingFailureMechanismSectionResult sectionResult, - IEnumerable calculationScenarios) + IEnumerable> calculationScenarios) { if (sectionResult == null) { @@ -97,7 +142,7 @@ } return (RoundedDouble) sectionResult - .GetCalculationScenarios(calculationScenarios) + .GetCalculationScenarios>(calculationScenarios) .Aggregate(0, (current, calculationScenario) => current + calculationScenario.Contribution); } @@ -106,11 +151,13 @@ /// /// The section result to get the relevant scenarios for. /// The calculation scenarios to get the relevant scenarios from. + /// The type of the calculation scenarios. /// A collection of relevant calculation scenarios. /// Thrown when any parameter is null. - public static IEnumerable GetCalculationScenarios( + public static IEnumerable GetCalculationScenarios( this PipingFailureMechanismSectionResult sectionResult, - IEnumerable calculationScenarios) + IEnumerable> calculationScenarios) + where T : IPipingCalculationScenario { if (sectionResult == null) { @@ -124,8 +171,8 @@ IEnumerable lineSegments = Math2D.ConvertPointsToLineSegments(sectionResult.Section.Points); - return calculationScenarios - .Where(pc => pc.IsRelevant && pc.IsSurfaceLineIntersectionWithReferenceLineInSection(lineSegments)); + return calculationScenarios.OfType() + .Where(pc => pc.IsRelevant && pc.IsSurfaceLineIntersectionWithReferenceLineInSection(lineSegments)); } } } \ No newline at end of file Index: Riskeer/Piping/test/Riskeer.Piping.Data.Test/PipingFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs =================================================================== diff -u -re19e5d4f6f9202bc80b4e4af5456b1192e37a671 -r5c1fa0be4802b9a798b5df51a570735e4a9d15a1 --- Riskeer/Piping/test/Riskeer.Piping.Data.Test/PipingFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs (.../PipingFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs) (revision e19e5d4f6f9202bc80b4e4af5456b1192e37a671) +++ Riskeer/Piping/test/Riskeer.Piping.Data.Test/PipingFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs (.../PipingFailureMechanismSectionResultDetailedAssessmentExtensionsTest.cs) (revision 5c1fa0be4802b9a798b5df51a570735e4a9d15a1) @@ -27,8 +27,10 @@ using NUnit.Framework; using Riskeer.Common.Data.FailureMechanism; using Riskeer.Common.Data.TestUtil; +using Riskeer.Piping.Data.Probabilistic; using Riskeer.Piping.Data.SemiProbabilistic; using Riskeer.Piping.Data.TestUtil; +using Riskeer.Piping.Data.TestUtil.Probabilistic; using Riskeer.Piping.Data.TestUtil.SemiProbabilistic; namespace Riskeer.Piping.Data.Test @@ -37,125 +39,318 @@ public class PipingFailureMechanismSectionResultDetailedAssessmentExtensionsTest { [Test] - public void GetDetailedAssessmentProbability_SectionResultNull_ThrowsArgumentNullException() + public void GetTotalContribution_SectionResultNull_ThrowsArgumentNullException() { // Call - void Call() => PipingFailureMechanismSectionResultDetailedAssessmentExtensions.GetDetailedAssessmentProbability( - null, Enumerable.Empty(), 0.1); + void Call() => PipingFailureMechanismSectionResultDetailedAssessmentExtensions.GetTotalContribution( + null, Enumerable.Empty()); // Assert var exception = Assert.Throws(Call); Assert.AreEqual("sectionResult", exception.ParamName); } [Test] - public void GetDetailedAssessmentProbability_CalculationScenariosNull_ThrowsArgumentNullException() + public void GetTotalContribution_CalculationScenariosNull_ThrowsArgumentNullException() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var sectionResult = new PipingFailureMechanismSectionResult(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 PipingFailureMechanismSectionResult(section); + var pipingCalculationScenario1 = + SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + pipingCalculationScenario1.Contribution = (RoundedDouble) 0.3211; + + var pipingCalculationScenario2 = + SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + pipingCalculationScenario2.Contribution = (RoundedDouble) 0.5435; + + SemiProbabilisticPipingCalculationScenario pipingCalculationScenario3 = CreateIrrelevantSemiProbabilisticPipingCalculationScenario(section); + + SemiProbabilisticPipingCalculationScenario[] calculationScenarios = + { + pipingCalculationScenario1, + pipingCalculationScenario2, + pipingCalculationScenario3 + }; + // Call - void Call() => failureMechanismSectionResult.GetDetailedAssessmentProbability(null, 0.1); + RoundedDouble totalContribution = failureMechanismSectionResult.GetTotalContribution(calculationScenarios); // Assert + Assert.AreEqual((RoundedDouble) 0.8646, totalContribution); + } + + [Test] + public void GetCalculationScenarios_SectionResultNull_ThrowsArgumentNullException() + { + // Call + void Call() => PipingFailureMechanismSectionResultDetailedAssessmentExtensions.GetCalculationScenarios>( + null, 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 PipingFailureMechanismSectionResult(section); + + // Call + void Call() => sectionResult.GetCalculationScenarios>(null); + + // Assert + var exception = Assert.Throws(Call); Assert.AreEqual("calculationScenarios", exception.ParamName); } [Test] - public void GetDetailedAssessmentProbability_MultipleScenarios_ReturnsValueBasedOnRelevantScenarios() + [TestCaseSource(nameof(GetCalculationScenariosTestCases))] + public void GetCalculationScenarios_WithRelevantAndIrrelevantScenarios_ReturnsRelevantCalculationScenarios( + FailureMechanismSection section, + IEnumerable> allScenarios, + Func>, IEnumerable>> getRelevantScenariosFunc, + IPipingCalculationScenario expectedRelevantScenario) { // Setup + var sectionResult = new PipingFailureMechanismSectionResult(section); + + // Call + IEnumerable> relevantScenarios = getRelevantScenariosFunc(sectionResult, allScenarios); + + // Assert + Assert.AreEqual(expectedRelevantScenario, 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 PipingFailureMechanismSectionResult(section); + var calculationScenario = + SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation( + FailureMechanismSectionTestFactory.CreateFailureMechanismSection()); + + // Call + IEnumerable> relevantScenarios = sectionResult.GetCalculationScenarios>(new[] + { + calculationScenario + }); + + // Assert + CollectionAssert.IsEmpty(relevantScenarios); + } + + private static IEnumerable GetCalculationScenariosTestCases() + { FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + + var semiProbabilisticCalculationScenario1 = SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + SemiProbabilisticPipingCalculationScenario semiProbabilisticCalculationScenario2 = CreateIrrelevantSemiProbabilisticPipingCalculationScenario(section); + + var probabilisticCalculationScenario1 = ProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + ProbabilisticPipingCalculationScenario probabilisticCalculationScenario2 = CreateIrrelevantProbabilisticPipingCalculationScenario(section); + + var allScenarios = new IPipingCalculationScenario[] + { + semiProbabilisticCalculationScenario1, + semiProbabilisticCalculationScenario2, + probabilisticCalculationScenario1, + probabilisticCalculationScenario2 + }; + + yield return new TestCaseData(section, allScenarios, + new Func>, IEnumerable>>( + (result, scenarios) => result.GetCalculationScenarios(scenarios)), + semiProbabilisticCalculationScenario1); + yield return new TestCaseData(section, allScenarios, + new Func>, IEnumerable>>( + (result, scenarios) => result.GetCalculationScenarios(scenarios)), + probabilisticCalculationScenario1); + } + + private static ProbabilisticPipingCalculationScenario CreateIrrelevantProbabilisticPipingCalculationScenario(FailureMechanismSection section) + { + var calculationScenario = + ProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + + calculationScenario.IsRelevant = false; + + return calculationScenario; + } + + private static SemiProbabilisticPipingCalculationScenario CreateIrrelevantSemiProbabilisticPipingCalculationScenario(FailureMechanismSection section) + { + var calculationScenario = + SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + + calculationScenario.IsRelevant = false; + + return calculationScenario; + } + + #region Probabilistic + + [Test] + public void ProbabilisticGetInitialFailureMechanismResultProbability_SectionResultNull_ThrowsArgumentNullException() + { + // Call + void Call() => PipingFailureMechanismSectionResultDetailedAssessmentExtensions.GetInitialFailureMechanismResultProbability( + null, Enumerable.Empty(), scenario => null); + + // Assert + var exception = Assert.Throws(Call); + Assert.AreEqual("sectionResult", exception.ParamName); + } + + [Test] + public void ProbabilisticGetInitialFailureMechanismResultProbability_CalculationScenariosNull_ThrowsArgumentNullException() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); + // Call + void Call() => failureMechanismSectionResult.GetInitialFailureMechanismResultProbability(null, scenario => null); + + // Assert + var exception = Assert.Throws(Call); + Assert.AreEqual("calculationScenarios", exception.ParamName); + } + + [Test] + public void ProbabilisticGetInitialFailureMechanismResultProbability_GetOutputFuncNull_ThrowsArgumentNullException() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); + + // Call + void Call() => failureMechanismSectionResult.GetInitialFailureMechanismResultProbability(Enumerable.Empty(), null); + + // Assert + var exception = Assert.Throws(Call); + Assert.AreEqual("getOutputFunc", exception.ParamName); + } + + [Test] + public void ProbabilisticGetInitialFailureMechanismResultProbability_MultipleScenarios_ReturnsValueBasedOnRelevantScenarios() + { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); + var pipingCalculationScenario1 = - SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateCalculation(section); var pipingCalculationScenario2 = - SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateCalculation(section); var pipingCalculationScenario3 = - SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateCalculation(section); pipingCalculationScenario1.IsRelevant = true; pipingCalculationScenario1.Contribution = (RoundedDouble) 0.2111; - pipingCalculationScenario1.Output = PipingTestDataGenerator.GetSemiProbabilisticPipingOutput(1.1, 2.2, 3.3); pipingCalculationScenario2.IsRelevant = true; pipingCalculationScenario2.Contribution = (RoundedDouble) 0.7889; - pipingCalculationScenario2.Output = PipingTestDataGenerator.GetSemiProbabilisticPipingOutput(4.4, 5.5, 6.6); pipingCalculationScenario3.IsRelevant = false; - SemiProbabilisticPipingCalculationScenario[] calculations = + ProbabilisticPipingCalculationScenario[] calculations = { pipingCalculationScenario1, pipingCalculationScenario2, pipingCalculationScenario3 }; // Call - double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(calculations, 0.1); + double initialFailureMechanismResultProbability = failureMechanismSectionResult.GetInitialFailureMechanismResultProbability( + calculations, scenario => scenario.Output.ProfileSpecificOutput); // Assert - Assert.AreEqual(4.2467174336864661e-7, detailedAssessmentProbability); + Assert.AreEqual(0.24284668249632746, initialFailureMechanismResultProbability); } [Test] - public void GetDetailedAssessmentProbability_NoScenarios_ReturnsNaN() + public void ProbabilisticGetInitialFailureMechanismResultProbability_NoScenarios_ReturnsNaN() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); // Call - double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(Enumerable.Empty(), 0.1); + double detailedAssessmentProbability = failureMechanismSectionResult.GetInitialFailureMechanismResultProbability( + Enumerable.Empty(), scenario => scenario.Output.ProfileSpecificOutput); // Assert Assert.IsNaN(detailedAssessmentProbability); } [Test] - public void GetDetailedAssessmentProbability_NoRelevantScenarios_ReturnsNaN() + public void ProbabilisticGetInitialFailureMechanismResultProbability_NoRelevantScenarios_ReturnsNaN() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); - SemiProbabilisticPipingCalculationScenario[] calculationScenarios = + ProbabilisticPipingCalculationScenario[] calculationScenarios = { - CreateIrrelevantPipingCalculationScenario(section) + CreateIrrelevantProbabilisticPipingCalculationScenario(section) }; // Call - double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(calculationScenarios, 0.1); + double initialFailureMechanismResultProbability = failureMechanismSectionResult.GetInitialFailureMechanismResultProbability( + calculationScenarios, scenario => scenario.Output.ProfileSpecificOutput); // Assert - Assert.IsNaN(detailedAssessmentProbability); + Assert.IsNaN(initialFailureMechanismResultProbability); } [Test] - public void GetDetailedAssessmentProbability_ScenarioNotCalculated_ReturnsNaN() + public void ProbabilisticGetInitialFailureMechanismResultProbability_ScenarioNotCalculated_ReturnsNaN() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); var pipingCalculationScenario = - SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); // Call - double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(new[] + double initialFailureMechanismResultProbability = failureMechanismSectionResult.GetInitialFailureMechanismResultProbability(new[] { pipingCalculationScenario - }, 0.1); + }, scenario => scenario.Output.ProfileSpecificOutput); // Assert - Assert.IsNaN(detailedAssessmentProbability); + Assert.IsNaN(initialFailureMechanismResultProbability); } [Test] - public void GetDetailedAssessmentProbability_ScenarioWithNaNResults_ReturnsNaN() + public void ProbabilisticGetInitialFailureMechanismResultProbability_ScenarioWithNaNResults_ReturnsNaN() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); @@ -165,194 +360,245 @@ const double contribution2 = 0.8; var pipingCalculationScenario1 = - SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateCalculation(section); var pipingCalculationScenario2 = - SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); pipingCalculationScenario1.IsRelevant = true; pipingCalculationScenario1.Contribution = (RoundedDouble) contribution1; pipingCalculationScenario2.IsRelevant = true; pipingCalculationScenario2.Contribution = (RoundedDouble) contribution2; - pipingCalculationScenario2.Output = new SemiProbabilisticPipingOutput(new SemiProbabilisticPipingOutput.ConstructionProperties()); + pipingCalculationScenario2.Output = new ProbabilisticPipingOutput(new TestPartialProbabilisticPipingOutput(double.NaN, null), + new TestPartialProbabilisticPipingOutput(double.NaN, null)); - SemiProbabilisticPipingCalculationScenario[] calculations = + ProbabilisticPipingCalculationScenario[] calculations = { pipingCalculationScenario1, pipingCalculationScenario2 }; // Call - double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(calculations, 0.1); + double initialFailureMechanismResultProbability = failureMechanismSectionResult.GetInitialFailureMechanismResultProbability( + calculations, scenario => scenario.Output.ProfileSpecificOutput); // Assert - Assert.IsNaN(detailedAssessmentProbability); + Assert.IsNaN(initialFailureMechanismResultProbability); } [Test] [TestCase(0.0, 0.0)] [TestCase(0.0, 0.5)] [TestCase(0.3, 0.7 + 1e-5)] - public void GetDetailedAssessmentProbability_RelevantScenarioContributionsDoNotAddUpTo1_ReturnNaN(double contributionA, double contributionB) + public void ProbabilisticGetInitialFailureMechanismResultProbability_RelevantScenarioContributionsDoNotAddUpTo1_ReturnNaN(double contributionA, double contributionB) { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); var pipingCalculationScenarioA = - SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); var pipingCalculationScenarioB = - SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + ProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); pipingCalculationScenarioA.Contribution = (RoundedDouble) contributionA; pipingCalculationScenarioB.Contribution = (RoundedDouble) contributionB; var result = new PipingFailureMechanismSectionResult(section); // Call - double detailedAssessmentProbability = result.GetDetailedAssessmentProbability(new[] + double initialFailureMechanismResultProbability = result.GetInitialFailureMechanismResultProbability(new[] { pipingCalculationScenarioA, pipingCalculationScenarioB - }, 0.1); + }, scenario => null); // Assert - Assert.IsNaN(detailedAssessmentProbability); + Assert.IsNaN(initialFailureMechanismResultProbability); } + #endregion + + #region Semi-probabilistic + [Test] - public void GetTotalContribution_SectionResultNull_ThrowsArgumentNullException() + public void GetDetailedAssessmentProbability_SectionResultNull_ThrowsArgumentNullException() { // Call - void Call() => ((PipingFailureMechanismSectionResult) null).GetTotalContribution(Enumerable.Empty()); + void Call() => PipingFailureMechanismSectionResultDetailedAssessmentExtensions.GetDetailedAssessmentProbability( + null, Enumerable.Empty(), 0.1); // Assert var exception = Assert.Throws(Call); Assert.AreEqual("sectionResult", exception.ParamName); } [Test] - public void GetTotalContribution_CalculationScenariosNull_ThrowsArgumentNullException() + public void GetDetailedAssessmentProbability_CalculationScenariosNull_ThrowsArgumentNullException() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); - var sectionResult = new PipingFailureMechanismSectionResult(section); + var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); // Call - void Call() => sectionResult.GetTotalContribution(null); + void Call() => failureMechanismSectionResult.GetDetailedAssessmentProbability(null, 0.1); // Assert var exception = Assert.Throws(Call); Assert.AreEqual("calculationScenarios", exception.ParamName); } [Test] - public void GetTotalContribution_WithScenarios_ReturnsTotalRelevantScenarioContribution() + public void GetDetailedAssessmentProbability_MultipleScenarios_ReturnsValueBasedOnRelevantScenarios() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); var pipingCalculationScenario1 = - SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); - pipingCalculationScenario1.Contribution = (RoundedDouble) 0.3211; - + SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); var pipingCalculationScenario2 = - SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); - pipingCalculationScenario2.Contribution = (RoundedDouble) 0.5435; + SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); + var pipingCalculationScenario3 = + SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); - SemiProbabilisticPipingCalculationScenario pipingCalculationScenario3 = CreateIrrelevantPipingCalculationScenario(section); + pipingCalculationScenario1.IsRelevant = true; + pipingCalculationScenario1.Contribution = (RoundedDouble) 0.2111; + pipingCalculationScenario1.Output = PipingTestDataGenerator.GetSemiProbabilisticPipingOutput(1.1, 2.2, 3.3); - SemiProbabilisticPipingCalculationScenario[] calculationScenarios = + pipingCalculationScenario2.IsRelevant = true; + pipingCalculationScenario2.Contribution = (RoundedDouble) 0.7889; + pipingCalculationScenario2.Output = PipingTestDataGenerator.GetSemiProbabilisticPipingOutput(4.4, 5.5, 6.6); + + pipingCalculationScenario3.IsRelevant = false; + + SemiProbabilisticPipingCalculationScenario[] calculations = { pipingCalculationScenario1, pipingCalculationScenario2, pipingCalculationScenario3 }; // Call - RoundedDouble totalContribution = failureMechanismSectionResult.GetTotalContribution(calculationScenarios); + double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(calculations, 0.1); // Assert - Assert.AreEqual((RoundedDouble) 0.8646, totalContribution); + Assert.AreEqual(4.2467174336864661e-7, detailedAssessmentProbability); } [Test] - public void GetCalculationScenarios_SectionResultNull_ThrowsArgumentNullException() + public void GetDetailedAssessmentProbability_NoScenarios_ReturnsNaN() { + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); + // Call - void Call() => ((PipingFailureMechanismSectionResult) null).GetCalculationScenarios(Enumerable.Empty()); + double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(Enumerable.Empty(), 0.1); // Assert - var exception = Assert.Throws(Call); - Assert.AreEqual("sectionResult", exception.ParamName); + Assert.IsNaN(detailedAssessmentProbability); } [Test] - public void GetCalculationScenarios_CalculationScenariosNull_ThrowsArgumentNullException() + public void GetDetailedAssessmentProbability_NoRelevantScenarios_ReturnsNaN() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); - var sectionResult = new PipingFailureMechanismSectionResult(section); + var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); + SemiProbabilisticPipingCalculationScenario[] calculationScenarios = + { + CreateIrrelevantSemiProbabilisticPipingCalculationScenario(section) + }; + // Call - void Call() => sectionResult.GetCalculationScenarios(null); + double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(calculationScenarios, 0.1); // Assert - var exception = Assert.Throws(Call); - Assert.AreEqual("calculationScenarios", exception.ParamName); + Assert.IsNaN(detailedAssessmentProbability); } [Test] - public void GetCalculationScenarios_WithRelevantAndIrrelevantScenarios_ReturnsRelevantCalculationScenarios() + public void GetDetailedAssessmentProbability_ScenarioNotCalculated_ReturnsNaN() { // Setup FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); - var sectionResult = new PipingFailureMechanismSectionResult(section); - var calculationScenario = + var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); + + var pipingCalculationScenario = SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); - SemiProbabilisticPipingCalculationScenario calculationScenario2 = CreateIrrelevantPipingCalculationScenario(section); // Call - IEnumerable relevantScenarios = sectionResult.GetCalculationScenarios(new[] + double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(new[] { - calculationScenario, - calculationScenario2 - }); + pipingCalculationScenario + }, 0.1); // Assert - Assert.AreEqual(calculationScenario, relevantScenarios.Single()); + Assert.IsNaN(detailedAssessmentProbability); } [Test] - public void GetCalculationScenarios_WithoutScenarioIntersectingSection_ReturnsNoCalculationScenarios() + public void GetDetailedAssessmentProbability_ScenarioWithNaNResults_ReturnsNaN() { // Setup - FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(new[] + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var failureMechanismSectionResult = new PipingFailureMechanismSectionResult(section); + + const double contribution1 = 0.2; + const double contribution2 = 0.8; + + var pipingCalculationScenario1 = + SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section); + var pipingCalculationScenario2 = + SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + + pipingCalculationScenario1.IsRelevant = true; + pipingCalculationScenario1.Contribution = (RoundedDouble) contribution1; + + pipingCalculationScenario2.IsRelevant = true; + pipingCalculationScenario2.Contribution = (RoundedDouble) contribution2; + pipingCalculationScenario2.Output = new SemiProbabilisticPipingOutput(new SemiProbabilisticPipingOutput.ConstructionProperties()); + + SemiProbabilisticPipingCalculationScenario[] calculations = { - new Point2D(999, 999), - new Point2D(998, 998) - }); - var sectionResult = new PipingFailureMechanismSectionResult(section); - var calculationScenario = - SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation( - FailureMechanismSectionTestFactory.CreateFailureMechanismSection()); + pipingCalculationScenario1, + pipingCalculationScenario2 + }; // Call - IEnumerable relevantScenarios = sectionResult.GetCalculationScenarios(new[] - { - calculationScenario - }); + double detailedAssessmentProbability = failureMechanismSectionResult.GetDetailedAssessmentProbability(calculations, 0.1); // Assert - CollectionAssert.IsEmpty(relevantScenarios); + Assert.IsNaN(detailedAssessmentProbability); } - private static SemiProbabilisticPipingCalculationScenario CreateIrrelevantPipingCalculationScenario(FailureMechanismSection section) + [Test] + [TestCase(0.0, 0.0)] + [TestCase(0.0, 0.5)] + [TestCase(0.3, 0.7 + 1e-5)] + public void GetDetailedAssessmentProbability_RelevantScenarioContributionsDoNotAddUpTo1_ReturnNaN(double contributionA, double contributionB) { - var calculationScenario = + // Setup + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var pipingCalculationScenarioA = SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + var pipingCalculationScenarioB = + SemiProbabilisticPipingCalculationTestFactory.CreateNotCalculatedCalculation(section); + pipingCalculationScenarioA.Contribution = (RoundedDouble) contributionA; + pipingCalculationScenarioB.Contribution = (RoundedDouble) contributionB; - calculationScenario.IsRelevant = false; + var result = new PipingFailureMechanismSectionResult(section); - return calculationScenario; + // Call + double detailedAssessmentProbability = result.GetDetailedAssessmentProbability(new[] + { + pipingCalculationScenarioA, + pipingCalculationScenarioB + }, 0.1); + + // Assert + Assert.IsNaN(detailedAssessmentProbability); } + + #endregion } } \ No newline at end of file Index: Riskeer/Piping/test/Riskeer.Piping.Data.TestUtil/Probabilistic/ProbabilisticPipingCalculationTestFactory.cs =================================================================== diff -u -rc37eebd9171a53987f5929013edbe3d82e618ed0 -r5c1fa0be4802b9a798b5df51a570735e4a9d15a1 --- Riskeer/Piping/test/Riskeer.Piping.Data.TestUtil/Probabilistic/ProbabilisticPipingCalculationTestFactory.cs (.../ProbabilisticPipingCalculationTestFactory.cs) (revision c37eebd9171a53987f5929013edbe3d82e618ed0) +++ Riskeer/Piping/test/Riskeer.Piping.Data.TestUtil/Probabilistic/ProbabilisticPipingCalculationTestFactory.cs (.../ProbabilisticPipingCalculationTestFactory.cs) (revision 5c1fa0be4802b9a798b5df51a570735e4a9d15a1) @@ -20,9 +20,13 @@ // All rights reserved. using System; +using System.Linq; using Core.Common.Base.Data; +using Core.Common.Base.Geometry; +using Riskeer.Common.Data.FailureMechanism; using Riskeer.Common.Data.Hydraulics; using Riskeer.Piping.Data.Probabilistic; +using Riskeer.Piping.Primitives; namespace Riskeer.Piping.Data.TestUtil.Probabilistic { @@ -32,6 +36,57 @@ public static class ProbabilisticPipingCalculationTestFactory { /// + /// Creates a calculated semi-probabilistic calculation for which the surface line on the input intersects with . + /// + /// The type of semi-probabilistic calculation to create. + /// The section for which an intersection will be created. + /// A new instance of type . + /// Thrown when is null. + public static T CreateCalculation(FailureMechanismSection section) + where T : ProbabilisticPipingCalculation, new() + { + var calculation = CreateNotCalculatedCalculation(section); + + calculation.Output = PipingTestDataGenerator.GetRandomProbabilisticPipingOutputWithoutIllustrationPoints(); + + return calculation; + } + + /// + /// Creates a semi-probabilistic calculation for which the surface line on the input intersects with + /// and the calculation has not been performed. + /// + /// The type of semi-probabilistic calculation to create. + /// The section for which an intersection will be created. + /// A new instance of type . + /// Thrown when is null. + public static T CreateNotCalculatedCalculation(FailureMechanismSection section) + where T : ProbabilisticPipingCalculation, new() + { + if (section == null) + { + throw new ArgumentNullException(nameof(section)); + } + + var pipingSurfaceLine = new PipingSurfaceLine(string.Empty); + Point2D p = section.Points.First(); + pipingSurfaceLine.SetGeometry(new[] + { + new Point3D(p.X, p.Y, 0), + new Point3D(p.X + 2, p.Y + 2, 0) + }); + pipingSurfaceLine.ReferenceLineIntersectionWorldPoint = section.Points.First(); + + return new T + { + InputParameters = + { + SurfaceLine = pipingSurfaceLine + } + }; + } + + /// /// Creates a probabilistic calculation with valid input. /// /// The hydraulic boundary location to set to the input.