diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index b7188467f..90d7afc94 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -203,6 +203,7 @@ if (HAVE_ECL_INPUT)
opm/simulators/utils/satfunc/OilPhaseConsistencyChecks.cpp
opm/simulators/utils/satfunc/PhaseCheckBase.cpp
opm/simulators/utils/satfunc/SatfuncConsistencyChecks.cpp
+ opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.cpp
opm/simulators/utils/satfunc/WaterPhaseConsistencyChecks.cpp
)
endif()
@@ -391,6 +392,7 @@ if (HAVE_ECL_INPUT)
tests/test_OilSatfuncConsistencyChecks.cpp
tests/test_SatfuncConsistencyChecks.cpp
tests/test_SatfuncConsistencyChecks_parallel.cpp
+ tests/test_ThreePointHorizontalSatfuncConsistencyChecks.cpp
tests/test_WaterSatfuncConsistencyChecks.cpp
)
endif()
@@ -999,6 +1001,7 @@ if (HAVE_ECL_INPUT)
opm/simulators/utils/satfunc/OilPhaseConsistencyChecks.hpp
opm/simulators/utils/satfunc/PhaseCheckBase.hpp
opm/simulators/utils/satfunc/SatfuncConsistencyChecks.hpp
+ opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.hpp
opm/simulators/utils/satfunc/WaterPhaseConsistencyChecks.hpp
)
endif()
diff --git a/opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.cpp b/opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.cpp
new file mode 100644
index 000000000..d86704c35
--- /dev/null
+++ b/opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.cpp
@@ -0,0 +1,110 @@
+/*
+ Copyright 2024 Equinor AS
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM 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.
+
+ OPM 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 OPM. If not, see .
+*/
+
+#include
+
+#include
+
+#include
+
+#include
+
+// ---------------------------------------------------------------------------
+
+template
+void Opm::Satfunc::PhaseChecks::ThreePointHorizontal::DisplacingOil_GO::
+testImpl(const EclEpsScalingPointsInfo& endPoints)
+{
+ // SGCR < 1-SOGCR-SWL < SGU
+
+ this->swl_ = endPoints.Swl;
+ this->sogcr_ = endPoints.Sogcr;
+ this->sgcr_ = endPoints.Sgcr;
+ this->sgu_ = endPoints.Sgu;
+
+ if (! std::isfinite(this->swl_) ||
+ ! std::isfinite(this->sogcr_) ||
+ ! std::isfinite(this->sgcr_) ||
+ ! std::isfinite(this->sgu_))
+ {
+ this->setViolated();
+ this->setCritical();
+
+ return;
+ }
+
+ const auto sr = Scalar{1} - (this->sogcr_ + this->swl_);
+
+ const auto low = ! (this->swl_ < sr);
+ const auto high = ! (sr < this->sgu_);
+
+ if (low || high) {
+ this->setViolated();
+ this->setCritical();
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+template
+void Opm::Satfunc::PhaseChecks::ThreePointHorizontal::DisplacingOil_OW::
+testImpl(const EclEpsScalingPointsInfo& endPoints)
+{
+ // SWCR < 1-SOWCR-SGL < SWU
+
+ this->sgl_ = endPoints.Sgl;
+ this->sowcr_ = endPoints.Sowcr;
+ this->swcr_ = endPoints.Swcr;
+ this->swu_ = endPoints.Swu;
+
+ if (! std::isfinite(this->sgl_) ||
+ ! std::isfinite(this->sowcr_) ||
+ ! std::isfinite(this->swcr_) ||
+ ! std::isfinite(this->swu_))
+ {
+ this->setViolated();
+ this->setCritical();
+
+ return;
+ }
+
+ const auto sr = Scalar{1} - (this->sowcr_ + this->sgl_);
+
+ const auto low = ! (this->sgl_ < sr);
+ const auto high = ! (sr < this->swu_);
+
+ if (low || high) {
+ this->setViolated();
+ this->setCritical();
+ }
+}
+
+// ===========================================================================
+// Explicit Specialisations of Individual Check Templates
+//
+// No other code below this separator
+// ===========================================================================
+
+template class Opm::Satfunc::PhaseChecks::ThreePointHorizontal::DisplacingOil_GO;
+template class Opm::Satfunc::PhaseChecks::ThreePointHorizontal::DisplacingOil_GO;
+
+// ---------------------------------------------------------------------------
+
+template class Opm::Satfunc::PhaseChecks::ThreePointHorizontal::DisplacingOil_OW;
+template class Opm::Satfunc::PhaseChecks::ThreePointHorizontal::DisplacingOil_OW;
diff --git a/opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.hpp b/opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.hpp
new file mode 100644
index 000000000..1261bb6b8
--- /dev/null
+++ b/opm/simulators/utils/satfunc/ThreePointHorizontalConsistencyChecks.hpp
@@ -0,0 +1,183 @@
+/*
+ Copyright 2024 Equinor AS
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM 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.
+
+ OPM 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 OPM. If not, see .
+*/
+
+#ifndef THREE_POINT_HORIZONTAL_CONSISTENCY_CHECKS_HPP_INCLUDED
+#define THREE_POINT_HORIZONTAL_CONSISTENCY_CHECKS_HPP_INCLUDED
+
+#include
+#include
+
+#include
+#include
+
+namespace Opm::Satfunc::PhaseChecks::ThreePointHorizontal {
+
+ /// Verify that critical saturation of displacing phase (oil/liquid) is
+ /// strictly between critical and maximum gas saturations for the
+ /// alternative (three point) horizontal scaling method (SCALECRS=YES)
+ /// in the gas/oil two-phase system.
+ ///
+ /// \tparam Scalar Element type. Typically \c float or \c double.
+ template
+ class DisplacingOil_GO : public PhaseCheckBase
+ {
+ public:
+ /// Number of \c Scalar values involved in the check.
+ std::size_t numExportedCheckValues() const override { return 5; };
+
+ /// Get a linearised copy of the \c Scalar values involved in the check.
+ ///
+ /// \param[in,out] exportedCheckValues Pointer to contiguous
+ /// sequence of at least numExportedCheckValues() \c Scalars.
+ void exportCheckValues(Scalar* exportedCheckValues) const override
+ {
+ exportedCheckValues[0] = this->swl_;
+ exportedCheckValues[1] = this->sogcr_;
+ exportedCheckValues[2] = this->sgcr_;
+ exportedCheckValues[3] = Scalar{1} - (this->sogcr_ + this->swl_);
+ exportedCheckValues[4] = this->sgu_;
+ }
+
+ /// Descriptive textual summary of this check.
+ std::string description() const override
+ {
+ return { "Mobile displacing oil in three point "
+ "horizontally scaled gas/oil system" };
+ }
+
+ /// Textual representation of the consistency condition.
+ std::string condition() const override
+ {
+ return { "SGCR < 1-SOGCR-SWL < SGU" };
+ }
+
+ /// Retrieve names of the exported check values.
+ ///
+ /// \param[in,out] headers Pointer to contiguous sequence of at
+ /// least numExportedCheckValues() strings.
+ void columnNames(std::string* headers) const override
+ {
+ headers[0] = "SWL";
+ headers[1] = "SOGCR";
+ headers[2] = "SGCR";
+ headers[3] = "1-SOGCR-SWL";
+ headers[4] = "SGU";
+ }
+
+ private:
+ /// Minimum (connate) water saturation.
+ Scalar swl_;
+
+ /// Critical oil saturation in two-phase gas/oil system.
+ Scalar sogcr_;
+
+ /// Critical gas saturation.
+ Scalar sgcr_;
+
+ /// Maximum gas saturation.
+ Scalar sgu_;
+
+ /// Run check against a set of saturation function end-points.
+ ///
+ /// \param[in] endPoints Set of saturation function end-points.
+ /// Might for instance be the scaled end-points of the drainage
+ /// functions in a single grid block or the unscaled end-points
+ /// of the tabulated saturation functions in a single saturation
+ /// region.
+ void testImpl(const EclEpsScalingPointsInfo& endPoints) override;
+ };
+
+ /// Verify that critical saturation of displacing phase (oil) is
+ /// strictly between critical and maximum water saturations for the
+ /// alternative (three point) horizontal scaling method (SCALECRS=YES)
+ /// in the oil/water two-phase system.
+ ///
+ /// \tparam Scalar Element type. Typically \c float or \c double.
+ template
+ class DisplacingOil_OW : public PhaseCheckBase
+ {
+ public:
+ /// Number of \c Scalar values involved in the check.
+ std::size_t numExportedCheckValues() const override { return 5; };
+
+ /// Get a linearised copy of the \c Scalar values involved in the check.
+ ///
+ /// \param[in,out] exportedCheckValues Pointer to contiguous
+ /// sequence of at least numExportedCheckValues() \c Scalars.
+ void exportCheckValues(Scalar* exportedCheckValues) const override
+ {
+ exportedCheckValues[0] = this->sgl_;
+ exportedCheckValues[1] = this->sowcr_;
+ exportedCheckValues[2] = this->swcr_;
+ exportedCheckValues[3] = Scalar{1} - (this->sowcr_ + this->sgl_);
+ exportedCheckValues[4] = this->swu_;
+ }
+
+ /// Descriptive textual summary of this check.
+ std::string description() const override
+ {
+ return { "Mobile displacing oil in three point "
+ "horizontally scaled oil/water system" };
+ }
+
+ /// Textual representation of the consistency condition.
+ std::string condition() const override
+ {
+ return { "SWCR < 1-SOWCR-SGL < SWU" };
+ }
+
+ /// Retrieve names of the exported check values.
+ ///
+ /// \param[in,out] headers Pointer to contiguous sequence of at
+ /// least numExportedCheckValues() strings.
+ void columnNames(std::string* headers) const override
+ {
+ headers[0] = "SGL";
+ headers[1] = "SOWCR";
+ headers[2] = "SWCR";
+ headers[3] = "1-SOWCR-SGL";
+ headers[4] = "SWU";
+ }
+
+ private:
+ /// Minimum gas saturation.
+ Scalar sgl_;
+
+ /// Critical oil saturation in two-phase oil/water system.
+ Scalar sowcr_;
+
+ /// Critical water saturation.
+ Scalar swcr_;
+
+ /// Maximum water saturation.
+ Scalar swu_;
+
+ /// Run check against a set of saturation function end-points.
+ ///
+ /// \param[in] endPoints Set of saturation function end-points.
+ /// Might for instance be the scaled end-points of the drainage
+ /// functions in a single grid block or the unscaled end-points
+ /// of the tabulated saturation functions in a single saturation
+ /// region.
+ void testImpl(const EclEpsScalingPointsInfo& endPoints) override;
+ };
+
+} // namespace Opm::Satfunc::PhaseChecks::ThreePointHorizontal
+
+#endif // THREE_POINT_HORIZONTAL_CONSISTENCY_CHECKS_HPP_INCLUDED
diff --git a/tests/test_ThreePointHorizontalSatfuncConsistencyChecks.cpp b/tests/test_ThreePointHorizontalSatfuncConsistencyChecks.cpp
new file mode 100644
index 000000000..10c3ccaba
--- /dev/null
+++ b/tests/test_ThreePointHorizontalSatfuncConsistencyChecks.cpp
@@ -0,0 +1,1687 @@
+/*
+ Copyright 2024 Equinor AS
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM 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.
+
+ OPM 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 OPM. If not, see .
+*/
+
+#include
+
+#define BOOST_TEST_MODULE TestThreePointHorizontalConsistencyChecks
+
+#ifndef HAVE_MPI
+// Suppress GCC diagnostics of the form
+//
+// warning: "HAVE_MPI" is not defined, evaluates to 0
+//
+// when compiling with "-Wundef".
+#define HAVE_MPI 0
+#endif // HAVE_MPI
+
+#include
+
+#include
+
+#include
+
+#include
+#include
+#include
+
+// ###########################################################################
+
+namespace Checks = Opm::Satfunc::PhaseChecks::ThreePointHorizontal;
+
+// ===========================================================================
+
+BOOST_AUTO_TEST_SUITE(Displacing_Oil_in_Gas_Oil)
+
+BOOST_AUTO_TEST_CASE(All_Good)
+{
+ auto check = Checks::DisplacingOil_GO{};
+
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ BOOST_CHECK_EQUAL(check.numExportedCheckValues(), expectNumExportedCheckValues);
+
+ {
+ auto columns = std::vector(expectNumExportedCheckValues);
+ check.columnNames(columns.data());
+
+ BOOST_CHECK_EQUAL(columns[0], "SWL");
+ BOOST_CHECK_EQUAL(columns[1], "SOGCR");
+ BOOST_CHECK_EQUAL(columns[2], "SGCR");
+ BOOST_CHECK_EQUAL(columns[3], "1-SOGCR-SWL");
+ BOOST_CHECK_EQUAL(columns[4], "SGU");
+ }
+
+ {
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+ }
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+ }
+
+ BOOST_CHECK_MESSAGE(! check.isViolated(), "Test must not be violated");
+ BOOST_CHECK_MESSAGE(! check.isCritical(), "Test must not be violated at critical level");
+}
+
+BOOST_AUTO_TEST_CASE(Non_Finite)
+{
+ // NaN
+ if constexpr (std::numeric_limits::has_quiet_NaN) {
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = 0.7;
+
+ auto check = Checks::DisplacingOil_GO{};
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sgcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sogcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sgcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sogcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sgcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sogcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sgcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sogcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = 0.7f;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sogcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sgcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sogcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sgcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sogcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sgcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::quiet_NaN();
+ endPoints.Sgcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sogcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sgu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sogcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sgcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sogcr-Swl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Sgu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+ }
+
+ // Inf
+ if constexpr (std::numeric_limits::has_infinity) {
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = 0.7;
+
+ auto check = Checks::DisplacingOil_GO{};
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sgcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sogcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sgcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sogcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sgcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sogcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sgcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sogcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = 0.7f;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sogcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sgcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sogcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = 0.3f;
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sgcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = 0.25f;
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sogcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sgcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Swl = std::numeric_limits::infinity();
+ endPoints.Sgcr = std::numeric_limits::infinity();
+ endPoints.Sogcr = std::numeric_limits::infinity();
+ endPoints.Sgu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sogcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sgcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sogcr-Swl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Sgu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Sr_TooSmall)
+{
+ auto check = Checks::DisplacingOil_GO{};
+
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ {
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Swl = 0.55f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.35f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+ }
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.55f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.35f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.1f, 3.0e-5f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+ }
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Test must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Test must be violated at critical level");
+}
+
+BOOST_AUTO_TEST_CASE(Sr_Is_Lower_Bound)
+{
+ auto check = Checks::DisplacingOil_GO{};
+
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ {
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Swl = 0.50f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.35f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+ }
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.50f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.35f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.15f, 2.0e-5f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+ }
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Test must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Test must be violated at critical level");
+}
+
+BOOST_AUTO_TEST_CASE(Sr_TooLarge)
+{
+ auto check = Checks::DisplacingOil_GO{};
+
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ {
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Swl = 0.0f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.25f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+ }
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.0f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.75f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+ }
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Test must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Test must be violated at critical level");
+}
+
+BOOST_AUTO_TEST_CASE(Sr_Is_Upper_Bound)
+{
+ auto check = Checks::DisplacingOil_GO{};
+
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ {
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Swl = 0.05f;
+ endPoints.Sgcr = 0.15f;
+ endPoints.Sogcr = 0.25f;
+ endPoints.Sgu = 0.7;
+
+ check.test(endPoints);
+ }
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.05f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.7f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+ }
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Test must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Test must be violated at critical level");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Displacing_Oil_in_Gas_Oil
+
+// ===========================================================================
+
+BOOST_AUTO_TEST_SUITE(Displacing_Oil_in_Oil_Water)
+
+BOOST_AUTO_TEST_CASE(All_Good)
+{
+ auto check = Checks::DisplacingOil_OW{};
+
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ BOOST_CHECK_EQUAL(check.numExportedCheckValues(), expectNumExportedCheckValues);
+
+ {
+ auto columns = std::vector(expectNumExportedCheckValues);
+ check.columnNames(columns.data());
+
+ BOOST_CHECK_EQUAL(columns[0], "SGL");
+ BOOST_CHECK_EQUAL(columns[1], "SOWCR");
+ BOOST_CHECK_EQUAL(columns[2], "SWCR");
+ BOOST_CHECK_EQUAL(columns[3], "1-SOWCR-SGL");
+ BOOST_CHECK_EQUAL(columns[4], "SWU");
+ }
+
+ {
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+ }
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+ }
+
+ BOOST_CHECK_MESSAGE(! check.isViolated(), "Test must not be violated");
+ BOOST_CHECK_MESSAGE(! check.isCritical(), "Test must not be violated at critical level");
+}
+
+BOOST_AUTO_TEST_CASE(Non_Finite)
+{
+ // NaN
+ if constexpr (std::numeric_limits::has_quiet_NaN) {
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = 0.7;
+
+ auto check = Checks::DisplacingOil_OW{};
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Swcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sowcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Swcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sowcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Swcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Sowcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Swcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sowcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = 0.7f;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sowcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Swcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sowcr value must be NaN");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Swcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sowcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Swcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::quiet_NaN();
+ endPoints.Swcr = std::numeric_limits::quiet_NaN();
+ endPoints.Sowcr = std::numeric_limits::quiet_NaN();
+ endPoints.Swu = std::numeric_limits::quiet_NaN();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isnan(values[0]), "Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[1]), "Sowcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[2]), "Swcr value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[3]), "1-Sowcr-Sgl value must be NaN");
+ BOOST_CHECK_MESSAGE(std::isnan(values[4]), "Swu value must be NaN");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+ }
+
+ // Inf
+ if constexpr (std::numeric_limits::has_infinity) {
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = 0.7;
+
+ auto check = Checks::DisplacingOil_OW{};
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Swcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sowcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Swcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sowcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Swcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Sowcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Swcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[3], 0.45f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sowcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = 0.7f;
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sowcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Swcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sowcr value must be Inf");
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = 0.3f;
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_CLOSE(values[1], 0.3f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Swcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = 0.25f;
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.25f, 1.0e-6f);
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sowcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Swcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+
+ endPoints.Sgl = std::numeric_limits::infinity();
+ endPoints.Swcr = std::numeric_limits::infinity();
+ endPoints.Sowcr = std::numeric_limits::infinity();
+ endPoints.Swu = std::numeric_limits::infinity();
+
+ check.test(endPoints);
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_MESSAGE(std::isinf(values[0]), "Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[1]), "Sowcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[2]), "Swcr value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[3]), "1-Sowcr-Sgl value must be Inf");
+ BOOST_CHECK_MESSAGE(std::isinf(values[4]), "Swu value must be Inf");
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Check must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Check must be violated at critical level");
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Sr_TooSmall)
+{
+ auto check = Checks::DisplacingOil_OW{};
+
+ constexpr auto expectNumExportedCheckValues = std::size_t{5};
+
+ {
+ auto endPoints = Opm::EclEpsScalingPointsInfo{};
+ endPoints.Sgl = 0.55f;
+ endPoints.Swcr = 0.15f;
+ endPoints.Sowcr = 0.35f;
+ endPoints.Swu = 0.7;
+
+ check.test(endPoints);
+ }
+
+ {
+ auto values = std::vector(expectNumExportedCheckValues);
+ check.exportCheckValues(values.data());
+
+ BOOST_CHECK_CLOSE(values[0], 0.55f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[1], 0.35f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[2], 0.15f, 1.0e-6f);
+ BOOST_CHECK_CLOSE(values[3], 0.1f, 3.0e-5f);
+ BOOST_CHECK_CLOSE(values[4], 0.7f, 1.0e-6f);
+ }
+
+ BOOST_CHECK_MESSAGE(check.isViolated(), "Test must be violated");
+ BOOST_CHECK_MESSAGE(check.isCritical(), "Test must be violated at critical level");
+}
+
+BOOST_AUTO_TEST_CASE(Sr_Is_Lower_Bound)
+{
+ auto check = Checks::DisplacingOil_OW