Merge pull request #1013 from jokva/understand-density-keyword

Provide DENSITY & ROCK table through EclipseState
This commit is contained in:
jokva
2016-12-20 14:06:47 +01:00
committed by GitHub
10 changed files with 200 additions and 92 deletions

View File

@@ -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

View File

@@ -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)

View 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

View File

@@ -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

View File

@@ -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 )

View File

@@ -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");
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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 );

View File

@@ -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 ) {