Files
opm-simulators/tests/test_rftcontainer.cpp
T
Bård Skaflestad bfe03b0a72 Fix RFT State Collection for Distributed Wells
Commit 6295bd08c (PR #6238) restricted RFT data reporting to only
those wells that are owned by the current rank.  In so doing,
however, we failed to properly account for distributed wells.  Such
wells will typically have RFT contributions from multiple MPI ranks
in a parallel run and we did not allow for this situation.
Moreover, as the simulator by default will distribute "inactive"
wells--wells that are never opened, but which exist primarily to
collect RFT-style data--the problem becomes more pronounced for
these wells.

We solve the problem by splitting the RFTContainer's "wellQuery_"
into two responsibilities.  One for determining if a particular
named well is owned by the current rank and another for determining
if the well is intersected on the current rank.  The latter will be
true for all ranks that have local well connections for the named
well.  This, in turn, means that the constructor now takes two
predicate functions instead of the one we originally used.
Furthermore, member function RFTContainer::allocate() will create
internal data structures for all potential connections on all ranks
that share a well, but RFTContainer::addToWells() will still collect
the RFT data only on the rank that owns the well.

Finally, we implement the owning vs. intersecting distinction for
the black-oil output module through a new member function

    bool BlackoilWellModelGeneric<>::hasLocalCells(name) const

while the compositional output module retains the original
owning-is-intersecting behaviour.  We do not support distributed
wells in compositional runs at the time of writing.
2025-09-05 14:45:26 +02:00

2071 lines
69 KiB
C++

/*
Copyright 2025 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 Test_RFTContainer_Parallel
#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 <boost/test/unit_test.hpp>
#include <opm/simulators/flow/RFTContainer.hpp>
#include <opm/simulators/utils/ParallelCommunication.hpp>
#include <opm/material/fluidsystems/BlackOilDefaultFluidSystemIndices.hpp>
#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
#include <opm/output/data/Wells.hpp>
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/input/eclipse/Python/Python.hpp>
#include <opm/input/eclipse/Schedule/Schedule.hpp>
#include <opm/input/eclipse/Deck/Deck.hpp>
#include <opm/input/eclipse/Parser/Parser.hpp>
#include <array>
#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
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<char, MPI_MAX_ERROR_STRING> 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<std::string_view::size_type>(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
class NProc_Is
{
public:
explicit NProc_Is(const int expectNP)
: expectNP_ { expectNP }
{}
boost::test_tools::assertion_result
operator()(boost::unit_test::test_unit_id) const
{
auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
if (comm.size() == this->expectNP_) {
return true;
}
boost::test_tools::assertion_result response(false);
response.message() << "Number of MPI processes ("
<< comm.size()
<< ") differs from expected "
<< this->expectNP_;
return response;
}
private:
int expectNP_{};
};
bool init_unit_test_func()
{
return true;
}
using TestFluidSystem = Opm::BlackOilFluidSystem
<double, Opm::BlackOilDefaultFluidSystemIndices>;
using RFTContainer = Opm::RFTContainer<TestFluidSystem>;
struct Case
{
explicit Case(const std::string& spec)
: Case { Opm::Parser{}.parseString(spec) }
{}
explicit Case(const Opm::Deck& deck)
: es { deck }
, sched { deck, es, std::make_shared<Opm::Python>() }
{}
Opm::EclipseState es{};
Opm::Schedule sched{};
};
Case singleCentreWell()
{
return Case { R"(RUNSPEC
DIMENS
3 3 3 /
START
3 SEP 2025 /
TABDIMS
/
OIL
GAS
WATER
GRID
DXV
3*100 /
DYV
3*100 /
DZV
3*5 /
DEPTHZ
16*2000 /
EQUALS
PERMX 100 /
PERMY 100 /
PERMZ 10 /
PORO 0.3 /
/
PROPS
DENSITY
800 1000 0.5 /
SCHEDULE
WELSPECS
R G 2 2 1* OIL /
/
COMPDAT
R 1* 1* 1 3 OPEN /
/
WCONPROD
R SHUT ORAT 0.0 /
/
WRFTPLT
R 'YES' /
/
DATES
10 SEP 2025 /
20 SEP 2025 /
30 SEP 2025 /
/
END
)" };
}
Case quarterFiveSpot()
{
return Case { R"(RUNSPEC
DIMENS
3 3 3 /
START
3 SEP 2025 /
TABDIMS
/
OIL
GAS
WATER
GRID
DXV
3*100 /
DYV
3*100 /
DZV
3*5 /
DEPTHZ
16*2000 /
EQUALS
PERMX 100 /
PERMY 100 /
PERMZ 10 /
PORO 0.3 /
/
PROPS
DENSITY
800 1000 0.5 /
SCHEDULE
WELSPECS
R1 G 1 1 1* OIL /
R2 G 3 3 1* OIL /
/
COMPDAT
R* 1* 1* 1 3 OPEN /
/
WCONPROD
R* SHUT ORAT 0.0 /
/
WRFTPLT
R* 'YES' /
/
DATES
10 SEP 2025 /
20 SEP 2025 /
30 SEP 2025 /
/
END
)" };
}
} // Anonymous namespace
BOOST_AUTO_TEST_SUITE(Single_Rank)
BOOST_AUTO_TEST_CASE(Single_Well)
{
const auto cse = singleCentreWell();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string&) { return r == 0; },
[r = comm.rank()](const std::string&) { return r == 0; }
};
rftc.allocate(0);
// IJK = (2,2,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (2,2,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (2,2,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
if (comm.rank() != 0) {
return;
}
const auto rPos = xw.find("R");
BOOST_REQUIRE_MESSAGE(rPos != xw.end(),
R"(There must be dynamic results for well "R")");
BOOST_CHECK_EQUAL(rPos->second.connections.size(), std::size_t{3});
// (2,2,1)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (2,2,2)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (2,2,3)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string&) { return r == 0; },
[r = comm.rank()](const std::string&) { return r == 0; }
};
rftc.allocate(0);
// --------------------------------------------------------------------
// IJK = (1,1,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (1,1,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (1,1,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
// --------------------------------------------------------------------
// IJK = (3,3,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
// IJK = (3,3,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
// IJK = (3,3,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
if (comm.rank() != 0) {
return;
}
// --------------------------------------------------------------------
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
// --------------------------------------------------------------------
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
BOOST_AUTO_TEST_SUITE_END()
// ===========================================================================
BOOST_AUTO_TEST_SUITE(NProc_2, * boost::unit_test::precondition(NProc_Is{2}))
BOOST_AUTO_TEST_CASE(Single_Split_Well)
{
const auto cse = singleCentreWell();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string&) { return r == 0; },
[](const std::string&) { return true; }
};
rftc.allocate(0);
if (comm.rank() == 0) {
// IJK = (2,2,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
}
else {
// IJK = (2,2,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (2,2,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
if (comm.rank() != 0) {
return;
}
const auto rPos = xw.find("R");
BOOST_REQUIRE_MESSAGE(rPos != xw.end(),
R"(There must be dynamic results for well "R")");
BOOST_CHECK_EQUAL(rPos->second.connections.size(), std::size_t{3});
// (2,2,1)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (2,2,2)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (2,2,3)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot_Non_Split_Wells)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string& wname) {
return ((r == 0) && (wname == "R2"))
|| ((r == 1) && (wname == "R1"));
},
[r = comm.rank()](const std::string& wname) {
return ((r == 0) && (wname == "R2"))
|| ((r == 1) && (wname == "R1"));
}
};
rftc.allocate(0);
// --------------------------------------------------------------------
if (comm.rank() == 1) {
// IJK = (1,1,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (1,1,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (1,1,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
// --------------------------------------------------------------------
if (comm.rank() == 0) {
// IJK = (3,3,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
// IJK = (3,3,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
// IJK = (3,3,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
}
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
// --------------------------------------------------------------------
if (comm.rank() == 1) {
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
// --------------------------------------------------------------------
if (comm.rank() == 0) {
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot_Split_Wells)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// Rank 0 owns R2, rank 1 ownes R1. Both wells intersected on both
// ranks.
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string& wname) {
return ((r == 0) && (wname == "R2"))
|| ((r == 1) && (wname == "R1"));
},
[](const std::string&) { return true; }
};
rftc.allocate(0);
// --------------------------------------------------------------------
if (comm.rank() == 1) {
// IJK = (1,1,1) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (3,3,1) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
// IJK = (3,3,2) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
}
// --------------------------------------------------------------------
if (comm.rank() == 0) {
// IJK = (1,1,2) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (1,1,3) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
// IJK = (3,3,3) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
}
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
// --------------------------------------------------------------------
if (comm.rank() == 1) {
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
// --------------------------------------------------------------------
if (comm.rank() == 0) {
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
}
BOOST_AUTO_TEST_SUITE_END() // NProc_2
// ===========================================================================
BOOST_AUTO_TEST_SUITE(NProc_3, * boost::unit_test::precondition(NProc_Is{3}))
BOOST_AUTO_TEST_CASE(Single_Split_Well)
{
const auto cse = singleCentreWell();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// Well owned by rank 2, but intersected on all ranks.
const auto owner = 2;
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank(), owner](const std::string&) { return r == owner; },
[](const std::string&) { return true; }
};
rftc.allocate(0);
if (comm.rank() == 0) {
// IJK = (2,2,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
}
else if (comm.rank() == 1) {
// IJK = (2,2,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
}
else {
// IJK = (2,2,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
if (comm.rank() != owner) {
return;
}
const auto rPos = xw.find("R");
BOOST_REQUIRE_MESSAGE(rPos != xw.end(),
R"(There must be dynamic results for well "R")");
BOOST_CHECK_EQUAL(rPos->second.connections.size(), std::size_t{3});
// (2,2,1)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (2,2,2)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (2,2,3)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot_Owned_And_Split)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// R1 is owned by rank 2 and intersected on rank 2. R2 is owned by rank
// 1 and intersected on ranks 0 and 1.
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string& wname) {
return ((r == 2) && (wname == "R1"))
|| ((r == 1) && (wname == "R2"));
},
[r = comm.rank()](const std::string& wname) {
return (((r == 0) || (r == 1)) && (wname == "R2"))
|| ((r == 2) && (wname == "R1"));
}
};
rftc.allocate(0);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
// IJK = (1,1,1) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (1,1,2) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (1,1,3) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
// IJK = (3,3,1) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
// IJK = (3,3,2) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
}
if (comm.rank() == 0) {
// IJK = (3,3,3) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
}
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot_Split_Wells)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// R1 is owned by rank 2. R2 is owned by rank 1. Both wells
// intersected on all ranks.
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string& wname) {
return ((r == 2) && (wname == "R1"))
|| ((r == 1) && (wname == "R2"));
},
[](const std::string&) { return true; }
};
rftc.allocate(0);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
// IJK = (1,1,1) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (3,3,1) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
// IJK = (3,3,3) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
// IJK = (1,1,3) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
if (comm.rank() == 0) {
// IJK = (1,1,2) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (3,3,2) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
}
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
}
BOOST_AUTO_TEST_SUITE_END() // NProc_3
// ===========================================================================
BOOST_AUTO_TEST_SUITE(NProc_4, * boost::unit_test::precondition(NProc_Is{4}))
BOOST_AUTO_TEST_CASE(Single_Split_Well)
{
const auto cse = singleCentreWell();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// Well owned by rank 2, but intersected on ranks 0, 1, and 3. Does
// typically not happen in a real simulator run...
const auto owner = 2;
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank(), owner](const std::string&) { return r == owner; },
[r = comm.rank(), owner](const std::string&) { return r != owner; }
};
rftc.allocate(0);
if (comm.rank() == 0) {
// IJK = (2,2,1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
}
else if (comm.rank() == 1) {
// IJK = (2,2,2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
}
else if (comm.rank() == 3) {
// IJK = (2,2,3)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(1, 1, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
if (comm.rank() != owner) {
return;
}
const auto rPos = xw.find("R");
BOOST_REQUIRE_MESSAGE(rPos != xw.end(),
R"(There must be dynamic results for well "R")");
BOOST_CHECK_EQUAL(rPos->second.connections.size(), std::size_t{3});
// (2,2,1)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (2,2,2)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (2,2,3)
{
const auto* xc = rPos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(1, 1, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R" must have dynamic results in connection (2,2,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot_Owned_And_Split)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// R1 is owned by rank 2 and intersected on rank 2. R2 is owned by rank
// 3 and intersected on ranks 0, 1, and 3.
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string& wname) {
return ((r == 2) && (wname == "R1"))
|| ((r == 3) && (wname == "R2"));
},
[r = comm.rank()](const std::string& wname) {
return (((r == 0) || (r == 1) || (r == 3)) && (wname == "R2"))
|| ((r == 2) && (wname == "R1"));
}
};
rftc.allocate(0);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
// IJK = (1,1,1) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (1,1,2) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
// IJK = (1,1,3) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
// IJK = (3,3,1) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
}
if (comm.rank() == 3) {
// IJK = (3,3,2) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
}
if (comm.rank() == 0) {
// IJK = (3,3,3) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
}
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
// --------------------------------------------------------------------
if (comm.rank() == 3) {
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot_Split_Wells_Even_Odd)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// R1 is owned by rank 2 and intersected on ranks 0 and 2. R2 is owned
// by rank 1 and intersected on ranks 1 and 3.
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string& wname) {
return ((r == 2) && (wname == "R1"))
|| ((r == 1) && (wname == "R2"));
},
[r = comm.rank()](const std::string& wname) {
return ((r % 2 == 0) && (wname == "R1"))
|| ((r % 2 == 1) && (wname == "R2"));
}
};
rftc.allocate(0);
// --------------------------------------------------------------------
if (comm.rank() == 0) {
// IJK = (1,1,3) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
if (comm.rank() == 2) {
// IJK = (1,1,1) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (1,1,2) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
// IJK = (3,3,3) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
}
if (comm.rank() == 3) {
// IJK = (3,3,2) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
// IJK = (3,3,1) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
}
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
}
BOOST_AUTO_TEST_CASE(Quarter_Five_Spot_Split_Wells_Cross)
{
const auto cse = quarterFiveSpot();
const auto comm = Opm::Parallel::Communication {
Dune::MPIHelper::getCommunicator()
};
// R1 is owned by rank 2 and intersected on ranks 1 and 2. R2 is owned
// by rank 0 and intersected on ranks 0, 2 and 3.
auto rftc = RFTContainer {
cse.es, cse.sched,
[r = comm.rank()](const std::string& wname) {
return ((r == 2) && (wname == "R1"))
|| ((r == 0) && (wname == "R2"));
},
[r = comm.rank()](const std::string& wname) {
return (((r == 1) || (r == 2)) && (wname == "R1"))
|| ((r != 1) && (wname == "R2"));
}
};
rftc.allocate(0);
// --------------------------------------------------------------------
if (comm.rank() == 0) {
// IJK = (3,3,3) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 2),
/* Po = */ []() { return 199; },
/* Sw = */ []() { return 0.42; },
/* Sg = */ []() { return 0.07; });
}
if (comm.rank() == 2) {
// IJK = (1,1,1) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 0),
/* Po = */ []() { return 100; },
/* Sw = */ []() { return 0.01; },
/* Sg = */ []() { return 0.8; });
// IJK = (3,3,2) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 1),
/* Po = */ []() { return 152; },
/* Sw = */ []() { return 0.12; },
/* Sg = */ []() { return 0.48; });
// IJK = (1,1,2) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 1),
/* Po = */ []() { return 150; },
/* Sw = */ []() { return 0.1; },
/* Sg = */ []() { return 0.5; });
}
// --------------------------------------------------------------------
if (comm.rank() == 1) {
// IJK = (1,1,3) (R1)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(0, 0, 2),
/* Po = */ []() { return 215; },
/* Sw = */ []() { return 0.4; },
/* Sg = */ []() { return 0.1; });
}
if (comm.rank() == 3) {
// IJK = (3,3,1) (R2)
rftc.assign(cse.es.getInputGrid().getGlobalIndex(2, 2, 0),
/* Po = */ []() { return 123; },
/* Sw = */ []() { return 0.02; },
/* Sg = */ []() { return 0.63; });
}
// --------------------------------------------------------------------
auto xw = Opm::data::Wells{};
rftc.addToWells(xw, 0, comm);
// --------------------------------------------------------------------
if (comm.rank() == 2) {
const auto r1Pos = xw.find("R1");
BOOST_REQUIRE_MESSAGE(r1Pos != xw.end(),
R"(There must be dynamic results for well "R1")");
BOOST_CHECK_EQUAL(r1Pos->second.connections.size(), std::size_t{3});
// (1,1,1)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 100.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.01, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.8 , 1.0e-8);
}
// (1,1,2)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 150.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.5, 1.0e-8);
}
// (1,1,3)
{
const auto* xc = r1Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(0, 0, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R1" must have dynamic results in connection (1,1,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 215.0, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.1, 1.0e-8);
}
}
// --------------------------------------------------------------------
if (comm.rank() == 0) {
const auto r2Pos = xw.find("R2");
BOOST_REQUIRE_MESSAGE(r2Pos != xw.end(),
R"(There must be dynamic results for well "R2")");
BOOST_CHECK_EQUAL(r2Pos->second.connections.size(), std::size_t{3});
// (3,3,1)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 0));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,1))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 123.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.02, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.63, 1.0e-8);
}
// (3,3,2)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 1));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,2))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 152.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.12, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.48, 1.0e-8);
}
// (3,3,3)
{
const auto* xc = r2Pos->second.find_connection
(cse.es.getInputGrid().getGlobalIndex(2, 2, 2));
BOOST_REQUIRE_MESSAGE(xc != nullptr,
R"(Well "R2" must have dynamic results in connection (3,3,3))");
BOOST_CHECK_CLOSE(xc->cell_pressure , 199.0 , 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_water, 0.42, 1.0e-8);
BOOST_CHECK_CLOSE(xc->cell_saturation_gas , 0.07, 1.0e-8);
}
}
}
BOOST_AUTO_TEST_SUITE_END() // NProc_4
// ===========================================================================
int main(int argc, char** argv)
{
Dune::MPIHelper::instance(argc, argv);
register_error_handler();
// Just enough initialisation for a working TestFluidSystem::phaseIsActive().
//
// This is a **massive** hack.
TestFluidSystem::initBegin(1);
return boost::unit_test::unit_test_main(&init_unit_test_func, argc, argv);
}