Merge pull request #797 from jokva/summary-config-from-eclipsestate

Summary config from eclipsestate
This commit is contained in:
Joakim Hove
2016-05-10 09:55:11 +02:00
19 changed files with 234 additions and 137 deletions

View File

@@ -49,10 +49,11 @@ namespace Opm {
};
auto first = std::find_if( deck.begin(), deck.end(), fn );
if( first == deck.end() )
throw std::invalid_argument( std::string( "Deck requires a '" ) + keyword + "' section" );
auto last = std::find_if( first + 1, deck.end(), &isSectionDelimiter );
if( first == deck.end() )
return { first, first };
auto last = std::find_if( first + 1, deck.end(), isSectionDelimiter );
if( last != deck.end() && last->name() == keyword )
throw std::invalid_argument( std::string( "Deck contains the '" ) + keyword + "' section multiple times" );

View File

@@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(IteratorTest) {
BOOST_AUTO_TEST_CASE(RUNSPECSection_EmptyDeck) {
DeckPtr deck(new Deck());
BOOST_REQUIRE_THROW(RUNSPECSection section(*deck), std::invalid_argument);
BOOST_REQUIRE_NO_THROW(RUNSPECSection section(*deck));
}
BOOST_AUTO_TEST_CASE(RUNSPECSection_ReadSimpleDeck) {

View File

@@ -449,6 +449,17 @@ namespace Opm {
}
}
std::vector< int > Eclipse3DProperties::getRegions( const std::string& kw ) const {
if( !this->hasDeckIntGridProperty( kw ) ) return {};
const auto& property = this->getIntGridProperty( kw );
std::set< int > regions( property.getData().begin(),
property.getData().end() );
return { regions.begin(), regions.end() };
}
/// Due to the post processor which might be applied to the GridProperty
/// objects it is essential that this method use the m_intGridProperties /
/// m_doubleGridProperties fields directly and *NOT* use the public methods

View File

@@ -61,6 +61,7 @@ namespace Opm {
const GridProperty<int>& getRegion(const DeckItem& regionItem) const;
std::vector< int > getRegions( const std::string& keyword ) const;
std::string getDefaultRegionKeyword() const;
const GridProperty<int>& getIntGridProperty ( const std::string& keyword ) const;

View File

@@ -49,25 +49,39 @@
namespace Opm {
static IOConfig mkIOConfig( const Deck& deck ) {
IOConfig config( deck.getDataFile() );
if( Section::hasGRID( deck ) )
config.handleGridSection( GRIDSection( deck ) );
if( Section::hasRUNSPEC( deck ) )
config.handleRunspecSection( RUNSPECSection( deck ) );
return config;
}
EclipseState::EclipseState(std::shared_ptr<const Deck> deckptr, ParseContext parseContext) :
EclipseState(*deckptr, parseContext)
{}
EclipseState::EclipseState(const Deck& deck, ParseContext parseContext) :
m_deckUnitSystem( deck.getActiveUnitSystem() ),
m_parseContext( parseContext ),
m_ioConfig( std::make_shared< IOConfig >( mkIOConfig( deck ) ) ),
m_tables( deck ),
m_inputGrid( std::make_shared<EclipseGrid>(deck, nullptr)),
m_eclipseProperties( deck, m_tables, *m_inputGrid)
m_inputGrid( std::make_shared<EclipseGrid>(deck, nullptr) ),
m_eclipseProperties( deck, m_tables, *m_inputGrid ),
m_schedule( std::make_shared<Schedule>( m_parseContext, m_inputGrid, deck, m_ioConfig ) ),
m_simulationConfig( std::make_shared<SimulationConfig>( m_parseContext, deck, m_eclipseProperties ) ),
m_summaryConfig( deck, *m_schedule, m_eclipseProperties, m_inputGrid->getNXYZ() ),
m_nnc( deck, m_inputGrid ),
m_deckUnitSystem( deck.getActiveUnitSystem() )
{
// after Eclipse3DProperties has been constructed, we have complete ACTNUM info
if (m_eclipseProperties.hasDeckIntGridProperty("ACTNUM"))
m_inputGrid->resetACTNUM(m_eclipseProperties.getIntGridProperty("ACTNUM").getData().data());
initIOConfig(deck);
m_schedule = ScheduleConstPtr(new Schedule(m_parseContext, getInputGrid(), deck, m_ioConfig));
initIOConfigPostSchedule(deck);
if (deck.hasKeyword( "TITLE" )) {
@@ -77,14 +91,9 @@ namespace Opm {
m_title = boost::algorithm::join( itemValue, " " );
}
m_initConfig = std::make_shared<const InitConfig>(deck);
m_simulationConfig = std::make_shared<const SimulationConfig>(m_parseContext, deck,
m_eclipseProperties);
initTransMult();
initFaults(deck);
initMULTREGT(deck);
m_nnc = NNC(deck, getInputGrid());
m_messageContainer.appendMessages(m_tables.getMessageContainer());
m_messageContainer.appendMessages(m_schedule->getMessageContainer());
@@ -104,6 +113,10 @@ namespace Opm {
return std::make_shared<EclipseGrid>( m_inputGrid->c_ptr() );
}
const SummaryConfig& EclipseState::getSummaryConfig() const {
return this->m_summaryConfig;
}
const Eclipse3DProperties& EclipseState::get3DProperties() const {
return m_eclipseProperties;
}
@@ -166,20 +179,6 @@ namespace Opm {
return m_title;
}
void EclipseState::initIOConfig(const Deck& deck) {
std::string dataFile = deck.getDataFile();
m_ioConfig = std::make_shared<IOConfig>(dataFile);
if (Section::hasGRID(deck)) {
auto gridSection = std::make_shared<const GRIDSection>(deck);
m_ioConfig->handleGridSection(gridSection);
}
if (Section::hasRUNSPEC(deck)) {
auto runspecSection = std::make_shared<const RUNSPECSection>(deck);
m_ioConfig->handleRunspecSection(runspecSection);
}
}
// Hmmm - would have thought this should iterate through the SCHEDULE section as well?
void EclipseState::initIOConfigPostSchedule(const Deck& deck) {
if (Section::hasSOLUTION(deck)) {
@@ -261,17 +260,6 @@ namespace Opm {
}
std::vector< int > EclipseState::getRegions( const std::string& kw ) const {
if( !this->get3DProperties().hasDeckIntGridProperty( kw ) ) return {};
const auto& property = this->get3DProperties().getIntGridProperty( kw );
std::set< int > regions( property.getData().begin(),
property.getData().end() );
return { regions.begin(), regions.end() };
}
void EclipseState::complainAboutAmbiguousKeyword(const Deck& deck, const std::string& keywordName) {
m_messageContainer.error("The " + keywordName + " keyword must be unique in the deck. Ignoring all!");

View File

@@ -31,6 +31,7 @@
#include <opm/parser/eclipse/EclipseState/Grid/Fault.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
#include <opm/parser/eclipse/Parser/MessageContainer.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
@@ -82,6 +83,7 @@ namespace Opm {
std::shared_ptr< const SimulationConfig > getSimulationConfig() const;
std::shared_ptr< const EclipseGrid > getInputGrid() const;
std::shared_ptr< EclipseGrid > getInputGridCopy() const;
const SummaryConfig& getSummaryConfig() const;
const MessageContainer& getMessageContainer() const;
MessageContainer& getMessageContainer();
std::string getTitle() const;
@@ -95,8 +97,6 @@ namespace Opm {
const TableManager& getTableManager() const;
std::vector< int > getRegions( const std::string& kw ) const;
// the unit system used by the deck. note that it is rarely needed to convert
// units because internally to opm-parser everything is represented by SI
// units...
@@ -107,7 +107,6 @@ namespace Opm {
void applyModifierDeck(const Deck& deck);
private:
void initIOConfig(const Deck& deck);
void initIOConfigPostSchedule(const Deck& deck);
void initTransMult();
void initFaults(const Deck& deck);
@@ -118,23 +117,23 @@ namespace Opm {
void complainAboutAmbiguousKeyword(const Deck& deck,
const std::string& keywordName);
ParseContext m_parseContext;
std::shared_ptr< IOConfig > m_ioConfig;
std::shared_ptr< const InitConfig > m_initConfig;
std::shared_ptr< const Schedule > m_schedule;
const TableManager m_tables;
std::shared_ptr<EclipseGrid> m_inputGrid;
Eclipse3DProperties m_eclipseProperties;
std::shared_ptr< const Schedule > m_schedule;
std::shared_ptr< const SimulationConfig > m_simulationConfig;
SummaryConfig m_summaryConfig;
std::string m_title;
std::shared_ptr<TransMult> m_transMult;
FaultCollection m_faults;
NNC m_nnc;
const UnitSystem& m_deckUnitSystem;
const ParseContext m_parseContext;
const TableManager m_tables;
std::shared_ptr<EclipseGrid> m_inputGrid;
Eclipse3DProperties m_eclipseProperties;
MessageContainer m_messageContainer;
const UnitSystem& m_deckUnitSystem;
};
typedef std::shared_ptr<EclipseState> EclipseStatePtr;

View File

@@ -267,6 +267,10 @@ namespace Opm {
return m_nz;
}
std::array< int, 3 > EclipseGrid::getNXYZ() const {
return {{ int( m_nx ), int( m_ny ), int( m_nz ) }};
}
size_t EclipseGrid::getCartesianSize( ) const {
return m_nx * m_ny * m_nz;
}

View File

@@ -87,6 +87,7 @@ namespace Opm {
size_t getNX( ) const;
size_t getNY( ) const;
size_t getNZ( ) const;
std::array< int, 3 > getNXYZ() const;
size_t getCartesianSize( ) const;
bool isPinchActive( ) const;
double getPinchThresholdThickness( ) const;

View File

@@ -295,11 +295,11 @@ namespace Opm {
void IOConfig::handleGridSection(std::shared_ptr<const GRIDSection> gridSection) {
m_write_INIT_file = gridSection->hasKeyword("INIT");
void IOConfig::handleGridSection( const GRIDSection& gridSection) {
m_write_INIT_file = gridSection.hasKeyword("INIT");
if (gridSection->hasKeyword("GRIDFILE")) {
const auto& gridfilekeyword = gridSection->getKeyword("GRIDFILE");
if (gridSection.hasKeyword("GRIDFILE")) {
const auto& gridfilekeyword = gridSection.getKeyword("GRIDFILE");
if (gridfilekeyword.size() > 0) {
const auto& rec = gridfilekeyword.getRecord(0);
const auto& item1 = rec.getItem(0);
@@ -314,17 +314,17 @@ namespace Opm {
}
}
}
if (gridSection->hasKeyword("NOGGF")) {
if (gridSection.hasKeyword("NOGGF")) {
m_write_EGRID_file = false;
}
}
void IOConfig::handleRunspecSection(std::shared_ptr<const RUNSPECSection> runspecSection) {
m_FMTIN = runspecSection->hasKeyword("FMTIN"); //Input files are formatted
m_FMTOUT = runspecSection->hasKeyword("FMTOUT"); //Output files are to be formatted
m_UNIFIN = runspecSection->hasKeyword("UNIFIN"); //Input files are unified
m_UNIFOUT = runspecSection->hasKeyword("UNIFOUT"); //Output files are to be unified
void IOConfig::handleRunspecSection( const RUNSPECSection& runspecSection) {
m_FMTIN = runspecSection.hasKeyword("FMTIN"); //Input files are formatted
m_FMTOUT = runspecSection.hasKeyword("FMTOUT"); //Output files are to be formatted
m_UNIFIN = runspecSection.hasKeyword("UNIFIN"); //Input files are unified
m_UNIFOUT = runspecSection.hasKeyword("UNIFOUT"); //Output files are to be unified
}

View File

@@ -142,8 +142,8 @@ namespace Opm {
bool reset_global = false);
void handleRPTSCHEDRestart(std::shared_ptr< const TimeMap > timemap, size_t timestep, size_t restart);
void handleSolutionSection(std::shared_ptr< const TimeMap > timemap, std::shared_ptr<const SOLUTIONSection> solutionSection);
void handleGridSection(std::shared_ptr<const GRIDSection> gridSection);
void handleRunspecSection(std::shared_ptr<const RUNSPECSection> runspecSection);
void handleGridSection( const GRIDSection& );
void handleRunspecSection( const RUNSPECSection& );
void setWriteInitialRestartFile(bool writeInitialRestartFile);
/// This method will internalize variables with information of

View File

@@ -209,8 +209,8 @@ BOOST_AUTO_TEST_CASE(IOConfigTest) {
IOConfigPtr ioConfigPtr;
BOOST_CHECK_NO_THROW(ioConfigPtr = std::make_shared<IOConfig>());
std::shared_ptr<const GRIDSection> gridSection = std::make_shared<const GRIDSection>(*deck);
std::shared_ptr<const RUNSPECSection> runspecSection = std::make_shared<const RUNSPECSection>(*deck);
GRIDSection gridSection( *deck );
RUNSPECSection runspecSection( *deck );
ioConfigPtr->handleGridSection(gridSection);
ioConfigPtr->handleRunspecSection(runspecSection);
@@ -433,8 +433,8 @@ BOOST_AUTO_TEST_CASE(IOConfigTest) {
IOConfigPtr ioConfigPtr3;
BOOST_CHECK_NO_THROW(ioConfigPtr3 = std::make_shared<IOConfig>());
std::shared_ptr<const GRIDSection> gridSection3 = std::make_shared<const GRIDSection>(*deck3);
std::shared_ptr<const RUNSPECSection> runspecSection3 = std::make_shared<const RUNSPECSection>(*deck3);
GRIDSection gridSection3( *deck3 );
RUNSPECSection runspecSection3( *deck3 );
ioConfigPtr3->handleGridSection(gridSection3);
ioConfigPtr3->handleRunspecSection(runspecSection3);
@@ -454,8 +454,8 @@ BOOST_AUTO_TEST_CASE(IOConfigTest) {
IOConfigPtr ioConfigPtr4;
BOOST_CHECK_NO_THROW(ioConfigPtr4 = std::make_shared<IOConfig>());
std::shared_ptr<const GRIDSection> gridSection4 = std::make_shared<const GRIDSection>(*deck4);
std::shared_ptr<const RUNSPECSection> runspecSection4 = std::make_shared<const RUNSPECSection>(*deck4);
GRIDSection gridSection4( *deck4 );
RUNSPECSection runspecSection4( *deck4 );
ioConfigPtr4->handleGridSection(gridSection4);
ioConfigPtr4->handleRunspecSection(runspecSection4);

View File

@@ -22,7 +22,6 @@
#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/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/CompletionSet.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/SegmentSet.hpp>
@@ -46,11 +45,7 @@ namespace Opm {
{
}
std::vector<CompsegsPtr> Compsegs::compsegsFromCOMPSEGSKeyword( const DeckKeyword& compsegsKeyword,
EclipseGridConstPtr grid) {
// the thickness of grid cells will be required in the future for more complete support.
// Silence warning about unused argument
static_cast<void>(grid);
std::vector<CompsegsPtr> Compsegs::compsegsFromCOMPSEGSKeyword( const DeckKeyword& compsegsKeyword ) {
// only handle the second record here
// The first record here only contains the well name

View File

@@ -30,7 +30,6 @@ namespace Opm {
class CompletionSet;
class DeckKeyword;
class EclipseGrid;
class SegmentSet;
struct Compsegs {
@@ -53,8 +52,7 @@ namespace Opm {
Compsegs(int i_in, int j_in, int k_in, int branch_number_in, double distance_start_in, double distance_end_in,
WellCompletion::DirectionEnum dir_in, double center_depth_in, int segment_number_in);
static std::vector<std::shared_ptr<Compsegs>> compsegsFromCOMPSEGSKeyword( const DeckKeyword& compsegsKeyword,
std::shared_ptr< const EclipseGrid > grid);
static std::vector<std::shared_ptr<Compsegs>> compsegsFromCOMPSEGSKeyword( const DeckKeyword& compsegsKeyword );
// get the segment number information and depth information based on the information from SegmentSet
static void processCOMPSEGS(std::vector<std::shared_ptr<Compsegs>>& compsegs, std::shared_ptr< const SegmentSet > segment_set);

View File

@@ -1312,7 +1312,7 @@ namespace Opm {
const std::string& well_name = record1.getItem("WELL").getTrimmedString(0);
WellPtr well = getWell(well_name);
std::vector<CompsegsPtr> compsegs_vector = Compsegs::compsegsFromCOMPSEGSKeyword(keyword, m_grid);
std::vector<CompsegsPtr> compsegs_vector = Compsegs::compsegsFromCOMPSEGSKeyword( keyword );
SegmentSetConstPtr current_segmentSet = well->getSegmentSet(currentStep);
Compsegs::processCOMPSEGS(compsegs_vector, current_segmentSet);

View File

@@ -23,6 +23,7 @@
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Deck/Section.hpp>
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Completion.hpp>
@@ -38,6 +39,7 @@
#include <algorithm>
#include <array>
#include <functional>
namespace Opm {
@@ -52,30 +54,29 @@ namespace Opm {
static inline std::vector< ERT::smspec_node > keywordWG(
ecl_smspec_var_type var_type,
const DeckKeyword& keyword,
const EclipseState& es ) {
const Schedule& schedule ) {
const auto mknode = [&keyword,var_type]( const std::string& name ) {
return ERT::smspec_node( var_type, name, keyword.name() );
};
const auto find = []( ecl_smspec_var_type v, const EclipseState& est ) {
const auto find = []( ecl_smspec_var_type v, const Schedule& sc ) {
if( v == ECL_SMSPEC_WELL_VAR )
return fun::map( wellName, est.getSchedule()->getWells() );
return fun::map( wellName, sc.getWells() );
else
return fun::map( groupName, est.getSchedule()->getGroups() );
return fun::map( groupName, sc.getGroups() );
};
const auto& item = keyword.getDataRecord().getDataItem();
const auto wgnames = item.size() > 0 && item.hasValue( 0 )
? item.getData< std::string >()
: find( var_type, es );
: find( var_type, schedule );
return fun::map( mknode, wgnames );
}
static inline std::vector< ERT::smspec_node > keywordF(
const DeckKeyword& keyword,
const EclipseState& /* es */ ) {
const DeckKeyword& keyword ) {
std::vector< ERT::smspec_node > res;
res.push_back( ERT::smspec_node( keyword.name() ) );
@@ -106,11 +107,9 @@ namespace Opm {
static inline std::vector< ERT::smspec_node > keywordB(
const DeckKeyword& keyword,
const EclipseState& es ) {
std::array< int, 3 > dims ) {
auto dims = dimensions( *es.getInputGrid() );
const auto mkrecord = [&dims,&keyword]( const DeckRecord& record ) {
const auto mkrecord = [dims,&keyword]( const DeckRecord& record ) {
auto ijk = getijk( record );
return ERT::smspec_node( keyword.name(), dims.data(), ijk.data() );
};
@@ -120,36 +119,40 @@ namespace Opm {
static inline std::vector< ERT::smspec_node > keywordR(
const DeckKeyword& keyword,
const EclipseState& es ) {
const Eclipse3DProperties& props,
std::array< int, 3 > dims ) {
auto dims = dimensions( *es.getInputGrid() );
/* RUNSUM is not a region keyword but a directive for how to format and
* print output. Unfortunately its *recognised* as a region keyword
* because of its structure and position. Hence the special handling of ignoring it.
*/
if( keyword.name() == "RUNSUM" ) return {};
const auto mknode = [&dims,&keyword]( int region ) {
const auto mknode = [dims,&keyword]( int region ) {
return ERT::smspec_node( keyword.name(), dims.data(), region );
};
const auto& item = keyword.getDataRecord().getDataItem();
const auto regions = item.size() > 0 && item.hasValue( 0 )
? item.getData< int >()
: es.getRegions( "FIPNUM" );
: props.getRegions( "FIPNUM" );
return fun::map( mknode, regions );
}
static inline std::vector< ERT::smspec_node > keywordC(
const DeckKeyword& keyword,
const EclipseState& es ) {
const Schedule& schedule,
std::array< int, 3 > dims ) {
std::vector< ERT::smspec_node > nodes;
const auto& keywordstring = keyword.name();
const auto& schedule = es.getSchedule();
const auto last_timestep = schedule->getTimeMap()->last();
auto dims = dimensions( *es.getInputGrid() );
const auto last_timestep = schedule.getTimeMap()->last();
for( const auto& record : keyword ) {
if( record.getItem( 0 ).defaultApplied( 0 ) ) {
for( const auto& well : schedule->getWells() ) {
for( const auto& well : schedule.getWells() ) {
const auto& name = wellName( well );
@@ -178,7 +181,7 @@ namespace Opm {
}
else {
/* well specified, block coordinates defaulted */
for( const auto& completion : *schedule->getWell( name ).getCompletions( last_timestep ) ) {
for( const auto& completion : *schedule.getWell( name ).getCompletions( last_timestep ) ) {
auto ijk = getijk( *completion );
nodes.emplace_back( keywordstring, name, dims.data(), ijk.data() );
}
@@ -189,27 +192,40 @@ namespace Opm {
return nodes;
}
std::vector< ERT::smspec_node > handleKW( const DeckKeyword& keyword, const EclipseState& es ) {
std::vector< ERT::smspec_node > handleKW( const DeckKeyword& keyword,
const Schedule& schedule,
const Eclipse3DProperties& props,
std::array< int, 3 > n_xyz ) {
const auto var_type = ecl_smspec_identify_var_type( keyword.name().c_str() );
switch( var_type ) {
case ECL_SMSPEC_WELL_VAR: /* intentional fall-through */
case ECL_SMSPEC_GROUP_VAR: return keywordWG( var_type, keyword, es );
case ECL_SMSPEC_FIELD_VAR: return keywordF( keyword, es );
case ECL_SMSPEC_BLOCK_VAR: return keywordB( keyword, es );
case ECL_SMSPEC_REGION_VAR: return keywordR( keyword, es );
case ECL_SMSPEC_COMPLETION_VAR: return keywordC( keyword, es );
case ECL_SMSPEC_GROUP_VAR: return keywordWG( var_type, keyword, schedule );
case ECL_SMSPEC_FIELD_VAR: return keywordF( keyword );
case ECL_SMSPEC_BLOCK_VAR: return keywordB( keyword, n_xyz );
case ECL_SMSPEC_REGION_VAR: return keywordR( keyword, props, n_xyz );
case ECL_SMSPEC_COMPLETION_VAR: return keywordC( keyword, schedule, n_xyz );
default: return {};
}
}
SummaryConfig::SummaryConfig( const Deck& deck, const EclipseState& es ) {
SummaryConfig::SummaryConfig( const Deck& deck, const EclipseState& es )
: SummaryConfig( deck,
*es.getSchedule(),
es.get3DProperties(),
dimensions( *es.getInputGrid() ) )
{}
SummaryConfig::SummaryConfig( const Deck& deck,
const Schedule& schedule,
const Eclipse3DProperties& props,
std::array< int, 3 > n_xyz ) {
SUMMARYSection section( deck );
const auto handler = [&es]( const DeckKeyword& kw ) {
return handleKW( kw, es );
};
using namespace std::placeholders;
const auto handler = std::bind( handleKW, _1, schedule, props, n_xyz );
this->keywords = fun::concat( fun::map( handler, section ) );
}

View File

@@ -20,6 +20,7 @@
#ifndef OPM_SUMMARY_CONFIG_HPP
#define OPM_SUMMARY_CONFIG_HPP
#include <array>
#include <vector>
#include <ert/ecl/Smspec.hpp>
@@ -27,14 +28,20 @@
namespace Opm {
class Deck;
class Eclipse3DProperties;
class EclipseState;
class ParserKeyword;
class Schedule;
class SummaryConfig {
public:
typedef std::vector< ERT::smspec_node >::const_iterator const_iterator;
SummaryConfig( const Deck&, const EclipseState& );
SummaryConfig( const Deck&, const Schedule&,
const Eclipse3DProperties&, std::array< int, 3 > );
SummaryConfig( const Deck&, const Schedule&,
const Eclipse3DProperties&, int, int, int );
const_iterator begin() const;
const_iterator end() const;

View File

@@ -235,3 +235,31 @@ BOOST_AUTO_TEST_CASE(PermxUnitAppliedCorrectly) {
BOOST_CHECK_CLOSE(4 * Opm::Metric::Permeability, permx.iget(i, j, 0), 0.0001);
}
}
BOOST_AUTO_TEST_CASE(getRegions) {
const char* input =
"START -- 0 \n"
"10 MAI 2007 / \n"
"RUNSPEC\n"
"\n"
"DIMENS\n"
" 2 2 1 /\n"
"GRID\n"
"DXV \n 2*400 /\n"
"DYV \n 2*400 /\n"
"DZV \n 1*400 /\n"
"REGIONS\n"
"FIPNUM\n"
"1 1 2 3 /\n";
auto deck = Opm::Parser().parseString(input, Opm::ParseContext());
Setup s( deck );
std::vector< int > ref = { 1, 2, 3 };
const auto regions = s.props.getRegions( "FIPNUM" );
BOOST_CHECK_EQUAL_COLLECTIONS( ref.begin(), ref.end(),
regions.begin(), regions.end() );
BOOST_CHECK( s.props.getRegions( "EQLNUM" ).empty() );
}

View File

@@ -584,31 +584,3 @@ BOOST_AUTO_TEST_CASE(TestIOConfigCreationWithSolutionRPTSOL) {
BOOST_CHECK_EQUAL(true, ioConfig->getWriteRestartFile(0));
}
}
BOOST_AUTO_TEST_CASE(getRegions) {
const char* input =
"START -- 0 \n"
"10 MAI 2007 / \n"
"RUNSPEC\n"
"\n"
"DIMENS\n"
" 2 2 1 /\n"
"GRID\n"
"DXV \n 2*400 /\n"
"DYV \n 2*400 /\n"
"DZV \n 1*400 /\n"
"REGIONS\n"
"FIPNUM\n"
"1 1 2 3 /\n";
const auto deck = Parser().parseString(input, ParseContext());
EclipseState es( deck, ParseContext() );
std::vector< int > ref = { 1, 2, 3 };
const auto regions = es.getRegions( "FIPNUM" );
BOOST_CHECK_EQUAL_COLLECTIONS( ref.begin(), ref.end(),
regions.begin(), regions.end() );
BOOST_CHECK( es.getRegions( "EQLNUM" ).empty() );
}

View File

@@ -237,7 +237,83 @@ namespace Opm {
const double Timestep = day;
}
namespace conversions {
/*
* It is VERY important that the dim enum has the same order as the
* metric and field arrays. C++ does not support designated initializers, so
* this cannot be done in a declaration-order independent matter.
*/
enum class dim : int {
length,
time,
density,
pressure,
temperature_absolute,
temperature,
viscosity,
permeability,
liquid_surface_volume,
gas_surface_volume,
volume,
liquid_surface_rate,
gas_surface_rate,
rate,
transmissibility,
mass,
};
/* lookup tables for SI-to-unit system
*
* We assume that all values in the report structures are plain SI units,
* but output can be configured to use other (inconsistent) unit systems.
* These lookup tables are passed to the convert function that translates
* between SI and the target unit.
*/
const double si2metric[] = {
1 / Metric::Length,
1 / Metric::Time,
1 / Metric::Density,
1 / Metric::Pressure,
1 / Metric::AbsoluteTemperature,
1 / Metric::Temperature,
1 / Metric::Viscosity,
1 / Metric::Permeability,
1 / Metric::LiquidSurfaceVolume,
1 / Metric::GasSurfaceVolume,
1 / Metric::ReservoirVolume,
1 / ( Metric::LiquidSurfaceVolume / Metric::Time ),
1 / ( Metric::GasSurfaceVolume / Metric::Time ),
1 / ( Metric::ReservoirVolume / Metric::Time ),
1 / Metric::Transmissibility,
1 / Metric::Mass,
};
const double si2field[] = {
1 / Field::Length,
1 / Field::Time,
1 / Field::Density,
1 / Field::Pressure,
1 / Field::AbsoluteTemperature,
1 / Field::Temperature,
1 / Field::Viscosity,
1 / Field::Permeability,
1 / Field::LiquidSurfaceVolume,
1 / Field::GasSurfaceVolume,
1 / Field::ReservoirVolume,
1 / ( Field::LiquidSurfaceVolume / Field::Time ),
1 / ( Field::GasSurfaceVolume / Field::Time ),
1 / ( Field::ReservoirVolume / Field::Time ),
1 / Field::Transmissibility,
1 / Field::Mass,
};
inline double from_si( const double* table, dim d, double val ) {
return val * table[ static_cast< int >( d ) ];
}
}
}
#endif