Files
opm-common/opm/parser/eclipse/EclipseState/Grid/GridProperty.cpp
2016-09-08 09:14:30 +02:00

485 lines
16 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 <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/Box.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/GridProperty.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/GridProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/RtempvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
namespace Opm {
template< typename T >
static std::function< std::vector< T >( size_t ) > constant( T val ) {
return [=]( size_t size ) { return std::vector< T >( size, val ); };
}
template< typename T >
static std::function< void( std::vector< T >& ) > noop() {
return []( std::vector< T >& ) { return; };
}
template< typename T >
GridPropertySupportedKeywordInfo< T >::GridPropertySupportedKeywordInfo(
const std::string& name,
std::function< std::vector< T >( size_t ) > init,
std::function< void( std::vector< T >& ) > post,
const std::string& dimString ) :
m_keywordName( name ),
m_initializer( init ),
m_postProcessor( post ),
m_dimensionString( dimString )
{}
template< typename T >
GridPropertySupportedKeywordInfo< T >::GridPropertySupportedKeywordInfo(
const std::string& name,
std::function< std::vector< T >( size_t ) > init,
const std::string& dimString ) :
m_keywordName( name ),
m_initializer( init ),
m_postProcessor( noop< T >() ),
m_dimensionString( dimString )
{}
template< typename T >
GridPropertySupportedKeywordInfo< T >::GridPropertySupportedKeywordInfo(
const std::string& name,
const T defaultValue,
const std::string& dimString ) :
m_keywordName( name ),
m_initializer( constant( defaultValue ) ),
m_postProcessor( noop< T >() ),
m_dimensionString( dimString )
{}
template< typename T >
GridPropertySupportedKeywordInfo< T >::GridPropertySupportedKeywordInfo(
const std::string& name,
const T defaultValue,
std::function< void( std::vector< T >& ) > post,
const std::string& dimString ) :
m_keywordName( name ),
m_initializer( constant( defaultValue ) ),
m_postProcessor( post ),
m_dimensionString( dimString )
{}
template< typename T >
const std::string& GridPropertySupportedKeywordInfo< T >::getKeywordName() const {
return this->m_keywordName;
}
template< typename T >
const std::string& GridPropertySupportedKeywordInfo< T >::getDimensionString() const {
return this->m_dimensionString;
}
template< typename T >
const std::function< std::vector< T >( size_t ) >& GridPropertySupportedKeywordInfo< T >::initializer() const {
return this->m_initializer;
}
template< typename T >
const std::function< void( std::vector< T >& ) >& GridPropertySupportedKeywordInfo< T >::postProcessor() const {
return this->m_postProcessor;
}
template< typename T >
GridProperty< T >::GridProperty( size_t nx, size_t ny, size_t nz, const SupportedKeywordInfo& kwInfo ) :
m_nx( nx ),
m_ny( ny ),
m_nz( nz ),
m_kwInfo( kwInfo ),
m_data( kwInfo.initializer()( nx * ny * nz ) ),
m_hasRunPostProcessor( false )
{}
template< typename T >
size_t GridProperty< T >::getCartesianSize() const {
return m_data.size();
}
template< typename T >
size_t GridProperty< T >::getNX() const {
return m_nx;
}
template< typename T >
size_t GridProperty< T >::getNY() const {
return m_ny;
}
template< typename T >
size_t GridProperty< T >::getNZ() const {
return m_nz;
}
template< typename T >
T GridProperty< T >::iget( size_t index ) const {
return this->m_data.at( index );
}
template< typename T >
T GridProperty< T >::iget(size_t i , size_t j , size_t k) const {
size_t g = i + j*m_nx + k*m_nx*m_ny;
return iget(g);
}
template< typename T >
void GridProperty< T >::iset(size_t index, T value) {
this->m_data.at( index ) = value;
}
template< typename T >
void GridProperty< T >::iset(size_t i , size_t j , size_t k , T value) {
size_t g = i + j*m_nx + k*m_nx*m_ny;
iset(g,value);
}
template< typename T >
const std::vector< T >& GridProperty< T >::getData() const {
return m_data;
}
template< typename T >
void GridProperty< T >::multiplyWith( const GridProperty< T >& other ) {
if ((m_nx == other.m_nx) && (m_ny == other.m_ny) && (m_nz == other.m_nz)) {
for (size_t g=0; g < m_data.size(); g++)
m_data[g] *= other.m_data[g];
} else
throw std::invalid_argument("Size mismatch between properties in mulitplyWith.");
}
template< typename T >
void GridProperty< T >::multiplyValueAtIndex(size_t index, T factor) {
m_data[index] *= factor;
}
template< typename T >
void GridProperty< T >::maskedSet( T value, const std::vector< bool >& mask ) {
for (size_t g = 0; g < getCartesianSize(); g++) {
if (mask[g])
m_data[g] = value;
}
}
template< typename T >
void GridProperty< T >::maskedMultiply( T value, const std::vector<bool>& mask ) {
for (size_t g = 0; g < getCartesianSize(); g++) {
if (mask[g])
m_data[g] *= value;
}
}
template< typename T >
void GridProperty< T >::maskedAdd( T value, const std::vector<bool>& mask ) {
for (size_t g = 0; g < getCartesianSize(); g++) {
if (mask[g])
m_data[g] += value;
}
}
template< typename T >
void GridProperty< T >::maskedCopy( const GridProperty< T >& other, const std::vector< bool >& mask) {
for (size_t g = 0; g < getCartesianSize(); g++) {
if (mask[g])
m_data[g] = other.m_data[g];
}
}
template< typename T >
void GridProperty< T >::initMask( T value, std::vector< bool >& mask ) const {
mask.resize(getCartesianSize());
for (size_t g = 0; g < getCartesianSize(); g++) {
if (m_data[g] == value)
mask[g] = true;
else
mask[g] = false;
}
}
template< typename T >
void GridProperty< T >::loadFromDeckKeyword( const DeckKeyword& deckKeyword ) {
const auto& deckItem = getDeckItem(deckKeyword);
const auto size = deckItem.size();
for (size_t dataPointIdx = 0; dataPointIdx < size; ++dataPointIdx) {
if (!deckItem.defaultApplied(dataPointIdx))
setDataPoint(dataPointIdx, dataPointIdx, deckItem);
}
}
template< typename T >
void GridProperty< T >::loadFromDeckKeyword( const Box& inputBox, const DeckKeyword& deckKeyword) {
if (inputBox.isGlobal())
loadFromDeckKeyword( deckKeyword );
else {
const auto& deckItem = getDeckItem(deckKeyword);
const std::vector<size_t>& indexList = inputBox.getIndexList();
if (indexList.size() == deckItem.size()) {
for (size_t sourceIdx = 0; sourceIdx < indexList.size(); sourceIdx++) {
size_t targetIdx = indexList[sourceIdx];
if (sourceIdx < deckItem.size()
&& !deckItem.defaultApplied(sourceIdx))
{
setDataPoint(sourceIdx, targetIdx, deckItem);
}
}
} else {
std::string boxSize = std::to_string(static_cast<long long>(indexList.size()));
std::string keywordSize = std::to_string(static_cast<long long>(deckItem.size()));
throw std::invalid_argument("Size mismatch: Box:" + boxSize + " DeckKeyword:" + keywordSize);
}
}
}
template< typename T >
void GridProperty< T >::copyFrom( const GridProperty< T >& src, const Box& inputBox ) {
if (inputBox.isGlobal()) {
for (size_t i = 0; i < src.getCartesianSize(); ++i)
m_data[i] = src.m_data[i];
} else {
const std::vector<size_t>& indexList = inputBox.getIndexList();
for (size_t i = 0; i < indexList.size(); i++) {
size_t targetIndex = indexList[i];
m_data[targetIndex] = src.m_data[targetIndex];
}
}
}
template< typename T >
void GridProperty< T >::scale( T scaleFactor, const Box& inputBox ) {
if (inputBox.isGlobal()) {
for (size_t i = 0; i < m_data.size(); ++i)
m_data[i] *= scaleFactor;
} else {
const std::vector<size_t>& indexList = inputBox.getIndexList();
for (size_t i = 0; i < indexList.size(); i++) {
size_t targetIndex = indexList[i];
m_data[targetIndex] *= scaleFactor;
}
}
}
template< typename T >
void GridProperty< T >::add( T shiftValue, const Box& inputBox ) {
if (inputBox.isGlobal()) {
for (size_t i = 0; i < m_data.size(); ++i)
m_data[i] += shiftValue;
} else {
const std::vector<size_t>& indexList = inputBox.getIndexList();
for (size_t i = 0; i < indexList.size(); i++) {
size_t targetIndex = indexList[i];
m_data[targetIndex] += shiftValue;
}
}
}
template< typename T >
void GridProperty< T >::setScalar( T value, const Box& inputBox ) {
if (inputBox.isGlobal()) {
std::fill(m_data.begin(), m_data.end(), value);
} else {
const std::vector<size_t>& indexList = inputBox.getIndexList();
for (size_t i = 0; i < indexList.size(); i++) {
size_t targetIndex = indexList[i];
m_data[targetIndex] = value;
}
}
}
template< typename T >
const std::string& GridProperty< T >::getKeywordName() const {
return m_kwInfo.getKeywordName();
}
template< typename T >
const typename GridProperty< T >::SupportedKeywordInfo&
GridProperty< T >::getKeywordInfo() const {
return m_kwInfo;
}
template< typename T >
void GridProperty< T >::runPostProcessor() {
if( this->m_hasRunPostProcessor ) return;
this->m_hasRunPostProcessor = true;
this->m_kwInfo.postProcessor()( m_data );
}
template< typename T >
void GridProperty< T >::checkLimits( T min, T max ) const {
for (size_t g=0; g < m_data.size(); g++) {
T value = m_data[g];
if ((value < min) || (value > max))
throw std::invalid_argument("Property element " + std::to_string( value) + " in " + getKeywordName() + " outside valid limits: [" + std::to_string(min) + ", " + std::to_string(max) + "]");
}
}
template< typename T >
const DeckItem& GridProperty< T >::getDeckItem( const DeckKeyword& deckKeyword ) {
if (deckKeyword.size() != 1)
throw std::invalid_argument("Grid properties can only have a single record (keyword "
+ deckKeyword.name() + ")");
if (deckKeyword.getRecord(0).size() != 1)
// this is an error of the definition of the ParserKeyword (most likely in
// the corresponding JSON file)
throw std::invalid_argument("Grid properties may only exhibit a single item (keyword "
+ deckKeyword.name() + ")");
const auto& deckItem = deckKeyword.getRecord(0).getItem(0);
if (deckItem.size() > m_data.size())
throw std::invalid_argument("Size mismatch when setting data for:" + getKeywordName()
+ " keyword size: " + std::to_string( deckItem.size() )
+ " input size: " + std::to_string( m_data.size()) );
return deckItem;
}
template<>
void GridProperty<int>::setDataPoint(size_t sourceIdx, size_t targetIdx, const DeckItem& deckItem) {
m_data[targetIdx] = deckItem.get< int >(sourceIdx);
}
template<>
void GridProperty<double>::setDataPoint(size_t sourceIdx, size_t targetIdx, const DeckItem& deckItem) {
m_data[targetIdx] = deckItem.getSIDouble(sourceIdx);
}
template<>
bool GridProperty<int>::containsNaN( ) const {
throw std::logic_error("Only <double> and can be meaningfully queried for nan");
}
template<>
bool GridProperty<double>::containsNaN( ) const {
bool return_value = false;
size_t size = m_data.size();
size_t index = 0;
while (true) {
if (std::isnan(m_data[index])) {
return_value = true;
break;
}
index++;
if (index == size)
break;
}
return return_value;
}
template<>
const std::string& GridProperty<int>::getDimensionString() const {
throw std::logic_error("Only <double> grid properties have dimension");
}
template<>
const std::string& GridProperty<double>::getDimensionString() const {
return m_kwInfo.getDimensionString();
}
template<typename T>
std::vector<T> GridProperty<T>::compressedCopy(const EclipseGrid& grid) const {
if (grid.allActive())
return m_data;
else {
return grid.compressedVector( m_data );
}
}
template<typename T>
std::vector<size_t> GridProperty<T>::cellsEqual(T value, const std::vector<int>& activeMap) const {
std::vector<size_t> cells;
for (size_t active_index = 0; active_index < activeMap.size(); active_index++) {
size_t global_index = activeMap[ active_index ];
if (m_data[global_index] == value)
cells.push_back( active_index );
}
return cells;
}
template<typename T>
std::vector<size_t> GridProperty<T>::indexEqual(T value) const {
std::vector<size_t> index_list;
for (size_t index = 0; index < m_data.size(); index++) {
if (m_data[index] == value)
index_list.push_back( index );
}
return index_list;
}
template<typename T>
std::vector<size_t> GridProperty<T>::cellsEqual(T value, const EclipseGrid& grid, bool active) const {
if (active)
return cellsEqual( value , grid.getActiveMap());
else
return indexEqual( value );
}
std::vector< double > temperature_lookup( size_t size,
const TableManager* tables,
const EclipseGrid* grid,
const GridProperties<int>* ig_props ) {
if( !tables->useEqlnum() ) {
/* if values are defaulted in the TEMPI keyword, but no
* EQLNUM is specified, you will get NaNs
*/
return std::vector< double >( size, std::numeric_limits< double >::quiet_NaN() );
}
std::vector< double > values( size, 0 );
const auto& rtempvdTables = tables->getRtempvdTables();
const std::vector< int >& eqlNum = ig_props->getKeyword("EQLNUM").getData();
for (size_t cellIdx = 0; cellIdx < eqlNum.size(); ++ cellIdx) {
int cellEquilNum = eqlNum[cellIdx];
const RtempvdTable& rtempvdTable = rtempvdTables.getTable<RtempvdTable>(cellEquilNum);
double cellDepth = std::get<2>(grid->getCellCenter(cellIdx));
values[cellIdx] = rtempvdTable.evaluate("Temperature", cellDepth);
}
return values;
}
}
template class Opm::GridPropertySupportedKeywordInfo< int >;
template class Opm::GridPropertySupportedKeywordInfo< double >;
template class Opm::GridProperty< int >;
template class Opm::GridProperty< double >;