// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- // vi: set et ts=4 sw=4 sts=4: /* Copyright 2024 Equinor. This file is part of the Open Porous Media project (OPM). OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OPM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OPM. If not, see . */ #include #define BOOST_TEST_MODULE Region_Phase_PVAverage #define BOOST_TEST_NO_MAIN #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { #if HAVE_MPI struct MPIError { MPIError(std::string_view errstr, const int ec) : errorstring { errstr } , errorcode { ec } {} std::string errorstring; int errorcode; }; void MPI_err_handler(MPI_Comm*, int* err_code, ...) { std::array err_string_vec{'\0'}; auto err_length = 0; MPI_Error_string(*err_code, err_string_vec.data(), &err_length); auto err_string = std::string_view { err_string_vec.data(), static_cast(err_length) }; std::cerr << "An MPI Error ocurred:\n -> " << err_string << '\n'; throw MPIError { err_string, *err_code }; } // Register a throwing error handler to allow for debugging with // // catch throw // // in GDB. void register_error_handler() { MPI_Errhandler handler{}; MPI_Comm_create_errhandler(MPI_err_handler, &handler); MPI_Comm_set_errhandler(MPI_COMM_WORLD, handler); } #else // !HAVE_MPI void register_error_handler() {} #endif // HAVE_MPI template auto selectSubset(const std::vector& keep, const GlobalVector& global) { using VT = std::remove_cv_t::value_type>>; auto local = std::vector{}; const auto n = keep.size(); auto elm = global.begin(); for (auto i = 0*n; i < n; ++i, ++elm) { if (keep[i]) { local.push_back(*elm); } } return local; } std::vector cellSubset(const int rank, const std::vector& p) { auto keep = std::vector(p.size(), false); const auto n = p.size(); for (auto i = 0*n; i < n; ++i) { keep[i] = p[i] == rank; } return keep; } std::vector fipnum() { return { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; } std::vector fiplayer() { return { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; } class RegionSets { public: RegionSets(); RegionSets& selectSubset(const std::vector& keep); std::vector names() const; const std::vector& operator()(const std::string& rname) const; private: std::unordered_map> regions_; }; RegionSets::RegionSets() : regions_ { { "FIPNUM", fipnum() }, { "FIPLRS", fiplayer() }, } {} RegionSets& RegionSets::selectSubset(const std::vector& keep) { for (auto& [name, region] : this->regions_) { if (region.size() != keep.size()) { continue; } auto local = ::selectSubset(keep, region); region.swap(local); } return *this; } std::vector RegionSets::names() const { auto rnames = std::vector {}; rnames.reserve(this->regions_.size()); for (const auto& region : this->regions_) { rnames.push_back(region.first); } return rnames; } const std::vector& RegionSets::operator()(const std::string& rname) const { auto rpos = this->regions_.find(rname); if (rpos == this->regions_.end()) { throw std::invalid_argument { fmt::format("Unknown region set '{}'", rname) }; } return rpos->second; } bool init_unit_test_func() { return true; } } // Anonymous namespace // =========================================================================== using PVAvg = Opm::RegionPhasePoreVolAverage; BOOST_AUTO_TEST_SUITE(Sequential) BOOST_AUTO_TEST_CASE(Single_Phase_Single_Val_Per_Layer) { auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto rset = RegionSets{}; const auto numPhases = std::size_t{1}; const auto p = PVAvg::Phase {0}; auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; BOOST_CHECK_MESSAGE(std::isnan(avgCalc.fieldValue(p)), "Field value must be NaN prior to accumulation"); avgCalc.prepareAccumulation(); { const auto activeCell = 0*9 + std::size_t{0}; const auto cv = PVAvg::CellValue { 1.0, 0.25, 200.0 }; avgCalc.addCell(activeCell, p, cv); } { const auto activeCell = 1*9 + std::size_t{0}; const auto cv = PVAvg::CellValue { 2.0, 0.0, 200.0 }; avgCalc.addCell(activeCell, p, cv); } { const auto activeCell = 2*9 + std::size_t{0}; const auto cv = PVAvg::CellValue { 3.0, 0.5, 200.0 }; avgCalc.addCell(activeCell, p, cv); } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(p), 7.0/3.0, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", p, PVAvg::Region{0}), 7.0/3.0, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{0}), 1.0, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{1}), 2.0, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{2}), 3.0, 1.0e-8); } BOOST_AUTO_TEST_CASE(Single_Phase_Full) { const auto x = std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }; const auto s = std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.0, 0.0, 0.0, // s=0 in layer 3 => use PV average instead 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, }; auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto rset = RegionSets{}; const auto numPhases = std::size_t{1}; const auto p = PVAvg::Phase {0}; auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], s[c], 200.0 }; avgCalc.addCell(c, p, cv); } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(p), 1.61, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", p, PVAvg::Region{0}), 1.61, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{0}), 1.11, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{1}), 2.11, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{2}), 3.11, 1.0e-8); } BOOST_AUTO_TEST_CASE(Single_Phase_Full_Varying_PV) { const auto x = std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }; const auto s = std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.0, 0.0, 0.0, // s=0 in layer 3 => use PV average instead 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, }; const auto pv = std::array { // K=1 1729.0, 271.82, 3141.5 , 0.1, 1000.0, 321.09, 4321.0, 1234.5, 67.89, // K=2 0.12, 0.34, 0.56, 0.78, 0.90, 1.23, 1.45, 1.67, 1.89, // K=3 500.0, 450.0, 400.0, 350.0, 1.0, 300.0, 250.0, 200.0, 150.0, }; auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto rset = RegionSets{}; const auto numPhases = std::size_t{1}; const auto p = PVAvg::Phase {0}; auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], s[c], pv[c] }; avgCalc.addCell(c, p, cv); } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(p), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", p, PVAvg::Region{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); } BOOST_AUTO_TEST_CASE(Three_Phase_All_Present_Full_Varying_PV) { const auto x = std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }; const auto s = std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.0, 0.0, 0.0, // s=0 in layer 3 => use PV average instead 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, }; const auto pv = std::array { // K=1 1729.0, 271.82, 3141.5 , 0.1, 1000.0, 321.09, 4321.0, 1234.5, 67.89, // K=2 0.12, 0.34, 0.56, 0.78, 0.90, 1.23, 1.45, 1.67, 1.89, // K=3 500.0, 450.0, 400.0, 350.0, 1.0, 300.0, 250.0, 200.0, 150.0, }; auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto transform = std::array { std::function { [](const double s0) { return s0 / 2; } }, std::function { [](const double s0) { return s0 / 4; } }, std::function { [](const double s0) { return 1 - (3*s0/4); } }, }; const auto rset = RegionSets{}; const auto numPhases = transform.size(); auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); { auto p = PVAvg::Phase {0}; for (const auto& t : transform) { for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], t(s[c]), pv[c] }; avgCalc.addCell(c, p, cv); } ++p.ix; } } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{1}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{2}), 1.471079741628658, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{0}, PVAvg::Region{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{1}, PVAvg::Region{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{2}, PVAvg::Region{0}), 1.471079741628658, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{0}), 1.111326195193250, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{1}), 2.156805281711179, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); } BOOST_AUTO_TEST_CASE(Three_Phase_Two_Present_Full_Varying_PV) { const auto x = std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }; const auto s = std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.25, 0.30, 0.25, 0.30, 0.35, 0.30, 0.25, 0.30, 0.25, }; const auto pv = std::array { // K=1 1729.0, 271.82, 3141.5 , 0.1, 1000.0, 321.09, 4321.0, 1234.5, 67.89, // K=2 0.12, 0.34, 0.56, 0.78, 0.90, 1.23, 1.45, 1.67, 1.89, // K=3 500.0, 450.0, 400.0, 350.0, 1.0, 300.0, 250.0, 200.0, 150.0, }; auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto transform = std::array { std::function { [](const double s0) { return s0; } }, std::function { [](const double s0) { return 0 * s0; } }, std::function { [](const double s0) { return 1 - s0; } }, }; const auto rset = RegionSets{}; const auto numPhases = transform.size(); auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); { auto p = PVAvg::Phase {0}; for (const auto& t : transform) { for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], t(s[c]), pv[c] }; avgCalc.addCell(c, p, cv); } ++p.ix; } } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{0}), 2.203870000146282, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{1}), 1.460875637211809, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{2}), 1.388846263879987, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{0}, PVAvg::Region{0}), 2.203870000146282, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{1}, PVAvg::Region{0}), 1.460875637211809, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{2}, PVAvg::Region{0}), 1.388846263879987, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{2}), 3.081133011812399, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{0}), 1.111895506705607, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{1}), 2.156118568232662, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{0}), 1.111126811726796, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{1}), 2.157055514795793, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{2}), 3.079851244928804, 1.0e-8); } BOOST_AUTO_TEST_SUITE_END() // Sequential // --------------------------------------------------------------------------- BOOST_AUTO_TEST_SUITE(Parallel) BOOST_AUTO_TEST_CASE(Single_Phase_Full) { auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto keep = cellSubset(comm.rank(), Opm::partitionCellsSimple(3 * 3 * 3, comm.size()).first); const auto x = selectSubset(keep, std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }); const auto s = selectSubset(keep, std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.0, 0.0, 0.0, // s=0 in layer 3 => use PV average instead 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, }); const auto rset = RegionSets{}.selectSubset(keep); const auto numPhases = std::size_t{1}; const auto p = PVAvg::Phase {0}; auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], s[c], 200.0 }; avgCalc.addCell(c, p, cv); } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(p), 1.61, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", p, PVAvg::Region{0}), 1.61, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{0}), 1.11, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{1}), 2.11, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{2}), 3.11, 1.0e-8); } BOOST_AUTO_TEST_CASE(Single_Phase_Full_Varying_PV) { auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto keep = cellSubset(comm.rank(), Opm::partitionCellsSimple(3 * 3 * 3, comm.size()).first); const auto x = selectSubset(keep, std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }); const auto s = selectSubset(keep, std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.0, 0.0, 0.0, // s=0 in layer 3 => use PV average instead 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, }); const auto pv = selectSubset(keep, std::array { // K=1 1729.0, 271.82, 3141.5 , 0.1, 1000.0, 321.09, 4321.0, 1234.5, 67.89, // K=2 0.12, 0.34, 0.56, 0.78, 0.90, 1.23, 1.45, 1.67, 1.89, // K=3 500.0, 450.0, 400.0, 350.0, 1.0, 300.0, 250.0, 200.0, 150.0, }); const auto rset = RegionSets{}.selectSubset(keep); const auto numPhases = std::size_t{1}; const auto p = PVAvg::Phase {0}; auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], s[c], pv[c] }; avgCalc.addCell(c, p, cv); } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(p), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", p, PVAvg::Region{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", p, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); } BOOST_AUTO_TEST_CASE(Three_Phase_All_Present_Full_Varying_PV) { auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto keep = cellSubset(comm.rank(), Opm::partitionCellsSimple(3 * 3 * 3, comm.size()).first); const auto x = selectSubset(keep, std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }); const auto s = selectSubset(keep, std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.0, 0.0, 0.0, // s=0 in layer 3 => use PV average instead 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, }); const auto pv = selectSubset(keep, std::array { // K=1 1729.0, 271.82, 3141.5 , 0.1, 1000.0, 321.09, 4321.0, 1234.5, 67.89, // K=2 0.12, 0.34, 0.56, 0.78, 0.90, 1.23, 1.45, 1.67, 1.89, // K=3 500.0, 450.0, 400.0, 350.0, 1.0, 300.0, 250.0, 200.0, 150.0, }); const auto transform = std::array { std::function { [](const double s0) { return s0 / 2; } }, std::function { [](const double s0) { return s0 / 4; } }, std::function { [](const double s0) { return 1 - (3*s0/4); } }, }; const auto rset = RegionSets{}.selectSubset(keep); const auto numPhases = transform.size(); auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); { auto p = PVAvg::Phase {0}; for (const auto& t : transform) { for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], t(s[c]), pv[c] }; avgCalc.addCell(c, p, cv); } ++p.ix; } } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{1}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{2}), 1.471079741628658, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{0}, PVAvg::Region{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{1}, PVAvg::Region{0}), 1.128401081038469, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{2}, PVAvg::Region{0}), 1.471079741628658, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{0}), 1.111326195193250, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{1}), 2.156805281711179, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); } BOOST_AUTO_TEST_CASE(Three_Phase_Two_Present_Full_Varying_PV) { auto comm = Opm::Parallel::Communication { Dune::MPIHelper::getCommunicator() }; const auto keep = cellSubset(comm.rank(), Opm::partitionCellsSimple(3 * 3 * 3, comm.size()).first); const auto x = selectSubset(keep, std::array { // K=1 1.0, 1.01, 1.02, 1.1, 1.11, 1.12, 1.2, 1.21, 1.22, // K=2 2.0, 2.01, 2.02, 2.1, 2.11, 2.12, 2.2, 2.21, 2.22, // K=3 3.0, 3.01, 3.02, 3.1, 3.11, 3.12, 3.2, 3.21, 3.22, }); const auto s = selectSubset(keep, std::array { // K=1 0.0, 0.1, 0.0, 0.1, 0.4, 0.1, 0.0, 0.1, 0.0, // K=2 0.1, 0.0, 0.1, 0.0, 0.4, 0.0, 0.1, 0.0, 0.1, // K=3 0.25, 0.30, 0.25, 0.30, 0.35, 0.30, 0.25, 0.30, 0.25, }); const auto pv = selectSubset(keep, std::array { // K=1 1729.0, 271.82, 3141.5 , 0.1, 1000.0, 321.09, 4321.0, 1234.5, 67.89, // K=2 0.12, 0.34, 0.56, 0.78, 0.90, 1.23, 1.45, 1.67, 1.89, // K=3 500.0, 450.0, 400.0, 350.0, 1.0, 300.0, 250.0, 200.0, 150.0, }); const auto transform = std::array { std::function { [](const double s0) { return s0; } }, std::function { [](const double s0) { return 0 * s0; } }, std::function { [](const double s0) { return 1 - s0; } }, }; const auto rset = RegionSets{}.selectSubset(keep); const auto numPhases = transform.size(); auto avgCalc = PVAvg { comm, numPhases, rset.names(), rset }; avgCalc.prepareAccumulation(); { auto p = PVAvg::Phase {0}; for (const auto& t : transform) { for (auto nc = x.size(), c = 0*nc; c < nc; ++c) { const auto cv = PVAvg::CellValue { x[c], t(s[c]), pv[c] }; avgCalc.addCell(c, p, cv); } ++p.ix; } } avgCalc.accumulateParallel(); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{0}), 2.203870000146282, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{1}), 1.460875637211809, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.fieldValue(PVAvg::Phase{2}), 1.388846263879987, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{0}, PVAvg::Region{0}), 2.203870000146282, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{1}, PVAvg::Region{0}), 1.460875637211809, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPNUM", PVAvg::Phase{2}, PVAvg::Region{0}), 1.388846263879987, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{0}), 1.127070395417597, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{1}), 2.146062992125984, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{0}, PVAvg::Region{2}), 3.081133011812399, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{0}), 1.111895506705607, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{1}), 2.156118568232662, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{1}, PVAvg::Region{2}), 3.080203767781622, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{0}), 1.111126811726796, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{1}), 2.157055514795793, 1.0e-8); BOOST_CHECK_CLOSE(avgCalc.value("FIPLRS", PVAvg::Phase{2}, PVAvg::Region{2}), 3.079851244928804, 1.0e-8); } BOOST_AUTO_TEST_SUITE_END() // Parallel // =========================================================================== int main(int argc, char** argv) { Dune::MPIHelper::instance(argc, argv); register_error_handler(); return boost::unit_test::unit_test_main(&init_unit_test_func, argc, argv); }