mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Add New Platform for Saturation Function Consistency Checks
The intention is that this will ultimately replace the existing
RelpermDiagnostics component which does not really work in parallel
and which does not report enough context to help diagnose underlying
issues. For now, though, we just add the shell of a new set of
checks and hook that up to the build.
Class SatfuncConsistencyChecks<Scalar> manages a configurable set of
consistency checks, the implementations of which must publicly
derive from SatfuncConsistencyChecks<Scalar>::Check. Client code
will configure a set of checks by first calling
SatfuncConsistencyChecks<Scalar>::resetCheckSet()
then register individual checks by calling
SatfuncConsistencyChecks<Scalar>::addCheck()
and finally build requisite internal structures by calling
SatfuncConsistencyChecks<Scalar>::finaliseCheckSet()
Client code will then run the checks by calling
SatfuncConsistencyChecks<Scalar>::checkEndpoints()
typically in a loop. Class SatfuncConsistencyChecks<Scalar> will
count consistency check failures and attribute these to each
individual check as needed. We also maintain separate counts for
"Standard" and "Critical" failures. The former will typically
generate warnings while the latter will typically cause the
simulation run to stop. Individual checks get to decide which check
is "Critical", and client code gets to decide how to respond to
"Critical" failures.
Member function SatfuncConsistencyChecks<Scalar>::reportFailures()
will generate a textual report of the known set of consistency check
failures at a give severity level.
As an internal implementation detail, SatfuncConsistencyChecks uses
"reservoir sampling"
(https://en.wikipedia.org/wiki/Reservoir_sampling) to track details
about individual failed checks. We maintain at most a fixed number
of individual points (constructor argument).
This commit is contained in:
811
tests/test_SatfuncConsistencyChecks.cpp
Normal file
811
tests/test_SatfuncConsistencyChecks.cpp
Normal file
@@ -0,0 +1,811 @@
|
||||
/*
|
||||
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.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
|
||||
Reference in New Issue
Block a user