From 095c0457bc4dc6399ddbc5924183deb43a1a54d9 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Thu, 5 Dec 2024 14:47:09 +0100 Subject: [PATCH] Code improvment for the group control switching Pass the controls as enums not strings Avoid pair as key in map --- .../wells/BlackoilWellModelConstraints.cpp | 87 ++++++++++--------- .../wells/BlackoilWellModelConstraints.hpp | 4 +- .../wells/BlackoilWellModelGeneric.cpp | 79 +++++++++-------- .../wells/BlackoilWellModelGeneric.hpp | 4 +- .../wells/BlackoilWellModel_impl.hpp | 41 ++++++--- tests/test_RestartSerialization.cpp | 5 +- 6 files changed, 119 insertions(+), 101 deletions(-) diff --git a/opm/simulators/wells/BlackoilWellModelConstraints.cpp b/opm/simulators/wells/BlackoilWellModelConstraints.cpp index 8205cce1c..471362f8d 100644 --- a/opm/simulators/wells/BlackoilWellModelConstraints.cpp +++ b/opm/simulators/wells/BlackoilWellModelConstraints.cpp @@ -562,8 +562,8 @@ bool BlackoilWellModelConstraints:: updateGroupIndividualControl(const Group& group, const int reportStepIdx, const int max_number_of_group_switch, - std::map,std::vector>& switched_inj, - std::map>& switched_prod, + std::map, 3>>& switched_inj, + std::map>& switched_prod, std::map>& closed_offending_wells, GroupState& group_state, WellState& well_state, @@ -577,31 +577,32 @@ updateGroupIndividualControl(const Group& group, if (!group.hasInjectionControl(phase)) { continue; } - bool group_is_oscillating = false; - if (switched_inj.count({group.name(), phase}) > 0) { - for (const auto& key : switched_inj[{group.name(), phase}]) { - if (std::count(switched_inj[{group.name(), phase}].begin(), switched_inj[{group.name(), phase}].end(), key) >= max_number_of_group_switch) { - const size_t sz = switched_inj[{group.name(), phase}].size(); - // only output if the two last keys are not the same. - if (key != switched_inj[{group.name(), phase}][sz-2]) { - if (wellModel_.comm().rank() == 0) { - std::ostringstream os; - os << phase; - const std::string msg = - fmt::format("Group control for {} injector group {} is oscillating. Group control kept at {}.", - std::move(os).str(), - group.name(), - key); - deferred_logger.info(msg); - } - switched_inj[{group.name(), phase}].push_back(key); - } - group_is_oscillating = true; - break; + if (auto groupPos = switched_inj.find(group.name()); groupPos != switched_inj.end()) { + auto& ctrls = groupPos->second[static_cast>(phase)]; + for (const auto& ctrl : ctrls) { + if (std::count(ctrls.begin(), ctrls.end(), ctrl) < max_number_of_group_switch) { + continue; } + + if (ctrls.back() != *(ctrls.end() - 2)) { + if (wellModel_.comm().rank() == 0 ) { + std::ostringstream os; + os << phase; + const std::string msg = + fmt::format("Group control for {} injector group {} is oscillating. Group control kept at {}.", + std::move(os).str(), + group.name(), + Group::InjectionCMode2String(ctrl)); + deferred_logger.info(msg); + } + ctrls.push_back(ctrl); + } + group_is_oscillating = true; + break; } } + if (group_is_oscillating) { continue; } @@ -611,8 +612,8 @@ updateGroupIndividualControl(const Group& group, phase); if (changed_this.first != Group::InjectionCMode::NONE) { - switched_inj[{group.name(), phase}].push_back( - Group::InjectionCMode2String(changed_this.first)); + switched_inj[group.name()][static_cast>(phase)].push_back( + changed_this.first); this->actionOnBrokenConstraints(group, changed_this.first, phase, group_state, deferred_logger); @@ -629,23 +630,24 @@ updateGroupIndividualControl(const Group& group, } if (group.isProductionGroup()) { - if (switched_prod.count(group.name()) > 0) { - for (const auto& key : switched_prod[group.name()]) { - if (std::count(switched_prod[group.name()].begin(), switched_prod[group.name()].end(), key) >= max_number_of_group_switch) { - const size_t sz = switched_prod[group.name()].size(); - // only output on rank 0 and if the two last keys are not the same. - if (key != switched_prod[group.name()][sz-2]) { - if (wellModel_.comm().rank() == 0) { - const std::string msg = - fmt::format("Group control for production group {} is oscillating. Group control kept at {}.", - group.name(), - key); - deferred_logger.info(msg); - } - switched_prod[group.name()].push_back(key); - } - return false; + if (auto groupPos = switched_prod.find(group.name()); groupPos != switched_prod.end()) { + auto& ctrls = groupPos->second; + for (const auto& ctrl : ctrls) { + if (std::count(ctrls.begin(), ctrls.end(), ctrl) < max_number_of_group_switch) { + continue; } + + if (ctrls.back() != *(ctrls.end() - 2)) { + if (wellModel_.comm().rank() == 0) { + const std::string msg = + fmt::format("Group control for production group {} is oscillating. Group control kept at {}.", + group.name(), + Group::ProductionCMode2String(ctrl)); + deferred_logger.info(msg); + } + ctrls.push_back(ctrl); + } + return false; } } @@ -664,8 +666,7 @@ updateGroupIndividualControl(const Group& group, group_state, deferred_logger); if(changed) { - switched_prod[group.name()].push_back( - Group::ProductionCMode2String(changed_this.first)); + switched_prod[group.name()].push_back(changed_this.first); WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed_this.second, group, wellModel_.schedule(), diff --git a/opm/simulators/wells/BlackoilWellModelConstraints.hpp b/opm/simulators/wells/BlackoilWellModelConstraints.hpp index 0fd7e22db..420e1fc97 100644 --- a/opm/simulators/wells/BlackoilWellModelConstraints.hpp +++ b/opm/simulators/wells/BlackoilWellModelConstraints.hpp @@ -74,8 +74,8 @@ public: bool updateGroupIndividualControl(const Group& group, const int reportStepIdx, const int max_number_of_group_switch, - std::map,std::vector>& switched_inj, - std::map>& switched_prod, + std::map, 3>>& switched_inj, + std::map>& switched_prod, std::map>& closed_offending_wells, GroupState& group_state, WellState& well_state, diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index 5012e331e..9df44e7a6 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -628,29 +628,31 @@ checkGroupHigherConstraints(const Group& group, const Phase all[] = { Phase::WATER, Phase::OIL, Phase::GAS }; for (Phase phase : all) { bool group_is_oscillating = false; - if (switched_inj_groups_.count({group.name(), phase}) > 0) { - for (const auto& key : switched_inj_groups_[{group.name(), phase}]) { - if (std::count(switched_inj_groups_[{group.name(), phase}].begin(), switched_inj_groups_[{group.name(), phase}].end(), key) >= max_number_of_group_switch) { - const size_t sz = switched_inj_groups_[{group.name(), phase}].size(); - // only output if the two last keys are not the same. - if (key != switched_inj_groups_[{group.name(), phase}][sz-2]) { - if (comm_.rank() == 0 ) { - std::ostringstream os; - os << phase; - const std::string msg = - fmt::format("Group control for {} injector group {} is oscillating. Group control kept at {}.", - std::move(os).str(), - group.name(), - key); - deferred_logger.info(msg); - } - switched_inj_groups_[{group.name(), phase}].push_back(key); - } - group_is_oscillating = true; - break; + if (auto groupPos = switched_inj_groups_.find(group.name()); groupPos != switched_inj_groups_.end()) { + auto& ctrls = groupPos->second[static_cast>(phase)]; + for (const auto& ctrl : ctrls) { + if (std::count(ctrls.begin(), ctrls.end(), ctrl) < max_number_of_group_switch) { + continue; } + + if (ctrls.back() != *(ctrls.end() - 2)) { + if (comm_.rank() == 0 ) { + std::ostringstream os; + os << phase; + const std::string msg = + fmt::format("Group control for {} injector group {} is oscillating. Group control kept at {}.", + std::move(os).str(), + group.name(), + Group::InjectionCMode2String(ctrl)); + deferred_logger.info(msg); + } + ctrls.push_back(ctrl); + } + group_is_oscillating = true; + break; } } + if (group_is_oscillating) { continue; } @@ -676,7 +678,7 @@ checkGroupHigherConstraints(const Group& group, resv_coeff_inj, deferred_logger); if (is_changed) { - switched_inj_groups_[{group.name(), phase}].push_back(Group::InjectionCMode2String(Group::InjectionCMode::FLD)); + switched_inj_groups_[group.name()][static_cast>(phase)].push_back(Group::InjectionCMode::FLD); BlackoilWellModelConstraints(*this). actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, this->groupState(), @@ -700,23 +702,24 @@ checkGroupHigherConstraints(const Group& group, // So when checking constraints, current groups rate must also be subtracted it's reduction rate const std::vector reduction_rates = this->groupState().production_reduction_rates(group.name()); - if (switched_prod_groups_.count(group.name()) > 0) { - for (const auto& key : switched_prod_groups_[group.name()]) { - if (std::count(switched_prod_groups_[group.name()].begin(), switched_prod_groups_[group.name()].end(), key) >= max_number_of_group_switch) { - const size_t sz = switched_prod_groups_[group.name()].size(); - // only output on rank 0 and if the two last keys are not the same. - if (key != switched_prod_groups_[group.name()][sz-2]) { - if (comm_.rank() == 0) { - const std::string msg = - fmt::format("Group control for production group {} is oscillating. Group control kept at {}.", - group.name(), - key); - deferred_logger.info(msg); - } - switched_prod_groups_[group.name()].push_back(key); - } - return false; + if (auto groupPos = switched_prod_groups_.find(group.name()); groupPos != switched_prod_groups_.end()) { + auto& ctrls = groupPos->second; + for (const auto& ctrl : ctrls) { + if (std::count(ctrls.begin(), ctrls.end(), ctrl) < max_number_of_group_switch) { + continue; } + + if (ctrls.back() != *(ctrls.end() - 2)) { + if (comm_.rank() == 0) { + const std::string msg = + fmt::format("Group control for production group {} is oscillating. Group control kept at {}.", + group.name(), + Group::ProductionCMode2String(ctrl)); + deferred_logger.info(msg); + } + ctrls.push_back(ctrl); + } + return false; } } for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) { @@ -762,7 +765,7 @@ checkGroupHigherConstraints(const Group& group, deferred_logger); if (changed) { - switched_prod_groups_[group.name()].push_back(Group::ProductionCMode2String(Group::ProductionCMode::FLD)); + switched_prod_groups_[group.name()].push_back(Group::ProductionCMode::FLD); WellGroupHelpers::updateWellRatesFromGroupTargetScale(scaling_factor, group, schedule(), diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index 8a2d19bac..10b66ab83 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -599,8 +599,8 @@ protected: bool wellStructureChangedDynamically_{false}; // Store maps of group name and new group controls for output - std::map> switched_prod_groups_; - std::map, std::vector> switched_inj_groups_; + std::map> switched_prod_groups_; + std::map, 3>> switched_inj_groups_; // Store map of group name and close offending well for output std::map> closed_offending_wells_; diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index 7f2d81ae1..9c0fce673 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -749,29 +749,42 @@ namespace Opm { // report group switching if (this->terminal_output_) { - for (const auto& [name, to] : this->switched_prod_groups_) { + for (const auto& [name, ctrls] : this->switched_prod_groups_) { const Group::ProductionCMode& oldControl = this->prevWGState().group_state.production_control(name); std::string from = Group::ProductionCMode2String(oldControl); - if (to.back() != from) { + std::string to = Group::ProductionCMode2String(ctrls.back()); + if (ctrls.back() != oldControl) { std::string msg = " Production Group " + name + " control mode changed from "; msg += from; - msg += " to " + to.back(); + msg += " to " + to; local_deferredLogger.info(msg); } } - for (const auto& [key, to] : this->switched_inj_groups_) { - const std::string& name = key.first; - const Opm::Phase& phase = key.second; - const Group::InjectionCMode& oldControl = this->prevWGState().group_state.injection_control(name, phase); - std::string from = Group::InjectionCMode2String(oldControl); - if (to.back() != from) { - std::string msg = " Injection Group " + name - + " control mode changed from "; - msg += from; - msg += " to " + to.back(); - local_deferredLogger.info(msg); + for (const auto& [grname, grdata] : this->switched_inj_groups_) { + //const std::string& name = key.first; + //const Opm::Phase& phase = key.second; + const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS}; + for (Phase phase : all) { + const auto& ctrls = grdata[static_cast>(phase)]; + + if (ctrls.empty()) { + continue; + } + if ( !this->prevWGState().group_state.has_injection_control(grname, phase)) + continue; + + const Group::InjectionCMode& oldControl = this->prevWGState().group_state.injection_control(grname, phase); + std::string from = Group::InjectionCMode2String(oldControl); + std::string to = Group::InjectionCMode2String(ctrls.back()); + if (ctrls.back() != oldControl) { + std::string msg = " Injection Group " + grname + + " control mode changed from "; + msg += from; + msg += " to " + to; + local_deferredLogger.info(msg); + } } } } diff --git a/tests/test_RestartSerialization.cpp b/tests/test_RestartSerialization.cpp index c62c09849..e2e25df3f 100644 --- a/tests/test_RestartSerialization.cpp +++ b/tests/test_RestartSerialization.cpp @@ -332,8 +332,9 @@ public: last_valid_wgstate_ = WGState::serializationTestObject(dummy); nupcol_wgstate_ = WGState::serializationTestObject(dummy); last_glift_opt_time_ = 5.0; - switched_prod_groups_ = {{"test4", {"test5", "test6"}}}; - switched_inj_groups_ = {{{"test4", Phase::SOLVENT}, {"test5", "test6"}}}; + switched_prod_groups_ = {{"test4", {Group::ProductionCMode::NONE, Group::ProductionCMode::ORAT}}}; + const auto controls = {Group::InjectionCMode::NONE, Group::InjectionCMode::RATE, Group::InjectionCMode::RATE }; + switched_inj_groups_ = {{"test4", {controls, {}, controls} }}; closed_offending_wells_ = {{"test4", {"test5", "test6"}}}; }