From 013b279682ad26ae866fae24ae2c691f4932f626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 24 Jun 2022 11:18:07 +0200 Subject: [PATCH] Apply Generalised ACTNUM Handling to All Grid Types Commit eca858335 introduced a more comprehensive way of forming the initial ACTNUM array used when constructing the EclipseGrid from a corner-point description. This commit applies that strategy to all known grid types. As an additional benefit this will also cover one special case that was not handled and would effectively discard the work done in the generalised initial ACTNUM construction. Add unit tests to exercise the ACTNUM handling for other grid types. --- .../eclipse/EclipseState/Grid/EclipseGrid.hpp | 2 +- .../eclipse/EclipseState/Grid/EclipseGrid.cpp | 70 +++---- tests/parser/EclipseGridTests.cpp | 173 ++++++++++++++++++ 3 files changed, 197 insertions(+), 48 deletions(-) diff --git a/opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp b/opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp index 4cc419ac3..ce38169bf 100644 --- a/opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp +++ b/opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp @@ -272,7 +272,7 @@ namespace Opm { void initCartesianGrid(const Deck&); void initDTOPSGrid(const Deck&); void initDVDEPTHZGrid(const Deck&); - void initGrid(const Deck&); + void initGrid(const Deck&, const int* actnum); void initCornerPointGrid(const Deck&); void assertCornerPointKeywords(const Deck&); diff --git a/src/opm/input/eclipse/EclipseState/Grid/EclipseGrid.cpp b/src/opm/input/eclipse/EclipseState/Grid/EclipseGrid.cpp index f57a92679..5ac6fe76b 100644 --- a/src/opm/input/eclipse/EclipseState/Grid/EclipseGrid.cpp +++ b/src/opm/input/eclipse/EclipseState/Grid/EclipseGrid.cpp @@ -274,39 +274,11 @@ EclipseGrid::EclipseGrid(const Deck& deck, const int * actnum) updateNumericalAquiferCells(deck); - initGrid(deck); + initGrid(deck, actnum); if (deck.hasKeyword()) this->m_mapaxes = std::make_optional( deck ); - if (actnum != nullptr) { - resetACTNUM(actnum); - } else { - if (m_useActnumFromGdfile){ - // actnum already reset in initBinaryGrid - } else { - if (deck.hasKeyword()) { - const auto& actnumData = deck.get().back().getIntData(); - /* - Would have liked to fail hard in the case where the size of the - ACTNUM array disagrees with nx*ny*nz; but it is possible to embed - the ACTNUM keyword in a BOX / ENDBOX pair and in that case it is - legitimate with size(ACTNUM) < nx*ny*nz. - - If size(actnum) != nx*ny*nz it is ignored here, however it is - taken into account when creating an final actnum in the field - property manager. - */ - if (actnumData.size() == getCartesianSize()) - resetACTNUM( actnumData); - else - resetACTNUM(); - } else { - resetACTNUM(); - } - } - } - /* The GRIDUNIT handling is simplified compared to the full specification: @@ -340,8 +312,8 @@ EclipseGrid::EclipseGrid(const Deck& deck, const int * actnum) return this->m_circle; } - void EclipseGrid::initGrid(const Deck& deck) { - + void EclipseGrid::initGrid(const Deck& deck, const int* actnum) + { if (deck.hasKeyword()) { initCylindricalGrid(deck ); } else if (deck.hasKeyword()) { @@ -389,6 +361,16 @@ EclipseGrid::EclipseGrid(const Deck& deck, const int * actnum) m_minpvMode = MinpvMode::ModeEnum::EclSTD; } + if (actnum != nullptr) { + this->resetACTNUM(actnum); + } + else if (! this->m_useActnumFromGdfile) { + const auto fp = FieldProps { + deck, EclipseGrid { static_cast(*this) } + }; + + this->resetACTNUM(fp.actnumRaw()); + } } void EclipseGrid::initGridFromEGridFile(Opm::EclIO::EclFile& egridfile, std::string fileName){ @@ -1159,25 +1141,19 @@ EclipseGrid::EclipseGrid(const Deck& deck, const int * actnum) this->resetACTNUM(actnum); } - void EclipseGrid::initCornerPointGrid(const Deck& deck) { - assertCornerPointKeywords(deck); - { - const auto& ZCORNKeyWord = deck.get().back(); - const auto& COORDKeyWord = deck.get().back(); + void EclipseGrid::initCornerPointGrid(const Deck& deck) + { + this->assertCornerPointKeywords(deck); - const std::vector& zcorn = ZCORNKeyWord.getSIDoubleData(); - const std::vector& coord = COORDKeyWord.getSIDoubleData(); + OpmLog::info(fmt::format("\nCreating corner-point grid from " + "keywords COORD, ZCORN and others")); - EclipseGrid topologyOnlyGrid(static_cast(*this)); - FieldProps fp(deck, topologyOnlyGrid); - const auto& actnumVector = fp.actnumRaw(); - if (actnumVector.size() != this->getCartesianSize()) - throw std::invalid_argument("ACTNUM vector has wrong size"); + const auto& coord = deck.get().back(); + const auto& zcorn = deck.get().back(); - OpmLog::info(fmt::format("\nCreating cornerpoint grid from keywords ZCORN, COORD and ACTNUM")); - - initCornerPointGrid( coord , zcorn, actnumVector.data()); - } + this->initCornerPointGrid(coord.getSIDoubleData(), + zcorn.getSIDoubleData(), + nullptr); } bool EclipseGrid::hasCornerPointKeywords(const Deck& deck) { diff --git a/tests/parser/EclipseGridTests.cpp b/tests/parser/EclipseGridTests.cpp index 04596dfb5..16855bd64 100644 --- a/tests/parser/EclipseGridTests.cpp +++ b/tests/parser/EclipseGridTests.cpp @@ -17,6 +17,7 @@ along with OPM. If not, see . */ +#include #include #include #include @@ -1082,6 +1083,178 @@ BOOST_AUTO_TEST_CASE(GridBoxActnum2) { } } +// 5-by-1-by-5 Cartesian grid in which all cells have dimension 1-by-1-by-1 +// metres. Setup otherwise very similar to createActnumBoxDeck2, but this +// deck uses a full initial ACTNUM, followed by EQUALS to reactivate. +static Opm::Deck createActnumBoxDeck3() { + return Opm::Parser{}.parseString(R"(RUNSPEC +DIMENS +5 1 5 / +GRID +SPECGRID +5 1 5 1 F / +COORD +0 0 0 0 0 0 +1 0 0 1 0 0 +2 0 0 2 0 0 +3 0 0 3 0 0 +4 0 0 4 0 0 +5 0 0 5 0 0 +0 1 0 0 1 0 +1 1 0 1 1 0 +2 1 0 2 1 0 +3 1 0 3 1 0 +4 1 0 4 1 0 +5 1 0 5 1 0 +/ +ZCORN +10*0 10*0 +10*1 10*1 +10*1 10*1 +10*2 10*2 +10*2 10*2 +10*3 10*3 +10*3 10*3 +10*4 10*4 +10*4 10*4 +10*5 10*5 +/ +ACTNUM +1 1 1 1 1 +1 1 1 1 1 +1 1 1 1 1 +0 0 1 1 1 +0 0 1 1 1 +/ +EQUALS +ACTNUM 1 1 3 1 1 5 5 / +PERMX 100.0 1 5 1 1 1 5 / +PORO 0.3 1 5 1 1 1 5 / +/ +COPY +PERMX PERMY / +PERMX PERMZ / +/ +)"); +} + +static Opm::Deck createActnumBoxDeck4() { + return Opm::Parser{}.parseString(R"(RUNSPEC +DIMENS +5 1 5 / +GRID +DXV +5*1 / +DYV +1*1 / +DZV +5*1 / +DEPTHZ +12*0 / +ACTNUM +1 1 1 1 1 +1 1 1 1 1 +1 1 1 1 1 +0 0 1 1 1 +0 0 1 1 1 +/ +EQUALS +ACTNUM 1 1 3 1 1 5 5 / +PERMX 100.0 1 5 1 1 1 5 / +PORO 0.3 1 5 1 1 1 5 / +/ +COPY +PERMX PERMY / +PERMX PERMZ / +/ +)"); +} + +static Opm::Deck createActnumBoxDeck5() { + return Opm::Parser{}.parseString(R"(RUNSPEC +DIMENS +5 1 5 / +GRID +DX +25*1 / +DY +25*1 / +DZ +25*1 / +TOPS +5*0 / +ACTNUM +1 1 1 1 1 +1 1 1 1 1 +1 1 1 1 1 +0 0 1 1 1 +0 0 1 1 1 +/ +EQUALS +ACTNUM 1 1 3 1 1 5 5 / +PERMX 100.0 1 5 1 1 1 5 / +PORO 0.3 1 5 1 1 1 5 / +/ +COPY +PERMX PERMY / +PERMX PERMZ / +/ +)"); +} + +BOOST_AUTO_TEST_CASE(GridBoxActnum3) { + const auto es = Opm::EclipseState { createActnumBoxDeck3() }; + const auto& grid = es.getInputGrid(); + BOOST_CHECK_EQUAL(grid.getNumActive(), std::size_t{23}); + + const auto expect = std::vector { + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, + }; + + const auto& actnum = grid.getACTNUM(); + BOOST_CHECK_EQUAL_COLLECTIONS(actnum.begin(), actnum.end(), + expect.begin(), expect.end()); +} + +BOOST_AUTO_TEST_CASE(GridBoxActnum4) { + const auto es = Opm::EclipseState { createActnumBoxDeck4() }; + const auto& grid = es.getInputGrid(); + BOOST_CHECK_EQUAL(grid.getNumActive(), std::size_t{23}); + + const auto expect = std::vector { + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, + }; + + const auto& actnum = grid.getACTNUM(); + BOOST_CHECK_EQUAL_COLLECTIONS(actnum.begin(), actnum.end(), + expect.begin(), expect.end()); +} + +BOOST_AUTO_TEST_CASE(GridBoxActnum5) { + const auto es = Opm::EclipseState { createActnumBoxDeck5() }; + const auto& grid = es.getInputGrid(); + BOOST_CHECK_EQUAL(grid.getNumActive(), std::size_t{23}); + + const auto expect = std::vector { + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, + }; + + const auto& actnum = grid.getACTNUM(); + BOOST_CHECK_EQUAL_COLLECTIONS(actnum.begin(), actnum.end(), + expect.begin(), expect.end()); +} BOOST_AUTO_TEST_CASE(GridActnumVia3D) { auto deck = createActnumDeck();