/* 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 TestSatfuncConsistencyCheckManager #define BOOST_TEST_NO_MAIN #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 #include #include #include #include #include #include #include #include #include #if HAVE_MPI #include #include #endif // HAVE_MPI // ########################################################################### namespace { #if HAVE_MPI struct MPIError { MPIError(std::string_view errstr, const int ec) : errorstring { errstr } , errorcode { ec } {} std::string errorstring; int errorcode; }; void MPI_err_handler(MPI_Comm*, int* err_code, ...) { std::array err_string_vec{'\0'}; auto err_length = 0; MPI_Error_string(*err_code, err_string_vec.data(), &err_length); auto err_string = std::string_view { err_string_vec.data(), static_cast(err_length) }; std::cerr << "An MPI Error ocurred:\n -> " << err_string << '\n'; throw MPIError { err_string, *err_code }; } // Register a throwing error handler to allow for debugging with // // catch throw // // in GDB. void register_error_handler() { MPI_Errhandler handler{}; MPI_Comm_create_errhandler(MPI_err_handler, &handler); MPI_Comm_set_errhandler(MPI_COMM_WORLD, handler); } #else // !HAVE_MPI void register_error_handler() {} #endif // HAVE_MPI bool init_unit_test_func() { return true; } // ----------------------------------------------------------------------- template using CheckMgr = Opm::Satfunc::PhaseChecks::SatfuncConsistencyCheckManager; template using ViolationLevel = typename CheckMgr::ViolationLevel; constexpr auto root = 0; constexpr auto numSamplePoints = std::size_t{1}; const auto localToGlobal = [](const int) { return std::size_t{0}; }; Opm::Deck makeEpsDeck(std::string_view epsSpec) { return Opm::Parser{}.parseString(fmt::format(R"(RUNSPEC DIMENS 1 1 1 / OIL GAS WATER TABDIMS / ENDSCALE / -- ================================================================= GRID DXV 100 / DYV 100 / DZV 5 / DEPTHZ 4*2000 / PERMX 100 / PERMY 100 / PERMZ 10 / PORO 0.3 / -- ================================================================= PROPS SGOF 0.00 0.0 1.0 0.0 0.80 1* 0.0 0.0 0.85 1.0 0.0 0.0 / SWOF 0.15 0.0 1.0 0.0 0.80 0.8 0.0 0.0 1.0 1.0 0.0 0.0 / {} -- ================================================================= REGIONS SATNUM 1 / END )", epsSpec)); } std::pair setup(std::string_view epsSpec) { auto ret = std::pair { std::piecewise_construct, std::forward_as_tuple(), std::forward_as_tuple(makeEpsDeck(epsSpec)) }; auto& [cpgrid, es] = ret; cpgrid.processEclipseFormat(&es.getInputGrid(), &es, /* periodic_extension = */ false, /* turn_normals = */ false, /* clip_z = */ false, /* pinchActive = */ false); return ret; } } // Anonymous namespace // =========================================================================== BOOST_AUTO_TEST_SUITE(Water_Phase) BOOST_AUTO_TEST_CASE(SWL_Too_Low) { using Scalar = double; const auto& [grid, es] = setup(R"( SWL -0.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum water saturation 0 <= SWL < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SWL | +------------+---------------+ | (1, 1, 1) | -5.000000e-02 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SWL_Too_High) { using Scalar = double; const auto& [grid, es] = setup(R"( SWL 1.0 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum oil saturation in G/O system SWL + SGU <= 1 Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SGU | SWL + SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.000000e+00 | 8.500000e-01 | 1.850000e+00 | +------------+---------------+---------------+---------------+ Consistency Problem: Mobile oil saturation in G/O system at minimum gas saturation SOGCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOGCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.000000e+00 | 0.000000e+00 | 5.000000e-02 | 0.000000e+00 | +------------+---------------+---------------+---------------+---------------+ Consistency Problem: Mobile oil saturation in G/O system at critical gas saturation SOGCR < 1 - SWL - SGCR Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SWL | SGCR | SOGCR | 1 - SWL - SGCR | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 1.000000e+00 | 0.000000e+00 | 5.000000e-02 | 0.000000e+00 | +------------+---------------+---------------+---------------+----------------+ Consistency Problem: Mobile oil saturation in O/W system at minimum water saturation SOWCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOWCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.000000e+00 | 0.000000e+00 | 2.000000e-01 | 0.000000e+00 | +------------+---------------+---------------+---------------+---------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum water saturation 0 <= SWL < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SWL | +------------+---------------+ | (1, 1, 1) | 1.000000e+00 | +------------+---------------+ Consistency Problem: Mobile water saturation SWL <= SWCR < SWU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SWCR | SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.000000e+00 | 1.500000e-01 | 1.000000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SWU_Too_Low) { using Scalar = double; const auto& [grid, es] = setup(R"( SWU 0.0 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Positive maximum water saturation 0 < SWU <= 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SWU | +------------+---------------+ | (1, 1, 1) | 0.000000e+00 | +------------+---------------+ Consistency Problem: Mobile water saturation SWL <= SWCR < SWU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SWCR | SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 1.500000e-01 | 0.000000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SWU_Too_High) { using Scalar = double; const auto& [grid, es] = setup(R"( SWU 1.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum oil saturation in G/O system SGL + SWU <= 1 Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SWU | SGL + SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 0.000000e+00 | 1.050000e+00 | 1.050000e+00 | +------------+---------------+---------------+---------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Positive maximum water saturation 0 < SWU <= 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SWU | +------------+---------------+ | (1, 1, 1) | 1.050000e+00 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SWCR_Too_Low) { using Scalar = double; const auto& [grid, es] = setup(R"( SWCR -0.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile water saturation SWL <= SWCR < SWU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SWCR | SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | -5.000000e-02 | 1.000000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SWCR_Too_High) { using Scalar = double; const auto& [grid, es] = setup(R"( SWCR 1.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in O/W system at critical water saturation SOWCR < 1 - SWCR - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SGL | SWCR | SOWCR | 1 - SWCR - SGL | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 0.000000e+00 | 1.050000e+00 | 2.000000e-01 | -5.000000e-02 | +------------+---------------+---------------+---------------+----------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile water saturation SWL <= SWCR < SWU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SWCR | SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 1.050000e+00 | 1.000000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_SUITE_END() // Water_Phase // =========================================================================== BOOST_AUTO_TEST_SUITE(Gas_Phase) BOOST_AUTO_TEST_CASE(SGL_Too_Low) { using Scalar = float; const auto& [grid, es] = setup(R"( SGL -0.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum gas saturation 0 <= SGL < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SGL | +------------+---------------+ | (1, 1, 1) | -5.000000e-02 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SGL_Too_High) { using Scalar = float; const auto& [grid, es] = setup(R"( SGL 1.0 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in G/O system at minimum gas saturation SOGCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOGCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 1.000000e+00 | 5.000000e-02 | -1.500000e-01 | +------------+---------------+---------------+---------------+---------------+ Consistency Problem: Non-negative minimum oil saturation in G/O system SGL + SWU <= 1 Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SWU | SGL + SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.000000e+00 | 1.000000e+00 | 2.000000e+00 | +------------+---------------+---------------+---------------+ Consistency Problem: Mobile oil saturation in O/W system at minimum water saturation SOWCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOWCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 1.000000e+00 | 2.000000e-01 | -1.500000e-01 | +------------+---------------+---------------+---------------+---------------+ Consistency Problem: Mobile oil saturation in O/W system at critical water saturation SOWCR < 1 - SWCR - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SGL | SWCR | SOWCR | 1 - SWCR - SGL | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 1.000000e+00 | 1.500000e-01 | 2.000000e-01 | -1.500000e-01 | +------------+---------------+---------------+---------------+----------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum gas saturation 0 <= SGL < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SGL | +------------+---------------+ | (1, 1, 1) | 1.000000e+00 | +------------+---------------+ Consistency Problem: Mobile gas saturation SGL <= SGCR < SGU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SGCR | SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.000000e+00 | 0.000000e+00 | 8.500000e-01 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SGU_Too_Low) { using Scalar = float; const auto& [grid, es] = setup(R"( SGU 0.0 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Positive maximum gas saturation must not exceed one 0 < SGU <= 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SGU | +------------+---------------+ | (1, 1, 1) | 0.000000e+00 | +------------+---------------+ Consistency Problem: Mobile gas saturation SGL <= SGCR < SGU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SGCR | SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SGU_Too_High) { using Scalar = float; const auto& [grid, es] = setup(R"( SGU 1.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum oil saturation in G/O system SWL + SGU <= 1 Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SGU | SWL + SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 1.050000e+00 | 1.200000e+00 | +------------+---------------+---------------+---------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Positive maximum gas saturation must not exceed one 0 < SGU <= 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SGU | +------------+---------------+ | (1, 1, 1) | 1.050000e+00 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SGCR_Too_Low) { using Scalar = float; const auto& [grid, es] = setup(R"( SGCR -0.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile gas saturation SGL <= SGCR < SGU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SGCR | SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 0.000000e+00 | -5.000000e-02 | 8.500000e-01 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SGCR_Too_High) { using Scalar = float; const auto& [grid, es] = setup(R"( SGCR 1.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in G/O system at critical gas saturation SOGCR < 1 - SWL - SGCR Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SWL | SGCR | SOGCR | 1 - SWL - SGCR | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 1.500000e-01 | 1.050000e+00 | 5.000000e-02 | -1.999999e-01 | +------------+---------------+---------------+---------------+----------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile gas saturation SGL <= SGCR < SGU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SGCR | SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 0.000000e+00 | 1.050000e+00 | 8.500000e-01 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_SUITE_END() // Gas_Phase // =========================================================================== BOOST_AUTO_TEST_SUITE(Oil_Phase) BOOST_AUTO_TEST_CASE(So_At_SGMax_Too_Low) { using Scalar = double; const auto& [grid, es] = setup(R"( SGU 0.9 / SWL 0.15 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedCriticalChecks(), "There must not be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum oil saturation in G/O system SWL + SGU <= 1 Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SGU | SWL + SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 9.000000e-01 | 1.050000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(So_At_SWMax_Too_Low) { using Scalar = double; const auto& [grid, es] = setup(R"( SWU 0.9 / SGL 0.15 / SGCR 0.15 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedCriticalChecks(), "There must not be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative minimum oil saturation in G/O system SGL + SWU <= 1 Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SWU | SGL + SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 9.000000e-01 | 1.050000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SOWCR_Too_Low) { using Scalar = double; const auto& [grid, es] = setup(R"( SOWCR -0.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative critical oil saturation in O/W system 0 <= SOWCR < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SOWCR | +------------+---------------+ | (1, 1, 1) | -5.000000e-02 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SOWCR_Too_High) { using Scalar = double; const auto& [grid, es] = setup(R"( SOWCR 1.0 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in O/W system at minimum water saturation SOWCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOWCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 0.000000e+00 | 1.000000e+00 | 8.500000e-01 | +------------+---------------+---------------+---------------+---------------+ Consistency Problem: Mobile oil saturation in O/W system at critical water saturation SOWCR < 1 - SWCR - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SGL | SWCR | SOWCR | 1 - SWCR - SGL | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 0.000000e+00 | 1.500000e-01 | 1.000000e+00 | 8.500000e-01 | +------------+---------------+---------------+---------------+----------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative critical oil saturation in O/W system 0 <= SOWCR < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SOWCR | +------------+---------------+ | (1, 1, 1) | 1.000000e+00 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SOGCR_Too_Low) { using Scalar = double; const auto& [grid, es] = setup(R"( SOGCR -0.05 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative critical oil saturation in G/O system 0 <= SOGCR < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SOGCR | +------------+---------------+ | (1, 1, 1) | -5.000000e-02 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(SOGCR_Too_High) { using Scalar = double; const auto& [grid, es] = setup(R"( SOGCR 1.0 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in G/O system at minimum gas saturation SOGCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOGCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 0.000000e+00 | 1.000000e+00 | 8.500000e-01 | +------------+---------------+---------------+---------------+---------------+ Consistency Problem: Mobile oil saturation in G/O system at critical gas saturation SOGCR < 1 - SWL - SGCR Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SWL | SGCR | SOGCR | 1 - SWL - SGCR | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 1.500000e-01 | 0.000000e+00 | 1.000000e+00 | 8.500000e-01 | +------------+---------------+---------------+---------------+----------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Non-negative critical oil saturation in G/O system 0 <= SOGCR < 1 Total Violations: 1 List of Violations +------------+---------------+ | Grid Block | SOGCR | +------------+---------------+ | (1, 1, 1) | 1.000000e+00 | +------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(Mobile_Oil_OW_System) { using Scalar = double; const auto& [grid, es] = setup(R"( SWCR 0.42 / SOWCR 0.63 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedCriticalChecks(), "There must not be any failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in O/W system at critical water saturation SOWCR < 1 - SWCR - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SGL | SWCR | SOWCR | 1 - SWCR - SGL | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 0.000000e+00 | 4.200000e-01 | 6.300000e-01 | 5.800000e-01 | +------------+---------------+---------------+---------------+----------------+ )"); } BOOST_AUTO_TEST_CASE(Mobile_Oil_OW_System_At_SWL) { using Scalar = double; const auto& [grid, es] = setup(R"( SWL 0.42 / SGU 0.57 / SOWCR 0.63 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in O/W system at minimum water saturation SOWCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOWCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 4.200000e-01 | 0.000000e+00 | 6.300000e-01 | 5.800000e-01 | +------------+---------------+---------------+---------------+---------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile water saturation SWL <= SWCR < SWU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SWL | SWCR | SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 4.200000e-01 | 1.500000e-01 | 1.000000e+00 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(Mobile_Oil_GO_System) { using Scalar = double; const auto& [grid, es] = setup(R"( SGCR 0.27 / SOGCR 0.63 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedCriticalChecks(), "There must not be any failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in G/O system at critical gas saturation SOGCR < 1 - SWL - SGCR Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+----------------+ | Grid Block | SWL | SGCR | SOGCR | 1 - SWL - SGCR | +------------+---------------+---------------+---------------+----------------+ | (1, 1, 1) | 1.500000e-01 | 2.700000e-01 | 6.300000e-01 | 5.800000e-01 | +------------+---------------+---------------+---------------+----------------+ )"); } BOOST_AUTO_TEST_CASE(Mobile_Oil_GO_System_At_SGL) { using Scalar = double; const auto& [grid, es] = setup(R"( SGL 0.27 / SOGCR 0.63 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(checkMgr.anyFailedStandardChecks(), "There must be failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Standard, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile oil saturation in G/O system at minimum gas saturation SOGCR < 1 - SWL - SGL Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SGL | SOGCR | 1 - SWL - SGL | +------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 2.700000e-01 | 6.300000e-01 | 5.800000e-01 | +------------+---------------+---------------+---------------+---------------+ Consistency Problem: Non-negative minimum oil saturation in G/O system SGL + SWU <= 1 Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SWU | SGL + SWU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 2.700000e-01 | 1.000000e+00 | 1.270000e+00 | +------------+---------------+---------------+---------------+ )"); msg.clear(); checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile gas saturation SGL <= SGCR < SGU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+ | Grid Block | SGL | SGCR | SGU | +------------+---------------+---------------+---------------+ | (1, 1, 1) | 2.700000e-01 | 0.000000e+00 | 8.500000e-01 | +------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(Displacing_Oil_OW_System) { using Scalar = double; const auto& [grid, es] = setup(R"( SCALECRS 'YES' / SWCR 0.4 / SWU 0.6 / SGL 0.15 / SGCR 0.15 / SOWCR 0.2 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile displacing oil in three point horizontally scaled oil/water system SWCR < 1-SOWCR-SGL < SWU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+---------------+ | Grid Block | SGL | SOWCR | SWCR | 1-SOWCR-SGL | SWU | +------------+---------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.500000e-01 | 2.000000e-01 | 4.000000e-01 | 6.500000e-01 | 6.000000e-01 | +------------+---------------+---------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_CASE(Displacing_Oil_GO_System) { using Scalar = double; const auto& [grid, es] = setup(R"( SCALECRS 'YES' / SWL 0.1 / SWCR 0.2 / SGCR 0.2 / SGU 0.6 / SOGCR 0.2 / )"); auto checkMgr = CheckMgr(numSamplePoints, es, localToGlobal); checkMgr.collectFailuresTo(root) .run(grid.leafGridView(), [](const auto&) { return 0; }); BOOST_CHECK_MESSAGE(! checkMgr.anyFailedStandardChecks(), "There must not be any failed checks at the standard level"); BOOST_CHECK_MESSAGE(checkMgr.anyFailedCriticalChecks(), "There must be failed checks at the critical level"); auto msg = std::string{}; checkMgr.reportFailures(ViolationLevel::Critical, [&msg](std::string_view record) { msg += fmt::format("{}\n", record); }); BOOST_CHECK_EQUAL(msg, R"(Consistency Problem: Mobile displacing oil in three point horizontally scaled gas/oil system SGCR < 1-SOGCR-SWL < SGU Total Violations: 1 List of Violations +------------+---------------+---------------+---------------+---------------+---------------+ | Grid Block | SWL | SOGCR | SGCR | 1-SOGCR-SWL | SGU | +------------+---------------+---------------+---------------+---------------+---------------+ | (1, 1, 1) | 1.000000e-01 | 2.000000e-01 | 2.000000e-01 | 7.000000e-01 | 6.000000e-01 | +------------+---------------+---------------+---------------+---------------+---------------+ )"); } BOOST_AUTO_TEST_SUITE_END() // Oil_Phase // =========================================================================== int main(int argc, char** argv) { Dune::MPIHelper::instance(argc, argv); register_error_handler(); return boost::unit_test::unit_test_main(&init_unit_test_func, argc, argv); }