Revise Convergence Report Collection Procedure

This commit switches the parallel implemenation of function
Opm::gatherConvergenceReport() into using the general serialisation
framework (classes Opm::Serializer<> and Opm::Mpi::Packer).  In
particular, we add serializeOp() functions to each of the types

  - ConvergenceReport
  - ConvergenceReport::ReservoirFailure
  - ConvergenceReport::ReservoirConvergenceMetric
  - ConvergenceReport::WellFailure

and defer the job of converting the objects between in-memory and
byte stream representations to Opm::Serializer<>.  The new special
purpose class CollectConvReports inherits from the latter and uses
its pack() and unpack() member functions, along with its internal
m_buffer data member, to distribute each rank's convergence report
object to all ranks.  We add this feature here, in a very narrowly
scoped use case, to enable testing and experimentation before we
consider adding this distribution mechanism as a general feature in
Opm::MpiSerializer.
This commit is contained in:
Bård Skaflestad
2024-08-07 17:47:11 +02:00
parent 68cc5d917e
commit 0b40277e01
4 changed files with 250 additions and 353 deletions

View File

@@ -106,6 +106,74 @@ BOOST_AUTO_TEST_CASE(EvenHaveFailure)
}
}
namespace {
class NProc_Is_Not
{
public:
explicit NProc_Is_Not(const int rejectNP)
: rejectNP_ { rejectNP }
{}
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->rejectNP_) {
return true;
}
boost::test_tools::assertion_result response(false);
response.message() << "Number of MPI processes ("
<< comm.size()
<< ") matches rejected case.";
return response;
}
private:
int rejectNP_{};
};
} // Anonymous namespace
BOOST_AUTO_TEST_CASE(CNV_PV_SPLIT, * boost::unit_test::precondition(NProc_Is_Not{1}))
{
const auto cc = Dune::MPIHelper::getCommunication();
auto loc_rpt = Opm::ConvergenceReport {};
if (cc.rank() != 0) {
// All ranks are supposed to have the *same* pore-volume split of
// the CNV metrics, except if the pv split is empty.
const auto pvSplit = Opm::ConvergenceReport::CnvPvSplit {
{ 0.75, 0.2, 0.05, },
{ 1234, 56 , 7 , }
};
loc_rpt.setCnvPoreVolSplit(pvSplit, 9.876e5);
}
const auto cr = gatherConvergenceReport(loc_rpt, cc);
const auto& [pvFrac, cellCnt] = cr.cnvPvSplit();
BOOST_REQUIRE_EQUAL(pvFrac.size(), std::size_t{3});
BOOST_REQUIRE_EQUAL(cellCnt.size(), std::size_t{3});
BOOST_CHECK_CLOSE(cr.eligiblePoreVolume(), 9.876e5, 1.0e-8);
BOOST_CHECK_CLOSE(pvFrac[0], 0.75, 1.0e-8);
BOOST_CHECK_CLOSE(pvFrac[1], 0.20, 1.0e-8);
BOOST_CHECK_CLOSE(pvFrac[2], 0.05, 1.0e-8);
BOOST_CHECK_EQUAL(cellCnt[0], 1234);
BOOST_CHECK_EQUAL(cellCnt[1], 56);
BOOST_CHECK_EQUAL(cellCnt[2], 7);
}
int main(int argc, char** argv)
{
Dune::MPIHelper::instance(argc, argv);