Files
opm-common/opm/parser/eclipse/EclipseState/Grid/MULTREGTScanner.cpp
Jørgen Kvalsvik 357e1e0e53 Move GridProperty< T > to source file
GridProperty< T > has only two sensible types to parametrise, int and
double. Moves the implementation and instantiation of GridProperty to
GridProperty.cpp. This also applies to GridPropertyInitializers which
has also been moved to source files.

Results are a cleaner header file (for reading & understanding the
interface) and faster compilations.
2016-03-01 08:46:23 +01:00

275 lines
10 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/>.
*/
#include <stdexcept>
#include <map>
#include <set>
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/FaceDir.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/GridProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/MULTREGTScanner.hpp>
namespace Opm {
namespace MULTREGT {
std::string RegionNameFromDeckValue(const std::string& stringValue) {
if (stringValue == "O")
return "OPERNUM";
if (stringValue == "F")
return "FLUXNUM";
if (stringValue == "M")
return "MULTNUM";
throw std::invalid_argument("The input string: " + stringValue + " was invalid. Expected: O/F/M");
}
NNCBehaviourEnum NNCBehaviourFromString(const std::string& stringValue) {
if (stringValue == "ALL")
return ALL;
if (stringValue == "NNC")
return NNC;
if (stringValue == "NONNC")
return NONNC;
if (stringValue == "NOAQUNNC")
return NOAQUNNC;
throw std::invalid_argument("The input string: " + stringValue + " was invalid. Expected: ALL/NNC/NONNC/NOAQUNNC");
}
}
MULTREGTRecord::MULTREGTRecord( const DeckRecord& deckRecord, const std::string& defaultRegion) :
m_srcRegion("SRC_REGION"),
m_targetRegion("TARGET_REGION"),
m_region("REGION" , defaultRegion)
{
const auto& srcItem = deckRecord.getItem("SRC_REGION");
const auto& targetItem = deckRecord.getItem("TARGET_REGION");
const auto& tranItem = deckRecord.getItem("TRAN_MULT");
const auto& dirItem = deckRecord.getItem("DIRECTIONS");
const auto& nncItem = deckRecord.getItem("NNC_MULT");
const auto& defItem = deckRecord.getItem("REGION_DEF");
if (!srcItem.defaultApplied(0))
m_srcRegion.setValue( srcItem.get< int >(0) );
if (!targetItem.defaultApplied(0))
m_targetRegion.setValue( targetItem.get< int >(0) );
m_transMultiplier = tranItem.get< double >(0);
m_directions = FaceDir::FromMULTREGTString( dirItem.get< std::string >(0) );
m_nncBehaviour = MULTREGT::NNCBehaviourFromString( nncItem.get< std::string >(0));
if (!defItem.defaultApplied(0))
m_region.setValue( MULTREGT::RegionNameFromDeckValue ( defItem.get< std::string >(0) ));
}
/*****************************************************************/
/*
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< const DeckKeyword* >& keywords , const std::string& defaultRegion ) :
m_cellRegionNumbers(cellRegionNumbers) {
for (size_t idx = 0; idx < keywords.size(); idx++)
this->addKeyword(*keywords[idx] , defaultRegion);
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;
}
}
void MULTREGTScanner::assertKeywordSupported( const DeckKeyword& deckKeyword, const std::string& defaultRegion) {
for (auto iter = deckKeyword.begin(); iter != deckKeyword.end(); ++iter) {
MULTREGTRecord record( *iter , defaultRegion);
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.");
if (!record.m_targetRegion.hasValue())
throw std::invalid_argument("Sorry - currently it is not supported with a defaulted target region value.");
if (record.m_srcRegion.getValue() == record.m_targetRegion.getValue())
throw std::invalid_argument("Sorry - multregt applied internally to a region is not yet supported");
}
}
void MULTREGTScanner::addKeyword( const DeckKeyword& deckKeyword , const std::string& defaultRegion) {
assertKeywordSupported( deckKeyword , defaultRegion );
for (auto iter = deckKeyword.begin(); iter != deckKeyword.end(); ++iter) {
MULTREGTRecord record( *iter , defaultRegion );
/*
The default value for the region item is to use the
region item on the previous record, or alternatively
'MULTNUM' for the first record.
*/
if (!record.m_region.hasValue()) {
if (m_records.size() > 0) {
auto previousRecord = m_records.back();
record.m_region.setValue( previousRecord.m_region.getValue() );
} else
record.m_region.setValue( "MULTNUM" );
}
m_records.push_back( record );
}
}
/*
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:
Assume the relevant MULTREGT record looks like:
1 2 0.10 XYZ ALL M /
I.e. we are checking for the boundary between regions 1 and
2. We assign the transmissibility multiplier to the correct face
of the cell with value 1:
-----------
| 1 | 2 | => MultTrans( i,j,k,FaceDir::XPlus ) *= 0.50
-----------
-----------
| 2 | 1 | => MultTrans( i+1,j,k,FaceDir::XMinus ) *= 0.50
-----------
*/
double MULTREGTScanner::getRegionMultiplier(size_t globalIndex1 , size_t globalIndex2, FaceDir::DirEnum faceDir) const {
for (auto iter = m_searchMap.begin(); iter != m_searchMap.end(); iter++) {
std::shared_ptr<const Opm::GridProperty<int> > region = m_cellRegionNumbers->getKeyword( (*iter).first );
MULTREGTSearchMap map = (*iter).second;
int regionId1 = region->iget(globalIndex1);
int regionId2 = region->iget(globalIndex2);
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];
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();
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;
}
if (applyMultiplier) {
return record->m_transMultiplier;
}
}
return 1;
}
}