Merge pull request #2210 from joakim-hove/sched-vfp

Sched vfp
This commit is contained in:
Joakim Hove 2021-01-15 07:39:34 +01:00 committed by GitHub
commit ccb0ecbea3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 131 additions and 219 deletions

View File

@ -37,8 +37,6 @@
#include <opm/parser/eclipse/EclipseState/Schedule/MessageLimits.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/MessageLimits.hpp>
#include <opm/parser/eclipse/EclipseState/Runspec.hpp> #include <opm/parser/eclipse/EclipseState/Runspec.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/RFTConfig.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/RFTConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Network/ExtNetwork.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Network/ExtNetwork.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/PAvgCalculatorCollection.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Well/PAvgCalculatorCollection.hpp>
@ -169,8 +167,6 @@ namespace Opm
public: public:
using WellMap = OrderedMap<std::string, DynamicState<std::shared_ptr<Well>>>; using WellMap = OrderedMap<std::string, DynamicState<std::shared_ptr<Well>>>;
using GroupMap = OrderedMap<std::string, DynamicState<std::shared_ptr<Group>>>; using GroupMap = OrderedMap<std::string, DynamicState<std::shared_ptr<Group>>>;
using VFPProdMap = std::map<int, DynamicState<std::shared_ptr<VFPProdTable>>>;
using VFPInjMap = std::map<int, DynamicState<std::shared_ptr<VFPInjTable>>>;
Schedule() = default; Schedule() = default;
explicit Schedule(std::shared_ptr<const Python> python_handle); explicit Schedule(std::shared_ptr<const Python> python_handle);
@ -300,10 +296,6 @@ namespace Opm
const GuideRateConfig& guideRateConfig(std::size_t timeStep) const; const GuideRateConfig& guideRateConfig(std::size_t timeStep) const;
const RFTConfig& rftConfig() const; const RFTConfig& rftConfig() const;
const VFPProdTable& getVFPProdTable(int table_id, std::size_t timeStep) const;
const VFPInjTable& getVFPInjTable(int table_id, std::size_t timeStep) const;
std::map<int, std::shared_ptr<const VFPProdTable> > getVFPProdTables(std::size_t timeStep) const;
std::map<int, std::shared_ptr<const VFPInjTable> > getVFPInjTables(std::size_t timeStep) const;
/* /*
Will remove all completions which are connected to cell which is not Will remove all completions which are connected to cell which is not
active. Will scan through all wells and all timesteps. active. Will scan through all wells and all timesteps.
@ -350,12 +342,6 @@ namespace Opm
auto splitGroups = splitDynMap(groups); auto splitGroups = splitDynMap(groups);
serializer.vector(splitGroups.first); serializer.vector(splitGroups.first);
serializer(splitGroups.second); serializer(splitGroups.second);
auto splitvfpprod = splitDynMap<Map2>(vfpprod_tables);
serializer.vector(splitvfpprod.first);
serializer(splitvfpprod.second);
auto splitvfpinj = splitDynMap<Map2>(vfpinj_tables);
serializer.vector(splitvfpinj.first);
serializer(splitvfpinj.second);
udq_config.serializeOp(serializer); udq_config.serializeOp(serializer);
udq_active.serializeOp(serializer); udq_active.serializeOp(serializer);
guide_rate_config.serializeOp(serializer); guide_rate_config.serializeOp(serializer);
@ -366,8 +352,6 @@ namespace Opm
if (!serializer.isSerializing()) { if (!serializer.isSerializing()) {
reconstructDynMap(splitWells.first, splitWells.second, wells_static); reconstructDynMap(splitWells.first, splitWells.second, wells_static);
reconstructDynMap(splitGroups.first, splitGroups.second, groups); reconstructDynMap(splitGroups.first, splitGroups.second, groups);
reconstructDynMap<Map2>(splitvfpprod.first, splitvfpprod.second, vfpprod_tables);
reconstructDynMap<Map2>(splitvfpinj.first, splitvfpinj.second, vfpinj_tables);
} }
serializer.vector(snapshots); serializer.vector(snapshots);
m_static.serializeOp(serializer); m_static.serializeOp(serializer);
@ -380,8 +364,6 @@ namespace Opm
TimeMap m_timeMap; TimeMap m_timeMap;
WellMap wells_static; WellMap wells_static;
GroupMap groups; GroupMap groups;
VFPProdMap vfpprod_tables;
VFPInjMap vfpinj_tables;
DynamicState<std::shared_ptr<UDQConfig>> udq_config; DynamicState<std::shared_ptr<UDQConfig>> udq_config;
DynamicState<std::shared_ptr<UDQActive>> udq_active; DynamicState<std::shared_ptr<UDQActive>> udq_active;
DynamicState<std::shared_ptr<GuideRateConfig>> guide_rate_config; DynamicState<std::shared_ptr<GuideRateConfig>> guide_rate_config;
@ -420,7 +402,8 @@ namespace Opm
void updateUDQActive( std::size_t timeStep, std::shared_ptr<UDQActive> udq ); void updateUDQActive( std::size_t timeStep, std::shared_ptr<UDQActive> udq );
bool updateWellStatus( const std::string& well, std::size_t reportStep, bool runtime, Well::Status status, std::optional<KeywordLocation> = {}); bool updateWellStatus( const std::string& well, std::size_t reportStep, bool runtime, Well::Status status, std::optional<KeywordLocation> = {});
void addWellToGroup( const std::string& group_name, const std::string& well_name , std::size_t timeStep); void addWellToGroup( const std::string& group_name, const std::string& well_name , std::size_t timeStep);
void iterateScheduleSection(std::optional<std::size_t> load_offset, void iterateScheduleSection(std::size_t load_start,
std::size_t load_end,
const ParseContext& parseContext, const ParseContext& parseContext,
ErrorGuard& errors, ErrorGuard& errors,
const EclipseGrid& grid, const EclipseGrid& grid,

View File

@ -37,6 +37,8 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSump.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSump.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSale.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSale.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Network/ExtNetwork.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Network/ExtNetwork.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp>
namespace Opm { namespace Opm {
@ -116,6 +118,14 @@ namespace Opm {
const RPTConfig& rpt_config() const; const RPTConfig& rpt_config() const;
void rpt_config(RPTConfig rpt_config); void rpt_config(RPTConfig rpt_config);
std::vector<const VFPProdTable*> vfpprod() const;
const VFPProdTable& vfpprod(int table_id) const;
void vfpprod(VFPProdTable vfpprod);
std::vector<const VFPInjTable*> vfpinj() const;
const VFPInjTable& vfpinj(int table_id) const;
void vfpinj(VFPInjTable vfpinj);
template<class Serializer> template<class Serializer>
void serializeOp(Serializer& serializer) { void serializeOp(Serializer& serializer) {
serializer(m_start_time); serializer(m_start_time);
@ -135,8 +145,11 @@ namespace Opm {
serializer(m_wlist_manager); serializer(m_wlist_manager);
serializer(m_network); serializer(m_network);
serializer(m_rptconfig); serializer(m_rptconfig);
serializer.map(m_vfpprod);
serializer.map(m_vfpinj);
} }
private: private:
std::chrono::system_clock::time_point m_start_time; std::chrono::system_clock::time_point m_start_time;
std::optional<std::chrono::system_clock::time_point> m_end_time; std::optional<std::chrono::system_clock::time_point> m_end_time;
@ -156,6 +169,8 @@ namespace Opm {
std::shared_ptr<WListManager> m_wlist_manager; std::shared_ptr<WListManager> m_wlist_manager;
std::shared_ptr<Network::ExtNetwork> m_network; std::shared_ptr<Network::ExtNetwork> m_network;
std::shared_ptr<RPTConfig> m_rptconfig; std::shared_ptr<RPTConfig> m_rptconfig;
std::map<int, std::shared_ptr<VFPProdTable>> m_vfpprod;
std::map<int, std::shared_ptr<VFPInjTable>> m_vfpinj;
}; };
} }

View File

@ -588,7 +588,7 @@ namespace {
sWell[Ix::HistBHPTarget] = sWell[Ix::BHPTarget]; sWell[Ix::HistBHPTarget] = sWell[Ix::BHPTarget];
if (pc.alq_value != 0.0) { if (pc.alq_value != 0.0) {
auto vfpTable = sched.getVFPProdTable(pc.vfp_table_number,sim_step); auto vfpTable = sched[sim_step].vfpprod(pc.vfp_table_number);
if (vfpTable.getALQType() == Opm::VFPProdTable::ALQ_GRAT) { if (vfpTable.getALQType() == Opm::VFPProdTable::ALQ_GRAT) {
sWell[Ix::Alq_value] = static_cast<float>(units.from_si(M::gas_surface_rate, pc.alq_value)); sWell[Ix::Alq_value] = static_cast<float>(units.from_si(M::gas_surface_rate, pc.alq_value));
} }

View File

@ -470,7 +470,6 @@ namespace {
} }
} }
} }
printf("GCONPROD complete\n");
} }
void Schedule::handleGCONSALE(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { void Schedule::handleGCONSALE(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
@ -742,6 +741,7 @@ namespace {
} }
void Schedule::handleRPTSCHED(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { void Schedule::handleRPTSCHED(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
printf("snapshost.size(): %ld \n", this->snapshots.size());
this->snapshots.back().rpt_config( RPTConfig(handlerContext.keyword )); this->snapshots.back().rpt_config( RPTConfig(handlerContext.keyword ));
} }
@ -838,31 +838,15 @@ namespace {
} }
void Schedule::handleVFPINJ(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { void Schedule::handleVFPINJ(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
std::shared_ptr<VFPInjTable> table = std::make_shared<VFPInjTable>(handlerContext.keyword, this->m_static.m_unit_system); auto table = VFPInjTable(handlerContext.keyword, this->m_static.m_unit_system);
int table_id = table->getTableNum(); this->snapshots.back().vfpinj( std::move(table) );
if (vfpinj_tables.find(table_id) == vfpinj_tables.end()) {
std::pair<int, DynamicState<std::shared_ptr<VFPInjTable> > > pair = std::make_pair(table_id, DynamicState<std::shared_ptr<VFPInjTable> >(this->m_timeMap, nullptr));
vfpinj_tables.insert( pair );
}
auto& table_state = vfpinj_tables.at(table_id);
table_state.update(handlerContext.currentStep, table);
this->snapshots.back().events().addEvent( ScheduleEvents::VFPINJ_UPDATE ); this->snapshots.back().events().addEvent( ScheduleEvents::VFPINJ_UPDATE );
} }
void Schedule::handleVFPPROD(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { void Schedule::handleVFPPROD(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
std::shared_ptr<VFPProdTable> table = std::make_shared<VFPProdTable>(handlerContext.keyword, this->m_static.m_unit_system); auto table = VFPProdTable(handlerContext.keyword, this->m_static.m_unit_system);
int table_id = table->getTableNum();
if (vfpprod_tables.find(table_id) == vfpprod_tables.end()) {
std::pair<int, DynamicState<std::shared_ptr<VFPProdTable> > > pair = std::make_pair(table_id, DynamicState<std::shared_ptr<VFPProdTable> >(this->m_timeMap, nullptr));
vfpprod_tables.insert( pair );
}
auto& table_state = vfpprod_tables.at(table_id);
table_state.update(handlerContext.currentStep, table);
this->snapshots.back().events().addEvent( ScheduleEvents::VFPPROD_UPDATE ); this->snapshots.back().events().addEvent( ScheduleEvents::VFPPROD_UPDATE );
this->snapshots.back().vfpprod( std::move(table) );
} }
void Schedule::handleWCONHIST(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { void Schedule::handleWCONHIST(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
@ -889,7 +873,7 @@ namespace {
table_nr = properties->VFPTableNumber; table_nr = properties->VFPTableNumber;
if (table_nr != 0) if (table_nr != 0)
alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); alq_type = this->snapshots.back().vfpprod(table_nr).getALQType();
properties->handleWCONHIST(alq_type, this->m_static.m_unit_system, record); properties->handleWCONHIST(alq_type, this->m_static.m_unit_system, record);
if (switching_from_injector) { if (switching_from_injector) {
@ -959,7 +943,7 @@ namespace {
table_nr = properties->VFPTableNumber; table_nr = properties->VFPTableNumber;
if (table_nr != 0) if (table_nr != 0)
alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); alq_type = this->snapshots.back().vfpprod(table_nr).getALQType();
properties->handleWCONPROD(alq_type, this->m_static.m_unit_system, well_name, record); properties->handleWCONPROD(alq_type, this->m_static.m_unit_system, well_name, record);
if (switching_from_injector) { if (switching_from_injector) {

View File

@ -121,10 +121,13 @@ namespace {
rft_config(this->m_timeMap), rft_config(this->m_timeMap),
restart_config(m_timeMap, deck, parseContext, errors) restart_config(m_timeMap, deck, parseContext, errors)
{ {
if (rst) if (rst) {
auto restart_step = rst->header.restart_info().second;
this->iterateScheduleSection( 0, restart_step, parseContext, errors, grid, fp);
this->load_rst(*rst, grid, fp); this->load_rst(*rst, grid, fp);
this->iterateScheduleSection( restart_step, this->m_sched_deck.size(), parseContext, errors, grid, fp);
this->iterateScheduleSection( {}, parseContext, errors, grid, fp); } else
this->iterateScheduleSection( 0, this->m_sched_deck.size(), parseContext, errors, grid, fp);
/* /*
The code in the #ifdef SCHEDULE_DEBUG is an enforced integration test The code in the #ifdef SCHEDULE_DEBUG is an enforced integration test
@ -135,14 +138,6 @@ namespace {
if (this->size() == 0) if (this->size() == 0)
return; return;
//Verify that we can safely re-iterate over the Schedule section
//if (!rst)
// this->iterateScheduleSection(0, parseContext, errors, grid, fp);
//else {
// auto restart_offset = this->m_sched_deck.restart_offset();
// this->iterateScheduleSection(restart_offset, parseContext, errors, grid, fp);
//}
// Verify that the time schedule is correct. // Verify that the time schedule is correct.
for (std::size_t report_step = 0; report_step < this->size() - 1; report_step++) { for (std::size_t report_step = 0; report_step < this->size() - 1; report_step++) {
const auto& this_block = this->m_sched_deck[report_step]; const auto& this_block = this->m_sched_deck[report_step];
@ -257,8 +252,6 @@ namespace {
result.m_timeMap = TimeMap::serializeObject(); result.m_timeMap = TimeMap::serializeObject();
result.wells_static.insert({"test1", {{std::make_shared<Opm::Well>(Opm::Well::serializeObject())},1}}); result.wells_static.insert({"test1", {{std::make_shared<Opm::Well>(Opm::Well::serializeObject())},1}});
result.groups.insert({"test2", {{std::make_shared<Opm::Group>(Opm::Group::serializeObject())},1}}); result.groups.insert({"test2", {{std::make_shared<Opm::Group>(Opm::Group::serializeObject())},1}});
result.vfpprod_tables = {{1, {{std::make_shared<VFPProdTable>(VFPProdTable::serializeObject())}, 1}}};
result.vfpinj_tables = {{2, {{std::make_shared<VFPInjTable>(VFPInjTable::serializeObject())}, 1}}};
result.udq_config = {{std::make_shared<UDQConfig>(UDQConfig::serializeObject())}, 1}; result.udq_config = {{std::make_shared<UDQConfig>(UDQConfig::serializeObject())}, 1};
result.m_glo = {{std::make_shared<GasLiftOpt>(GasLiftOpt::serializeObject())}, 1}; result.m_glo = {{std::make_shared<GasLiftOpt>(GasLiftOpt::serializeObject())}, 1};
result.udq_active = {{std::make_shared<UDQActive>(UDQActive::serializeObject())}, 1}; result.udq_active = {{std::make_shared<UDQActive>(UDQActive::serializeObject())}, 1};
@ -366,7 +359,7 @@ private:
} }
void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset, void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_end,
const ParseContext& parseContext , const ParseContext& parseContext ,
ErrorGuard& errors, ErrorGuard& errors,
const EclipseGrid& grid, const EclipseGrid& grid,
@ -377,74 +370,6 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
auto deck_time = [this](double seconds) { return this->m_static.m_unit_system.from_si(UnitSystem::measure::time, seconds); }; auto deck_time = [this](double seconds) { return this->m_static.m_unit_system.from_si(UnitSystem::measure::time, seconds); };
std::string current_file; std::string current_file;
const auto& time_map = this->m_timeMap; const auto& time_map = this->m_timeMap;
/*
The process of transitioning to Schedule model based on ScheduleState
instances is a gradual one. For the keywords which have been converted
to the ScheduleState implementation the iterateScheduleSection()
function can be called repeatedly, whereas for the keywords which have
not yet been converted that is not safe. The old_style_keywords is a
list of keywords which should be ignored when iterateScheduleSection()
is called repeatedly.
*/
std::unordered_set<std::string> old_style_keywords = {
"PYACTION",
"GCONPROD",
"GCONINJE",
"GLIFTOPT",
"WELPI",
"BRANPROP",
"COMPDAT",
"COMPLUMP",
"COMPORD",
"COMPSEGS",
"GCONINJE",
"GCONPROD",
"GCONSALE",
"GCONSUMP",
"GEFAC",
"GLIFTOPT",
"GPMAINT",
"GRUPNET",
"GRUPTREE",
"GUIDERAT",
"LIFTOPT",
"LINCOM",
"MESSAGES",
"MXUNSUPP",
"NODEPROP",
"RPTSCHED",
"UDQ",
"VFPINJ",
"VFPPROD",
"WCONHIST",
"WCONINJE",
"WCONINJH",
"WCONPROD",
"WECON",
"WEFAC",
"WELOPEN",
"WELPI",
"WELSEGS",
"WELSPECS",
"WELTARG",
"WFOAM",
"WGRUPCON",
"WINJTEMP",
"WLIFTOPT",
"WPAVEDEP",
"WPIMULT",
"WPMITAB",
"WPOLYMER",
"WSALT",
"WSEGSICD",
"WSEGAICD",
"WSEGVALV",
"WSKPTAB",
"WSOLVENT",
"WTEMP",
"WTRACER"
};
/* /*
The keywords in the skiprest_whitelist set are loaded from the The keywords in the skiprest_whitelist set are loaded from the
SCHEDULE section even though the SKIPREST keyword is in action. The SCHEDULE section even though the SKIPREST keyword is in action. The
@ -452,7 +377,6 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
all. all.
*/ */
std::unordered_set<std::string> skiprest_whitelist = {"VFPPROD", "VFPINJ", "RPTSCHED", "RPTRST", "TUNING", "MESSAGES"}; std::unordered_set<std::string> skiprest_whitelist = {"VFPPROD", "VFPINJ", "RPTSCHED", "RPTRST", "TUNING", "MESSAGES"};
std::size_t currentStep = 0;
/* /*
The behavior of variable restart_skip is more lenient than the The behavior of variable restart_skip is more lenient than the
SKIPREST keyword. If this is a restarted[1] run the loop iterating SKIPREST keyword. If this is a restarted[1] run the loop iterating
@ -469,7 +393,7 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
these keywords will be assigned to report step 0. these keywords will be assigned to report step 0.
*/ */
auto restart_skip = currentStep < this->m_timeMap.restart_offset(); auto restart_skip = load_start < this->m_timeMap.restart_offset();
ScheduleLogger logger(restart_skip); ScheduleLogger logger(restart_skip);
{ {
const auto& location = this->m_sched_deck.location(); const auto& location = this->m_sched_deck.location();
@ -479,44 +403,38 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
logger.info(fmt::format("This is a restarted run - skipping until report step {} at {}", time_map.restart_offset(), Schedule::formatDate(time_map.restart_time()))); logger.info(fmt::format("This is a restarted run - skipping until report step {} at {}", time_map.restart_offset(), Schedule::formatDate(time_map.restart_time())));
logger(fmt::format("Initializing report step {}/{} at {} {} {} line {}", logger(fmt::format("Initializing report step {}/{} at {} {} {} line {}",
currentStep + 1, load_start + 1,
this->size(), this->size(),
Schedule::formatDate(this->getStartTime()), Schedule::formatDate(this->getStartTime()),
deck_time(time_map.getTimePassedUntil(currentStep)), deck_time(time_map.getTimePassedUntil(load_start)),
time_unit, time_unit,
location.lineno)); location.lineno));
} }
if (load_offset.has_value()) { for (auto report_step = load_start; report_step < load_end; report_step++) {
if (load_offset.value() < this->m_sched_deck.restart_offset())
throw std::logic_error("BUG: Tried to replay schedule keywords from historical section in restarted run");
this->snapshots.resize( load_offset.value() );
}
for (const auto& block : this->m_sched_deck) {
std::size_t keyword_index = 0; std::size_t keyword_index = 0;
auto& block = this->m_sched_deck[report_step];
auto time_type = block.time_type(); auto time_type = block.time_type();
if (time_type == ScheduleTimeType::DATES || time_type == ScheduleTimeType::TSTEP) { if (time_type == ScheduleTimeType::DATES || time_type == ScheduleTimeType::TSTEP) {
const auto& start_date = Schedule::formatDate(std::chrono::system_clock::to_time_t(block.start_time())); const auto& start_date = Schedule::formatDate(std::chrono::system_clock::to_time_t(block.start_time()));
const auto& days = deck_time(this->stepLength(currentStep - 1)); const auto& days = deck_time(this->stepLength(report_step - 1));
const auto& days_total = deck_time(time_map.getTimePassedUntil(currentStep)); const auto& days_total = deck_time(time_map.getTimePassedUntil(report_step));
logger.complete_step(fmt::format("Complete report step {0} ({1} {2}) at {3} ({4} {2})", logger.complete_step(fmt::format("Complete report step {0} ({1} {2}) at {3} ({4} {2})",
currentStep, report_step,
days, days,
time_unit, time_unit,
start_date, start_date,
days_total)); days_total));
logger(fmt::format("Initializing report step {}/{} at {} ({} {}) - line {}", logger(fmt::format("Initializing report step {}/{} at {} ({} {}) - line {}",
currentStep + 1, report_step + 1,
this->size(), this->size(),
start_date, start_date,
days_total, days_total,
time_unit, time_unit,
block.location().lineno)); block.location().lineno));
} }
if (time_type != ScheduleTimeType::RESTART) this->create_next(block);
this->create_next(block);
while (true) { while (true) {
if (keyword_index == block.size()) if (keyword_index == block.size())
@ -529,13 +447,8 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
current_file = location.filename; current_file = location.filename;
} }
if (load_offset.has_value() && old_style_keywords.count(keyword.name()) == 1) {
keyword_index += 1;
continue;
}
if (keyword.name() == "ACTIONX") { if (keyword.name() == "ACTIONX") {
Action::ActionX action(keyword, this->m_timeMap.getStartTime(currentStep)); Action::ActionX action(keyword, this->m_timeMap.getStartTime(report_step));
while (true) { while (true) {
keyword_index++; keyword_index++;
if (keyword_index == block.size()) if (keyword_index == block.size())
@ -553,13 +466,13 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
parseContext.handleError( ParseContext::ACTIONX_ILLEGAL_KEYWORD, msg_fmt, action_keyword.location(), errors); parseContext.handleError( ParseContext::ACTIONX_ILLEGAL_KEYWORD, msg_fmt, action_keyword.location(), errors);
} }
} }
this->addACTIONX(action, currentStep); this->addACTIONX(action, report_step);
keyword_index++; keyword_index++;
continue; continue;
} }
logger(fmt::format("Processing keyword {} at line {}", location.keyword, location.lineno)); logger(fmt::format("Processing keyword {} at line {}", location.keyword, location.lineno));
this->handleKeyword(currentStep, this->handleKeyword(report_step,
block, block,
keyword, keyword,
parseContext, parseContext,
@ -570,8 +483,7 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
keyword_index++; keyword_index++;
} }
checkIfAllConnectionsIsShut(currentStep); checkIfAllConnectionsIsShut(report_step);
currentStep += 1;
} }
@ -1396,49 +1308,6 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
} }
} }
const VFPProdTable& Schedule::getVFPProdTable(int table_id, std::size_t timeStep) const {
const auto pair = vfpprod_tables.find(table_id);
if (pair == vfpprod_tables.end())
throw std::invalid_argument("No such table id: " + std::to_string(table_id));
auto table_ptr = pair->second.get(timeStep);
if (!table_ptr)
throw std::invalid_argument("Table not yet defined at timeStep:" + std::to_string(timeStep));
return *table_ptr;
}
const VFPInjTable& Schedule::getVFPInjTable(int table_id, std::size_t timeStep) const {
const auto pair = vfpinj_tables.find(table_id);
if (pair == vfpinj_tables.end())
throw std::invalid_argument("No such table id: " + std::to_string(table_id));
auto table_ptr = pair->second.get(timeStep);
if (!table_ptr)
throw std::invalid_argument("Table not yet defined at timeStep:" + std::to_string(timeStep));
return *table_ptr;
}
std::map<int, std::shared_ptr<const VFPInjTable> > Schedule::getVFPInjTables(std::size_t timeStep) const {
std::map<int, std::shared_ptr<const VFPInjTable> > tables;
for (const auto& pair : this->vfpinj_tables) {
if (pair.second.get(timeStep)) {
tables.insert(std::make_pair(pair.first, pair.second.get(timeStep)) );
}
}
return tables;
}
std::map<int, std::shared_ptr<const VFPProdTable> > Schedule::getVFPProdTables(std::size_t timeStep) const {
std::map<int, std::shared_ptr<const VFPProdTable> > tables;
for (const auto& pair : this->vfpprod_tables) {
if (pair.second.get(timeStep)) {
tables.insert(std::make_pair(pair.first, pair.second.get(timeStep)) );
}
}
return tables;
}
const UDQActive& Schedule::udqActive(std::size_t timeStep) const { const UDQActive& Schedule::udqActive(std::size_t timeStep) const {
return *this->udq_active[timeStep]; return *this->udq_active[timeStep];
@ -1624,8 +1493,6 @@ void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
this->m_static == data.m_static && this->m_static == data.m_static &&
compareMap(this->wells_static, data.wells_static) && compareMap(this->wells_static, data.wells_static) &&
compareMap(this->groups, data.groups) && compareMap(this->groups, data.groups) &&
compareMap(this->vfpprod_tables, data.vfpprod_tables) &&
compareMap(this->vfpinj_tables, data.vfpinj_tables) &&
compareDynState(this->m_glo, data.m_glo) && compareDynState(this->m_glo, data.m_glo) &&
compareDynState(this->udq_config, data.udq_config) && compareDynState(this->udq_config, data.udq_config) &&
compareDynState(this->udq_active, data.udq_active) && compareDynState(this->udq_active, data.udq_active) &&
@ -1666,16 +1533,8 @@ namespace {
void Schedule::load_rst(const RestartIO::RstState& rst_state, const EclipseGrid& grid, const FieldPropsManager& fp) void Schedule::load_rst(const RestartIO::RstState& rst_state, const EclipseGrid& grid, const FieldPropsManager& fp)
{ {
double udq_undefined = 0;
const auto report_step = rst_state.header.report_step - 1; const auto report_step = rst_state.header.report_step - 1;
auto start_time = std::chrono::system_clock::from_time_t( this->getStartTime() ); double udq_undefined = 0;
for (int step = 0; step < report_step; step++)
this->create_next(start_time, start_time);
{
auto restart_time = std::chrono::system_clock::from_time_t( rst_state.header.restart_info().first );
this->create_next(start_time, restart_time);
}
for (const auto& rst_group : rst_state.groups) { for (const auto& rst_group : rst_state.groups) {
auto group = Group{ rst_group, this->groups.size(), static_cast<std::size_t>(report_step), udq_undefined, this->m_static.m_unit_system }; auto group = Group{ rst_group, this->groups.size(), static_cast<std::size_t>(report_step), udq_undefined, this->m_static.m_unit_system };
this->addGroup(group, report_step); this->addGroup(group, report_step);

View File

@ -16,11 +16,15 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <fmt/format.h>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSump.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSump.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSale.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSale.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp>
namespace Opm { namespace Opm {
@ -141,6 +145,30 @@ void ScheduleState::whistctl(Well::ProducerCMode whistctl) {
} }
bool ScheduleState::operator==(const ScheduleState& other) const { bool ScheduleState::operator==(const ScheduleState& other) const {
auto&& map_equal = [](const auto& map1, const auto& map2) {
if (map1.size() != map2.size())
return false;
auto it2 = map2.begin();
for (const auto& it1 : map1) {
if (it1.first != it2->first)
return false;
if (!(*it1.second == *it2->second))
return false;
++it2;
}
return true;
};
if (!map_equal(this->m_vfpprod, other.m_vfpprod))
return false;
if (!map_equal(this->m_vfpinj, other.m_vfpinj))
return false;
return this->m_start_time == other.m_start_time && return this->m_start_time == other.m_start_time &&
this->m_oilvap == other.m_oilvap && this->m_oilvap == other.m_oilvap &&
this->m_tuning == other.m_tuning && this->m_tuning == other.m_tuning &&
@ -172,6 +200,11 @@ ScheduleState ScheduleState::serializeObject() {
ts.m_gconsale = std::make_shared<GConSale>( GConSale::serializeObject() ); ts.m_gconsale = std::make_shared<GConSale>( GConSale::serializeObject() );
ts.m_wlist_manager = std::make_shared<WListManager>( WListManager::serializeObject() ); ts.m_wlist_manager = std::make_shared<WListManager>( WListManager::serializeObject() );
ts.m_rptconfig = std::make_shared<RPTConfig>( RPTConfig::serializeObject() ); ts.m_rptconfig = std::make_shared<RPTConfig>( RPTConfig::serializeObject() );
ts.m_vfpprod.emplace( std::make_pair(77, std::make_shared<VFPProdTable>(VFPProdTable::serializeObject() )));
ts.m_vfpprod.emplace( std::make_pair(78, std::make_shared<VFPProdTable>(VFPProdTable::serializeObject() )));
ts.m_vfpinj.emplace( std::make_pair(177, std::make_shared<VFPInjTable>(VFPInjTable::serializeObject() )));
ts.m_vfpinj.emplace( std::make_pair(178, std::make_shared<VFPInjTable>(VFPInjTable::serializeObject() )));
return ts; return ts;
} }
@ -260,4 +293,48 @@ const RPTConfig& ScheduleState::rpt_config() const {
void ScheduleState::rpt_config(RPTConfig rpt_config) { void ScheduleState::rpt_config(RPTConfig rpt_config) {
this->m_rptconfig = std::make_shared<RPTConfig>(std::move(rpt_config)); this->m_rptconfig = std::make_shared<RPTConfig>(std::move(rpt_config));
} }
std::vector<const VFPProdTable*> ScheduleState::vfpprod() const {
std::vector<const VFPProdTable*> tables;
for (const auto& [_, table] : this->m_vfpprod) {
(void)_;
tables.push_back( table.get() );
}
return tables;
}
const VFPProdTable& ScheduleState::vfpprod(int table_id) const {
auto vfp_iter = this->m_vfpprod.find(table_id);
if (vfp_iter == this->m_vfpprod.end())
throw std::logic_error(fmt::format("No VFPPROD table with id: {} has been registered", table_id));
return *vfp_iter->second;
}
void ScheduleState::vfpprod(VFPProdTable vfpprod) {
int table_id = vfpprod.getTableNum();
this->m_vfpprod[table_id] = std::make_shared<VFPProdTable>( std::move(vfpprod) );
}
std::vector<const VFPInjTable*> ScheduleState::vfpinj() const {
std::vector<const VFPInjTable*> tables;
for (const auto& [_, table] : this->m_vfpinj) {
(void)_;
tables.push_back( table.get() );
}
return tables;
}
const VFPInjTable& ScheduleState::vfpinj(int table_id) const {
auto vfp_iter = this->m_vfpinj.find(table_id);
if (vfp_iter == this->m_vfpinj.end())
throw std::logic_error(fmt::format("No VFPINJ table with id: {} has been registered", table_id));
return *vfp_iter->second;
}
void ScheduleState::vfpinj(VFPInjTable vfpinj) {
int table_id = vfpinj.getTableNum();
this->m_vfpinj[table_id] = std::make_shared<VFPInjTable>( std::move(vfpinj) );
}
} }

View File

@ -3006,31 +3006,26 @@ VFPINJ
BOOST_CHECK( schedule[2].events().hasEvent(ScheduleEvents::VFPINJ_UPDATE)); BOOST_CHECK( schedule[2].events().hasEvent(ScheduleEvents::VFPINJ_UPDATE));
// No such table id // No such table id
BOOST_CHECK_THROW(schedule.getVFPInjTable(77,0), std::invalid_argument); BOOST_CHECK_THROW(schedule[0].vfpinj(77), std::exception);
// Table not defined at step 0 // Table not defined at step 0
BOOST_CHECK_THROW(schedule.getVFPInjTable(10,0), std::invalid_argument); BOOST_CHECK_THROW(schedule[0].vfpinj(10), std::exception);
const Opm::VFPInjTable& vfpinjTable2 = schedule.getVFPInjTable(5, 2); const Opm::VFPInjTable& vfpinjTable2 = schedule[2].vfpinj(5);
BOOST_CHECK_EQUAL(vfpinjTable2.getTableNum(), 5); BOOST_CHECK_EQUAL(vfpinjTable2.getTableNum(), 5);
BOOST_CHECK_EQUAL(vfpinjTable2.getDatumDepth(), 100); BOOST_CHECK_EQUAL(vfpinjTable2.getDatumDepth(), 100);
BOOST_CHECK_EQUAL(vfpinjTable2.getFloType(), Opm::VFPInjTable::FLO_GAS); BOOST_CHECK_EQUAL(vfpinjTable2.getFloType(), Opm::VFPInjTable::FLO_GAS);
const Opm::VFPInjTable& vfpinjTable3 = schedule.getVFPInjTable(10, 2); const Opm::VFPInjTable& vfpinjTable3 = schedule[2].vfpinj(10);
BOOST_CHECK_EQUAL(vfpinjTable3.getTableNum(), 10); BOOST_CHECK_EQUAL(vfpinjTable3.getTableNum(), 10);
BOOST_CHECK_EQUAL(vfpinjTable3.getDatumDepth(), 200); BOOST_CHECK_EQUAL(vfpinjTable3.getDatumDepth(), 200);
BOOST_CHECK_EQUAL(vfpinjTable3.getFloType(), Opm::VFPInjTable::FLO_WAT); BOOST_CHECK_EQUAL(vfpinjTable3.getFloType(), Opm::VFPInjTable::FLO_WAT);
const Opm::VFPInjTable& vfpinjTable = schedule.getVFPInjTable(5, 0); const Opm::VFPInjTable& vfpinjTable = schedule[0].vfpinj(5);
BOOST_CHECK_EQUAL(vfpinjTable.getTableNum(), 5); BOOST_CHECK_EQUAL(vfpinjTable.getTableNum(), 5);
BOOST_CHECK_EQUAL(vfpinjTable.getDatumDepth(), 32.9); BOOST_CHECK_EQUAL(vfpinjTable.getDatumDepth(), 32.9);
BOOST_CHECK_EQUAL(vfpinjTable.getFloType(), Opm::VFPInjTable::FLO_WAT); BOOST_CHECK_EQUAL(vfpinjTable.getFloType(), Opm::VFPInjTable::FLO_WAT);
const auto vfp_tables0 = schedule.getVFPInjTables(0);
BOOST_CHECK_EQUAL( vfp_tables0.size(), 1U);
const auto vfp_tables2 = schedule.getVFPInjTables(2);
BOOST_CHECK_EQUAL( vfp_tables2.size(), 2U);
//Flo axis //Flo axis
{ {
const std::vector<double>& flo = vfpinjTable.getFloAxis(); const std::vector<double>& flo = vfpinjTable.getFloAxis();
@ -3698,8 +3693,7 @@ BOOST_AUTO_TEST_CASE(SKIPREST_VFP) {
Opm::EclIO::ERst rst_file(rst_filename); Opm::EclIO::ERst rst_file(rst_filename);
const auto& rst = Opm::RestartIO::RstState::load(rst_file, report_step); const auto& rst = Opm::RestartIO::RstState::load(rst_file, report_step);
const auto sched = Schedule{ deck, es, python , &rst}; const auto sched = Schedule{ deck, es, python , &rst};
const auto& tables = sched.getVFPProdTables(3); BOOST_CHECK_NO_THROW( sched[3].vfpprod(5) );
BOOST_CHECK( !tables.empty() );
} }
@ -4229,7 +4223,7 @@ BOOST_AUTO_TEST_CASE(VFPPROD_SCALING) {
const auto deck = Parser{}.parseFile("VFP_CASE.DATA"); const auto deck = Parser{}.parseFile("VFP_CASE.DATA");
const auto es = EclipseState{ deck }; const auto es = EclipseState{ deck };
const auto sched = Schedule{ deck, es }; const auto sched = Schedule{ deck, es };
const auto& vfp_table = sched.getVFPProdTable(1, 0); const auto& vfp_table = sched[0].vfpprod(1);
const std::vector<double> flo = { 0.000578704, 0.001157407, 0.002893519, 0.005787037, 0.008680556, 0.011574074, 0.017361111, 0.023148148, 0.034722222, 0.046296296}; const std::vector<double> flo = { 0.000578704, 0.001157407, 0.002893519, 0.005787037, 0.008680556, 0.011574074, 0.017361111, 0.023148148, 0.034722222, 0.046296296};
const std::vector<double> thp = {1300000.000000000, 2500000.000000000, 5000000.000000000, 7500000.000000000, 10000000.000000000}; const std::vector<double> thp = {1300000.000000000, 2500000.000000000, 5000000.000000000, 7500000.000000000, 10000000.000000000};
const std::vector<double> wfr = { 0.000000000, 0.100000000, 0.200000000, 0.300000000, 0.400000000, 0.500000000, 0.600000000, 0.700000000, 0.800000000, 0.990000000}; const std::vector<double> wfr = { 0.000000000, 0.100000000, 0.200000000, 0.300000000, 0.400000000, 0.500000000, 0.600000000, 0.700000000, 0.800000000, 0.990000000};