Use ScheduleState to manage groups
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user