Files
opm-common/tests/parser/MULTREGTScannerTests.cpp
Bård Skaflestad 07ddc15068 Calculate Multiplier Values for Non-Neighbouring Connections
This is intended as a possibly temporary measure for processing
explicitly assigned NNCs (keywords NNC/EDITNNC/EDITNNCR) along with
those NNCs arising from numerical aquifers, and for which there is
no associate face direction.

Add a set of unit tests to probe the implementation of all MULTREGT
connection behaviours as exhibited by MULTREGTScanner member
functions getRegionMultiplier() and getRegionMultiplierNNC().
2023-09-14 15:29:58 +02:00

753 lines
27 KiB
C++

/*
Copyright 2014 Statoil ASA.
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/>.
*/
#define BOOST_TEST_MODULE MULTREGTScannerTests
#include <boost/test/unit_test.hpp>
#include <opm/input/eclipse/EclipseState/Grid/MULTREGTScanner.hpp>
#include <opm/input/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquifers.hpp>
#include <opm/input/eclipse/EclipseState/Grid/Box.hpp>
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
#include <opm/input/eclipse/Deck/Deck.hpp>
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
#include <opm/input/eclipse/Deck/DeckSection.hpp>
#include <opm/input/eclipse/Parser/Parser.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/M.hpp>
#include <array>
#include <initializer_list>
#include <stdexcept>
#include <vector>
BOOST_AUTO_TEST_CASE(TestRegionName) {
BOOST_CHECK_EQUAL( "FLUXNUM" , Opm::MULTREGT::RegionNameFromDeckValue( "F"));
BOOST_CHECK_EQUAL( "MULTNUM" , Opm::MULTREGT::RegionNameFromDeckValue( "M"));
BOOST_CHECK_EQUAL( "OPERNUM" , Opm::MULTREGT::RegionNameFromDeckValue( "O"));
BOOST_CHECK_THROW( Opm::MULTREGT::RegionNameFromDeckValue("o") , std::invalid_argument);
BOOST_CHECK_THROW( Opm::MULTREGT::RegionNameFromDeckValue("X") , std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(TestNNCBehaviourEnum) {
BOOST_CHECK_MESSAGE(Opm::MULTREGT::NNCBehaviourEnum::ALL == Opm::MULTREGT::NNCBehaviourFromString("ALL"),
R"(Behaviour("ALL") must be ALL)");
BOOST_CHECK_MESSAGE(Opm::MULTREGT::NNCBehaviourEnum::NNC == Opm::MULTREGT::NNCBehaviourFromString("NNC"),
R"(Behaviour("NNC") must be NNC)");
BOOST_CHECK_MESSAGE(Opm::MULTREGT::NNCBehaviourEnum::NONNC == Opm::MULTREGT::NNCBehaviourFromString("NONNC"),
R"(Behaviour("NONNC") must be NONNC)");
BOOST_CHECK_MESSAGE(Opm::MULTREGT::NNCBehaviourEnum::NOAQUNNC == Opm::MULTREGT::NNCBehaviourFromString("NOAQUNNC"),
R"(Behaviour("NOAQUNNC") must be NOAQUNNC)");
BOOST_CHECK_THROW(Opm::MULTREGT::NNCBehaviourFromString("Invalid"), std::invalid_argument);
}
namespace {
Opm::Deck createInvalidMULTREGTDeck()
{
return Opm::Parser{}.parseString(R"(RUNSPEC
DIMENS
3 3 2 /
GRID
DX
18*0.25 /
DY
18*0.25 /
DZ
18*0.25 /
TOPS
9*0.25 /
FLUXNUM
1 1 2
1 1 2
1 1 2
3 4 5
3 4 5
3 4 5
/
MULTREGT
1 2 0.50 G ALL M / -- Invalid direction
/
MULTREGT
1 2 0.50 X ALL G / -- Invalid region
/
MULTREGT
1 2 0.50 X ALL M / -- Region not in deck
/
EDIT
)");
}
} // Anonymous namespace
BOOST_AUTO_TEST_CASE(InvalidInput) {
Opm::Deck deck = createInvalidMULTREGTDeck();
Opm::EclipseGrid grid( deck );
Opm::TableManager tm(deck);
Opm::EclipseGrid eg( deck );
Opm::FieldPropsManager fp(deck, Opm::Phases{true, true, true}, eg, tm);
// Invalid direction
std::vector<const Opm::DeckKeyword*> keywords0;
const auto& multregtKeyword0 = deck["MULTREGT"][0];
keywords0.push_back( &multregtKeyword0 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner( grid, &fp, keywords0 ); , std::invalid_argument );
// Not supported region
std::vector<const Opm::DeckKeyword*> keywords1;
const auto& multregtKeyword1 = deck["MULTREGT"][1];
keywords1.push_back( &multregtKeyword1 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner( grid, &fp, keywords1 ); , std::invalid_argument );
// The keyword is ok; but it refers to a region which is not in the deck.
std::vector<const Opm::DeckKeyword*> keywords2;
const auto& multregtKeyword2 = deck["MULTREGT"][2];
keywords2.push_back( &multregtKeyword2 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner( grid, &fp, keywords2 ); , std::logic_error );
}
namespace {
Opm::Deck createNotSupportedMULTREGTDeck()
{
return Opm::Parser{}.parseString(R"(RUNSPEC
DIMENS
3 3 2 /
GRID
DX
18*0.25 /
DY
18*0.25 /
DZ
18*0.25 /
TOPS
9*0.25 /
FLUXNUM
1 1 2
1 1 2
1 1 2
3 4 5
3 4 5
3 4 5
/
MULTREGT
1 2 0.50 X NOAQUNNC F / -- Not support NOAQUNNC behaviour
/
MULTREGT
2 2 0.50 X ALL M / -- Region values equal
/
EDIT
)");
}
} // Anonymous namespace
BOOST_AUTO_TEST_CASE(NotSupported) {
Opm::Deck deck = createNotSupportedMULTREGTDeck();
Opm::EclipseGrid grid( deck );
Opm::TableManager tm(deck);
Opm::EclipseGrid eg( deck );
Opm::FieldPropsManager fp(deck, Opm::Phases{true, true, true}, eg, tm);
// srcValue == targetValue - not supported
std::vector<const Opm::DeckKeyword*> keywords1;
const Opm::DeckKeyword& multregtKeyword1 = deck["MULTREGT"][1];
keywords1.push_back( &multregtKeyword1 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner( grid, &fp, keywords1 ); , std::invalid_argument );
}
namespace {
Opm::Deck createDefaultedRegions()
{
return Opm::Parser{}.parseString(R"(RUNSPEC
DIMENS
3 3 2 /
GRID
DX
18*0.25 /
DY
18*0.25 /
DZ
18*0.25 /
TOPS
9*0.25 /
FLUXNUM
1 1 2
1 1 2
1 1 2
3 4 5
3 4 5
3 4 5
/
MULTREGT
3 4 1.25 XYZ ALL F /
2 -1 0 XYZ ALL F / -- Defaulted from region value
1 -1 0 XYZ ALL F / -- Defaulted from region value
2 1 1 XYZ ALL F / Override default
/
MULTREGT
2 * 0.75 XYZ ALL F / -- Defaulted to region value
/
EDIT
)");
}
} // Anonymous namespace
BOOST_AUTO_TEST_CASE(DefaultedRegions) {
Opm::Deck deck = createDefaultedRegions();
Opm::EclipseGrid grid( deck );
Opm::TableManager tm(deck);
Opm::EclipseGrid eg( deck );
Opm::FieldPropsManager fp(deck, Opm::Phases{true, true, true}, eg, tm);
std::vector<const Opm::DeckKeyword*> keywords0;
const auto& multregtKeyword0 = deck["MULTREGT"][0];
keywords0.push_back( &multregtKeyword0 );
Opm::MULTREGTScanner scanner0(grid, &fp, keywords0);
BOOST_CHECK_EQUAL( scanner0.getRegionMultiplier(grid.getGlobalIndex(0,0,1), grid.getGlobalIndex(1,0,1), Opm::FaceDir::XPlus ), 1.25);
BOOST_CHECK_EQUAL( scanner0.getRegionMultiplier(grid.getGlobalIndex(1,0,0), grid.getGlobalIndex(2,0,0), Opm::FaceDir::XPlus ), 1.0);
BOOST_CHECK_EQUAL( scanner0.getRegionMultiplier(grid.getGlobalIndex(2,0,1), grid.getGlobalIndex(2,0,0), Opm::FaceDir::ZMinus ), 0.0);
std::vector<const Opm::DeckKeyword*> keywords1;
const Opm::DeckKeyword& multregtKeyword1 = deck["MULTREGT"][1];
keywords1.push_back( &multregtKeyword1 );
Opm::MULTREGTScanner scanner1(grid, &fp, keywords1 );
BOOST_CHECK_EQUAL( scanner1.getRegionMultiplier(grid.getGlobalIndex(2,0,0), grid.getGlobalIndex(1,0,0), Opm::FaceDir::XMinus ), 0.75);
BOOST_CHECK_EQUAL( scanner1.getRegionMultiplier(grid.getGlobalIndex(2,0,0), grid.getGlobalIndex(2,0,1), Opm::FaceDir::ZPlus), 0.75);
}
namespace {
Opm::Deck createCopyMULTNUMDeck()
{
return Opm::Parser{}.parseString(R"(RUNSPEC
DIMENS
2 2 2 /
GRID
DX
8*0.25 /
DY
8*0.25 /
DZ
8*0.25 /
TOPS
4*0.25 /
FLUXNUM
1 2
1 2
3 4
3 4
/
COPY
FLUXNUM MULTNUM /
/
MULTREGT
1 2 0.50/
/
EDIT
)");
}
} // Anonymous namespace
BOOST_AUTO_TEST_CASE(MULTREGT_COPY_MULTNUM) {
Opm::Deck deck = createCopyMULTNUMDeck();
Opm::TableManager tm(deck);
Opm::EclipseGrid eg(deck);
Opm::FieldPropsManager fp(deck, Opm::Phases{true, true, true}, eg, tm);
BOOST_CHECK_NO_THROW(fp.has_int("FLUXNUM"));
BOOST_CHECK_NO_THROW(fp.has_int("MULTNUM"));
const auto& fdata = fp.get_global_int("FLUXNUM");
const auto& mdata = fp.get_global_int("MULTNUM");
std::vector<int> data = { 1, 2, 1, 2, 3, 4, 3, 4 };
for (auto i = 0; i < 2 * 2 * 2; i++) {
BOOST_CHECK_EQUAL(fdata[i], mdata[i]);
BOOST_CHECK_EQUAL(fdata[i], data[i]);
}
}
namespace {
Opm::Deck aquNNCDeck_OneAquCell()
{
return Opm::Parser{}.parseString(R"(RUNSPEC
DIMENS
1 6 2 /
AQUDIMS
-- mxnaqn mxnaqc niftbl nriftb nanaqu ncamax mxnali mxaaql
1 1 1* 1* 1* 1 1* 1* /
GRID
DXV
100.0 /
DYV
6*100.0 /
DZV
2*10.0 /
DEPTHZ
14*2000.0 /
PORO
12*0.25 /
PERMX
12*100.0 /
PERMZ
12*10.0 /
COPY
PERMX PERMY /
/
MULTNUM
-- J= 1 2 3 4 5 6
1 2 2 2 1 1 -- K=1
1 2 2 2 1 1 / -- K=2
ACTNUM
-- J= 1 2 3 4 5 6
1 1 1 1 0 0 -- K=1
1 1 1 1 0 0 / -- K=2
MULTREGT -- 0
1 2 0.1 1* 'NONNC' /
/
MULTREGT -- 1
1 2 0.2 1* 'ALL' /
/
MULTREGT -- 2
1 2 0.3 1* 'NOAQUNNC' /
/
MULTREGT -- 3
1 2 0.4 1* 'NNC' /
/
AQUNUM
--AQnr. I J K Area Length Poro Perm Depth Initial.Pr PVTNUM SATNUM
1 1 5 2 100.0E+3 1000 0.25 400 2005.00 300.0 1 1 / MULTNUM=1
/
AQUCON
-- Connect numerical aquifer to the reservoir
-- Id.nr I1 I2 J1 J2 K1 K2 Face Trans.mult. Trans.opt.
1 1 1 4 4 2 2 'J+' 1.00 1* /
/
)");
}
Opm::Deck aquNNCDeck_ThreeAquCells()
{
return Opm::Parser{}.parseString(R"(RUNSPEC
DIMENS
1 10 2 /
AQUDIMS
-- mxnaqn mxnaqc niftbl nriftb nanaqu ncamax mxnali mxaaql
1 1 1* 1* 1* 1 1* 1* /
GRID
DXV
100.0 /
DYV
10*100.0 /
DZV
2*10.0 /
DEPTHZ
22*2000.0 /
PORO
20*0.25 /
PERMX
20*100.0 /
PERMZ
20*10.0 /
COPY
PERMX PERMY /
/
MULTNUM
-- J= 1 2 3 4 5 6 7 8 9 10
1 2 2 2 2 2 3 4 4 4 -- K=1
1 2 2 2 2 2 3 4 4 4 / -- K=2
ACTNUM
-- J= 1 2 3 4 5 6 7 8 9 10
1 1 1 1 0 0 0 0 0 0 -- K=1
1 1 1 1 0 0 0 0 0 0 / -- K=2
MULTREGT -- 0
1 2 0.5 1* 'ALL' /
2 3 0.1 1* 'ALL' /
3 4 0.01 1* 'ALL' /
/
MULTREGT -- 1
1 2 0.5 1* 'NONNC' /
2 3 0.1 1* 'NONNC' /
3 4 0.01 1* 'NONNC' /
/
MULTREGT -- 2
1 2 0.5 1* 'NOAQUNNC' /
2 3 0.1 1* 'NOAQUNNC' /
3 4 0.01 1* 'NOAQUNNC' /
/
MULTREGT -- 3
1 2 0.5 1* 'NNC' /
2 3 0.1 1* 'NNC' /
3 4 0.01 1* 'NNC' /
/
AQUNUM
--AQnr. I J K Area Length Poro Perm Depth Initial.Pr PVTNUM SATNUM
1 1 6 2 100.0E+3 1000 0.25 400 2005.00 300.0 1 1 / MULTNUM=2
1 1 7 2 100.0E+3 1000 0.25 400 2005.00 300.0 1 1 / MULTNUM=3
1 1 8 2 100.0E+3 1000 0.25 400 2005.00 300.0 1 1 / MULTNUM=4
/
AQUCON
-- Connect numerical aquifer to the reservoir
-- Id.nr I1 I2 J1 J2 K1 K2 Face Trans.mult. Trans.opt.
1 1 1 4 4 2 2 'J+' 1.00 1* /
/
)");
}
} // Anonymous namespace
BOOST_AUTO_TEST_CASE(AQUNNC_Handling_OneAquCell)
{
const auto deck = aquNNCDeck_OneAquCell();
const auto grid = Opm::EclipseGrid { deck };
const auto fp = Opm::FieldPropsManager {
deck, Opm::Phases { true, true, true },
grid, Opm::TableManager { deck }
};
auto makeScanner = [&deck, &grid, &fp, aquNum = Opm::NumericalAquifers { deck, grid, fp }]
(const std::size_t mrtID)
{
auto scanner = Opm::MULTREGTScanner {
grid, &fp, { &deck.get<Opm::ParserKeywords::MULTREGT>()[mrtID] }
};
scanner.applyNumericalAquifer(aquNum.allAquiferCellIds());
return scanner;
};
auto getMultRegular = [&grid]
(const Opm::MULTREGTScanner& scanner,
const std::array<int,3>& c1,
const std::array<int,3>& c2,
const Opm::FaceDir::DirEnum direction)
{
return scanner.getRegionMultiplier(grid.getGlobalIndex(c1[0], c1[1], c1[2]),
grid.getGlobalIndex(c2[0], c2[1], c2[2]),
direction);
};
auto getMultNNC = [&grid]
(const Opm::MULTREGTScanner& scanner,
const std::array<int,3>& c1,
const std::array<int,3>& c2)
{
return scanner.getRegionMultiplierNNC(grid.getGlobalIndex(c1[0], c1[1], c1[2]),
grid.getGlobalIndex(c2[0], c2[1], c2[2]));
};
// 1->2: 0.1, NONNC
{
const auto scanner = makeScanner(0);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.1, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.1, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 4, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 1 }, { 0, 1, 0 }), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 4, 1 }), 1.0, 1.0e-8); // Numerical aquifer
}
// 1->2: 0.2, ALL
{
const auto scanner = makeScanner(1);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.2, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.2, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.2, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.2, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 4, 1 }, Opm::FaceDir::YPlus), 0.2, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 0.2, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 1 }, { 0, 1, 0 }), 0.2, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 4, 1 }), 0.2, 1.0e-8); // Numerical aquifer
}
// 1->2: 0.3, NOAQUNNC
{
const auto scanner = makeScanner(2);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.3, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.3, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.3, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.3, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 4, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 0.3, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 1 }, { 0, 1, 0 }), 0.3, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 4, 1 }), 1.0, 1.0e-8); // Numerical aquifer
}
// 1->2: 0.4, NNC
{
const auto scanner = makeScanner(3);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.4, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.4, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 4, 1 }, Opm::FaceDir::YPlus), 0.4, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 1 }, { 0, 1, 0 }), 0.4, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 4, 1 }), 0.4, 1.0e-8); // Numerical aquifer
}
}
BOOST_AUTO_TEST_CASE(AQUNNC_Handling_ThreeAquCells)
{
const auto deck = aquNNCDeck_ThreeAquCells();
const auto grid = Opm::EclipseGrid { deck };
const auto fp = Opm::FieldPropsManager {
deck, Opm::Phases { true, true, true },
grid, Opm::TableManager { deck }
};
auto makeScanner = [&deck, &grid, &fp, aquNum = Opm::NumericalAquifers { deck, grid, fp }]
(const std::size_t mrtID)
{
auto scanner = Opm::MULTREGTScanner {
grid, &fp, { &deck.get<Opm::ParserKeywords::MULTREGT>()[mrtID] }
};
scanner.applyNumericalAquifer(aquNum.allAquiferCellIds());
return scanner;
};
auto getMultRegular = [&grid]
(const Opm::MULTREGTScanner& scanner,
const std::array<int,3>& c1,
const std::array<int,3>& c2,
const Opm::FaceDir::DirEnum direction)
{
return scanner.getRegionMultiplier(grid.getGlobalIndex(c1[0], c1[1], c1[2]),
grid.getGlobalIndex(c2[0], c2[1], c2[2]),
direction);
};
auto getMultNNC = [&grid]
(const Opm::MULTREGTScanner& scanner,
const std::array<int,3>& c1,
const std::array<int,3>& c2)
{
return scanner.getRegionMultiplierNNC(grid.getGlobalIndex(c1[0], c1[1], c1[2]),
grid.getGlobalIndex(c2[0], c2[1], c2[2]));
};
// 1->2: 0.5 , ALL
// 2->3: 0.1 , ALL
// 3->4: 0.01, ALL
{
const auto scanner = makeScanner(0);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 5, 1 }, Opm::FaceDir::YPlus), 1.0 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 5, 1 }, { 0, 6, 1 }, Opm::FaceDir::YPlus), 0.1 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 6, 1 }, { 0, 7, 1 }, Opm::FaceDir::YPlus), 0.01, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 0.5 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 5, 1 }), 1.0 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 5, 1 }, { 0, 6, 1 }), 0.1 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 6, 1 }, { 0, 7, 1 }), 0.01, 1.0e-8);
}
// 1->2: 0.5 , NONNC
// 2->3: 0.1 , NONNC
// 3->4: 0.01, NONNC
{
const auto scanner = makeScanner(1);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 5, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 5, 1 }, { 0, 6, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 6, 1 }, { 0, 7, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 1.0 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 5, 1 }), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 5, 1 }, { 0, 6, 1 }), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 6, 1 }, { 0, 7, 1 }), 1.0, 1.0e-8);
}
// 1->2: 0.5 , NOAQUNNC
// 2->3: 0.1 , NOAQUNNC
// 3->4: 0.01, NOAQUNNC
{
const auto scanner = makeScanner(2);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 5, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 5, 1 }, { 0, 6, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 6, 1 }, { 0, 7, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 0.5 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 5, 1 }), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 5, 1 }, { 0, 6, 1 }), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 6, 1 }, { 0, 7, 1 }), 1.0, 1.0e-8);
}
// 1->2: 0.5 , NNC
// 2->3: 0.1 , NNC
// 3->4: 0.01, NNC
{
const auto scanner = makeScanner(3);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 0 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 0 }, Opm::FaceDir::YPlus), 0.5, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 0, 1 }, { 0, 1, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Both cells in MULTNUM == 2
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 0 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 0 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8); // NNC
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 1, 1 }, { 0, 2, 1 }, Opm::FaceDir::YPlus), 1.0, 1.0e-8);
// Numerical aquifer
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 3, 1 }, { 0, 5, 1 }, Opm::FaceDir::YPlus), 1.0 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 5, 1 }, { 0, 6, 1 }, Opm::FaceDir::YPlus), 0.1 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultRegular(scanner, { 0, 6, 1 }, { 0, 7, 1 }, Opm::FaceDir::YPlus), 0.01, 1.0e-8);
// NNCs
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 0, 0 }, { 0, 1, 1 }), 0.5 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 3, 1 }, { 0, 5, 1 }), 1.0 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 5, 1 }, { 0, 6, 1 }), 0.1 , 1.0e-8);
BOOST_CHECK_CLOSE(getMultNNC(scanner, { 0, 6, 1 }, { 0, 7, 1 }), 0.01, 1.0e-8);
}
}