Merge pull request #3063 from bska/ensure-correct-initial-actnum

Apply Generalised ACTNUM Handling to All Grid Types
This commit is contained in:
Markus Blatt 2022-06-27 11:32:48 +02:00 committed by GitHub
commit 80545120b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 197 additions and 48 deletions

View File

@ -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&);

View File

@ -274,39 +274,11 @@ EclipseGrid::EclipseGrid(const Deck& deck, const int * actnum)
updateNumericalAquiferCells(deck);
initGrid(deck);
initGrid(deck, actnum);
if (deck.hasKeyword<ParserKeywords::MAPAXES>())
this->m_mapaxes = std::make_optional<MapAxes>( deck );
if (actnum != nullptr) {
resetACTNUM(actnum);
} else {
if (m_useActnumFromGdfile){
// actnum already reset in initBinaryGrid
} else {
if (deck.hasKeyword<ParserKeywords::ACTNUM>()) {
const auto& actnumData = deck.get<ParserKeywords::ACTNUM>().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<ParserKeywords::RADIAL>()) {
initCylindricalGrid(deck );
} else if (deck.hasKeyword<ParserKeywords::SPIDER>()) {
@ -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<GridDims&>(*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<ParserKeywords::ZCORN>().back();
const auto& COORDKeyWord = deck.get<ParserKeywords::COORD>().back();
void EclipseGrid::initCornerPointGrid(const Deck& deck)
{
this->assertCornerPointKeywords(deck);
const std::vector<double>& zcorn = ZCORNKeyWord.getSIDoubleData();
const std::vector<double>& coord = COORDKeyWord.getSIDoubleData();
OpmLog::info(fmt::format("\nCreating corner-point grid from "
"keywords COORD, ZCORN and others"));
EclipseGrid topologyOnlyGrid(static_cast<GridDims&>(*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<ParserKeywords::COORD>().back();
const auto& zcorn = deck.get<ParserKeywords::ZCORN>().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) {

View File

@ -17,6 +17,7 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstddef>
#include <cstdio>
#include <ctime>
#include <iostream>
@ -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<int> {
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<int> {
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<int> {
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();