Merge pull request #3655 from bska/multregt-item-5
Implement NOAQUNNC Region Multiplier Behaviour in MULTREGT
This commit is contained in:
@@ -98,10 +98,14 @@ namespace Opm {
|
||||
bool operator==(const MULTREGTScanner& data) const;
|
||||
MULTREGTScanner& operator=(const MULTREGTScanner& data);
|
||||
|
||||
void applyNumericalAquifer(const std::vector<std::size_t>& aquifer_cells);
|
||||
|
||||
double getRegionMultiplier(std::size_t globalCellIdx1,
|
||||
std::size_t globalCellIdx2,
|
||||
FaceDir::DirEnum faceDir) const;
|
||||
|
||||
double getRegionMultiplierNNC(std::size_t globalCellIdx1,
|
||||
std::size_t globalCellIdx2) const;
|
||||
|
||||
template <class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
@@ -112,6 +116,7 @@ namespace Opm {
|
||||
serializer(m_searchMap);
|
||||
|
||||
serializer(regions);
|
||||
serializer(aquifer_cells);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -126,9 +131,13 @@ namespace Opm {
|
||||
std::vector<MULTREGTRecord> m_records{};
|
||||
std::map<std::string, MULTREGTSearchMap> m_searchMap{};
|
||||
std::map<std::string, std::vector<int>> regions{};
|
||||
std::vector<std::size_t> aquifer_cells{};
|
||||
|
||||
void addKeyword(const DeckKeyword& deckKeyword);
|
||||
void assertKeywordSupported(const DeckKeyword& deckKeyword);
|
||||
|
||||
bool isAquNNC(std::size_t globalCellIdx1, std::size_t globalCellIdx2) const;
|
||||
bool isAquCell(std::size_t globalCellIdx) const;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
@@ -56,9 +56,11 @@ namespace Opm {
|
||||
double getMultiplier(size_t globalIndex, FaceDir::DirEnum faceDir) const;
|
||||
double getMultiplier(size_t i , size_t j , size_t k, FaceDir::DirEnum faceDir) const;
|
||||
double getRegionMultiplier( size_t globalCellIndex1, size_t globalCellIndex2, FaceDir::DirEnum faceDir) const;
|
||||
double getRegionMultiplierNNC(std::size_t globalCellIndex1, std::size_t globalCellIndex2) const;
|
||||
void applyMULT(const std::vector<double>& srcMultProp, FaceDir::DirEnum faceDir);
|
||||
void applyMULTFLT(const FaultCollection& faults);
|
||||
void applyMULTFLT(const Fault& fault);
|
||||
void applyNumericalAquifer(const std::vector<std::size_t>& aquifer_cells);
|
||||
|
||||
bool operator==(const TransMult& data) const;
|
||||
|
||||
|
||||
@@ -352,6 +352,8 @@ namespace Opm {
|
||||
// Add NNCs between aquifer cells and first aquifer cell and aquifer
|
||||
// connections.
|
||||
this->appendInputNNC(numerical_aquifer.aquiferCellNNCs());
|
||||
|
||||
this->m_transMult.applyNumericalAquifer(numerical_aquifer.allAquiferCellIds());
|
||||
}
|
||||
|
||||
void EclipseState::applyMULTXYZ() {
|
||||
|
||||
@@ -205,6 +205,7 @@ namespace Opm {
|
||||
std::forward_as_tuple(std::make_pair(1, 2)),
|
||||
std::forward_as_tuple(0));
|
||||
result.regions = {{"test3", {11}}};
|
||||
result.aquifer_cells = { std::size_t{17}, std::size_t{29} };
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -215,6 +216,7 @@ namespace Opm {
|
||||
&& (this->m_records == data.m_records)
|
||||
&& (this->m_searchMap == data.m_searchMap)
|
||||
&& (this->regions == data.regions)
|
||||
&& (this->aquifer_cells == data.aquifer_cells)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -226,10 +228,23 @@ namespace Opm {
|
||||
this->m_records = data.m_records;
|
||||
this->m_searchMap = data.m_searchMap;
|
||||
this->regions = data.regions;
|
||||
this->aquifer_cells = data.aquifer_cells;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MULTREGTScanner::applyNumericalAquifer(const std::vector<std::size_t>& aquifer_cells_arg)
|
||||
{
|
||||
this->aquifer_cells.insert(this->aquifer_cells.end(),
|
||||
aquifer_cells_arg.begin(),
|
||||
aquifer_cells_arg.end());
|
||||
|
||||
std::sort(this->aquifer_cells.begin(), this->aquifer_cells.end());
|
||||
this->aquifer_cells.erase(std::unique(this->aquifer_cells.begin(),
|
||||
this->aquifer_cells.end()),
|
||||
this->aquifer_cells.end());
|
||||
}
|
||||
|
||||
// This function will check the region values in globalIndex1 and
|
||||
// globalIndex and see if they match the regionvalues specified in the
|
||||
// deck. The function checks both directions:
|
||||
@@ -264,15 +279,19 @@ namespace Opm {
|
||||
};
|
||||
|
||||
auto ignoreMultiplierRecord =
|
||||
[is_adj = is_adjacent(this->gridDims, globalIndex1, globalIndex2)]
|
||||
[is_adj = is_adjacent(this->gridDims, globalIndex1, globalIndex2),
|
||||
is_aqu = this->isAquNNC(globalIndex1, globalIndex2)]
|
||||
(const MULTREGT::NNCBehaviourEnum nnc_behaviour)
|
||||
{
|
||||
// We ignore the record if either of the following conditions hold
|
||||
//
|
||||
// 1. Cells are adjacent, but record stipulates NNCs only
|
||||
// 2. Connection is an NNC, but record stipulates no NNCs
|
||||
return ( is_adj && (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NNC))
|
||||
|| (!is_adj && (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NONNC));
|
||||
// 3. Connection is associated to a numerical aquifer, but
|
||||
// record stipulates that no such connections apply.
|
||||
return ((is_adj && !is_aqu) && (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NNC))
|
||||
|| ((!is_adj || is_aqu) && (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NONNC))
|
||||
|| (is_aqu && (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NOAQUNNC));
|
||||
};
|
||||
|
||||
for (const auto& [regName, regMap] : this->m_searchMap) {
|
||||
@@ -305,6 +324,48 @@ namespace Opm {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
double MULTREGTScanner::getRegionMultiplierNNC(const std::size_t globalCellIdx1,
|
||||
const std::size_t globalCellIdx2) const
|
||||
{
|
||||
if (this->m_searchMap.empty()) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
auto ignoreMultiplierRecord =
|
||||
[is_aqu = this->isAquNNC(globalCellIdx1, globalCellIdx2)]
|
||||
(const MULTREGT::NNCBehaviourEnum nnc_behaviour)
|
||||
{
|
||||
return (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NONNC)
|
||||
|| (is_aqu && (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NOAQUNNC));
|
||||
};
|
||||
|
||||
for (const auto& [regName, regMap] : this->m_searchMap) {
|
||||
const auto& region_data = this->regions.at(regName);
|
||||
|
||||
const auto regionId1 = region_data[globalCellIdx1];
|
||||
const auto regionId2 = region_data[globalCellIdx2];
|
||||
|
||||
auto regPairPos = regMap.find({ regionId1, regionId2 });
|
||||
if ((regionId1 != regionId2) && (regPairPos == regMap.end())) {
|
||||
// 1 -> 2 not found. Try reverse direction.
|
||||
regPairPos = regMap.find({ regionId2, regionId1 });
|
||||
}
|
||||
|
||||
if (regPairPos == regMap.end()) {
|
||||
// Neither 1->2 nor 2->1 found. Move on to next region set.
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& record = this->m_records[regPairPos->second];
|
||||
|
||||
if (! ignoreMultiplierRecord(record.nnc_behaviour)) {
|
||||
return record.trans_mult;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
void MULTREGTScanner::assertKeywordSupported(const DeckKeyword& deckKeyword)
|
||||
{
|
||||
using Kw = ParserKeywords::MULTREGT;
|
||||
@@ -320,15 +381,6 @@ namespace Opm {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const auto nnc_behaviour = MULTREGT::
|
||||
NNCBehaviourFromString(deckRecord.getItem("NNC_MULT").get<std::string>(0));
|
||||
|
||||
if (nnc_behaviour == MULTREGT::NNCBehaviourEnum::NOAQUNNC) {
|
||||
throw std::invalid_argument {
|
||||
"Sorry - currently we do not support 'NOAQUNNC' for MULTREGT."
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,4 +427,18 @@ namespace Opm {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MULTREGTScanner::isAquNNC(const std::size_t globalCellIdx1,
|
||||
const std::size_t globalCellIdx2) const
|
||||
{
|
||||
return this->isAquCell(globalCellIdx1)
|
||||
|| this->isAquCell(globalCellIdx2);
|
||||
}
|
||||
|
||||
bool MULTREGTScanner::isAquCell(const std::size_t globalCellIdx) const
|
||||
{
|
||||
return std::binary_search(this->aquifer_cells.begin(),
|
||||
this->aquifer_cells.end(),
|
||||
globalCellIdx);
|
||||
}
|
||||
} // namespace Opm
|
||||
|
||||
@@ -114,6 +114,10 @@ namespace Opm {
|
||||
return m_multregtScanner.getRegionMultiplier(globalCellIndex1, globalCellIndex2, faceDir);
|
||||
}
|
||||
|
||||
double TransMult::getRegionMultiplierNNC(std::size_t globalCellIndex1, std::size_t globalCellIndex2) const {
|
||||
return m_multregtScanner.getRegionMultiplierNNC(globalCellIndex1, globalCellIndex2);
|
||||
}
|
||||
|
||||
bool TransMult::hasDirectionProperty(FaceDir::DirEnum faceDir) const {
|
||||
return m_trans.count(faceDir) == 1;
|
||||
}
|
||||
@@ -156,6 +160,10 @@ namespace Opm {
|
||||
}
|
||||
}
|
||||
|
||||
void TransMult::applyNumericalAquifer(const std::vector<std::size_t>& aquifer_cells) {
|
||||
m_multregtScanner.applyNumericalAquifer(aquifer_cells);
|
||||
}
|
||||
|
||||
bool TransMult::operator==(const TransMult& data) const {
|
||||
return this->m_nx == data.m_nx &&
|
||||
this->m_ny == data.m_ny &&
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#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>
|
||||
@@ -172,13 +173,6 @@ BOOST_AUTO_TEST_CASE(NotSupported) {
|
||||
Opm::EclipseGrid eg( deck );
|
||||
Opm::FieldPropsManager fp(deck, Opm::Phases{true, true, true}, eg, tm);
|
||||
|
||||
|
||||
// Not support NOAQUNNC behaviour
|
||||
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 );
|
||||
|
||||
// srcValue == targetValue - not supported
|
||||
std::vector<const Opm::DeckKeyword*> keywords1;
|
||||
const Opm::DeckKeyword& multregtKeyword1 = deck["MULTREGT"][1];
|
||||
@@ -296,3 +290,463 @@ BOOST_AUTO_TEST_CASE(MULTREGT_COPY_MULTNUM) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user