// Copyright (C) Stichting Deltares 2017. All rights reserved.
//
// This file is part of Ringtoets.
//
// Ringtoets is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Common.Base.Data;
using Core.Common.Base.Geometry;
using Core.Common.TestUtil;
using NUnit.Framework;
using Ringtoets.Common.Data.Probabilistics;
using Ringtoets.Common.Data.TestUtil;
using Ringtoets.Common.Service.TestUtil;
using Ringtoets.Piping.Data;
using Ringtoets.Piping.Data.SoilProfile;
using Ringtoets.Piping.Data.TestUtil;
using Ringtoets.Piping.KernelWrapper.SubCalculator;
using Ringtoets.Piping.KernelWrapper.TestUtil.SubCalculator;
using Ringtoets.Piping.Primitives;
namespace Ringtoets.Piping.Service.Test
{
[TestFixture]
public class PipingCalculationServiceTest
{
private const string averagingSoilLayerPropertiesMessage = "Meerdere aaneengesloten deklagen gevonden. De grondeigenschappen worden bepaald door het nemen van een gewogen gemiddelde, mits de standaardafwijkingen en verschuivingen voor alle lagen gelijk zijn.";
private double testSurfaceLineTopLevel;
private PipingCalculationScenario testCalculation;
[SetUp]
public void Setup()
{
testCalculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithValidInput(new TestHydraulicBoundaryLocation());
testSurfaceLineTopLevel = testCalculation.InputParameters.SurfaceLine.Points.Max(p => p.Z);
}
[Test]
public void Validate_CalculationNull_ThrowArgumentNullException()
{
// Call
TestDelegate test = () => PipingCalculationService.Validate(null, RoundedDouble.NaN);
// Assert
var exception = Assert.Throws(test);
Assert.AreEqual("calculation", exception.ParamName);
}
[Test]
public void Validate_Always_LogStartAndEndOfValidatingInputs()
{
// Call
Action call = () => PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[1]);
});
}
[Test]
public void Validate_InvalidPipingCalculationWithOutput_ReturnsFalseNoOutputChange()
{
// Setup
PipingOutput output = PipingOutputTestFactory.Create();
PipingCalculation invalidPipingCalculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithInvalidInput();
invalidPipingCalculation.Output = output;
// Call
bool isValid = PipingCalculationService.Validate(invalidPipingCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
Assert.IsFalse(isValid);
Assert.AreSame(output, invalidPipingCalculation.Output);
}
[Test]
public void Validate_InvalidCalculationInput_LogsErrorAndReturnsFalse()
{
// Setup
var calculation = new PipingCalculation(new GeneralPipingInput());
// Call
var isValid = false;
Action call = () => isValid = PipingCalculationService.Validate(calculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(7, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Er is geen hydraulische belastingenlocatie geselecteerd.", msgs[1]);
Assert.AreEqual("Er is geen profielschematisatie geselecteerd.", msgs[2]);
Assert.AreEqual("Er is geen ondergrondschematisatie geselecteerd.", msgs[3]);
Assert.AreEqual("De waarde voor 'uittredepunt' moet een concreet getal zijn.", msgs[4]);
Assert.AreEqual("De waarde voor 'intredepunt' moet een concreet getal zijn.", msgs[5]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[6]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_NormativeAssessmentLevelNotCalculated_LogsErrorAndReturnsFalse()
{
// Setup
testCalculation.InputParameters.UseAssessmentLevelManualInput = false;
// Call
var isValid = false;
Action call = () => isValid = PipingCalculationService.Validate(testCalculation, RoundedDouble.NaN);
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(4, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Kan de waterstand niet afleiden op basis van de invoer.", msgs[1]);
Assert.AreEqual("Kan de stijghoogte bij het uittredepunt niet afleiden op basis van de invoer.", msgs[2]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[3]);
});
Assert.IsFalse(isValid);
}
[Test]
[TestCase(double.NaN)]
[TestCase(double.NegativeInfinity)]
[TestCase(double.PositiveInfinity)]
public void Validate_InvalidManualAssessmentLevel_LogsErrorAndReturnsFalse(double assessmentLevel)
{
// Setup
testCalculation.InputParameters.UseAssessmentLevelManualInput = true;
testCalculation.InputParameters.AssessmentLevel = (RoundedDouble) assessmentLevel;
// Call
var isValid = false;
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(4, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("De waarde voor 'waterstand' moet een concreet getal zijn.", msgs[1]);
Assert.AreEqual("Kan de stijghoogte bij het uittredepunt niet afleiden op basis van de invoer.", msgs[2]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[3]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_WithoutEntryPointL_LogsErrorAndReturnsFalse()
{
// Setup
testCalculation.InputParameters.EntryPointL = RoundedDouble.NaN;
// Call
var isValid = false;
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("De waarde voor 'intredepunt' moet een concreet getal zijn.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_WithoutExitPointL_LogsErrorAndReturnsFalse()
{
// Setup
testCalculation.InputParameters.ExitPointL = RoundedDouble.NaN;
// Call
var isValid = false;
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("De waarde voor 'uittredepunt' moet een concreet getal zijn.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_WithoutSurfaceLine_LogsErrorAndReturnsFalse()
{
// Setup
testCalculation.InputParameters.SurfaceLine = null;
testCalculation.InputParameters.ExitPointL = (RoundedDouble) 0.9;
testCalculation.InputParameters.EntryPointL = (RoundedDouble) 0.1;
// Call
var isValid = false;
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Er is geen profielschematisatie geselecteerd.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_WithSurfaceLineOneOutOfFourDitchPoints_LogsErrorAndReturnsFalse()
{
// Setup
IEnumerable geometry = testCalculation.InputParameters.SurfaceLine.Points;
const string surfaceLineName = "surfaceLineA";
var surfaceLineMissingCharacteristicPoint = new PipingSurfaceLine(surfaceLineName);
surfaceLineMissingCharacteristicPoint.SetGeometry(geometry);
surfaceLineMissingCharacteristicPoint.SetDitchDikeSideAt(geometry.ElementAt(2));
testCalculation.InputParameters.SurfaceLine = surfaceLineMissingCharacteristicPoint;
testCalculation.InputParameters.ExitPointL = (RoundedDouble) 0.9;
testCalculation.InputParameters.EntryPointL = (RoundedDouble) 0.1;
// Call
var isValid = false;
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
string expected = $"De sloot in de hoogtegeometrie {surfaceLineName} is niet correct. Niet alle 4 punten zijn gedefinieerd of de volgorde is incorrect.";
Assert.AreEqual(expected, msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_WithoutStochasticSoilProfile_LogsErrorAndReturnsFalse()
{
// Setup
testCalculation.InputParameters.StochasticSoilProfile = null;
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Er is geen ondergrondschematisatie geselecteerd.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_StochasticSoilProfileBelowSurfaceLine_LogsErrorAndReturnsFalse()
{
// Setup
var topLayer = new PipingSoilLayer(testSurfaceLineTopLevel - 1e-6)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = (RoundedDouble) 15,
StandardDeviation = (RoundedDouble) 2,
Shift = (RoundedDouble) 0
}
};
var bottomLayer = new PipingSoilLayer(2.0)
{
IsAquifer = true,
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1e-4,
CoefficientOfVariation = (RoundedDouble) 0
},
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
}
};
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(
0.0, new PipingSoilProfile(
string.Empty, 0.0,
new[]
{
topLayer,
bottomLayer
},
SoilProfileType.SoilProfile1D));
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Hoogtegeometrie ligt (deels) boven de ondergrondschematisatie.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_WithoutAquiferLayer_LogsErrorAndReturnsFalse()
{
// Setup
var aquitardLayer = new PipingSoilLayer(2.0)
{
IsAquifer = false
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
aquitardLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(6, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Geen deklaag gevonden voor de ondergrondschematisatie onder de profielschematisatie bij het uittredepunt.", msgs[1]);
Assert.AreEqual("Kan de totale deklaagdikte bij het uittredepunt niet afleiden op basis van de invoer.", msgs[2]);
Assert.AreEqual("Kan de dikte van het watervoerend pakket niet afleiden op basis van de invoer.", msgs[3]);
Assert.AreEqual("Geen watervoerende laag gevonden voor de ondergrondschematisatie onder de profielschematisatie bij het uittredepunt.", msgs[4]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[5]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_WithoutAquitardLayer_LogsWarningsAndReturnsTrue()
{
// Setup
var aquiferLayer = new PipingSoilLayer(10.56)
{
IsAquifer = true,
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1e-4,
CoefficientOfVariation = (RoundedDouble) 0
},
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
aquiferLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(4, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Geen deklaag gevonden voor de ondergrondschematisatie onder de profielschematisatie bij het uittredepunt.", msgs[1]);
Assert.AreEqual("Kan de totale deklaagdikte bij het uittredepunt niet afleiden op basis van de invoer.", msgs[2]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[3]);
});
Assert.IsTrue(isValid);
}
[Test]
public void Validate_WithoutCoverageLayer_LogsWarningsAndReturnsTrue()
{
// Setup
var coverageLayerAboveSurfaceLine = new PipingSoilLayer(13.0)
{
IsAquifer = false
};
var bottomAquiferLayer = new PipingSoilLayer(11.0)
{
IsAquifer = true,
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1e-4,
CoefficientOfVariation = (RoundedDouble) 0
},
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
coverageLayerAboveSurfaceLine,
bottomAquiferLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(4, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Geen deklaag gevonden voor de ondergrondschematisatie onder de profielschematisatie bij het uittredepunt.", msgs[1]);
Assert.AreEqual("Kan de totale deklaagdikte bij het uittredepunt niet afleiden op basis van de invoer.", msgs[2]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[3]);
});
Assert.IsTrue(isValid);
}
[Test]
public void Validate_MultipleCoverageLayer_LogsWarningAndReturnsTrue()
{
// Setup
var random = new Random(21);
const double belowPhreaticLevelDeviation = 0.5;
const int belowPhreaticLevelShift = 1;
const double belowPhreaticLevelMeanBase = 15.0;
var topCoverageLayer = new PipingSoilLayer(testSurfaceLineTopLevel)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = (RoundedDouble) (belowPhreaticLevelMeanBase + belowPhreaticLevelShift + random.NextDouble()),
StandardDeviation = (RoundedDouble) belowPhreaticLevelDeviation,
Shift = (RoundedDouble) belowPhreaticLevelShift
}
};
var middleCoverageLayer = new PipingSoilLayer(8.5)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = (RoundedDouble) (belowPhreaticLevelMeanBase + belowPhreaticLevelShift + random.NextDouble()),
StandardDeviation = (RoundedDouble) belowPhreaticLevelDeviation,
Shift = (RoundedDouble) belowPhreaticLevelShift
}
};
var bottomAquiferLayer = new PipingSoilLayer(5.0)
{
IsAquifer = true,
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
},
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1e-4,
CoefficientOfVariation = (RoundedDouble) 0
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
topCoverageLayer,
middleCoverageLayer,
bottomAquiferLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual(averagingSoilLayerPropertiesMessage, msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsTrue(isValid);
}
[Test]
[TestCase(false, false)]
[TestCase(false, true)]
[TestCase(true, false)]
public void Validate_IncompleteDiameterD70Definition_LogsErrorAndReturnsFalse(bool meanSet, bool coefficientOfVariationSet)
{
// Setup
var random = new Random(21);
var incompletePipingSoilLayer = new PipingSoilLayer(5.0)
{
IsAquifer = true,
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
},
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = meanSet
? random.NextRoundedDouble(1, double.MaxValue)
: RoundedDouble.NaN,
CoefficientOfVariation = coefficientOfVariationSet
? random.NextRoundedDouble()
: RoundedDouble.NaN
}
};
var completeLayer = new PipingSoilLayer(testSurfaceLineTopLevel)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = random.NextRoundedDouble(15.0, 999.999),
StandardDeviation = random.NextRoundedDouble(1e-6, 5.0),
Shift = random.NextRoundedDouble(1e-6, 10)
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
completeLayer,
incompletePipingSoilLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Kan de definitie voor het 70%-fraktiel van de korreldiameter van de watervoerende laag niet (volledig) afleiden.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
[TestCase(6.2e-5)]
[TestCase(5.1e-3)]
public void Validate_InvalidDiameterD70Value_LogsWarningAndReturnsTrue(double diameter70Value)
{
// Setup
var random = new Random(21);
var coverageLayerInvalidD70 = new PipingSoilLayer(5.0)
{
IsAquifer = true,
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
},
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) diameter70Value,
CoefficientOfVariation = (RoundedDouble) 0
}
};
var validLayer = new PipingSoilLayer(testSurfaceLineTopLevel)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = random.NextRoundedDouble(15.0, 999.999),
StandardDeviation = random.NextRoundedDouble(1e-6, 5.0),
Shift = random.NextRoundedDouble(1e-6, 10)
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
validLayer,
coverageLayerInvalidD70
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual($"Rekenwaarde voor d70 ({new RoundedDouble(6, diameter70Value)} m) ligt buiten het geldigheidsbereik van dit model. Geldige waarden liggen tussen 0.000063 m en 0.0005 m.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsTrue(isValid);
}
[Test]
[TestCase(false, false)]
[TestCase(false, true)]
[TestCase(true, false)]
public void Validate_IncompletePermeabilityDefinition_LogsErrorAndReturnsFalse(bool meanSet, bool coefficientOfVariationSet)
{
// Setup
var random = new Random(21);
var incompletePipingSoilLayer = new PipingSoilLayer(5.0)
{
IsAquifer = true,
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1e-4,
CoefficientOfVariation = (RoundedDouble) 0
},
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = meanSet
? random.NextRoundedDouble(1, double.MaxValue)
: RoundedDouble.NaN,
CoefficientOfVariation = coefficientOfVariationSet
? random.NextRoundedDouble()
: RoundedDouble.NaN
}
};
var completeLayer = new PipingSoilLayer(testSurfaceLineTopLevel)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = random.NextRoundedDouble(15.0, 999.999),
StandardDeviation = random.NextRoundedDouble(1e-6, 999.999),
Shift = random.NextRoundedDouble(1e-6, 10)
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
completeLayer,
incompletePipingSoilLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Kan de definitie voor de doorlatendheid van de watervoerende laag niet (volledig) afleiden.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
[TestCase(false, false, false)]
[TestCase(false, true, true)]
[TestCase(true, false, true)]
[TestCase(true, true, false)]
public void Validate_IncompleteSaturatedVolumicWeightDefinition_LogsErrorAndReturnsFalse(bool meanSet, bool deviationSet, bool shiftSet)
{
// Setup
var random = new Random(21);
var incompletePipingSoilLayer = new PipingSoilLayer(testSurfaceLineTopLevel)
{
IsAquifer = false
};
incompletePipingSoilLayer.BelowPhreaticLevel = new LogNormalDistribution
{
Mean = meanSet
? random.NextRoundedDouble(1, double.MaxValue)
: RoundedDouble.NaN,
StandardDeviation = deviationSet
? random.NextRoundedDouble()
: RoundedDouble.NaN,
Shift = shiftSet
? random.NextRoundedDouble()
: RoundedDouble.NaN
};
var completeLayer = new PipingSoilLayer(5.0)
{
IsAquifer = true,
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
},
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1e-4,
CoefficientOfVariation = (RoundedDouble) 0
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
incompletePipingSoilLayer,
completeLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual("Kan de definitie voor het verzadigd gewicht van de deklaag niet (volledig) afleiden.", msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_SaturatedCoverageLayerVolumicWeightLessThanWaterVolumicWeight_LogsErrorAndReturnsFalse()
{
// Setup
var coverageLayerInvalidSaturatedVolumicWeight = new PipingSoilLayer(testSurfaceLineTopLevel)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = (RoundedDouble) 9.81,
StandardDeviation = (RoundedDouble) 2,
Shift = (RoundedDouble) 0
}
};
var validLayer = new PipingSoilLayer(5.0)
{
IsAquifer = true,
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 1,
CoefficientOfVariation = (RoundedDouble) 0.5
},
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 0.0002,
CoefficientOfVariation = (RoundedDouble) 0
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
coverageLayerInvalidSaturatedVolumicWeight,
validLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
var isValid = false;
// Call
Action call = () => isValid = PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(3, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual(
"Het verzadigd volumetrisch gewicht van de deklaag moet groter zijn dan het volumetrisch gewicht van water.",
msgs[1]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[2]);
});
Assert.IsFalse(isValid);
}
[Test]
public void Validate_SaturatedCoverageLayerLessThanWaterLayerAndMissingSaturatedParameter_LogsErrorOnlyForIncompleteDefinition()
{
// Setup
var topCoverageLayer = new PipingSoilLayer(testSurfaceLineTopLevel)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = (RoundedDouble) 5,
StandardDeviation = (RoundedDouble) 2,
Shift = (RoundedDouble) 0
}
};
var middleCoverageLayerMissingParameter = new PipingSoilLayer(8.5)
{
IsAquifer = false,
BelowPhreaticLevel = new LogNormalDistribution
{
Mean = (RoundedDouble) 5,
StandardDeviation = (RoundedDouble) 2,
Shift = RoundedDouble.NaN
}
};
var bottomAquiferLayer = new PipingSoilLayer(5.0)
{
IsAquifer = true,
Permeability = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 0.3,
CoefficientOfVariation = (RoundedDouble) 0.6
},
DiameterD70 = new VariationCoefficientLogNormalDistribution
{
Mean = (RoundedDouble) 0.0002,
CoefficientOfVariation = (RoundedDouble) 0
}
};
var profile = new PipingSoilProfile(string.Empty, 0.0,
new[]
{
topCoverageLayer,
middleCoverageLayerMissingParameter,
bottomAquiferLayer
},
SoilProfileType.SoilProfile1D);
testCalculation.InputParameters.StochasticSoilProfile = new PipingStochasticSoilProfile(0.0, profile);
// Call
Action call = () => PipingCalculationService.Validate(testCalculation,
AssessmentSectionHelper.GetTestAssessmentLevel());
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(4, msgs.Length);
CalculationServiceTestHelper.AssertValidationStartMessage(msgs[0]);
Assert.AreEqual(averagingSoilLayerPropertiesMessage, msgs[1]);
Assert.AreEqual(
"Kan de definitie voor het verzadigd gewicht van de deklaag niet (volledig) afleiden.",
msgs[2]);
CalculationServiceTestHelper.AssertValidationEndMessage(msgs[3]);
});
}
[Test]
public void Calculate_CalculationNull_ThrowArgumentNullException()
{
// Call
TestDelegate test = () => PipingCalculationService.Calculate(null, RoundedDouble.NaN);
// Assert
var exception = Assert.Throws(test);
Assert.AreEqual("calculation", exception.ParamName);
}
[Test]
public void Calculate_ValidPipingCalculation_LogStartAndEndOfCalculation()
{
// Call
Action call = () =>
{
using (new PipingSubCalculatorFactoryConfig())
{
PipingCalculationService.Calculate(testCalculation, AssessmentSectionHelper.GetTestAssessmentLevel());
}
};
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
CalculationServiceTestHelper.AssertCalculationStartMessage(msgs[0]);
CalculationServiceTestHelper.AssertCalculationEndMessage(msgs[1]);
});
}
[Test]
public void Calculate_ValidPipingCalculationNoOutput_ShouldSetOutput()
{
// Setup
RoundedDouble normativeAssessmentLevel = AssessmentSectionHelper.GetTestAssessmentLevel();
// Precondition
Assert.IsNull(testCalculation.Output);
// Call
using (new PipingSubCalculatorFactoryConfig())
{
PipingCalculationService.Calculate(testCalculation, normativeAssessmentLevel);
}
// Assert
PipingOutput pipingOutput = testCalculation.Output;
Assert.IsNotNull(pipingOutput);
Assert.IsFalse(double.IsNaN(pipingOutput.UpliftEffectiveStress));
Assert.IsFalse(double.IsNaN(pipingOutput.UpliftZValue));
Assert.IsFalse(double.IsNaN(pipingOutput.UpliftFactorOfSafety));
Assert.IsFalse(double.IsNaN(pipingOutput.HeaveZValue));
Assert.IsFalse(double.IsNaN(pipingOutput.HeaveFactorOfSafety));
Assert.IsFalse(double.IsNaN(pipingOutput.SellmeijerZValue));
Assert.IsFalse(double.IsNaN(pipingOutput.SellmeijerFactorOfSafety));
}
[Test]
public void Calculate_ValidPipingCalculationWithOutput_ShouldChangeOutput()
{
// Setup
PipingOutput output = PipingOutputTestFactory.Create();
RoundedDouble normativeAssessmentLevel = AssessmentSectionHelper.GetTestAssessmentLevel();
testCalculation.Output = output;
// Call
using (new PipingSubCalculatorFactoryConfig())
{
PipingCalculationService.Calculate(testCalculation, normativeAssessmentLevel);
}
// Assert
Assert.AreNotSame(output, testCalculation.Output);
}
[TestCase(true)]
[TestCase(false)]
public void Validate_CompleteInput_InputSetOnSubCalculators(bool useAssessmentLevelManualInput)
{
// Setup
RoundedDouble normativeAssessmentLevel = AssessmentSectionHelper.GetTestAssessmentLevel();
PipingInput input = testCalculation.InputParameters;
input.AssessmentLevel = (RoundedDouble) 2.2;
input.UseAssessmentLevelManualInput = useAssessmentLevelManualInput;
using (new PipingSubCalculatorFactoryConfig())
{
// Call
PipingCalculationService.Validate(testCalculation, normativeAssessmentLevel);
// Assert
RoundedDouble expectedAssessmentLevel = useAssessmentLevelManualInput
? input.AssessmentLevel
: normativeAssessmentLevel;
AssertSubCalculatorInputs(input, expectedAssessmentLevel);
}
}
[TestCase(true)]
[TestCase(false)]
public void Calculate_CompleteInput_InputSetOnSubCalculators(bool useAssessmentLevelManualInput)
{
// Setup
RoundedDouble normativeAssessmentLevel = AssessmentSectionHelper.GetTestAssessmentLevel();
PipingInput input = testCalculation.InputParameters;
input.UseAssessmentLevelManualInput = useAssessmentLevelManualInput;
using (new PipingSubCalculatorFactoryConfig())
{
// Call
PipingCalculationService.Calculate(testCalculation, normativeAssessmentLevel);
// Assert
RoundedDouble expectedAssessmentLevel = useAssessmentLevelManualInput
? input.AssessmentLevel
: normativeAssessmentLevel;
AssertSubCalculatorInputs(input, expectedAssessmentLevel);
}
}
private static void AssertSubCalculatorInputs(PipingInput input, RoundedDouble expectedAssessmentLevel)
{
var testFactory = (TestPipingSubCalculatorFactory) PipingSubCalculatorFactory.Instance;
HeaveCalculatorStub heaveCalculator = testFactory.LastCreatedHeaveCalculator;
UpliftCalculatorStub upliftCalculator = testFactory.LastCreatedUpliftCalculator;
SellmeijerCalculatorStub sellmeijerCalculator = testFactory.LastCreatedSellmeijerCalculator;
RoundedDouble expectedThicknessCoverageLayerDesignValue = PipingSemiProbabilisticDesignVariableFactory.GetThicknessCoverageLayer(input).GetDesignValue();
double thicknessCoverageLayerAccuracy = DerivedPipingInput.GetThicknessCoverageLayer(input).GetAccuracy();
RoundedDouble expectedPhreaticLevelExitDesignValue = PipingSemiProbabilisticDesignVariableFactory.GetPhreaticLevelExit(input).GetDesignValue();
double phreaticLevelExitDesignAccuracy = input.PhreaticLevelExit.GetAccuracy();
double expectedPiezometricHeadExit = DerivedPipingInput.GetPiezometricHeadExit(input, expectedAssessmentLevel).Value;
RoundedDouble expectedDampingFactorExitDesignValue = PipingSemiProbabilisticDesignVariableFactory.GetDampingFactorExit(input).GetDesignValue();
double dampingFactorExitAccuracy = input.DampingFactorExit.GetAccuracy();
Assert.AreEqual(expectedThicknessCoverageLayerDesignValue, heaveCalculator.DTotal, thicknessCoverageLayerAccuracy);
Assert.AreEqual(expectedPhreaticLevelExitDesignValue, heaveCalculator.HExit, phreaticLevelExitDesignAccuracy);
Assert.AreEqual(input.CriticalHeaveGradient, heaveCalculator.Ich);
Assert.AreEqual(expectedPhreaticLevelExitDesignValue, heaveCalculator.PhiPolder, phreaticLevelExitDesignAccuracy);
Assert.AreEqual(expectedPiezometricHeadExit, heaveCalculator.PhiExit);
Assert.AreEqual(expectedDampingFactorExitDesignValue, heaveCalculator.RExit, dampingFactorExitAccuracy);
Assert.AreEqual(expectedPhreaticLevelExitDesignValue, upliftCalculator.HExit, phreaticLevelExitDesignAccuracy);
Assert.AreEqual(expectedAssessmentLevel, upliftCalculator.HRiver);
Assert.AreEqual(input.UpliftModelFactor, upliftCalculator.ModelFactorUplift);
Assert.AreEqual(expectedPiezometricHeadExit, upliftCalculator.PhiExit);
Assert.AreEqual(expectedPhreaticLevelExitDesignValue, upliftCalculator.PhiPolder, phreaticLevelExitDesignAccuracy);
Assert.AreEqual(expectedDampingFactorExitDesignValue, upliftCalculator.RExit, dampingFactorExitAccuracy);
Assert.AreEqual(input.WaterVolumetricWeight, upliftCalculator.VolumetricWeightOfWater);
RoundedDouble effectiveThickness = PipingSemiProbabilisticDesignVariableFactory.GetEffectiveThicknessCoverageLayer(input).GetDesignValue();
RoundedDouble saturatedVolumicWeight = PipingSemiProbabilisticDesignVariableFactory.GetSaturatedVolumicWeightOfCoverageLayer(input).GetDesignValue();
RoundedDouble expectedEffectiveStress = effectiveThickness * (saturatedVolumicWeight - input.WaterVolumetricWeight);
Assert.AreEqual(expectedEffectiveStress, upliftCalculator.EffectiveStress, expectedEffectiveStress.GetAccuracy());
Assert.AreEqual(PipingSemiProbabilisticDesignVariableFactory.GetSeepageLength(input).GetDesignValue(),
sellmeijerCalculator.SeepageLength,
DerivedPipingInput.GetSeepageLength(input).GetAccuracy());
Assert.AreEqual(expectedPhreaticLevelExitDesignValue, sellmeijerCalculator.HExit, phreaticLevelExitDesignAccuracy);
Assert.AreEqual(expectedAssessmentLevel, sellmeijerCalculator.HRiver);
Assert.AreEqual(input.WaterKinematicViscosity, sellmeijerCalculator.KinematicViscosityWater);
Assert.AreEqual(input.SellmeijerModelFactor, sellmeijerCalculator.ModelFactorPiping);
Assert.AreEqual(input.SellmeijerReductionFactor, sellmeijerCalculator.Rc);
Assert.AreEqual(input.WaterVolumetricWeight, sellmeijerCalculator.VolumetricWeightOfWater);
Assert.AreEqual(input.WhitesDragCoefficient, sellmeijerCalculator.WhitesDragCoefficient);
Assert.AreEqual(input.BeddingAngle, sellmeijerCalculator.BeddingAngle);
Assert.AreEqual(expectedThicknessCoverageLayerDesignValue, sellmeijerCalculator.DTotal, thicknessCoverageLayerAccuracy);
Assert.AreEqual(PipingSemiProbabilisticDesignVariableFactory.GetDiameter70(input).GetDesignValue(),
sellmeijerCalculator.D70,
DerivedPipingInput.GetDiameterD70(input).GetAccuracy());
Assert.AreEqual(input.MeanDiameter70, sellmeijerCalculator.D70Mean);
Assert.AreEqual(PipingSemiProbabilisticDesignVariableFactory.GetThicknessAquiferLayer(input).GetDesignValue(),
sellmeijerCalculator.DAquifer,
DerivedPipingInput.GetThicknessAquiferLayer(input).GetAccuracy());
Assert.AreEqual(PipingSemiProbabilisticDesignVariableFactory.GetDarcyPermeability(input).GetDesignValue(),
sellmeijerCalculator.DarcyPermeability,
DerivedPipingInput.GetDarcyPermeability(input).GetAccuracy());
Assert.AreEqual(input.SandParticlesVolumicWeight, sellmeijerCalculator.GammaSubParticles);
Assert.AreEqual(input.Gravity, sellmeijerCalculator.Gravity);
}
}
}