diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index bc200cc15..21a34afee 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -187,6 +187,7 @@ namespace Opm double seconds(std::size_t timeStep) const; double stepLength(std::size_t timeStep) const; std::optional exitStatus() const; + const UnitSystem& getUnits() const { return this->unit_system; } const TimeMap& getTimeMap() const; diff --git a/src/opm/output/eclipse/Summary.cpp b/src/opm/output/eclipse/Summary.cpp index 74f758be0..3e4c31caf 100644 --- a/src/opm/output/eclipse/Summary.cpp +++ b/src/opm/output/eclipse/Summary.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -405,6 +406,8 @@ struct fn_args { const Opm::out::RegionCache& regionCache; const Opm::EclipseGrid& grid; const std::vector< std::pair< std::string, double > > eff_factors; + const Opm::Inplace& initial_inplace; + const Opm::UnitSystem& unit_system; }; /* Since there are several enums in opm scattered about more-or-less @@ -745,6 +748,28 @@ inline quantity bhp( const fn_args& args ) { return { p->second.bhp, measure::pressure }; } + + +/* + This function is slightly ugly - the evaluation of ROEW uses the already + calculated WOPT results. We do not really have any formalism for such + dependencies between the summary vectors. For this particualar case there is a + hack in SummaryConfig which should ensure that this is safe. +*/ + +quantity roew(const fn_args& args) { + double oil_prod = 0; + const auto& region_name = std::get(*args.extra_data); + const auto& wells = args.regionCache.wells( region_name, args.num ); + for (const auto& well : wells) + oil_prod += args.st.get_well_var(well, "WOPT"); + + //oil_prod = args.unit_system.to_si(Opm::UnitSystem::measure::volume, oil_prod); + return { oil_prod / args.initial_inplace.get( region_name, Opm::Inplace::Phase::OIL, args.num ) , measure::identity }; +} + + + inline quantity temperature( const fn_args& args ) { const quantity zero = { 0, measure::temperature }; if( args.schedule_wells.empty() ) return zero; @@ -1563,6 +1588,7 @@ static const std::unordered_map< std::string, ofun > funs = { { "WOPI", potential_rate< rt::well_potential_oil , false, true>}, { "WGPI", potential_rate< rt::well_potential_gas , false, true>}, { "WGIP", potential_rate< rt::well_potential_gas , false, true>}, // Alias for 'WGPI' + { "ROEW", roew }, }; @@ -1819,6 +1845,7 @@ namespace Evaluator { const Opm::Schedule& sched; const Opm::EclipseGrid& grid; const Opm::out::RegionCache& reg; + const Opm::Inplace initial_inplace; }; struct SimulatorResults @@ -1877,7 +1904,7 @@ namespace Evaluator { std::max(0, this->node_.number), this->node_.fip_region, st, simRes.wellSol, simRes.grpNwrkSol, input.reg, input.grid, - std::move(efac.factors) + std::move(efac.factors), input.initial_inplace, input.sched.getUnits() }; const auto& usys = input.es.getUnits(); @@ -2422,8 +2449,7 @@ namespace Evaluator { {}, "", 0.0, 0, std::max(0, this->node_->number), this->node_->fip_region, this->st_, {}, {}, reg, this->grid_, - {} - }; + {}, {}, Opm::UnitSystem(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC)}; const auto prm = this->paramFunction_(args); @@ -2672,6 +2698,7 @@ public: const data::WellRates& well_solution, const data::GroupAndNetworkValues& grp_nwrk_solution, GlobalProcessParameters& single_values, + const Inplace& initial_inplace, const RegionParameters& region_values, const BlockValues& block_values, const data::Aquifers& aquifer_values, @@ -2780,6 +2807,7 @@ eval(const int sim_step, const data::WellRates& well_solution, const data::GroupAndNetworkValues& grp_nwrk_solution, GlobalProcessParameters& single_values, + const Inplace& initial_inplace, const RegionParameters& region_values, const BlockValues& block_values, const data::Aquifers& aquifer_values, @@ -2792,7 +2820,7 @@ eval(const int sim_step, st.update("TIMESTEP", this->es_.get().getUnits().from_si(Opm::UnitSystem::measure::time, duration)); const Evaluator::InputData input { - this->es_, this->sched_, this->grid_, this->regCache_ + this->es_, this->sched_, this->grid_, this->regCache_, initial_inplace }; const Evaluator::SimulatorResults simRes { @@ -3177,7 +3205,7 @@ void Summary::eval(SummaryState& st, const data::WellRates& well_solution, const data::GroupAndNetworkValues& grp_nwrk_solution, GlobalProcessParameters single_values, - const Inplace& , + const Inplace& initial_inplace, const RegionParameters& region_values, const BlockValues& block_values, const Opm::data::Aquifers& aquifer_values) const @@ -3194,8 +3222,8 @@ void Summary::eval(SummaryState& st, * wells, groups, connections &c in the Schedule object. */ const auto sim_step = std::max( 0, report_step - 1 ); - this->pImpl_->eval(sim_step, secs_elapsed, - well_solution, grp_nwrk_solution, single_values, + this->pImpl_->eval(sim_step, secs_elapsed, well_solution, + grp_nwrk_solution, single_values, initial_inplace, region_values, block_values, aquifer_values, st); } diff --git a/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp b/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp index 44afffdee..f1fd90568 100644 --- a/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp +++ b/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp @@ -725,6 +725,7 @@ inline void keywordR2R( SummaryConfig::keyword_list& /* list */, inline void keywordR( SummaryConfig::keyword_list& list, const DeckKeyword& deck_keyword, + const Schedule& schedule, const TableManager& tables, const ParseContext& parseContext, ErrorGuard& errors ) { @@ -749,6 +750,11 @@ inline void keywordR( SummaryConfig::keyword_list& list, regions.push_back( region ); } + // See comment on function roew() in Summary.cpp for this weirdness. + if (keyword.rfind("ROEW", 0) == 0) + keywordW(list, "WOPT", {}, schedule); + + auto param = SummaryConfigNode { keyword, SummaryConfigNode::Category::Region, deck_keyword.location() } @@ -1054,7 +1060,7 @@ inline void keywordMISC( SummaryConfig::keyword_list& list, case Cat::Group: return keywordG( list, parseContext, errors, keyword, schedule ); case Cat::Field: return keywordF( list, keyword ); case Cat::Block: return keywordB( list, keyword, dims ); - case Cat::Region: return keywordR( list, keyword, tables, parseContext, errors ); + case Cat::Region: return keywordR( list, keyword, schedule, tables, parseContext, errors ); case Cat::Connection: return keywordC( list, parseContext, errors, keyword, schedule, dims); case Cat::Segment: return keywordS( list, parseContext, errors, keyword, schedule ); case Cat::Node: return keyword_node( list, node_names, parseContext, errors, keyword ); diff --git a/tests/parser/SummaryConfigTests.cpp b/tests/parser/SummaryConfigTests.cpp index 6e4c12d97..0f221dd36 100644 --- a/tests/parser/SummaryConfigTests.cpp +++ b/tests/parser/SummaryConfigTests.cpp @@ -1187,9 +1187,10 @@ ROEW_REG RHPV_REG / + )"; const auto& summary_config = createSummary(deck_string); - BOOST_CHECK_EQUAL(summary_config.size(), 15U); + BOOST_CHECK_EQUAL(summary_config.size(), 15 + 4); BOOST_CHECK(summary_config.hasKeyword("RPR__REG")); BOOST_CHECK(summary_config.hasKeyword("ROPT_REG")); BOOST_CHECK(summary_config.hasKeyword("RRPV_REG")); @@ -1210,11 +1211,11 @@ RHPV_REG BOOST_CHECK( reg_iter != fip_regions.end() ); - auto wkeywords = summary_config.keywords("W*"); - BOOST_CHECK(wkeywords.empty()); - auto rpr = summary_config.keywords("RP*"); BOOST_CHECK_EQUAL(rpr.size(), 3U); + + // See comment on the roew() function in Summary.cpp for this uglyness. + BOOST_CHECK(summary_config.hasKeyword("WOPT")); } BOOST_AUTO_TEST_CASE( WOPRL ) {