Make MULTREGT work for NNC.

The region multipliers are no longer added  to the cartesian logical
MULT[XYZ] structure. Instead a new method
getRegionMultiplier(globalIndex1, globalIndex2,FaceDir) is added that
return the multiplier between globalIndex1 cell and globalIndex2 cell.
The face direction is added to support directional dependent MULTREGT
input. This implementation of MULTREGT also supports restricting the
multipliers to only apply for NNC or NONNNC.
This commit is contained in:
Tor Harald Sandve 2014-12-05 11:14:53 +01:00 committed by Andreas Lauser
parent b924f6cd02
commit bb40baa96f
8 changed files with 204 additions and 246 deletions

View File

@ -360,13 +360,13 @@ namespace Opm {
void EclipseState::initMULTREGT(DeckConstPtr deck, ParserLogPtr /*parserLog*/) {
EclipseGridConstPtr grid = getEclipseGrid();
std::shared_ptr<MULTREGTScanner> scanner = std::make_shared<MULTREGTScanner>();
std::vector<Opm::DeckKeywordConstPtr> keywords;
{
std::shared_ptr<Opm::GRIDSection> gridSection(new Opm::GRIDSection(deck) );
for (size_t index=0; index < gridSection->count("MULTREGT"); index++) {
DeckKeywordConstPtr multregtKeyword = gridSection->getKeyword("MULTREGT" , index);
scanner->addKeyword( multregtKeyword );
keywords.push_back( multregtKeyword );
}
}
@ -375,11 +375,12 @@ namespace Opm {
std::shared_ptr<Opm::EDITSection> editSection(new Opm::EDITSection(deck) );
for (size_t index=0; index < editSection->count("MULTREGT"); index++) {
DeckKeywordConstPtr multregtKeyword = editSection->getKeyword("MULTREGT" , index);
scanner->addKeyword( multregtKeyword );
keywords.push_back( multregtKeyword );
}
}
std::shared_ptr<MULTREGTScanner> scanner = std::make_shared<MULTREGTScanner>( m_intGridProperties, keywords);
m_transMult->applyMULTREGT( scanner , m_intGridProperties);
m_transMult->setMultregtScanner( scanner );
}

View File

@ -94,8 +94,68 @@ namespace Opm {
/*****************************************************************/
/*
Observe that the (REGION1 -> REGION2) pairs behave like keys;
i.e. for the MULTREGT keyword
MULTREGT
2 4 0.75 Z ALL M /
2 4 2.50 XY ALL F /
/
The first record is completely overweritten by the second
record, this is because the both have the (2 -> 4) region
identifiers. This behaviourt is ensured by using a map with
std::pair<region1,region2> as key.
This function starts with some initial preprocessing to create a
map which looks like this:
searchMap = {"MULTNUM" : {std::pair(1,2) : std::tuple(TransFactor , Face , Region),
std::pair(4,7) : std::tuple(TransFactor , Face , Region),
...},
"FLUXNUM" : {std::pair(4,8) : std::tuple(TransFactor , Face , Region),
std::pair(1,4) : std::tuple(TransFactor , Face , Region),
...}}
Then it will go through the different regions and looking for
interface with the wanted region values.
*/
MULTREGTScanner::MULTREGTScanner(std::shared_ptr<GridProperties<int> > cellRegionNumbers, const std::vector<DeckKeywordConstPtr>& keywords ) :
m_cellRegionNumbers(cellRegionNumbers) {
for (int indx = 0; indx < keywords.size(); indx++){
addKeyword(keywords[indx]);
}
MULTREGTSearchMap searchPairs;
for (std::vector<MULTREGTRecord>::const_iterator record = m_records.begin(); record != m_records.end(); ++record) {
if (cellRegionNumbers->hasKeyword( record->m_region.getValue())) {
if (record->m_srcRegion.hasValue() && record->m_targetRegion.hasValue()) {
int srcRegion = record->m_srcRegion.getValue();
int targetRegion = record->m_targetRegion.getValue();
if (srcRegion != targetRegion) {
std::pair<int,int> pair{ srcRegion, targetRegion };
searchPairs[pair] = &(*record);
}
}
}
else
throw std::logic_error("MULTREGT record is based on region: " + record->m_region.getValue() + " which is not in the deck");
}
for (auto iter = searchPairs.begin(); iter != searchPairs.end(); ++iter) {
const MULTREGTRecord * record = (*iter).second;
std::pair<int,int> pair = (*iter).first;
const std::string& keyword = record->m_region.getValue();
if (m_searchMap.count(keyword) == 0)
m_searchMap[keyword] = MULTREGTSearchMap();
m_searchMap[keyword][pair] = record;
}
MULTREGTScanner::MULTREGTScanner() {
}
@ -104,8 +164,8 @@ namespace Opm {
for (auto iter = deckKeyword->begin(); iter != deckKeyword->end(); ++iter) {
MULTREGTRecord record( *iter );
if (record.m_nncBehaviour != MULTREGT::ALL)
throw std::invalid_argument("Sorry - currently only \'ALL\' is supported for MULTREGT NNC behaviour.");
if (record.m_nncBehaviour == MULTREGT::NOAQUNNC)
throw std::invalid_argument("Sorry - currently we do not support \'NOAQUNNC\' for MULTREGT.");
if (!record.m_srcRegion.hasValue())
throw std::invalid_argument("Sorry - currently it is not supported with a defaulted source region value.");
@ -166,131 +226,46 @@ namespace Opm {
-----------
*/
void MULTREGTScanner::checkConnection( MULTREGTSearchMap& map , std::vector< MULTREGTConnection >& connections, std::shared_ptr<GridProperty<int> > region, size_t globalIndex1 , size_t globalIndex2 , FaceDir::DirEnum faceDir1 ,FaceDir::DirEnum faceDir2) {
int regionValue1 = region->iget(globalIndex1);
int regionValue2 = region->iget(globalIndex2);
double MULTREGTScanner::getRegionMultiplier(size_t globalIndex1 , size_t globalIndex2, FaceDir::DirEnum faceDir) const {
std::pair<int,int> pair{regionValue1 , regionValue2};
if (map.count(pair) == 1) {
const MULTREGTRecord * record = map[pair];
if (record->m_directions & faceDir1) {
connections.push_back( MULTREGTConnection{ globalIndex1 , faceDir1 , record->m_transMultiplier } );
}
}
pair = std::pair<int,int>{regionValue2 , regionValue1};
if (map.count(pair) == 1) {
const MULTREGTRecord * record = map[pair];
if (record->m_directions & faceDir2) {
connections.push_back( MULTREGTConnection{ globalIndex2 , faceDir2 , record->m_transMultiplier } );
}
}
}
/*
Observe that the (REGION1 -> REGION2) pairs behave like keys;
i.e. for the MULTREGT keyword
MULTREGT
2 4 0.75 Z ALL M /
2 4 2.50 XY ALL F /
/
The first record is completely overweritten by the second
record, this is because the both have the (2 -> 4) region
identifiers. This behaviourt is ensured by using a map with
std::pair<region1,region2> as key.
This function starts with some initial preprocessing to create a
map which looks like this:
searchMap = {"MULTNUM" : {std::pair(1,2) : std::tuple(TransFactor , Face , Region),
std::pair(4,7) : std::tuple(TransFactor , Face , Region),
...},
"FLUXNUM" : {std::pair(4,8) : std::tuple(TransFactor , Face , Region),
std::pair(1,4) : std::tuple(TransFactor , Face , Region),
...}}
Then it will go through the different regions and looking for
interface with the wanted region values.
*/
const std::vector< MULTREGTConnection > MULTREGTScanner::scanRegions( std::shared_ptr<Opm::GridProperties<int> > regions) {
std::vector< MULTREGTConnection > connections;
std::map<std::string , MULTREGTSearchMap> searchMap;
{
MULTREGTSearchMap searchPairs;
for (std::vector<MULTREGTRecord>::const_iterator record = m_records.begin(); record != m_records.end(); ++record) {
if (regions->hasKeyword( record->m_region.getValue())) {
if (record->m_srcRegion.hasValue() && record->m_targetRegion.hasValue()) {
int srcRegion = record->m_srcRegion.getValue();
int targetRegion = record->m_targetRegion.getValue();
if (srcRegion != targetRegion) {
std::pair<int,int> pair{ srcRegion, targetRegion };
searchPairs[pair] = &(*record);
}
}
}
else
throw std::logic_error("MULTREGT record is based on region: " + record->m_region.getValue() + " which is not in the deck");
}
for (auto iter = searchPairs.begin(); iter != searchPairs.end(); ++iter) {
const MULTREGTRecord * record = (*iter).second;
std::pair<int,int> pair = (*iter).first;
const std::string& keyword = record->m_region.getValue();
if (searchMap.count(keyword) == 0)
searchMap[keyword] = MULTREGTSearchMap();
searchMap[keyword][pair] = record;
}
}
// Iterate through the different regions
for (auto iter = searchMap.begin(); iter != searchMap.end(); iter++) {
std::shared_ptr<GridProperty<int> > region = regions->getKeyword( (*iter).first );
for (auto iter = m_searchMap.begin(); iter != m_searchMap.end(); iter++) {
std::shared_ptr<Opm::GridProperty<int> > region = m_cellRegionNumbers->getKeyword( (*iter).first );
MULTREGTSearchMap map = (*iter).second;
int regionId1 = region->iget(globalIndex1);
int regionId2 = region->iget(globalIndex2);
// Iterate through all the cells in the region.
for (size_t k=0; k < region->getNZ(); k++) {
for (size_t j = 0; j < region->getNY(); j++) {
for (size_t i = 0; i < region->getNX(); i++) {
size_t globalIndex1 = i + j*region->getNX() + k*region->getNY() * region->getNX();
// X Direction
if ((i + 1) < region->getNX()) {
size_t globalIndex2 = globalIndex1 + 1;
std::pair<int,int> pair{regionId1 , regionId2};
if (map.count(pair) != 1 || !(map.at(pair)->m_directions & faceDir)) {
pair = std::pair<int,int>{regionId2 , regionId1};
if (map.count(pair) != 1 || !(map.at(pair)->m_directions & faceDir))
continue;
}
const MULTREGTRecord * record = map[pair];
checkConnection( map , connections, region , globalIndex1 , globalIndex2 , FaceDir::XPlus , FaceDir::XMinus);
}
bool applyMultiplier = true;
int i1 = globalIndex1%region->getNX();
int i2 = globalIndex2%region->getNX();
int j1 = globalIndex1/region->getNX()%region->getNY();
int j2 = globalIndex2/region->getNX()%region->getNY();
// Y Direction
if ((j + 1) < region->getNY()) {
size_t globalIndex2 = globalIndex1 + region->getNX();
if (record->m_nncBehaviour == MULTREGT::NNC){
applyMultiplier = true;
if ((std::abs(i1-i2) == 0 && std::abs(j1-j2) == 1) || (std::abs(i1-i2) == 1 && std::abs(j1-j2) == 0))
applyMultiplier = false;
}
else if (record->m_nncBehaviour == MULTREGT::NONNC){
applyMultiplier = false;
if ((std::abs(i1-i2) == 0 && std::abs(j1-j2) == 1) || (std::abs(i1-i2) == 1 && std::abs(j1-j2) == 0))
applyMultiplier = true;
}
checkConnection( map , connections, region , globalIndex1 , globalIndex2 , FaceDir::YPlus , FaceDir::YMinus);
}
// Z Direction
if ((k + 1) < region->getNZ()) {
size_t globalIndex2 = globalIndex1 + region->getNX() * region->getNY();
checkConnection( map , connections, region , globalIndex1 , globalIndex2 , FaceDir::ZPlus , FaceDir::ZMinus);
}
}
}
if (applyMultiplier) {
return record->m_transMultiplier;
}
}
return connections;
return 1;
}
}

View File

@ -66,16 +66,15 @@ namespace Opm {
class MULTREGTScanner {
public:
MULTREGTScanner();
void addKeyword(DeckKeywordConstPtr deckKeyword);
const std::vector< std::tuple<size_t , FaceDir::DirEnum , double> > scanRegions( std::shared_ptr<Opm::GridProperties<int> > regions);
static void assertKeywordSupported(DeckKeywordConstPtr deckKeyword);
MULTREGTScanner(std::shared_ptr<GridProperties<int> > cellRegionNumbers, const std::vector<DeckKeywordConstPtr>& keywords);
double getRegionMultiplier(size_t globalCellIdx1, size_t globalCellIdx2, FaceDir::DirEnum faceDir) const;
private:
void checkConnection( MULTREGTSearchMap& map , std::vector< MULTREGTConnection >& connections, std::shared_ptr<GridProperty<int> > region , size_t globalIndex1 , size_t globalIndex2 , FaceDir::DirEnum faceDir1 ,FaceDir::DirEnum faceDir2);
void addKeyword(DeckKeywordConstPtr deckKeyword);
void assertKeywordSupported(DeckKeywordConstPtr deckKeyword);
std::vector< MULTREGTRecord > m_records;
std::map<std::string , MULTREGTSearchMap> m_searchMap;
std::shared_ptr<GridProperties<int> > m_cellRegionNumbers;
};
}

View File

@ -73,6 +73,10 @@ namespace Opm {
return getMultiplier__( globalIndex , faceDir );
}
double TransMult::getRegionMultiplier(size_t globalCellIndex1, size_t globalCellIndex2, FaceDir::DirEnum faceDir) const {
return m_multregtScanner->getRegionMultiplier(globalCellIndex1, globalCellIndex2, faceDir);
}
bool TransMult::hasDirectionProperty(FaceDir::DirEnum faceDir) const {
if (m_trans.count(faceDir) == 1)
@ -127,18 +131,7 @@ namespace Opm {
void TransMult::applyMULTREGT( std::shared_ptr<MULTREGTScanner> multregtScanner , std::shared_ptr<GridProperties<int> > regions) {
const std::vector< MULTREGTConnection > connections = multregtScanner->scanRegions( regions );
for (auto iter = connections.begin(); iter != connections.end(); ++iter) {
MULTREGTConnection connection = *iter;
FaceDir::DirEnum faceDir = std::get<1>( connection );
std::shared_ptr<GridProperty<double> > multProperty = getDirectionProperty(faceDir);
{
size_t globalIndex = std::get<0>( connection );
double transMult = std::get<2>( connection );
multProperty->multiplyValueAtIndex( globalIndex , transMult);
}
}
void TransMult::setMultregtScanner( std::shared_ptr<const MULTREGTScanner> multregtScanner) {
m_multregtScanner = multregtScanner;
}
}

View File

@ -48,11 +48,12 @@ namespace Opm {
TransMult(size_t nx , size_t ny , size_t nz);
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;
bool hasDirectionProperty(FaceDir::DirEnum faceDir) const;
std::shared_ptr<GridProperty<double> > getDirectionProperty(FaceDir::DirEnum faceDir);
void applyMULT(std::shared_ptr<const GridProperty<double> > srcMultProp, FaceDir::DirEnum faceDir);
void applyMULTFLT( std::shared_ptr<const FaultCollection> faults);
void applyMULTREGT( std::shared_ptr<MULTREGTScanner> multregtScanner , std::shared_ptr<GridProperties<int> > regions);
void setMultregtScanner(std::shared_ptr<const MULTREGTScanner> multregtScanner);
private:
size_t getGlobalIndex(size_t i , size_t j , size_t k) const;
@ -63,6 +64,7 @@ namespace Opm {
size_t m_nx , m_ny , m_nz;
std::map<FaceDir::DirEnum , std::shared_ptr<GridProperty<double> > > m_trans;
std::map<FaceDir::DirEnum , std::string> m_names;
std::shared_ptr<const MULTREGTScanner> m_multregtScanner;
};
}

View File

@ -104,24 +104,28 @@ BOOST_AUTO_TEST_CASE(InvalidInput) {
SupportedKeywordInfo("OPERNUM" , 1 , "1") ,
SupportedKeywordInfo("MULTNUM" , 1 , "1") });
Opm::MULTREGTScanner scanner;
Opm::DeckPtr deck = createInvalidMULTREGTDeck();
std::shared_ptr<Opm::EclipseGrid> grid = std::make_shared<Opm::EclipseGrid>( deck );
std::shared_ptr<Opm::GridProperties<int> > gridProperties = std::make_shared<Opm::GridProperties<int> >(grid, supportedKeywords);
Opm::DeckKeywordConstPtr multregtKeyword0 = deck->getKeyword("MULTREGT",0);
Opm::DeckKeywordConstPtr multregtKeyword1 = deck->getKeyword("MULTREGT",1);
Opm::DeckKeywordConstPtr multregtKeyword2 = deck->getKeyword("MULTREGT",2);
// Invalid direction
BOOST_CHECK_THROW( scanner.addKeyword( multregtKeyword0 ) , std::invalid_argument);
std::vector<Opm::DeckKeywordConstPtr> keywords0;
Opm::DeckKeywordConstPtr multregtKeyword0 = deck->getKeyword("MULTREGT",0);
keywords0.push_back( multregtKeyword0 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner(gridProperties,keywords0); , std::invalid_argument);
// Not supported region
BOOST_CHECK_THROW( scanner.addKeyword( multregtKeyword1 ) , std::invalid_argument);
std::vector<Opm::DeckKeywordConstPtr> keywords1;
Opm::DeckKeywordConstPtr multregtKeyword1 = deck->getKeyword("MULTREGT",1);
keywords1.push_back( multregtKeyword1 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner(gridProperties,keywords1); , std::invalid_argument);
// The keyword is ok; but it refers to a region which is not in the deck.
scanner.addKeyword( multregtKeyword2 );
BOOST_CHECK_THROW( scanner.scanRegions( gridProperties ) , std::logic_error);
std::vector<Opm::DeckKeywordConstPtr> keywords2;
Opm::DeckKeywordConstPtr multregtKeyword2 = deck->getKeyword("MULTREGT",2);
keywords2.push_back( multregtKeyword2 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner(gridProperties,keywords2); , std::logic_error);
}
@ -141,7 +145,7 @@ static Opm::DeckPtr createNotSupportedMULTREGTDeck() {
"3 4 5\n"
"/\n"
"MULTREGT\n"
"1 2 0.50 X NNC M / -- Not yet support NNC behaviour \n"
"1 2 0.50 X NOAQUNNC F / -- Not support NOAQUNNC behaviour \n"
"/\n"
"MULTREGT\n"
"* 2 0.50 X ALL M / -- Defaulted from region value \n"
@ -161,28 +165,41 @@ static Opm::DeckPtr createNotSupportedMULTREGTDeck() {
BOOST_AUTO_TEST_CASE(NotSupported) {
typedef Opm::GridProperties<int>::SupportedKeywordInfo SupportedKeywordInfo;
std::shared_ptr<std::vector<SupportedKeywordInfo> > supportedKeywords(new std::vector<SupportedKeywordInfo>{
SupportedKeywordInfo("FLUXNUM" , 1 , "1") ,
SupportedKeywordInfo("OPERNUM" , 1 , "1") ,
SupportedKeywordInfo("MULTNUM" , 1 , "1") });
Opm::DeckPtr deck = createNotSupportedMULTREGTDeck();
Opm::DeckKeywordConstPtr multregtKeyword0 = deck->getKeyword("MULTREGT",0);
Opm::DeckKeywordConstPtr multregtKeyword1 = deck->getKeyword("MULTREGT",1);
Opm::DeckKeywordConstPtr multregtKeyword2 = deck->getKeyword("MULTREGT",2);
Opm::DeckKeywordConstPtr multregtKeyword3 = deck->getKeyword("MULTREGT",3);
Opm::MULTREGTScanner scanner;
// Not supported NNC behaviour
BOOST_CHECK_THROW( Opm::MULTREGTScanner::assertKeywordSupported(multregtKeyword0) , std::invalid_argument);
BOOST_CHECK_THROW( scanner.addKeyword(multregtKeyword0) , std::invalid_argument);
std::shared_ptr<Opm::EclipseGrid> grid = std::make_shared<Opm::EclipseGrid>( deck );
std::shared_ptr<Opm::GridProperties<int> > gridProperties = std::make_shared<Opm::GridProperties<int> >(grid, supportedKeywords);
// Not support NOAQUNNC behaviour
std::vector<Opm::DeckKeywordConstPtr> keywords0;
Opm::DeckKeywordConstPtr multregtKeyword0 = deck->getKeyword("MULTREGT",0);
keywords0.push_back( multregtKeyword0 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner(gridProperties,keywords0); , std::invalid_argument);
// Defaulted from value - not supported
BOOST_CHECK_THROW( Opm::MULTREGTScanner::assertKeywordSupported(multregtKeyword1) , std::invalid_argument);
BOOST_CHECK_THROW( scanner.addKeyword(multregtKeyword1) , std::invalid_argument);
std::vector<Opm::DeckKeywordConstPtr> keywords1;
Opm::DeckKeywordConstPtr multregtKeyword1 = deck->getKeyword("MULTREGT",1);
keywords1.push_back( multregtKeyword1 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner(gridProperties,keywords1); , std::invalid_argument);
// Defaulted to value - not supported
BOOST_CHECK_THROW( Opm::MULTREGTScanner::assertKeywordSupported(multregtKeyword2) , std::invalid_argument);
BOOST_CHECK_THROW( scanner.addKeyword(multregtKeyword2) , std::invalid_argument);
std::vector<Opm::DeckKeywordConstPtr> keywords2;
Opm::DeckKeywordConstPtr multregtKeyword2 = deck->getKeyword("MULTREGT",2);
keywords2.push_back( multregtKeyword2 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner(gridProperties,keywords2); , std::invalid_argument);
// srcValue == targetValue - not supported
BOOST_CHECK_THROW( Opm::MULTREGTScanner::assertKeywordSupported(multregtKeyword3) , std::invalid_argument);
BOOST_CHECK_THROW( scanner.addKeyword(multregtKeyword3) , std::invalid_argument);
std::vector<Opm::DeckKeywordConstPtr> keywords3;
Opm::DeckKeywordConstPtr multregtKeyword3 = deck->getKeyword("MULTREGT",3);
keywords3.push_back( multregtKeyword3 );
BOOST_CHECK_THROW( Opm::MULTREGTScanner scanner(gridProperties,keywords3); , std::invalid_argument);
}
@ -211,6 +228,10 @@ static Opm::DeckPtr createSimpleMULTREGTDeck() {
"MULTREGT\n"
"2 1 1.50 X ALL M / \n"
"/\n"
"MULTREGT\n"
"2 1 2.50 XYZ NNC M / \n"
"2 1 3.50 XYZ NONNC M / \n"
"/\n"
"EDIT\n"
"\n";
@ -219,72 +240,6 @@ static Opm::DeckPtr createSimpleMULTREGTDeck() {
}
BOOST_AUTO_TEST_CASE(SimpleMULTREGT) {
typedef Opm::GridProperties<int>::SupportedKeywordInfo SupportedKeywordInfo;
std::shared_ptr<std::vector<SupportedKeywordInfo> > supportedKeywords(new std::vector<SupportedKeywordInfo>{
SupportedKeywordInfo("FLUXNUM" , 1 , "1") ,
SupportedKeywordInfo("OPERNUM" , 1 , "1") ,
SupportedKeywordInfo("MULTNUM" , 1 , "1") });
Opm::DeckPtr deck = createSimpleMULTREGTDeck();
std::shared_ptr<Opm::EclipseGrid> grid = std::make_shared<Opm::EclipseGrid>( deck );
std::shared_ptr<const Opm::Box> inputBox = std::make_shared<const Opm::Box>( grid->getNX() , grid->getNY() , grid->getNZ() );
std::shared_ptr<Opm::GridProperties<int> > gridProperties = std::make_shared<Opm::GridProperties<int> >(grid, supportedKeywords);
std::shared_ptr<Opm::GridProperty<int> > fluxNum = gridProperties->getKeyword("FLUXNUM");
std::shared_ptr<Opm::GridProperty<int> > multNum = gridProperties->getKeyword("MULTNUM");
Opm::DeckKeywordConstPtr fluxnumKeyword = deck->getKeyword("FLUXNUM",0);
Opm::DeckKeywordConstPtr multnumKeyword = deck->getKeyword("MULTNUM",0);
Opm::DeckKeywordConstPtr multregtKeyword0 = deck->getKeyword("MULTREGT",0);
Opm::DeckKeywordConstPtr multregtKeyword1 = deck->getKeyword("MULTREGT",1);
multNum->loadFromDeckKeyword( inputBox , multnumKeyword );
fluxNum->loadFromDeckKeyword( inputBox , fluxnumKeyword );
{
Opm::MULTREGTScanner scanner;
scanner.addKeyword(multregtKeyword0);
auto cells = scanner.scanRegions(gridProperties);
BOOST_CHECK_EQUAL( 2 , cells.size() );
auto cell0 = cells[0];
auto cell1 = cells[1];
BOOST_CHECK_EQUAL( 0 , std::get<0>(cell0));
BOOST_CHECK_EQUAL( Opm::FaceDir::XPlus , std::get<1>(cell0));
BOOST_CHECK_EQUAL( 0.50 , std::get<2>(cell0));
BOOST_CHECK_EQUAL( 2 , std::get<0>(cell1));
BOOST_CHECK_EQUAL( Opm::FaceDir::XPlus , std::get<1>(cell1));
BOOST_CHECK_EQUAL( 0.50 , std::get<2>(cell1));
}
{
Opm::MULTREGTScanner scanner;
scanner.addKeyword(multregtKeyword1);
auto cells = scanner.scanRegions(gridProperties);
BOOST_CHECK_EQUAL( 2 , cells.size() );
auto cell0 = cells[0];
auto cell1 = cells[1];
BOOST_CHECK_EQUAL( 1 , std::get<0>(cell0));
BOOST_CHECK_EQUAL( Opm::FaceDir::XMinus , std::get<1>(cell0));
BOOST_CHECK_EQUAL( 1.50 , std::get<2>(cell0));
BOOST_CHECK_EQUAL( 3 , std::get<0>(cell1));
BOOST_CHECK_EQUAL( Opm::FaceDir::XMinus , std::get<1>(cell1));
BOOST_CHECK_EQUAL( 1.50 , std::get<2>(cell1));
}
}
static Opm::DeckPtr createCopyMULTNUMDeck() {
const char *deckData =
"RUNSPEC\n"

View File

@ -40,8 +40,7 @@ using namespace Opm;
BOOST_AUTO_TEST_CASE( parse_MULTREGT_OK ) {
ParserPtr parser(new Parser());
DeckPtr deck = parser->parseFile("testdata/integration_tests/MULTREGT/MULTREGT");
DeckKeywordConstPtr multregtKeyword = deck->getKeyword("MULTREGT" , 0);
BOOST_CHECK_NO_THROW( MULTREGTScanner::assertKeywordSupported( multregtKeyword ) );
BOOST_CHECK_NO_THROW( deck->getKeyword("MULTREGT" , 0); );
}
@ -52,14 +51,47 @@ BOOST_AUTO_TEST_CASE( MULTREGT_ECLIPSE_STATE ) {
EclipseState state(deck);
auto transMult = state.getTransMult();
BOOST_CHECK_EQUAL( 0.10 , transMult->getMultiplier( 0 , 0 , 0 , FaceDir::XPlus ));
BOOST_CHECK_EQUAL( 0.10 , transMult->getMultiplier( 0 , 1 , 0 , FaceDir::XPlus ));
BOOST_CHECK_EQUAL( 0.20 , transMult->getMultiplier( 1 , 0 , 0 , FaceDir::XMinus ));
BOOST_CHECK_EQUAL( 0.20 , transMult->getMultiplier( 1 , 1 , 0 , FaceDir::XMinus ));
BOOST_CHECK_EQUAL( 1.50 , transMult->getMultiplier( 0 , 0 , 0 , FaceDir::ZPlus ));
BOOST_CHECK_EQUAL( 1.50 , transMult->getMultiplier( 0 , 1 , 0 , FaceDir::ZPlus ));
BOOST_CHECK_EQUAL( 1.00 , transMult->getMultiplier( 1 , 0 , 0 , FaceDir::ZPlus ));
BOOST_CHECK_EQUAL( 1.00 , transMult->getMultiplier( 1 , 1 , 0 , FaceDir::ZPlus ));
BOOST_CHECK_EQUAL( 0.60 , transMult->getMultiplier( 1 , 0 , 1 , FaceDir::ZMinus ));
BOOST_CHECK_EQUAL( 0.60 , transMult->getMultiplier( 1 , 1 , 1 , FaceDir::ZMinus ));
// Test NONNC
// cell 0 and 1 are neigbours
BOOST_CHECK_EQUAL( 0.10 , transMult->getRegionMultiplier( 0 , 1 , FaceDir::DirEnum::XPlus));
// cell 0 and 3 are not neigbours ==> 1
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 0 , 3 , FaceDir::DirEnum::XPlus));
// Test NNC
// cell 4 and 5 are neigbours ==> 1
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 4 , 5 , FaceDir::DirEnum::XPlus));
// cell 4 and 7 are not neigbours
BOOST_CHECK_EQUAL( 0.50 , transMult->getRegionMultiplier( 4 , 7 , FaceDir::DirEnum::XPlus));
// Test direction X, returns 1 for directions other than +-X
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 0 , 1 , FaceDir::DirEnum::YPlus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 0 , 1 , FaceDir::DirEnum::ZPlus));
BOOST_CHECK_EQUAL( 0.10 , transMult->getRegionMultiplier( 0 , 1 , FaceDir::DirEnum::XMinus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 0 , 1 , FaceDir::DirEnum::YMinus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 0 , 1 , FaceDir::DirEnum::ZMinus));
BOOST_CHECK_EQUAL( 0.20 , transMult->getRegionMultiplier( 1 , 0 , FaceDir::DirEnum::XPlus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 1 , 0 , FaceDir::DirEnum::YPlus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 1 , 0 , FaceDir::DirEnum::ZPlus));
BOOST_CHECK_EQUAL( 0.20 , transMult->getRegionMultiplier( 1 , 0 , FaceDir::DirEnum::XMinus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 1 , 0 , FaceDir::DirEnum::YMinus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 1 , 0 , FaceDir::DirEnum::ZMinus));
// Multipliers between cells of the same region should return 1
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 0 , 2 , FaceDir::DirEnum::XPlus));
BOOST_CHECK_EQUAL( 1.00 , transMult->getRegionMultiplier( 2 , 0 , FaceDir::DirEnum::XPlus));
// Test direcion XYZ, returns values for all directions
BOOST_CHECK_EQUAL( 1.50 , transMult->getRegionMultiplier( 0 , 4 , FaceDir::DirEnum::XPlus));
BOOST_CHECK_EQUAL( 1.50 , transMult->getRegionMultiplier( 0 , 4 , FaceDir::DirEnum::YPlus));
BOOST_CHECK_EQUAL( 1.50 , transMult->getRegionMultiplier( 0 , 4 , FaceDir::DirEnum::ZPlus));
BOOST_CHECK_EQUAL( 1.50 , transMult->getRegionMultiplier( 4 , 0 , FaceDir::DirEnum::XPlus));
// The first record is overwritten by the second
BOOST_CHECK_EQUAL( 2.50 , transMult->getRegionMultiplier( 3 , 7 , FaceDir::DirEnum::XPlus));
BOOST_CHECK_EQUAL( 2.50 , transMult->getRegionMultiplier( 3 , 7 , FaceDir::DirEnum::YPlus));
// The 2 4 0.75 Z input is overwritten by 2 4 2.5 XY, ==) that 2 4 Z returns the 4 2 value = 0.6
BOOST_CHECK_EQUAL( 0.60 , transMult->getRegionMultiplier( 7 , 3 , FaceDir::DirEnum::XPlus));
BOOST_CHECK_EQUAL( 0.60 , transMult->getRegionMultiplier( 3 , 7 , FaceDir::DirEnum::ZPlus));
}

View File

@ -31,7 +31,8 @@ MULTNUM
/
MULTREGT
1 2 0.10 X ALL M /
1 2 0.10 X NONNC M /
3 4 0.50 X NNC M /
/
MULTREGT