From 5f8642cee8b19b5d5243fbf42547cda56d71e665 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 29 Jan 2025 09:12:01 +0100 Subject: [PATCH] WIP update group target reduction during local solve (only works in serial --- opm/simulators/wells/MultisegmentWell.hpp | 2 +- .../wells/MultisegmentWell_impl.hpp | 4 +- opm/simulators/wells/StandardWell.hpp | 2 +- opm/simulators/wells/StandardWell_impl.hpp | 4 +- opm/simulators/wells/WellInterface.hpp | 18 +++---- opm/simulators/wells/WellInterface_impl.hpp | 49 ++++++++++++++----- opm/simulators/wells/WellState.cpp | 14 ++++++ opm/simulators/wells/WellState.hpp | 1 + 8 files changed, 67 insertions(+), 27 deletions(-) diff --git a/opm/simulators/wells/MultisegmentWell.hpp b/opm/simulators/wells/MultisegmentWell.hpp index 3d861f11a6..8ef3d94c1a 100644 --- a/opm/simulators/wells/MultisegmentWell.hpp +++ b/opm/simulators/wells/MultisegmentWell.hpp @@ -268,7 +268,7 @@ namespace Opm { const Well::InjectionControls& inj_controls, const Well::ProductionControls& prod_controls, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger, const bool fixed_control = false, const bool fixed_status = false) override; diff --git a/opm/simulators/wells/MultisegmentWell_impl.hpp b/opm/simulators/wells/MultisegmentWell_impl.hpp index a6a3bbbdde..fd76517a7f 100644 --- a/opm/simulators/wells/MultisegmentWell_impl.hpp +++ b/opm/simulators/wells/MultisegmentWell_impl.hpp @@ -527,7 +527,7 @@ namespace Opm // store a copy of the well state, we don't want to update the real well state WellState well_state_copy = simulator.problem().wellModel().wellState(); - const auto& group_state = simulator.problem().wellModel().groupState(); + auto group_state = simulator.problem().wellModel().groupState(); auto& ws = well_state_copy.well(this->index_of_well_); // get current controls @@ -1622,7 +1622,7 @@ namespace Opm const Well::InjectionControls& inj_controls, const Well::ProductionControls& prod_controls, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger, const bool fixed_control /*false*/, const bool fixed_status /*false*/) diff --git a/opm/simulators/wells/StandardWell.hpp b/opm/simulators/wells/StandardWell.hpp index b6e2408b62..904ccb4b9f 100644 --- a/opm/simulators/wells/StandardWell.hpp +++ b/opm/simulators/wells/StandardWell.hpp @@ -207,7 +207,7 @@ namespace Opm const Well::InjectionControls& inj_controls, const Well::ProductionControls& prod_controls, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger, const bool fixed_control = false, const bool fixed_status = false) override; diff --git a/opm/simulators/wells/StandardWell_impl.hpp b/opm/simulators/wells/StandardWell_impl.hpp index 0d12926033..1d1f3d8a9b 100644 --- a/opm/simulators/wells/StandardWell_impl.hpp +++ b/opm/simulators/wells/StandardWell_impl.hpp @@ -1632,7 +1632,7 @@ namespace Opm // store a copy of the well state, we don't want to update the real well state WellState well_state_copy = simulator.problem().wellModel().wellState(); - const auto& group_state = simulator.problem().wellModel().groupState(); + auto group_state = simulator.problem().wellModel().groupState(); auto& ws = well_state_copy.well(this->index_of_well_); // get current controls @@ -2396,7 +2396,7 @@ namespace Opm const Well::InjectionControls& inj_controls, const Well::ProductionControls& prod_controls, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger, const bool fixed_control /*false*/, const bool fixed_status /*false*/) diff --git a/opm/simulators/wells/WellInterface.hpp b/opm/simulators/wells/WellInterface.hpp index d6df2b7a68..b5b13b2cd9 100644 --- a/opm/simulators/wells/WellInterface.hpp +++ b/opm/simulators/wells/WellInterface.hpp @@ -162,7 +162,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger); void assembleWellEqWithoutIteration(const Simulator& simulator, @@ -175,7 +175,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger); @@ -246,7 +246,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, const Well::InjectionControls& inj_controls, const Well::ProductionControls& prod_controls, const Scalar WQTotal, @@ -305,7 +305,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger); void gliftBeginTimeStepWellTestUpdateALQ(const Simulator& simulator, @@ -344,7 +344,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger); const std::vector& connectionRates() const @@ -368,7 +368,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger, const bool fixed_control = false, const bool fixed_status = false) = 0; @@ -432,7 +432,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger); bool solveWellWithTHPConstraint(const Simulator& simulator, @@ -440,7 +440,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger); std::optional @@ -463,7 +463,7 @@ class WellInterface : public WellInterfaceIndices& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger); diff --git a/opm/simulators/wells/WellInterface_impl.hpp b/opm/simulators/wells/WellInterface_impl.hpp index bf01c5abd3..bc5a9665d0 100644 --- a/opm/simulators/wells/WellInterface_impl.hpp +++ b/opm/simulators/wells/WellInterface_impl.hpp @@ -34,7 +34,7 @@ #include #include - +#include #include #include #include @@ -275,7 +275,7 @@ namespace Opm WellInterface:: updateWellControlAndStatusLocalIteration(const Simulator& simulator, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, const Well::InjectionControls& inj_controls, const Well::ProductionControls& prod_controls, const Scalar wqTotal, @@ -320,7 +320,7 @@ namespace Opm if (hasGroupControl && this->param_.check_group_constraints_inner_well_iterations_) { changed = changed || this->checkGroupConstraints(well_state, group_state, schedule, summary_state,deferred_logger); } - + if (changed) { const bool thp_controlled = this->isInjector() ? ws.injection_cmode == Well::InjectorCMode::THP : ws.production_cmode == Well::ProducerCMode::THP; @@ -332,6 +332,29 @@ namespace Opm } updatePrimaryVariables(simulator, well_state, deferred_logger); } + + bool isNowGroupControl = ws.production_cmode == Well::ProducerCMode::GRUP || ws.injection_cmode == Well::InjectorCMode::GRUP; + if (isGroupControl != isNowGroupControl) { + well_state.updateGlobalIsGrup(); + int reportStepIdx = simulator.episodeIndex(); + const Group& fieldGroup = schedule.getGroup("FIELD", reportStepIdx); + std::vector groupTargetReduction(well_state.numPhases(), 0.0); + WellGroupHelpers::updateGroupTargetReduction(fieldGroup, + schedule, + reportStepIdx, + this->isInjector(), + well_state.phaseUsage(), + *this->guideRate(), + well_state, + summary_state, + group_state, + groupTargetReduction); + + if (isNowGroupControl) { + updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger); + updatePrimaryVariables(simulator, well_state, deferred_logger); + } + } } return changed; } @@ -395,6 +418,8 @@ namespace Opm deferred_logger.info(" well " + this->name() + " is being tested"); WellState well_state_copy = well_state; + GroupState group_state_copy = group_state; + auto& ws = well_state_copy.well(this->indexOfWell()); updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger); @@ -424,7 +449,7 @@ namespace Opm // untill the number of closed completions do not increase anymore. while (testWell) { const std::size_t original_number_closed_completions = welltest_state_temp.num_closed_completions(); - bool converged = solveWellForTesting(simulator, well_state_copy, group_state, deferred_logger); + bool converged = solveWellForTesting(simulator, well_state_copy, group_state_copy, deferred_logger); if (!converged) { const auto msg = fmt::format("WTEST: Well {} is not solvable (physical)", this->name()); deferred_logger.debug(msg); @@ -499,7 +524,7 @@ namespace Opm iterateWellEquations(const Simulator& simulator, const double dt, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger) { OPM_TIMEFUNCTION(); @@ -535,7 +560,7 @@ namespace Opm const Well::InjectionControls& inj_controls, const Well::ProductionControls& prod_controls, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger) { OPM_TIMEFUNCTION(); @@ -712,7 +737,7 @@ namespace Opm WellInterface:: solveWellForTesting(const Simulator& simulator, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger) { OPM_TIMEFUNCTION(); @@ -746,7 +771,7 @@ namespace Opm WellInterface:: solveWellEquation(const Simulator& simulator, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger) { OPM_TIMEFUNCTION(); @@ -805,7 +830,7 @@ namespace Opm assembleWellEq(const Simulator& simulator, const double dt, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger) { OPM_TIMEFUNCTION(); @@ -841,7 +866,7 @@ namespace Opm prepareWellBeforeAssembling(const Simulator& simulator, const double dt, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger) { OPM_TIMEFUNCTION(); @@ -993,7 +1018,7 @@ namespace Opm gliftBeginTimeStepWellTestIterateWellEquations(const Simulator& simulator, const double dt, WellState& well_state, - const GroupState& group_state, + GroupState& group_state, DeferredLogger& deferred_logger) { OPM_TIMEFUNCTION(); @@ -1135,7 +1160,7 @@ namespace Opm assert(this->param_.local_well_solver_control_switching_); this->operability_status_.resetOperability(); WellState well_state_copy = well_state; - const auto& group_state = simulator.problem().wellModel().groupState(); + auto group_state = simulator.problem().wellModel().groupState(); const double dt = simulator.timeStepSize(); // equations should be converged at this stage, so only one it is needed bool converged = iterateWellEquations(simulator, dt, well_state_copy, group_state, deferred_logger); diff --git a/opm/simulators/wells/WellState.cpp b/opm/simulators/wells/WellState.cpp index 4f5a65de23..e5b154c911 100644 --- a/opm/simulators/wells/WellState.cpp +++ b/opm/simulators/wells/WellState.cpp @@ -974,6 +974,20 @@ void WellState::updateGlobalIsGrup(const Parallel::Communication& comm) this->global_well_info.value().communicate(comm); } +template +void WellState::updateGlobalIsGrup() +{ + this->global_well_info.value().clear(); + for (std::size_t well_index = 0; well_index < this->size(); well_index++) { + const auto& ws = this->well(well_index); + this->global_well_info.value().update_efficiency_scaling_factor(well_index, ws.efficiency_scaling_factor); + if (ws.producer) + this->global_well_info.value().update_producer(well_index, ws.status, ws.production_cmode); + else + this->global_well_info.value().update_injector(well_index, ws.status, ws.injection_cmode); + } +} + template void WellState:: updateEfficiencyScalingFactor(const std::string& wellName, diff --git a/opm/simulators/wells/WellState.hpp b/opm/simulators/wells/WellState.hpp index e2a8edf7ae..6d2ad5d1be 100644 --- a/opm/simulators/wells/WellState.hpp +++ b/opm/simulators/wells/WellState.hpp @@ -164,6 +164,7 @@ class WellState void communicateGroupRates(const Parallel::Communication& comm); void updateGlobalIsGrup(const Parallel::Communication& comm); + void updateGlobalIsGrup(); void updateEfficiencyScalingFactor(const std::string& wellName, const Scalar value);