Use ScheduleState to manage groups

This commit is contained in:
Joakim Hove
2021-01-30 14:51:55 +01:00
parent bd22745ec0
commit e016d357d8
14 changed files with 181 additions and 184 deletions

View File

@@ -283,10 +283,6 @@ namespace Opm
GTNode groupTree(std::size_t report_step) const;
GTNode groupTree(const std::string& root_node, std::size_t report_step) const;
std::size_t numGroups() const;
std::size_t numGroups(std::size_t timeStep) const;
bool hasGroup(const std::string& groupName) const;
bool hasGroup(const std::string& groupName, std::size_t timeStep) const;
const Group& getGroup(const std::string& groupName, std::size_t timeStep) const;
void invalidNamePattern (const std::string& namePattern, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors, const DeckKeyword& keyword) const;
@@ -337,9 +333,6 @@ namespace Opm
auto splitWells = splitDynMap<UnorderedMap>(wells_static);
serializer.vector(splitWells.first);
serializer(splitWells.second);
auto splitGroups = splitDynMap<Map>(groups);
serializer.vector(splitGroups.first);
serializer(splitGroups.second);
udq_config.serializeOp(serializer);
guide_rate_config.serializeOp(serializer);
m_glo.serializeOp(serializer);
@@ -347,7 +340,6 @@ namespace Opm
restart_config.serializeOp(serializer);
if (!serializer.isSerializing()) {
reconstructDynMap<UnorderedMap>(splitWells.first, splitWells.second, wells_static);
reconstructDynMap<Map>(splitGroups.first, splitGroups.second, groups);
}
serializer.vector(snapshots);
m_static.serializeOp(serializer);
@@ -366,6 +358,7 @@ namespace Opm
pack_unpack_map<int, VFPProdTable, Serializer>(serializer);
pack_unpack_map<int, VFPInjTable, Serializer>(serializer);
pack_unpack_map<std::string, Group, Serializer>(serializer);
}
template <typename T, class Serializer>
@@ -495,7 +488,6 @@ namespace Opm
ScheduleDeck m_sched_deck;
TimeMap m_timeMap;
WellMap wells_static;
GroupMap groups;
DynamicState<std::shared_ptr<UDQConfig>> udq_config;
DynamicState<std::shared_ptr<GuideRateConfig>> guide_rate_config;
DynamicState<std::shared_ptr<GasLiftOpt>> m_glo;
@@ -527,7 +519,6 @@ namespace Opm
void updateGuideRateModel(const GuideRateModel& new_model, std::size_t report_step);
GTNode groupTree(const std::string& root_node, std::size_t report_step, std::size_t level, const std::optional<std::string>& parent_name) const;
void updateGroup(std::shared_ptr<Group> group, std::size_t reportStep);
bool checkGroups(const ParseContext& parseContext, ErrorGuard& errors);
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);
@@ -540,7 +531,6 @@ namespace Opm
void addACTIONX(const Action::ActionX& action);
void addGroupToGroup( const std::string& parent_group, const std::string& child_group, std::size_t timeStep);
void addGroup(const std::string& groupName , std::size_t timeStep);
void addGroup(const Group& group, std::size_t timeStep);
void addWell(const std::string& wellName, const DeckRecord& record, std::size_t timeStep, Connection::Order connection_order);
void checkIfAllConnectionsIsShut(std::size_t currentStep);
void updateUDQ(const DeckKeyword& keyword, std::size_t current_step);

View File

@@ -31,6 +31,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/NameOrder.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WListManager.hpp>
@@ -43,6 +44,18 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
namespace {
[[maybe_unused]] std::string as_string(int value) {
return std::to_string(value);
}
[[maybe_unused]] std::string as_string(const std::string& value) {
return value;
}
}
namespace Opm {
/*
@@ -143,6 +156,12 @@ namespace Opm {
}
bool has(const K& key) const {
auto ptr = this->get_ptr(key);
return (ptr != nullptr);
}
void update(T object) {
auto key = object.name();
this->m_data[key] = std::make_shared<T>( std::move(object) );
@@ -153,13 +172,18 @@ namespace Opm {
if (other_ptr)
this->m_data[key] = other.get_ptr(key);
else
throw std::logic_error(std::string{"Tried to update member: "} + std::to_string(key) + std::string{"with uninitialized object"});
throw std::logic_error(std::string{"Tried to update member: "} + as_string(key) + std::string{"with uninitialized object"});
}
const T& operator()(const K& key) const {
return this->get(key);
}
const T& get(const K& key) const {
return *this->m_data.at(key);
}
std::vector<std::reference_wrapper<const T>> operator()() const {
std::vector<std::reference_wrapper<const T>> as_vector;
for (const auto& [_, elm_ptr] : this->m_data) {
@@ -185,6 +209,12 @@ namespace Opm {
return true;
}
std::size_t size() const {
return this->m_data.size();
}
static map_member<K,T> serializeObject() {
map_member<K,T> map_object;
T value_object = T::serializeObject();
@@ -294,12 +324,19 @@ namespace Opm {
map_member<K,T>& get_map() {
if constexpr ( std::is_same_v<T, VFPProdTable> )
return this->vfpprod;
if constexpr ( std::is_same_v<T, VFPInjTable> )
else if constexpr ( std::is_same_v<T, VFPInjTable> )
return this->vfpinj;
else if constexpr ( std::is_same_v<T, Group> )
return this->groups;
else
static_assert(always_false2<K,T>::value, "Template type <K,T> not supported in get_map()");
}
map_member<int, VFPProdTable> vfpprod;
map_member<int, VFPInjTable> vfpinj;
map_member<std::string, Group> groups;
template<class Serializer>
void serializeOp(Serializer& serializer) {

View File

@@ -85,6 +85,11 @@ namespace {
return sch.hasWell( wellName );
}
const Group& get_group(const ScheduleState& st, const std::string& group_name) {
return st.groups.get(group_name);
}
const RestartConfig& restart(const Schedule& sch) {
return sch.restart();
}
@@ -104,7 +109,8 @@ void python::common::export_Schedule(py::module& module) {
py::class_<ScheduleState>(module, "ScheduleState")
.def_property_readonly("nupcol", py::overload_cast<>(&ScheduleState::nupcol, py::const_));
.def_property_readonly("nupcol", py::overload_cast<>(&ScheduleState::nupcol, py::const_))
.def("group", &get_group, ref_internal);
py::class_< Schedule >( module, "Schedule")
@@ -122,8 +128,7 @@ void python::common::export_Schedule(py::module& module) {
.def( "get_wells", &Schedule::getWells)
.def("well_names", py::overload_cast<const std::string&>(&Schedule::wellNames, py::const_))
.def( "get_well", &get_well)
.def( "__contains__", &has_well )
.def( "group", &Schedule::getGroup, ref_internal);
.def( "__contains__", &has_well );
py::class_< RestartConfig >( module, "RestartConfig")
.def( "getKeyword", &RestartConfig::getKeyword )

View File

@@ -43,7 +43,7 @@ class TestSchedule(unittest.TestCase):
def testGroups(self):
G1 = self.sch.group( 'G1', 0 )
G1 = self.sch[0].group( 'G1')
self.assertTrue(G1.name == 'G1')
self.assertTrue(G1.num_wells == 2)
@@ -54,8 +54,8 @@ class TestSchedule(unittest.TestCase):
self.assertTrue(self.sch.get_well('INJ', 0).isinjector())
self.assertTrue(self.sch.get_well('PROD', 0).isproducer())
with self.assertRaises(ValueError):
self.sch.group('foo', 0)
with self.assertRaises(Exception):
self.sch[0].group('foo')
def test_open_shut(self):
deck = Parser().parse(test_path('spe3/SPE3CASE1.DATA'))

View File

@@ -86,7 +86,7 @@ namespace {
int numGroupsInField(const Opm::Schedule& sched,
const std::size_t lookup_step)
{
const auto ngmax = sched.numGroups(lookup_step);
const auto ngmax = sched[lookup_step].groups.size();
if (ngmax < 1) {
throw std::invalid_argument {

View File

@@ -1806,7 +1806,7 @@ inline std::vector<Opm::Well> find_wells( const Opm::Schedule& schedule,
case Opm::EclIO::SummaryNode::Category::Group: {
const auto& name = node.wgname;
if( !schedule.hasGroup( name ) ) return {};
if( !schedule[sim_step].groups.has( name ) ) return {};
return schedule.getChildWells2( name, sim_step);
}

View File

@@ -98,7 +98,7 @@ namespace {
const Opm::ParseContext& ctxt,
Opm::ErrorGuard& guard)
{
const auto nGroups = sched.numGroups();
const auto nGroups = sched.back().groups.size();
// Note: "1 +" to account for FIELD group being in 'sched.numGroups()'
// but excluded from WELLDIMS(3).

View File

@@ -311,7 +311,7 @@ namespace {
for (const auto& group_name : group_names) {
const bool availableForGroupControl = is_free && (group_name != "FIELD");
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, current_step));
auto new_group = this->snapshots.back().groups.get(group_name);
Group::GroupInjectionProperties injection;
injection.phase = phase;
injection.cmode = controlMode;
@@ -340,8 +340,8 @@ namespace {
if (record.getItem("VOIDAGE_GROUP").hasValue(0))
injection.voidage_group = record.getItem("VOIDAGE_GROUP").getTrimmedString(0);
if (group_ptr->updateInjection(injection)) {
this->updateGroup(std::move(group_ptr), current_step);
if (new_group.updateInjection(injection)) {
this->snapshots.back().groups.update( std::move(new_group));
this->snapshots.back().events().addEvent( ScheduleEvents::GROUP_INJECTION_UPDATE );
this->snapshots.back().wellgroup_events().addEvent( group_name, ScheduleEvents::GROUP_INJECTION_UPDATE);
}
@@ -416,7 +416,7 @@ namespace {
}
{
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, current_step));
auto new_group = this->snapshots.back().groups.get(group_name);
Group::GroupProductionProperties production(this->m_static.m_unit_system, group_name);
production.gconprod_cmode = controlMode;
production.active_cmode = controlMode;
@@ -454,12 +454,12 @@ namespace {
if (!apply_default_resv_target)
production.production_controls += static_cast<int>(Group::ProductionCMode::RESV);
if (group_ptr->updateProduction(production)) {
if (new_group.updateProduction(production)) {
auto new_config = std::make_shared<GuideRateConfig>( this->guideRateConfig(current_step) );
new_config->update_group(*group_ptr);
new_config->update_group(new_group);
this->guide_rate_config.update( current_step, std::move(new_config) );
this->updateGroup(std::move(group_ptr), current_step);
this->snapshots.back().groups.update( std::move(new_group));
this->snapshots.back().events().addEvent(ScheduleEvents::GROUP_PRODUCTION_UPDATE);
this->snapshots.back().wellgroup_events().addEvent( group_name, ScheduleEvents::GROUP_PRODUCTION_UPDATE);
@@ -484,12 +484,11 @@ namespace {
new_gconsale.add(groupName, sales_target, max_rate, min_rate, procedure, udqconfig, this->m_static.m_unit_system);
auto group_ptr = std::make_shared<Group>(this->getGroup(groupName, handlerContext.currentStep));
auto new_group = this->snapshots.back().groups.get( groupName );
Group::GroupInjectionProperties injection;
injection.phase = Phase::GAS;
if (group_ptr->updateInjection(injection)) {
this->updateGroup(std::move(group_ptr), handlerContext.currentStep);
}
if (new_group.updateInjection(injection))
this->snapshots.back().groups.update(new_group);
}
this->snapshots.back().gconsale.update( std::move(new_gconsale) );
}
@@ -524,11 +523,11 @@ namespace {
const auto gefac = record.getItem("EFFICIENCY_FACTOR").get<double>(0);
for (const auto& group_name : group_names) {
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, handlerContext.currentStep));
if (group_ptr->update_gefac(gefac, transfer)) {
auto new_group = this->snapshots.back().groups.get(group_name);
if (new_group.update_gefac(gefac, transfer)) {
this->snapshots.back().wellgroup_events().addEvent( group_name, ScheduleEvents::WELLGROUP_EFFICIENCY_UPDATE);
this->snapshots.back().events().addEvent( ScheduleEvents::WELLGROUP_EFFICIENCY_UPDATE );
this->updateGroup(std::move(group_ptr), handlerContext.currentStep);
this->snapshots.back().groups.update(std::move(new_group));
}
}
}
@@ -579,14 +578,14 @@ namespace {
const auto& target_string = record.getItem<ParserKeywords::GPMAINT::FLOW_TARGET>().get<std::string>(0);
for (const auto& group_name : group_names) {
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, handlerContext.currentStep));
auto new_group = this->snapshots.back().groups.get(group_name);
if (target_string == "NONE") {
group_ptr->set_gpmaint();
new_group.set_gpmaint();
} else {
GPMaint gpmaint(record);
group_ptr->set_gpmaint(std::move(gpmaint));
new_group.set_gpmaint(std::move(gpmaint));
}
this->updateGroup(std::move(group_ptr), handlerContext.currentStep);
this->snapshots.back().groups.update( std::move(new_group) );
}
}
}
@@ -595,14 +594,14 @@ namespace {
for (const auto& record : handlerContext.keyword) {
const auto& groupName = record.getItem("NAME").getTrimmedString(0);
if (!hasGroup(groupName))
if (!this->snapshots.back().groups.has(groupName))
addGroup(groupName , handlerContext.currentStep);
int table = record.getItem("VFP_TABLE").get< int >(0);
auto group_ptr = std::make_shared<Group>( this->getGroup(groupName, handlerContext.currentStep) );
if (group_ptr->updateNetVFPTable(table))
this->updateGroup(std::move(group_ptr), handlerContext.currentStep);
auto new_group = this->snapshots.back().groups.get( groupName );
if (new_group.updateNetVFPTable(table))
this->snapshots.back().groups.update( std::move(new_group) );
}
}
@@ -611,10 +610,10 @@ namespace {
const std::string& childName = trim_wgname(handlerContext.keyword, record.getItem("CHILD_GROUP").get<std::string>(0), parseContext, errors);
const std::string& parentName = trim_wgname(handlerContext.keyword, record.getItem("PARENT_GROUP").get<std::string>(0), parseContext, errors);
if (!hasGroup(childName))
if (!this->snapshots.back().groups.has(childName))
addGroup(childName, handlerContext.currentStep);
if (!hasGroup(parentName))
if (!this->snapshots.back().groups.has(parentName))
addGroup(parentName, handlerContext.currentStep);
this->addGroupToGroup(parentName, childName, handlerContext.currentStep);
@@ -712,7 +711,7 @@ namespace {
target_group = target_item.get<std::string>(0);
if (target_group != name) {
if (this->hasGroup(name, handlerContext.currentStep)) {
if (this->snapshots.back().groups.has(name)) {
const auto& group = this->getGroup(name, handlerContext.currentStep);
if (group.numWells() > 0)
throw std::invalid_argument("A manifold group must respond to its own target");
@@ -741,7 +740,6 @@ namespace {
}
void Schedule::handleRPTSCHED(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
printf("snapshost.size(): %ld \n", this->snapshots.size());
this->snapshots.back().rpt_config.update( RPTConfig(handlerContext.keyword ));
}
@@ -1202,7 +1200,7 @@ namespace {
OpmLog::warning(msg);
}
if (!hasGroup(groupName))
if (!this->snapshots.back().groups.has(groupName))
addGroup(groupName, handlerContext.currentStep);
if (!hasWell(wellName)) {

View File

@@ -19,7 +19,6 @@
#include <algorithm>
#include <ctime>
#include <fnmatch.h>
#include <functional>
#include <iostream>
#include <optional>
@@ -30,6 +29,7 @@
#include <vector>
#include <fmt/format.h>
#include <fnmatch.h>
#include <opm/common/OpmLog/LogUtil.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
@@ -249,7 +249,6 @@ namespace {
result.m_static = ScheduleStatic::serializeObject();
result.m_timeMap = TimeMap::serializeObject();
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.udq_config = {{std::make_shared<UDQConfig>(UDQConfig::serializeObject())}, 1};
result.m_glo = {{std::make_shared<GasLiftOpt>(GasLiftOpt::serializeObject())}, 1};
result.guide_rate_config = {{std::make_shared<GuideRateConfig>(GuideRateConfig::serializeObject())}, 1};
@@ -907,44 +906,33 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
}
std::vector< const Group* > Schedule::getChildGroups2(const std::string& group_name, std::size_t timeStep) const {
if (!hasGroup(group_name))
throw std::invalid_argument("No such group: '" + group_name + "'");
const auto& sched_state = this->snapshots[timeStep];
const auto& group = sched_state.groups.get(group_name);
std::vector<const Group*> child_groups;
const auto& dynamic_state = this->groups.at(group_name);
auto& group_ptr = dynamic_state.get(timeStep);
if (group_ptr) {
for (const auto& child_name : group_ptr->groups())
child_groups.push_back( std::addressof(this->getGroup(child_name, timeStep)));
}
for (const auto& child_name : group.groups())
child_groups.push_back( std::addressof(this->getGroup(child_name, timeStep)));
return child_groups;
}
std::vector< Well > Schedule::getChildWells2(const std::string& group_name, std::size_t timeStep) const {
if (!hasGroup(group_name))
throw std::invalid_argument("No such group: '" + group_name + "'");
const auto& sched_state = this->snapshots[timeStep];
const auto& group = sched_state.groups.get(group_name);
const auto& dynamic_state = this->groups.at(group_name);
const auto& group_ptr = dynamic_state.get(timeStep);
if (group_ptr) {
std::vector<Well> wells;
std::vector<Well> wells;
if (group_ptr->groups().size()) {
for (const auto& child_name : group_ptr->groups()) {
const auto& child_wells = getChildWells2(child_name, timeStep);
wells.insert(wells.end(), child_wells.begin(), child_wells.end());
}
} else {
for (const auto& well_name : group_ptr->wells()) {
wells.push_back( this->getWell(well_name, timeStep));
}
if (group.groups().size()) {
for (const auto& child_name : group.groups()) {
const auto& child_wells = this->getChildWells2(child_name, timeStep);
wells.insert(wells.end(), child_wells.begin(), child_wells.end());
}
return wells;
} else {
return {};
for (const auto& well_name : group.wells()) {
wells.push_back( this->getWell(well_name, timeStep));
}
}
return wells;
}
/*
@@ -1012,20 +1000,7 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
}
const Group& Schedule::getGroup(const std::string& groupName, std::size_t timeStep) const {
if (this->groups.count(groupName) == 0)
throw std::invalid_argument("No such group: '" + groupName + "'");
const auto& dynamic_state = this->groups.at(groupName);
auto& group_ptr = dynamic_state.get(timeStep);
if (!group_ptr)
throw std::invalid_argument("Group: " + groupName + " not yet defined at step: " + std::to_string(timeStep));
return *group_ptr;
}
void Schedule::updateGroup(std::shared_ptr<Group> group, std::size_t reportStep) {
auto& dynamic_state = this->groups.at(group->name());
dynamic_state.update(reportStep, std::move(group));
return this->snapshots[timeStep].groups.get(groupName);
}
@@ -1136,75 +1111,42 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
}
void Schedule::addGroup(const Group& group, std::size_t timeStep) {
this->groups.insert( std::make_pair( group.name(), DynamicState<std::shared_ptr<Group>>(this->m_timeMap, nullptr)));
auto group_ptr = std::make_shared<Group>(group);
auto& dynamic_state = this->groups.at(group.name());
dynamic_state.update(timeStep, group_ptr);
void Schedule::addGroup(const std::string& groupName, std::size_t timeStep) {
auto udq_undefined = this->getUDQConfig(timeStep).params().undefinedValue();
auto& sched_state = this->snapshots.back();
auto insert_index = sched_state.groups.size();
sched_state.groups.update( Group{ groupName, insert_index, udq_undefined, this->m_static.m_unit_system} );
sched_state.events().addEvent( ScheduleEvents::NEW_GROUP );
sched_state.wellgroup_events().addGroup(group.name());
sched_state.wellgroup_events().addGroup(groupName);
{
auto go = sched_state.group_order.get();
go.add( group.name() );
go.add( groupName );
sched_state.group_order.update( std::move(go) );
}
// All newly created groups are attached to the field group,
// can then be relocated with the GRUPTREE keyword.
if (group.name() != "FIELD")
this->addGroupToGroup("FIELD", group_ptr->name(), timeStep);
if (groupName != "FIELD")
this->addGroupToGroup("FIELD", groupName, timeStep);
}
void Schedule::addGroup(const std::string& groupName, std::size_t timeStep) {
const std::size_t insert_index = this->groups.size();
auto udq_undefined = this->getUDQConfig(timeStep).params().undefinedValue();
auto group = Group{ groupName, insert_index, udq_undefined, this->m_static.m_unit_system };
this->addGroup(group, timeStep);
}
std::size_t Schedule::numGroups() const {
return groups.size();
}
std::size_t Schedule::numGroups(std::size_t timeStep) const {
const auto group_names = this->groupNames(timeStep);
return group_names.size();
}
bool Schedule::hasGroup(const std::string& groupName) const {
return groups.count(groupName) > 0;
}
bool Schedule::hasGroup(const std::string& groupName, std::size_t timeStep) const {
if (timeStep >= this->size())
return false;
auto grpMap = this->groups.find(groupName);
return (grpMap != this->groups.end())
&& grpMap->second.at(timeStep);
}
void Schedule::addGroupToGroup( const std::string& parent_name, const std::string& child_name, std::size_t timeStep) {
// Add to new parent
auto& dynamic_state = this->groups.at(parent_name);
auto parent_ptr = std::make_shared<Group>( *dynamic_state[timeStep] );
if (parent_ptr->addGroup(child_name))
this->updateGroup(std::move(parent_ptr), timeStep);
auto parent_group = this->snapshots.back().groups.get(parent_name);
if (parent_group.addGroup(child_name))
this->snapshots.back().groups.update( std::move(parent_group) );
// Check and update backreference in child
const auto& child_group = this->getGroup(child_name, timeStep);
if (child_group.parent() != parent_name) {
auto old_parent = std::make_shared<Group>( this->getGroup(child_group.parent(), timeStep) );
old_parent->delGroup(child_group.name());
this->updateGroup(std::move(old_parent), timeStep);
auto old_parent = this->snapshots.back().groups.get(child_group.parent());
old_parent.delGroup(child_group.name());
this->snapshots.back().groups.update( std::move(old_parent) );
auto new_child_group = std::make_shared<Group>( child_group );
new_child_group->updateParent(parent_name);
this->updateGroup(std::move(new_child_group), timeStep);
auto new_child_group = Group{ child_group };
new_child_group.updateParent(parent_name);
this->snapshots.back().groups.update( std::move(new_child_group) );
}
}
@@ -1218,15 +1160,15 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
this->snapshots.back().wellgroup_events().addEvent( well_ptr->name(), ScheduleEvents::WELL_WELSPECS_UPDATE );
// Remove well child reference from previous group
auto group = std::make_shared<Group>(this->getGroup(old_gname, timeStep));
group->delWell(well_name);
this->updateGroup(std::move(group), timeStep);
auto group = this->snapshots.back().groups.get( old_gname );
group.delWell(well_name);
this->snapshots.back().groups.update( std::move(group) );
}
// Add well child reference to new group
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, timeStep));
group_ptr->addWell(well_name);
this->updateGroup(group_ptr, timeStep);
auto group = this->snapshots.back().groups.get( group_name );
group.addWell(well_name);
this->snapshots.back().groups.update( std::move(group) );
this->snapshots.back().events().addEvent( ScheduleEvents::GROUP_CHANGE );
}
@@ -1435,7 +1377,6 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
return this->m_timeMap == data.m_timeMap &&
this->m_static == data.m_static &&
compareMap(this->wells_static, data.wells_static) &&
compareMap(this->groups, data.groups) &&
compareDynState(this->m_glo, data.m_glo) &&
compareDynState(this->udq_config, data.udq_config) &&
compareDynState(this->guide_rate_config, data.guide_rate_config) &&
@@ -1477,9 +1418,8 @@ namespace {
const auto report_step = rst_state.header.report_step - 1;
double udq_undefined = 0;
for (const auto& rst_group : rst_state.groups) {
auto group = Group{ rst_group, this->groups.size(), udq_undefined, this->m_static.m_unit_system };
this->addGroup(group, report_step);
this->addGroup(rst_group.name, report_step);
const auto& group = this->snapshots.back().groups.get( rst_group.name );
if (group.isProductionGroup()) {
// Was originally at report_step + 1
this->snapshots.back().events().addEvent(ScheduleEvents::GROUP_PRODUCTION_UPDATE );

View File

@@ -30,7 +30,6 @@ namespace Opm {
namespace {
/*
This is to ensure that only time_points which can be represented with
std::time_t are used. The reason for clamping to std::time_t resolution is
@@ -154,16 +153,20 @@ bool ScheduleState::operator==(const ScheduleState& other) const {
this->wlist_manager.get() == other.wlist_manager.get() &&
this->rpt_config.get() == other.rpt_config.get() &&
this->udq_active.get() == other.udq_active.get() &&
this->groups == other.groups &&
this->vfpprod == other.vfpprod &&
this->vfpinj == other.vfpinj;
}
ScheduleState ScheduleState::serializeObject() {
auto t1 = std::chrono::system_clock::now();
auto t2 = t1 + std::chrono::hours(48);
ScheduleState ts(t1, t2);
ts.vfpprod = map_member<int, VFPProdTable>::serializeObject();
ts.vfpinj = map_member<int, VFPInjTable>::serializeObject();
ts.groups = map_member<std::string, Group>::serializeObject();
ts.m_events = Events::serializeObject();
ts.update_nupcol(77);
ts.update_oilvap( Opm::OilVaporizationProperties::serializeObject() );
@@ -181,6 +184,7 @@ ScheduleState ScheduleState::serializeObject() {
ts.network.update( Network::ExtNetwork::serializeObject() );
ts.well_order.update( NameOrder::serializeObject() );
ts.group_order.update( GroupOrder::serializeObject() );
return ts;
}

View File

@@ -631,7 +631,7 @@ inline void keywordG( SummaryConfig::keyword_list& list,
const auto& item = keyword.getDataRecord().getDataItem();
for( const std::string& group : item.getData< std::string >() ) {
if( schedule.hasGroup( group ) )
if( schedule.back().groups.has( group ) )
list.push_back( param.namedEntity(group) );
else
handleMissingGroup( parseContext, errors, keyword.location(), group );

View File

@@ -226,6 +226,10 @@ DATES -- 3
20 JUN 2007 /
/
GRUPTREE
'G3' 'G2' /
/
GCONSALE
'G1' 12345 12345 12345 WELL /
/
@@ -435,6 +439,31 @@ BOOST_AUTO_TEST_CASE(SerializeVFP) {
BOOST_CHECK( vfpinj2 == sched0[5].vfpinj);
}
BOOST_AUTO_TEST_CASE(SerializeGROUPS) {
auto sched = make_schedule(GCONSALE_deck);
auto sched0 = make_schedule(deck0);
auto groups1 = sched[0].groups;
auto groups2 = sched[3].groups;
{
std::vector<Opm::Group> value_list;
std::vector<std::size_t> index_list;
sched.pack_map<std::string, Opm::Group>( value_list, index_list );
BOOST_CHECK_EQUAL( value_list.size(), 5 );
sched0.unpack_map<std::string, Opm::Group>( value_list, index_list );
}
BOOST_CHECK( groups1 == sched0[0].groups);
BOOST_CHECK( groups1 == sched0[1].groups);
BOOST_CHECK( groups1 == sched0[2].groups);
BOOST_CHECK( groups2 == sched0[3].groups);
BOOST_CHECK( groups2 == sched0[4].groups);
BOOST_CHECK( groups2 == sched0[5].groups);
}

View File

@@ -440,7 +440,7 @@ static bool has_well( const std::vector<Well>& wells, const std::string& well_na
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsOrderedGRUPTREE) {
const auto& schedule = make_schedule( createDeckWithWellsOrderedGRUPTREE() );
BOOST_CHECK_THROW( schedule.getChildWells2( "NO_SUCH_GROUP" , 1 ), std::invalid_argument);
BOOST_CHECK_THROW( schedule.getChildWells2( "NO_SUCH_GROUP" , 0 ), std::exception);
{
auto field_wells = schedule.getChildWells2("FIELD" , 0);
BOOST_CHECK_EQUAL( field_wells.size() , 4U);
@@ -486,7 +486,7 @@ BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsOrderedGRUPTREE) {
BOOST_AUTO_TEST_CASE(GroupTree2TEST) {
const auto& schedule = make_schedule( createDeckWithWellsOrderedGRUPTREE() );
BOOST_CHECK_THROW( schedule.groupTree("NO_SUCH_GROUP", 0), std::invalid_argument);
BOOST_CHECK_THROW( schedule.groupTree("NO_SUCH_GROUP", 0), std::exception);
auto cg1 = schedule.getGroup("CG1", 0);
BOOST_CHECK( cg1.hasWell("DW_0"));
BOOST_CHECK( cg1.hasWell("CW_1"));
@@ -521,7 +521,7 @@ BOOST_AUTO_TEST_CASE(EmptyScheduleHasNoWells) {
const auto& schedule = make_schedule( createDeck() );
BOOST_CHECK_EQUAL( 0U , schedule.numWells() );
BOOST_CHECK_EQUAL( false , schedule.hasWell("WELL1") );
BOOST_CHECK_THROW( schedule.getWell("WELL2", 0) , std::invalid_argument );
BOOST_CHECK_THROW( schedule.getWell("WELL2", 0) , std::exception);
}
@@ -529,10 +529,10 @@ BOOST_AUTO_TEST_CASE(EmptyScheduleHasNoWells) {
BOOST_AUTO_TEST_CASE(EmptyScheduleHasFIELDGroup) {
const auto& schedule = make_schedule( createDeck() );
BOOST_CHECK_EQUAL( 1U , schedule.numGroups() );
BOOST_CHECK_EQUAL( true , schedule.hasGroup("FIELD") );
BOOST_CHECK_EQUAL( false , schedule.hasGroup("GROUP") );
BOOST_CHECK_THROW( schedule.getGroup("GROUP", 0) , std::invalid_argument );
BOOST_CHECK_EQUAL( 1U , schedule.back().groups.size() );
BOOST_CHECK_EQUAL( true , schedule.back().groups.has("FIELD") );
BOOST_CHECK_EQUAL( false , schedule.back().groups.has("GROUP") );
BOOST_CHECK_THROW( schedule[0].groups.get("GROUP") , std::exception);
}
BOOST_AUTO_TEST_CASE(HasGroup_At_Time) {
@@ -562,23 +562,17 @@ END
const auto sched = make_schedule(input);
BOOST_CHECK_MESSAGE(sched.hasGroup("P"), R"(Group "P" Must Exist)");
BOOST_CHECK_MESSAGE(sched.hasGroup("I"), R"(Group "I" Must Exist)");
BOOST_CHECK_MESSAGE(sched.back().groups.has("P"), R"(Group "P" Must Exist)");
BOOST_CHECK_MESSAGE(sched.back().groups.has("I"), R"(Group "I" Must Exist)");
BOOST_CHECK_MESSAGE( sched.hasGroup("P", 3), R"(Group "P" Must Exist at Report Step 3)");
BOOST_CHECK_MESSAGE(! sched.hasGroup("I", 3), R"(Group "I" Must NOT Exist at Report Step 3)");
BOOST_CHECK_MESSAGE( sched.hasGroup("I", 4), R"(Group "I" Must Exist at Report Step 4)");
BOOST_CHECK_MESSAGE( sched[3].groups.has("P"), R"(Group "P" Must Exist at Report Step 3)");
BOOST_CHECK_MESSAGE(! sched[3].groups.has("I"), R"(Group "I" Must NOT Exist at Report Step 3)");
BOOST_CHECK_MESSAGE( sched[4].groups.has("I"), R"(Group "I" Must Exist at Report Step 4)");
BOOST_CHECK_MESSAGE(sched.hasGroup("P", 6), R"(Group "P" Must Exist At Last Report Step)");
BOOST_CHECK_MESSAGE(sched.hasGroup("I", 6), R"(Group "I" Must Exist At Last Report Step)");
BOOST_CHECK_MESSAGE(sched[6].groups.has("P"), R"(Group "P" Must Exist At Last Report Step)");
BOOST_CHECK_MESSAGE(sched[6].groups.has("I"), R"(Group "I" Must Exist At Last Report Step)");
BOOST_CHECK_MESSAGE(! sched.hasGroup("P", 7), R"(Group "P" Must NOT Exist Immediately After Last Report Step)");
BOOST_CHECK_MESSAGE(! sched.hasGroup("I", 7), R"(Group "I" Must NOT Exist Immediately After Last Report Step)");
BOOST_CHECK_MESSAGE(! sched.hasGroup("P", 1729), R"(Group "P" Must NOT Exist Long After Last Report Step)");
BOOST_CHECK_MESSAGE(! sched.hasGroup("I", 1729), R"(Group "I" Must NOT Exist Long After Last Report Step)");
BOOST_CHECK_THROW(sched.getGroup("I", 3), std::invalid_argument);
BOOST_CHECK_THROW(sched[3].groups.get("I"), std::exception);
}
BOOST_AUTO_TEST_CASE(WellsIterator_Empty_EmptyVectorReturned) {

View File

@@ -338,13 +338,13 @@ BOOST_AUTO_TEST_CASE(GroupTreeTest_GRUPTREE_correct) {
auto python = std::make_shared<Python>();
Schedule schedule(deck, grid , fp, runspec, python);
BOOST_CHECK( schedule.hasGroup( "FIELD" ));
BOOST_CHECK( schedule.hasGroup( "PROD" ));
BOOST_CHECK( schedule.hasGroup( "INJE" ));
BOOST_CHECK( schedule.hasGroup( "MANI-PROD" ));
BOOST_CHECK( schedule.hasGroup( "MANI-INJ" ));
BOOST_CHECK( schedule.hasGroup( "DUMMY-PROD" ));
BOOST_CHECK( schedule.hasGroup( "DUMMY-INJ" ));
BOOST_CHECK( schedule.back().groups.has( "FIELD" ));
BOOST_CHECK( schedule.back().groups.has( "PROD" ));
BOOST_CHECK( schedule.back().groups.has( "INJE" ));
BOOST_CHECK( schedule.back().groups.has( "MANI-PROD" ));
BOOST_CHECK( schedule.back().groups.has( "MANI-INJ" ));
BOOST_CHECK( schedule.back().groups.has( "DUMMY-PROD" ));
BOOST_CHECK( schedule.back().groups.has( "DUMMY-INJ" ));
}
@@ -387,9 +387,9 @@ BOOST_AUTO_TEST_CASE( WellTestGroups ) {
Schedule sched(deck, grid , fp, runspec, python);
SummaryState st(std::chrono::system_clock::now());
BOOST_CHECK_EQUAL( 3U , sched.numGroups() );
BOOST_CHECK( sched.hasGroup( "INJ" ));
BOOST_CHECK( sched.hasGroup( "OP" ));
BOOST_CHECK_EQUAL( 3U , sched.back().groups.size() );
BOOST_CHECK( sched.back().groups.has( "INJ" ));
BOOST_CHECK( sched.back().groups.has( "OP" ));
{
auto& group = sched.getGroup("INJ", 3);