Merge pull request #1013 from jokva/understand-density-keyword
Provide DENSITY & ROCK table through EclipseState
This commit is contained in:
@@ -226,6 +226,7 @@ EclipseState/SummaryConfig/SummaryConfig.hpp
|
||||
EclipseState/IOConfig/RestartConfig.hpp
|
||||
EclipseState/IOConfig/IOConfig.hpp
|
||||
#
|
||||
EclipseState/Tables/FlatTable.hpp
|
||||
EclipseState/Tables/Tabdims.hpp
|
||||
EclipseState/Tables/Eqldims.hpp
|
||||
EclipseState/Tables/Regdims.hpp
|
||||
@@ -262,7 +263,6 @@ EclipseState/Tables/OilvisctTable.hpp
|
||||
EclipseState/Tables/GasvisctTable.hpp
|
||||
EclipseState/Tables/WatvisctTable.hpp
|
||||
EclipseState/Tables/PvtgTable.hpp
|
||||
EclipseState/Tables/PvtwTable.hpp
|
||||
EclipseState/Tables/VFPProdTable.hpp
|
||||
EclipseState/Tables/VFPInjTable.hpp
|
||||
EclipseState/Tables/TableManager.hpp
|
||||
|
||||
@@ -358,6 +358,8 @@ namespace Opm {
|
||||
supportedDoubleKeywords.emplace_back( "PRESSURE", 0.0 , "Pressure" );
|
||||
supportedDoubleKeywords.emplace_back( "SWAT", 0.0 , "1" );
|
||||
supportedDoubleKeywords.emplace_back( "SGAS", 0.0 , "1" );
|
||||
supportedDoubleKeywords.emplace_back( "RS", 0.0, "1" );
|
||||
supportedDoubleKeywords.emplace_back( "RV", 0.0, "1" );
|
||||
|
||||
|
||||
// cell temperature (E300 only, but makes a lot of sense for E100, too)
|
||||
|
||||
53
opm/parser/eclipse/EclipseState/Tables/FlatTable.hpp
Normal file
53
opm/parser/eclipse/EclipseState/Tables/FlatTable.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef OPM_FLAT_TABLE_HPP
|
||||
#define OPM_FLAT_TABLE_HPP
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class DeckKeyword;
|
||||
|
||||
template< typename T >
|
||||
struct FlatTable : public std::vector< T > {
|
||||
FlatTable() = default;
|
||||
explicit FlatTable( const DeckKeyword& );
|
||||
};
|
||||
|
||||
struct DENSITYRecord {
|
||||
static constexpr std::size_t size = 3;
|
||||
|
||||
double oil;
|
||||
double water;
|
||||
double gas;
|
||||
};
|
||||
|
||||
struct DensityTable : public FlatTable< DENSITYRecord > {
|
||||
using FlatTable< DENSITYRecord >::FlatTable;
|
||||
};
|
||||
|
||||
struct PVTWRecord {
|
||||
static constexpr std::size_t size = 5;
|
||||
|
||||
double reference_pressure;
|
||||
double volume_factor;
|
||||
double compressibility;
|
||||
double viscosity;
|
||||
double viscosibility;
|
||||
};
|
||||
|
||||
struct PvtwTable : public FlatTable< PVTWRecord > {
|
||||
using FlatTable< PVTWRecord >::FlatTable;
|
||||
};
|
||||
|
||||
struct ROCKRecord {
|
||||
static constexpr std::size_t size = 2;
|
||||
|
||||
double reference_pressure;
|
||||
double compressibility;
|
||||
};
|
||||
|
||||
struct RockTable : public FlatTable< ROCKRecord > {
|
||||
using FlatTable< ROCKRecord >::FlatTable;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPM_FLAT_TABLE_HPP
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef OPM_PVTWTABLE_HPP
|
||||
#define OPM_PVTWTABLE_HPP
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class DeckKeyword;
|
||||
|
||||
class PvtwTable {
|
||||
public:
|
||||
struct record {
|
||||
double reference_pressure;
|
||||
double volume_factor;
|
||||
double compressibility;
|
||||
double viscosity;
|
||||
double viscosibility;
|
||||
};
|
||||
|
||||
PvtwTable() = default;
|
||||
explicit PvtwTable( const DeckKeyword& );
|
||||
|
||||
const record& operator[]( size_t region ) const;
|
||||
const record& at( size_t region ) const;
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
|
||||
using const_iterator = std::vector< record >::const_iterator;
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
private:
|
||||
std::vector< record > records;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPM_PVTWTABLE_HPP
|
||||
@@ -20,65 +20,13 @@
|
||||
#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/Tables/PvtwTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/FlatTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PvtxTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SimpleTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableSchema.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
namespace {
|
||||
std::vector< PvtwTable::record > pvtw_records( const DeckKeyword& kw ) {
|
||||
std::vector< PvtwTable::record > rs;
|
||||
|
||||
for( const auto& record : kw ) {
|
||||
if( record.getItem( 0 ).defaultApplied( 0 ) ) {
|
||||
throw std::invalid_argument(
|
||||
"PvtwTable reference pressure cannot be defaulted" );
|
||||
}
|
||||
|
||||
rs.emplace_back(
|
||||
PvtwTable::record {
|
||||
record.getItem( 0 ).getSIDouble( 0 ),
|
||||
record.getItem( 1 ).getSIDouble( 0 ),
|
||||
record.getItem( 2 ).getSIDouble( 0 ),
|
||||
record.getItem( 3 ).getSIDouble( 0 ),
|
||||
record.getItem( 4 ).getSIDouble( 0 ),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PvtwTable::PvtwTable( const DeckKeyword& kw ) : records( pvtw_records( kw ) ) {}
|
||||
|
||||
const PvtwTable::record& PvtwTable::operator[]( size_t region ) const {
|
||||
return this->records.at( region );
|
||||
}
|
||||
|
||||
const PvtwTable::record& PvtwTable::at( size_t region ) const {
|
||||
return this->records.at( region );
|
||||
}
|
||||
|
||||
bool PvtwTable::empty() const {
|
||||
return this->records.empty();
|
||||
}
|
||||
|
||||
size_t PvtwTable::size() const {
|
||||
return this->records.size();
|
||||
}
|
||||
|
||||
PvtwTable::const_iterator PvtwTable::begin() const {
|
||||
return this->records.begin();
|
||||
}
|
||||
|
||||
PvtwTable::const_iterator PvtwTable::end() const {
|
||||
return this->records.end();
|
||||
}
|
||||
|
||||
PvtxTable::PvtxTable(const std::string& columnName) :
|
||||
m_outerColumnSchema( columnName , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE ),
|
||||
m_outerColumn( m_outerColumnSchema )
|
||||
|
||||
@@ -87,6 +87,12 @@ namespace Opm {
|
||||
if( deck.hasKeyword( "PVTW" ) )
|
||||
this->m_pvtwTable = PvtwTable( deck.getKeyword( "PVTW" ) );
|
||||
|
||||
if( deck.hasKeyword( "DENSITY" ) )
|
||||
this->m_densityTable = DensityTable( deck.getKeyword( "DENSITY" ) );
|
||||
|
||||
if( deck.hasKeyword( "ROCK" ) )
|
||||
this->m_rockTable = RockTable( deck.getKeyword( "ROCK" ) );
|
||||
|
||||
initVFPProdTables(deck, m_vfpprodTables);
|
||||
initVFPInjTables(deck, m_vfpinjTables);
|
||||
}
|
||||
@@ -637,6 +643,14 @@ namespace Opm {
|
||||
return this->m_pvtwTable;
|
||||
}
|
||||
|
||||
const DensityTable& TableManager::getDensityTable() const {
|
||||
return this->m_densityTable;
|
||||
}
|
||||
|
||||
const RockTable& TableManager::getRockTable() const {
|
||||
return this->m_rockTable;
|
||||
}
|
||||
|
||||
const TableContainer& TableManager::getMsfnTables() const {
|
||||
return getTables("MSFN");
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp> // Phase::PhaseEnum
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PvtgTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PvtoTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PvtwTable.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/FlatTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/VFPProdTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/VFPInjTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SorwmisTable.hpp>
|
||||
@@ -102,6 +102,8 @@ namespace Opm {
|
||||
const std::vector<PvtgTable>& getPvtgTables() const;
|
||||
const std::vector<PvtoTable>& getPvtoTables() const;
|
||||
const PvtwTable& getPvtwTable() const;
|
||||
const DensityTable& getDensityTable() const;
|
||||
const RockTable& getRockTable() const;
|
||||
const std::map<int, VFPProdTable>& getVFPProdTables() const;
|
||||
const std::map<int, VFPInjTable>& getVFPInjTables() const;
|
||||
|
||||
@@ -231,6 +233,8 @@ namespace Opm {
|
||||
std::vector<PvtgTable> m_pvtgTables;
|
||||
std::vector<PvtoTable> m_pvtoTables;
|
||||
PvtwTable m_pvtwTable;
|
||||
DensityTable m_densityTable;
|
||||
RockTable m_rockTable;
|
||||
|
||||
Tabdims m_tabdims;
|
||||
std::shared_ptr<Regdims> m_regdims;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <opm/parser/eclipse/Units/Dimension.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/FlatTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/EnkrvdTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/EnptvdTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/GasvisctTable.hpp>
|
||||
@@ -1013,4 +1014,86 @@ const TableColumn& MsfnTable::getOilRelpermMultiplierColumn() const {
|
||||
return SimpleTable::getColumn(2);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
* Create a compile-time sequence of integers [0,N). In C++14 this can be
|
||||
* replaced by std::index_sequence.
|
||||
*/
|
||||
template< std::size_t... > struct seq { using type = seq; };
|
||||
template< std::size_t N, std::size_t... Is >
|
||||
struct mkseq : mkseq< N - 1, N - 1, Is... > {};
|
||||
template< std::size_t... Is >
|
||||
struct mkseq< 0u, Is... > : seq< Is... >{ using type = seq< Is... >; };
|
||||
|
||||
/*
|
||||
* Convenince function for creating a 'flat table', e.g. PVTW and DENSITY.
|
||||
* Assumes the following:
|
||||
*
|
||||
* 1. The table has vector semantics with no other to enforce
|
||||
* 2. That the following struct is implemented:
|
||||
* struct record {
|
||||
* static constexpr std::size_t size = [number-of-members]
|
||||
* double members ...;
|
||||
* };
|
||||
* 3. The table is declared as
|
||||
* struct table : public FlatTable< table > {
|
||||
* using FlatTable< table >::FlatTable;
|
||||
* }
|
||||
*
|
||||
* If some field can *not* be defaulted, e.g. 0, specialise the flat_props
|
||||
* struct (in this namespace) as such:
|
||||
* template<> struct< record, 0 > {
|
||||
* static constexpr bool can_default() { return false; }
|
||||
* static constexpr const char* errmsg() { "error message"; }
|
||||
* };
|
||||
* and the parser will throw std::invalid_argument if the field is defaulted in
|
||||
* the input.
|
||||
*
|
||||
*/
|
||||
|
||||
template< typename T, std::size_t N >
|
||||
struct flat_props {
|
||||
static constexpr bool can_default() { return true; }
|
||||
static constexpr const char* errmsg() { return ""; }
|
||||
};
|
||||
|
||||
template< typename T, std::size_t N >
|
||||
double flat_get( const DeckRecord& rec ) {
|
||||
if( !flat_props< T, N >::can_default()
|
||||
&& rec.getItem( N ).defaultApplied( 0 ) ) {
|
||||
throw std::invalid_argument( flat_props< T, N >::errmsg() );
|
||||
}
|
||||
|
||||
return rec.getItem( N ).getSIDouble( 0 );
|
||||
}
|
||||
|
||||
template< typename T, std::size_t... Is >
|
||||
std::vector< T > flat_records( const DeckKeyword& kw, seq< Is... > ) {
|
||||
std::vector< T > xs;
|
||||
for( const auto& record : kw )
|
||||
xs.emplace_back( T { flat_get< T, Is >( record )... } );
|
||||
|
||||
return xs;
|
||||
}
|
||||
|
||||
template<>
|
||||
struct flat_props< PVTWRecord, 0 > {
|
||||
static constexpr bool can_default() { return false; }
|
||||
static constexpr const char* errmsg() {
|
||||
return "PVTW reference pressure cannot be defaulted";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
FlatTable< T >::FlatTable( const DeckKeyword& kw ) :
|
||||
std::vector< T >( flat_records< T >( kw, mkseq< T::size >{} ) )
|
||||
{}
|
||||
|
||||
template FlatTable< DENSITYRecord >::FlatTable( const DeckKeyword& );
|
||||
template FlatTable< PVTWRecord >::FlatTable( const DeckKeyword& );
|
||||
template FlatTable< ROCKRecord >::FlatTable( const DeckKeyword& );
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
@@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE( PVTWTable ) {
|
||||
const auto& rec1 = pvtw[0];
|
||||
const auto& rec2 = pvtw.at(1);
|
||||
|
||||
BOOST_CHECK_THROW( pvtw[2], std::out_of_range );
|
||||
BOOST_CHECK_THROW( pvtw.at(2), std::out_of_range );
|
||||
|
||||
BOOST_CHECK_CLOSE( 3600.00, rec1.reference_pressure / 1e5, 1e-5 );
|
||||
BOOST_CHECK_CLOSE( 1.00341, rec1.volume_factor, 1e-5 );
|
||||
|
||||
@@ -1060,6 +1060,46 @@ BOOST_AUTO_TEST_CASE( TestPLYMAX ) {
|
||||
BOOST_CHECK_EQUAL( table1.getMaxPolymerConcentrationColumn()[0] , 20.0 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TestParseDENSITY ) {
|
||||
const std::string data = R"(
|
||||
TABDIMS
|
||||
1* 1 /
|
||||
|
||||
DENSITY
|
||||
1.1 1.2 1.3 /
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto deck = parser.parseString(data, Opm::ParseContext());
|
||||
Opm::TableManager tables( deck );
|
||||
const auto& density = tables.getDensityTable();
|
||||
BOOST_CHECK_EQUAL( 1.1, density[0].oil );
|
||||
BOOST_CHECK_EQUAL( 1.2, density[0].water );
|
||||
BOOST_CHECK_EQUAL( 1.3, density[0].gas );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TestParseROCK ) {
|
||||
const std::string data = R"(
|
||||
TABDIMS
|
||||
1* 2 /
|
||||
|
||||
ROCK
|
||||
1.1 1.2 /
|
||||
2.1 2.2 /
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto deck = parser.parseString(data, Opm::ParseContext());
|
||||
Opm::TableManager tables( deck );
|
||||
const auto& rock = tables.getRockTable();
|
||||
BOOST_CHECK_EQUAL( 1.1 * 1e5, rock[0].reference_pressure );
|
||||
BOOST_CHECK_EQUAL( 1.2 * 1e-5, rock[0].compressibility );
|
||||
|
||||
BOOST_CHECK_EQUAL( 2.1 * 1e5, rock[1].reference_pressure );
|
||||
BOOST_CHECK_EQUAL( 2.2 * 1e-5, rock[1].compressibility );
|
||||
|
||||
BOOST_CHECK_THROW( rock.at( 2 ), std::out_of_range );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TestParseTABDIMS ) {
|
||||
|
||||
Reference in New Issue
Block a user