diff --git a/opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp b/opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp index 546f53404..f2e9fa80f 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp @@ -42,6 +42,10 @@ public: private: const Group2 m_group; const GTNode * m_parent; + /* + Class T with a stl container - supposedly undefined behavior before + C++17 - but it compiles without warnings. + */ std::vector m_child_groups; std::vector m_wells; }; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp b/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp index e853d5c1a..f42187a9f 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp @@ -90,6 +90,7 @@ struct GroupProductionProperties { const std::vector& wells() const; const std::vector& groups() const; + bool wellgroup() const; private: bool hasType(GroupType gtype) const; void addType(GroupType new_gtype); diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 6c1b3b3dd..c6e125999 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -45,6 +45,48 @@ #include #include + +/* + The DynamicState> pattern: The quantities in the Schedule + section like e.g. wellrates and completion properties are typically + characterized by the following behaviour: + + 1. They can be updated repeatedly at arbitrary points in the Schedule + section. + + 2. The value set at one timestep will apply until is explicitly set again at + a later timestep. + + These properties are typically stored in a DynamicState container; the + DynamicState class is a container which implements this semantics: + + 1. It is legitimate to ask for an out-of-range value, you will then get the + last value which has been set. + + 2. When assigning an out-of-bounds value the container will append the + currently set value until correct length has been reached, and then the + new value will be assigned. + + 3. The DynamicState has an awareness of the total length of the time + axis, trying to access values beyound that is illegal. + + For many of the non-trival objects like eg Well2 and Group2 the DynamicState<> + contains a shared pointer to an underlying object, that way the fill operation + when the vector is resized is quite fast. The following pattern is quite + common for the Schedule implementation: + + + // Create a new well object. + std::shared_ptr new_well = this->getWell2( well_name, time_step ); + + // Update the new well object with new settings from the deck, the + // updateXXXX() method will return true if the well object was actually + // updated: + if (new_well->updateRate( new_rate )) + this->dynamic_state.update( time_step, new_well); + +*/ + namespace Opm { diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.cpp index b775b69ac..03b3c382a 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group2.cpp @@ -41,10 +41,7 @@ std::size_t Group2::insert_index() const { } bool Group2::defined(size_t timeStep) const { - if (timeStep < this->init_step) - return false; - else - return true; + return (timeStep >= this->init_step); } const std::string& Group2::name() const { @@ -190,6 +187,11 @@ const std::vector& Group2::groups() const { return this->m_groups.data(); } +bool Group2::wellgroup() const { + if (this->m_groups.size() > 0) + return false; + return true; +} bool Group2::addWell(const std::string& well_name) { if (!this->m_groups.empty()) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index c77f75185..b5fff7f1d 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -1446,7 +1446,7 @@ namespace { injection.target_void_fraction = voidage_target; if (group_ptr->updateInjection(injection)) - this->updateGroup(group_ptr, currentStep); + this->updateGroup(std::move(group_ptr), currentStep); } } } @@ -1492,7 +1492,7 @@ namespace { production.exceed_action = exceedAction; if (group_ptr->updateProduction(production)) - this->updateGroup(group_ptr, currentStep); + this->updateGroup(std::move(group_ptr), currentStep); } } } @@ -1519,7 +1519,7 @@ namespace { { auto group_ptr = std::make_shared(this->getGroup2(group_name, currentStep)); if (group_ptr->update_gefac(gefac, transfer)) - this->updateGroup(group_ptr, currentStep); + this->updateGroup(std::move(group_ptr), currentStep); } } } @@ -1729,6 +1729,8 @@ namespace { OpmLog::note(msg); } + if (well2->updateConnections(connections)) + this->updateWell(well2, currentStep); } this->addWellEvent(name, ScheduleEvents::COMPLETION_CHANGE, currentStep); } @@ -1820,7 +1822,7 @@ namespace { { auto group_ptr = std::make_shared( this->getGroup2(groupName, currentStep) ); if (group_ptr->updateNetVFPTable(table)) - this->updateGroup(group_ptr, currentStep); + this->updateGroup(std::move(group_ptr), currentStep); } } } @@ -2089,7 +2091,7 @@ namespace { void Schedule::updateGroup(std::shared_ptr group, size_t reportStep) { auto& dynamic_state = this->groups.at(group->name()); - dynamic_state.update(reportStep, group); + dynamic_state.update(reportStep, std::move(group)); } /* @@ -2292,17 +2294,17 @@ namespace { auto& dynamic_state = this->groups.at(parent_group); auto parent_ptr = std::make_shared( *dynamic_state[timeStep] ); if (parent_ptr->addGroup(child_group.name())) - this->updateGroup(parent_ptr, timeStep); + this->updateGroup(std::move(parent_ptr), timeStep); // Check and update backreference in child if (child_group.parent() != parent_group) { auto old_parent = std::make_shared( this->getGroup2(child_group.parent(), timeStep) ); old_parent->delGroup(child_group.name()); - this->updateGroup(old_parent, timeStep); + this->updateGroup(std::move(old_parent), timeStep); auto child_ptr = std::make_shared( child_group ); child_ptr->updateParent(parent_group); - this->updateGroup(child_ptr, timeStep); + this->updateGroup(std::move(child_ptr), timeStep); } } @@ -2332,7 +2334,7 @@ namespace { { auto group = std::make_shared(this->getGroup2(old_gname, timeStep)); group->delWell(well_name); - this->updateGroup(group, timeStep); + this->updateGroup(std::move(group), timeStep); } } @@ -2344,7 +2346,7 @@ namespace { { auto group = std::make_shared(this->getGroup2(group_name, timeStep)); group->addWell(well_name); - this->updateGroup(group, timeStep); + this->updateGroup(std::move(group), timeStep); } }