mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-01 13:29:08 -06:00
0c71d0701c
This commit adds a new public member function SatfuncConsistencyChecks<>::collectFailures(root, comm) which aggregates consistency check violations from all ranks in the MPI communication object 'comm' onto rank 'root' of 'comm'. This amounts to summing the total number of violations from all ranks and potentially resampling the failure points for reporting purposes. To this end, extract the body of function processViolation() into a general helper which performs reservoir sampling and records point IDs and which uses a call-back function to populate the check values associated to a single failed check. Re-implement the original function in terms of this helper by wrapping exportCheckValues() in a lambda function. Extract similar helpers for numPoints() and anyFailedChecks(), and add a new helper function SatfuncConsistencyChecks<>::incorporateRankViolations() which brings sampled points from an MPI rank into the 'root's internal data structures. One caveat applies here. Our current approach to collecting check failures implies that calling member function reportFailures() is safe only on the 'root' process in a parallel run. On the other hand functions anyFailedChecks() and anyFailedCriticalChecks() are safe, and guaranteed to return the same answer, on all MPI ranks. On a final note, the internal helper functions are at present mostly implemented in terms of non-owning pointers. I intend to switch to using 'std::span<>' once we enable C++20 mode.
815 lines
26 KiB
C++
815 lines
26 KiB
C++
/*
|
|
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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#define BOOST_TEST_MODULE TestSatfuncConsistencyChecks
|
|
|
|
#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 <boost/test/unit_test.hpp>
|
|
|
|
#include <opm/simulators/utils/satfunc/SatfuncConsistencyChecks.hpp>
|
|
|
|
#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
|
|
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include <fmt/format.h>
|
|
|
|
BOOST_AUTO_TEST_SUITE(NoFailures)
|
|
|
|
namespace {
|
|
class Standard : public Opm::SatfuncConsistencyChecks<double>::Check
|
|
{
|
|
public:
|
|
void test(const Opm::EclEpsScalingPointsInfo<double>&) override {}
|
|
bool isViolated() const override { return false; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 1; }
|
|
|
|
void exportCheckValues(double* exportedCheckValues) const override
|
|
{
|
|
*exportedCheckValues = 17.29;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Water Phase End-Point";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "0 <= SWL < 1";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
*headers = "SWL";
|
|
}
|
|
};
|
|
|
|
Opm::EclEpsScalingPointsInfo<double> makePoints() { return {}; }
|
|
} // Anonymous namespace
|
|
|
|
BOOST_AUTO_TEST_CASE(All_Good)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<double>{"Cell", 1};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<Standard>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.checkEndpoints(1234, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(! checker.anyFailedChecks(),
|
|
"There must be no failed checks");
|
|
|
|
BOOST_CHECK_MESSAGE(! checker.anyFailedCriticalChecks(),
|
|
"There must be no failed critical checks");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<double>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
BOOST_CHECK_MESSAGE(rpt.empty(), "There must be no output from reportFailures()");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|
|
|
|
// ===========================================================================
|
|
|
|
BOOST_AUTO_TEST_SUITE(Single_Exported_Value)
|
|
|
|
namespace {
|
|
class StandardViolation : public Opm::SatfuncConsistencyChecks<double>::Check
|
|
{
|
|
public:
|
|
void test(const Opm::EclEpsScalingPointsInfo<double>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 1; }
|
|
|
|
void exportCheckValues(double* exportedCheckValues) const override
|
|
{
|
|
*exportedCheckValues = 17.29;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Water Phase End-Point";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "0 <= SWL < 1";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
*headers = "SWL";
|
|
}
|
|
};
|
|
|
|
class CriticalViolation : public Opm::SatfuncConsistencyChecks<double>::Check
|
|
{
|
|
public:
|
|
void test(const Opm::EclEpsScalingPointsInfo<double>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return true; }
|
|
std::size_t numExportedCheckValues() const override { return 1; }
|
|
|
|
void exportCheckValues(double* exportedCheckValues) const override
|
|
{
|
|
*exportedCheckValues = 314.15926;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Minimum Pressure";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "PRESS > 350";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
*headers = "PRESS";
|
|
}
|
|
};
|
|
|
|
Opm::EclEpsScalingPointsInfo<double> makePoints() { return {}; }
|
|
} // Anonymous namespace
|
|
|
|
BOOST_AUTO_TEST_CASE(Standard_Violation)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<double>{"Cell", 1};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<StandardViolation>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.checkEndpoints(1234, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedChecks(),
|
|
"There must be at least one failed check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<double>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Water Phase End-Point
|
|
0 <= SWL < 1
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+------+---------------+
|
|
| Cell | SWL |
|
|
+------+---------------+
|
|
| 1234 | 1.729000e+01 |
|
|
+------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Standard_Violation_ReportIJK)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<double>{"Cell", 1};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<StandardViolation>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.setPointIDFormatCallback([](const std::size_t)
|
|
{
|
|
return std::string { "(11, 22, 33)" };
|
|
});
|
|
|
|
checker.checkEndpoints(1234, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedChecks(),
|
|
"There must be at least one failed check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<double>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Water Phase End-Point
|
|
0 <= SWL < 1
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+--------------+---------------+
|
|
| Cell | SWL |
|
|
+--------------+---------------+
|
|
| (11, 22, 33) | 1.729000e+01 |
|
|
+--------------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Critical_Violation)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<double>{"PVTNUM", 1};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<CriticalViolation>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.checkEndpoints(42, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(! checker.anyFailedChecks(),
|
|
"There must be no failed standard level checks");
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedCriticalChecks(),
|
|
"There must be at least one failed Critical check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<double>::ViolationLevel::Critical,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Minimum Pressure
|
|
PRESS > 350
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+--------+---------------+
|
|
| PVTNUM | PRESS |
|
|
+--------+---------------+
|
|
| 42 | 3.141593e+02 |
|
|
+--------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END() // Single_Exported_Value
|
|
|
|
// ===========================================================================
|
|
|
|
BOOST_AUTO_TEST_SUITE(Two_Exported_Values)
|
|
|
|
namespace {
|
|
class Violation : public Opm::SatfuncConsistencyChecks<float>::Check
|
|
{
|
|
void test(const Opm::EclEpsScalingPointsInfo<float>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 2; }
|
|
|
|
void exportCheckValues(float* exportedCheckValues) const override
|
|
{
|
|
exportedCheckValues[0] = 1.6f;
|
|
exportedCheckValues[1] = 1.6f + 0.5f;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Sum";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "a + 1/2 < 2";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
headers[0] = "a";
|
|
headers[1] = "a + 1/2";
|
|
}
|
|
};
|
|
|
|
Opm::EclEpsScalingPointsInfo<float> makePoints() { return {}; }
|
|
} // Anonymous namespace
|
|
|
|
BOOST_AUTO_TEST_CASE(Standard)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<float>{"Bucket", 1};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<Violation>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.checkEndpoints(1234, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedChecks(),
|
|
"There must be at least one failed check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<float>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Sum
|
|
a + 1/2 < 2
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+--------+---------------+---------------+
|
|
| Bucket | a | a + 1/2 |
|
|
+--------+---------------+---------------+
|
|
| 1234 | 1.600000e+00 | 2.100000e+00 |
|
|
+--------+---------------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END() // Two_Exported_Values
|
|
|
|
// ===========================================================================
|
|
|
|
BOOST_AUTO_TEST_SUITE(Five_Exported_Values)
|
|
|
|
namespace {
|
|
class Violation : public Opm::SatfuncConsistencyChecks<float>::Check
|
|
{
|
|
void test(const Opm::EclEpsScalingPointsInfo<float>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 5; }
|
|
|
|
void exportCheckValues(float* exportedCheckValues) const override
|
|
{
|
|
exportedCheckValues[0] = 0.1f;
|
|
exportedCheckValues[1] = 0.7f;
|
|
exportedCheckValues[2] = 0.3f;
|
|
exportedCheckValues[3] = 0.2f;
|
|
exportedCheckValues[4] = 0.88f;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Water Phase End-Point Displacing Saturation";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "SWCR < 1-SOWCR-SGL < SWU";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
headers[0] = "SGL";
|
|
headers[1] = "SOWCR";
|
|
headers[2] = "SWCR";
|
|
headers[3] = "1-SOWCR-SGL";
|
|
headers[4] = "SWU";
|
|
}
|
|
};
|
|
|
|
Opm::EclEpsScalingPointsInfo<float> makePoints() { return {}; }
|
|
} // Anonymous namespace
|
|
|
|
BOOST_AUTO_TEST_CASE(Standard)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<float>{"Grid Block", 1};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<Violation>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.setPointIDFormatCallback([](const std::size_t)
|
|
{
|
|
return std::string { "(121, 323, 42)" };
|
|
});
|
|
|
|
checker.checkEndpoints(1234, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedChecks(),
|
|
"There must be at least one failed check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<float>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Water Phase End-Point Displacing Saturation
|
|
SWCR < 1-SOWCR-SGL < SWU
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+----------------+---------------+---------------+---------------+---------------+---------------+
|
|
| Grid Block | SGL | SOWCR | SWCR | 1-SOWCR-SGL | SWU |
|
|
+----------------+---------------+---------------+---------------+---------------+---------------+
|
|
| (121, 323, 42) | 1.000000e-01 | 7.000000e-01 | 3.000000e-01 | 2.000000e-01 | 8.800000e-01 |
|
|
+----------------+---------------+---------------+---------------+---------------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Standard_Multiple_Failing_Points)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<float>{"Grid Block", 5};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<Violation>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.checkEndpoints( 1234, makePoints());
|
|
checker.checkEndpoints( 1729, makePoints());
|
|
checker.checkEndpoints( 1618, makePoints());
|
|
checker.checkEndpoints(31415, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedChecks(),
|
|
"There must be at least one failed check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<float>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
// Note that grid blocks are reported in sorted order rather in the
|
|
// order of insertion.
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Water Phase End-Point Displacing Saturation
|
|
SWCR < 1-SOWCR-SGL < SWU
|
|
Total Violations: 4
|
|
|
|
List of Violations
|
|
+------------+---------------+---------------+---------------+---------------+---------------+
|
|
| Grid Block | SGL | SOWCR | SWCR | 1-SOWCR-SGL | SWU |
|
|
+------------+---------------+---------------+---------------+---------------+---------------+
|
|
| 1234 | 1.000000e-01 | 7.000000e-01 | 3.000000e-01 | 2.000000e-01 | 8.800000e-01 |
|
|
| 1618 | 1.000000e-01 | 7.000000e-01 | 3.000000e-01 | 2.000000e-01 | 8.800000e-01 |
|
|
| 1729 | 1.000000e-01 | 7.000000e-01 | 3.000000e-01 | 2.000000e-01 | 8.800000e-01 |
|
|
| 31415 | 1.000000e-01 | 7.000000e-01 | 3.000000e-01 | 2.000000e-01 | 8.800000e-01 |
|
|
+------------+---------------+---------------+---------------+---------------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END() // Five_Exported_Values
|
|
|
|
// ===========================================================================
|
|
|
|
BOOST_AUTO_TEST_SUITE(Multiple_Failing_Tests)
|
|
|
|
namespace {
|
|
class MonotoneWater : public Opm::SatfuncConsistencyChecks<float>::Check
|
|
{
|
|
void test(const Opm::EclEpsScalingPointsInfo<float>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 3; }
|
|
|
|
void exportCheckValues(float* exportedCheckValues) const override
|
|
{
|
|
exportedCheckValues[0] = 0.1f;
|
|
exportedCheckValues[1] = 0.3f;
|
|
exportedCheckValues[2] = 0.3f;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Water Phase End-Point Monotonicity";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "SWL <= SWCR < SWU";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
headers[0] = "SWL";
|
|
headers[1] = "SWCR";
|
|
headers[2] = "SWU";
|
|
}
|
|
};
|
|
|
|
class MonotoneGas : public Opm::SatfuncConsistencyChecks<float>::Check
|
|
{
|
|
void test(const Opm::EclEpsScalingPointsInfo<float>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 3; }
|
|
|
|
void exportCheckValues(float* exportedCheckValues) const override
|
|
{
|
|
exportedCheckValues[0] = 0.0f;
|
|
exportedCheckValues[1] = -0.1f;
|
|
exportedCheckValues[2] = 0.8f;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Gas Phase End-Point Monotonicity";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "SGL <= SGCR < SGU";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
headers[0] = "SGL";
|
|
headers[1] = "SGCR";
|
|
headers[2] = "SGU";
|
|
}
|
|
};
|
|
|
|
class NonNegOSAT_OW : public Opm::SatfuncConsistencyChecks<float>::Check
|
|
{
|
|
void test(const Opm::EclEpsScalingPointsInfo<float>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 3; }
|
|
|
|
void exportCheckValues(float* exportedCheckValues) const override
|
|
{
|
|
exportedCheckValues[0] = 0.1f;
|
|
exportedCheckValues[1] = 1.0f;
|
|
exportedCheckValues[2] = 1.1f;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Oil Phase Non-Negative Saturation (O/W)";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "SGL + SWU <= 1";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
headers[0] = "SGL";
|
|
headers[1] = "SWU";
|
|
headers[2] = "SGL + SWU";
|
|
}
|
|
};
|
|
|
|
class NonNegOSAT_GO : public Opm::SatfuncConsistencyChecks<float>::Check
|
|
{
|
|
void test(const Opm::EclEpsScalingPointsInfo<float>&) override {}
|
|
bool isViolated() const override { return true; }
|
|
bool isCritical() const override { return false; }
|
|
std::size_t numExportedCheckValues() const override { return 3; }
|
|
|
|
void exportCheckValues(float* exportedCheckValues) const override
|
|
{
|
|
exportedCheckValues[0] = 0.25f;
|
|
exportedCheckValues[1] = 0.8f;
|
|
exportedCheckValues[2] = 1.05f;
|
|
}
|
|
|
|
std::string description() const override
|
|
{
|
|
return "Oil Phase Non-Negative Saturation (G/O)";
|
|
}
|
|
|
|
std::string condition() const override
|
|
{
|
|
return "SWL + SGU <= 1";
|
|
}
|
|
|
|
void columnNames(std::string* headers) const override
|
|
{
|
|
headers[0] = "SWL";
|
|
headers[1] = "SGU";
|
|
headers[2] = "SWL + SGU";
|
|
}
|
|
};
|
|
|
|
Opm::EclEpsScalingPointsInfo<float> makePoints() { return {}; }
|
|
} // Anonymous namespace
|
|
|
|
BOOST_AUTO_TEST_CASE(Standard)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<float>{"Grid Block", 1};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<MonotoneGas>());
|
|
checker.addCheck(std::make_unique<NonNegOSAT_GO>());
|
|
checker.addCheck(std::make_unique<MonotoneWater>());
|
|
checker.addCheck(std::make_unique<NonNegOSAT_OW>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.setPointIDFormatCallback([](const std::size_t)
|
|
{
|
|
return std::string { "(121, 323, 42)" };
|
|
});
|
|
|
|
checker.checkEndpoints(1234, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedChecks(),
|
|
"There must be at least one failed check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<float>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Gas Phase End-Point Monotonicity
|
|
SGL <= SGCR < SGU
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+----------------+---------------+---------------+---------------+
|
|
| Grid Block | SGL | SGCR | SGU |
|
|
+----------------+---------------+---------------+---------------+
|
|
| (121, 323, 42) | 0.000000e+00 | -1.000000e-01 | 8.000000e-01 |
|
|
+----------------+---------------+---------------+---------------+
|
|
|
|
|
|
Consistency Problem:
|
|
Oil Phase Non-Negative Saturation (G/O)
|
|
SWL + SGU <= 1
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+----------------+---------------+---------------+---------------+
|
|
| Grid Block | SWL | SGU | SWL + SGU |
|
|
+----------------+---------------+---------------+---------------+
|
|
| (121, 323, 42) | 2.500000e-01 | 8.000000e-01 | 1.050000e+00 |
|
|
+----------------+---------------+---------------+---------------+
|
|
|
|
|
|
Consistency Problem:
|
|
Water Phase End-Point Monotonicity
|
|
SWL <= SWCR < SWU
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+----------------+---------------+---------------+---------------+
|
|
| Grid Block | SWL | SWCR | SWU |
|
|
+----------------+---------------+---------------+---------------+
|
|
| (121, 323, 42) | 1.000000e-01 | 3.000000e-01 | 3.000000e-01 |
|
|
+----------------+---------------+---------------+---------------+
|
|
|
|
|
|
Consistency Problem:
|
|
Oil Phase Non-Negative Saturation (O/W)
|
|
SGL + SWU <= 1
|
|
Total Violations: 1
|
|
|
|
List of Violations
|
|
+----------------+---------------+---------------+---------------+
|
|
| Grid Block | SGL | SWU | SGL + SWU |
|
|
+----------------+---------------+---------------+---------------+
|
|
| (121, 323, 42) | 1.000000e-01 | 1.000000e+00 | 1.100000e+00 |
|
|
+----------------+---------------+---------------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Standard_Multiple_Failing_Points)
|
|
{
|
|
auto checker = Opm::SatfuncConsistencyChecks<float>{"Grid Block", 5};
|
|
|
|
checker.resetCheckSet();
|
|
checker.addCheck(std::make_unique<MonotoneGas>());
|
|
checker.addCheck(std::make_unique<NonNegOSAT_GO>());
|
|
checker.addCheck(std::make_unique<MonotoneWater>());
|
|
checker.addCheck(std::make_unique<NonNegOSAT_OW>());
|
|
checker.finaliseCheckSet();
|
|
|
|
checker.checkEndpoints( 1234, makePoints());
|
|
checker.checkEndpoints( 1729, makePoints());
|
|
checker.checkEndpoints( 1618, makePoints());
|
|
checker.checkEndpoints(31415, makePoints());
|
|
|
|
BOOST_CHECK_MESSAGE(checker.anyFailedChecks(),
|
|
"There must be at least one failed check");
|
|
|
|
auto rpt = std::string{};
|
|
checker.reportFailures(Opm::SatfuncConsistencyChecks<float>::ViolationLevel::Standard,
|
|
[&rpt](std::string_view record)
|
|
{
|
|
rpt += fmt::format("{}\n", record);
|
|
});
|
|
|
|
// Note that grid blocks are reported in sorted order rather in the
|
|
// order of insertion.
|
|
BOOST_CHECK_EQUAL(rpt, R"(Consistency Problem:
|
|
Gas Phase End-Point Monotonicity
|
|
SGL <= SGCR < SGU
|
|
Total Violations: 4
|
|
|
|
List of Violations
|
|
+------------+---------------+---------------+---------------+
|
|
| Grid Block | SGL | SGCR | SGU |
|
|
+------------+---------------+---------------+---------------+
|
|
| 1234 | 0.000000e+00 | -1.000000e-01 | 8.000000e-01 |
|
|
| 1618 | 0.000000e+00 | -1.000000e-01 | 8.000000e-01 |
|
|
| 1729 | 0.000000e+00 | -1.000000e-01 | 8.000000e-01 |
|
|
| 31415 | 0.000000e+00 | -1.000000e-01 | 8.000000e-01 |
|
|
+------------+---------------+---------------+---------------+
|
|
|
|
|
|
Consistency Problem:
|
|
Oil Phase Non-Negative Saturation (G/O)
|
|
SWL + SGU <= 1
|
|
Total Violations: 4
|
|
|
|
List of Violations
|
|
+------------+---------------+---------------+---------------+
|
|
| Grid Block | SWL | SGU | SWL + SGU |
|
|
+------------+---------------+---------------+---------------+
|
|
| 1234 | 2.500000e-01 | 8.000000e-01 | 1.050000e+00 |
|
|
| 1618 | 2.500000e-01 | 8.000000e-01 | 1.050000e+00 |
|
|
| 1729 | 2.500000e-01 | 8.000000e-01 | 1.050000e+00 |
|
|
| 31415 | 2.500000e-01 | 8.000000e-01 | 1.050000e+00 |
|
|
+------------+---------------+---------------+---------------+
|
|
|
|
|
|
Consistency Problem:
|
|
Water Phase End-Point Monotonicity
|
|
SWL <= SWCR < SWU
|
|
Total Violations: 4
|
|
|
|
List of Violations
|
|
+------------+---------------+---------------+---------------+
|
|
| Grid Block | SWL | SWCR | SWU |
|
|
+------------+---------------+---------------+---------------+
|
|
| 1234 | 1.000000e-01 | 3.000000e-01 | 3.000000e-01 |
|
|
| 1618 | 1.000000e-01 | 3.000000e-01 | 3.000000e-01 |
|
|
| 1729 | 1.000000e-01 | 3.000000e-01 | 3.000000e-01 |
|
|
| 31415 | 1.000000e-01 | 3.000000e-01 | 3.000000e-01 |
|
|
+------------+---------------+---------------+---------------+
|
|
|
|
|
|
Consistency Problem:
|
|
Oil Phase Non-Negative Saturation (O/W)
|
|
SGL + SWU <= 1
|
|
Total Violations: 4
|
|
|
|
List of Violations
|
|
+------------+---------------+---------------+---------------+
|
|
| Grid Block | SGL | SWU | SGL + SWU |
|
|
+------------+---------------+---------------+---------------+
|
|
| 1234 | 1.000000e-01 | 1.000000e+00 | 1.100000e+00 |
|
|
| 1618 | 1.000000e-01 | 1.000000e+00 | 1.100000e+00 |
|
|
| 1729 | 1.000000e-01 | 1.000000e+00 | 1.100000e+00 |
|
|
| 31415 | 1.000000e-01 | 1.000000e+00 | 1.100000e+00 |
|
|
+------------+---------------+---------------+---------------+
|
|
|
|
|
|
)");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END() // Multiple_Failing_Tests
|