opm-simulators
ReservoirCouplingSlaveReportStep.hpp
1 /*
2  Copyright 2025 Equinor ASA
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_RESERVOIR_COUPLING_SLAVE_REPORT_STEP_HPP
21 #define OPM_RESERVOIR_COUPLING_SLAVE_REPORT_STEP_HPP
22 
23 #include <opm/simulators/flow/rescoup/ReservoirCoupling.hpp>
24 #include <opm/input/eclipse/EclipseState/Phase.hpp>
25 #include <opm/input/eclipse/Schedule/Group/Group.hpp>
26 
27 #include <map>
28 #include <string>
29 #include <utility>
30 
31 namespace Opm {
32 
33 // Avoid including the complete definition of ReservoirCouplingSlave here to avoid circular dependency.
34 template <class Scalar> class ReservoirCouplingSlave;
35 
54 template <class Scalar>
55 class ReservoirCouplingSlaveReportStep {
56 public:
57  using InjectionGroupTarget = ReservoirCoupling::InjectionGroupTarget<Scalar>;
58  using ProductionGroupConstraints = ReservoirCoupling::ProductionGroupConstraints<Scalar>;
59  using MasterGroupNodePressure = ReservoirCoupling::MasterGroupNodePressure<Scalar>;
60  using MessageTag = ReservoirCoupling::MessageTag;
61  using MasterProductionLimits = ReservoirCoupling::MasterProductionLimits<Scalar>;
62  using SlaveGroupInjectionData = ReservoirCoupling::SlaveGroupInjectionData<Scalar>;
63  using SlaveGroupProductionData = ReservoirCoupling::SlaveGroupProductionData<Scalar>;
64 
68  ReservoirCouplingSlave<Scalar> &slave
69  );
70 
73  const Parallel::Communication &comm() const { return this->slave_.getComm(); }
74 
77  MPI_Comm getSlaveMasterComm() const { return this->slave_.getMasterComm(); }
78 
83  bool hasMasterInjectionTarget(const std::string& gname, const Phase phase) const;
84 
88  bool hasMasterGroupNodePressure(const std::string& gname) const;
89 
93  bool hasMasterProductionLimits(const std::string& gname) const;
94 
98  bool hasMasterProductionTarget(const std::string& gname) const;
99 
105  bool isFirstSubstepOfSyncTimestep() const { return is_first_substep_of_sync_timestep_; }
106 
114  bool isLastSubstepOfSyncTimestep() const { return is_last_substep_of_sync_timestep_; }
115 
118  ReservoirCoupling::Logger& logger() const { return this->slave_.logger(); }
119 
124  Scalar masterGroupNodePressure(const std::string& gname) const;
125 
128  const std::map<std::string, Scalar>& masterGroupNodePressures() const
129  { return master_group_node_pressures_; }
130 
136  std::pair<Scalar, Group::InjectionCMode> masterInjectionTarget(
137  const std::string& gname, const Phase phase) const;
138 
143  const MasterProductionLimits& masterProductionLimits(const std::string& gname) const;
144 
149  std::pair<Scalar, Group::ProductionCMode> masterProductionTarget(const std::string& gname) const;
150 
155  void receiveMasterGroupNodePressuresFromMaster(std::size_t num_pressures);
156 
160  std::pair<std::size_t, bool> receiveNumMasterGroupNodePressuresFromMaster();
161 
169 
177  { return last_received_master_group_node_pressures_is_final_; }
178 
187  { return connected_to_master_coupled_network_; }
188 
191  std::pair<std::size_t, std::size_t> receiveNumGroupConstraintsFromMaster() const;
192 
195  void receiveInjectionGroupTargetsFromMaster(std::size_t num_targets);
196 
199  void receiveProductionGroupConstraintsFromMaster(std::size_t num_targets);
200 
211  void sendProductionDataToMaster(const std::vector<SlaveGroupProductionData> &production_data) const;
212 
223  void sendInjectionDataToMaster(const std::vector<SlaveGroupInjectionData> &injection_data) const;
224 
227  void setFirstSubstepOfSyncTimestep(bool value) { is_first_substep_of_sync_timestep_ = value; }
228 
232  void setLastSubstepOfSyncTimestep(bool value) { is_last_substep_of_sync_timestep_ = value; }
233 
240  void markSlaveGroupsInSchedule(Schedule& schedule, int report_step_idx);
241 
244  const std::string& slaveName() const { return this->slave_.getSlaveName(); }
245 
249  void setMasterGroupNodePressure(const std::string& gname, const Scalar pressure);
250 
257  const std::string& gname, const Phase phase, const Scalar target, const Group::InjectionCMode cmode);
258 
262  void setMasterProductionLimits(const std::string& gname, const MasterProductionLimits& limits);
263 
268  void setMasterProductionTarget(const std::string& gname, const Scalar target, const Group::ProductionCMode cmode);
269 
270 
271 private:
288  template <class DataType>
289  void sendDataToMaster_(
290  const std::vector<DataType>& data,
291  MessageTag tag,
292  const std::string& data_type_name
293  ) const;
294 
297  // Flag to track if this is the first substep within a "sync" timestep.
298  // Used to control reservoir coupling synchronization.
299  bool is_first_substep_of_sync_timestep_{true};
300  // Flag to track if this is the last substep within a "sync" timestep.
301  // Used to control reservoir coupling synchronization of summary data sent from
302  // the slave to the master process.
303  bool is_last_substep_of_sync_timestep_{false};
304 
305  // Master-imposed targets and corresponding control modes, received from the master
306  // process at the beginning of each sync timestep. Cleared and repopulated on every
307  // receive cycle. Used by GroupStateHelper to override slave group targets.
308  //
309  // Key: slave group name. Value: (target rate, production control mode).
310  std::map<std::string, std::pair<Scalar, Group::ProductionCMode>> master_production_targets_;
311  // Key: (injection phase, slave group name). Value: (target rate, injection control mode).
312  std::map<std::pair<Phase, std::string>, std::pair<Scalar, Group::InjectionCMode>> master_injection_targets_;
313  // Per-rate-type production limits from master hierarchy. Key: slave group name.
314  // A limit of -1 means no limit defined in the hierarchy for that rate type.
315  std::map<std::string, MasterProductionLimits> master_production_limits_;
316  // Master-computed network-leaf node pressures keyed by slave group name. Only
317  // populated for master groups that are leaf nodes in the master's extended
318  // network. Cleared and repopulated on every receive cycle.
319  std::map<std::string, Scalar> master_group_node_pressures_;
320  // Whether *this* slave is connected to the master's cross-rescoup network
321  // this sync step. Set once per sync step by
322  // receiveCoupledNetworkActiveStatusFromMaster() from the master's per-slave
323  // flag (BlackoilWellModelRescoup::masterNetworkHasMasterGroupLeavesForSlave_()).
324  // A slave that is not connected does not participate in the cross-rescoup
325  // exchange at all and balances only its own (local) network.
326  //
327  // This is deliberately separate from
328  // last_received_master_group_node_pressures_is_final_ below: connectivity is
329  // a per-sync-step property, whereas is_final is the per-iteration
330  // termination signal (only meaningful while connected).
331  bool connected_to_master_coupled_network_{false};
332  // The iteration-termination flag. Initialized for each sync step through:
333  // beginTimeStep() -> BlackoilWellModelRescoup::sendCoupledNetworkActiveStatus()
334  // to is_final = !connected (so an unconnected slave sees is_final = true and
335  // never enters the per-iteration receive). For a connected slave it then
336  // tracks the per-iteration is_final from the node-pressure header:
337  //
338  // In that case it is set to "true" in the course of the network iteration
339  // in BlackoilWellModel::assemble() -> BlackoilWellModel::updateWellControlsAndNetworkIteration()
340  // based on the "more_network_update" return value of BlackoilWellModelNetwork::update().
341  // If it returns "false" the flag is reset to "true" and stays true for the rest of the sync timestep.
342  //
343  // Connected slaves use this variable to determine when to exit the outer
344  // network loop such that the MPI master-slave communication protocol is kept in sync.
345  bool last_received_master_group_node_pressures_is_final_{true};
346 };
347 } // namespace Opm
348 #endif // OPM_RESERVOIR_COUPLING_SLAVE_REPORT_STEP_HPP
bool connectedToMasterCoupledNetwork() const
Whether this slave is connected to the master&#39;s cross-rescoup network this sync step (i...
Definition: ReservoirCouplingSlaveReportStep.hpp:186
void sendProductionDataToMaster(const std::vector< SlaveGroupProductionData > &production_data) const
Send production data to the master process.
Definition: ReservoirCouplingSlaveReportStep.cpp:363
void setMasterGroupNodePressure(const std::string &gname, const Scalar pressure)
Store a master-computed network-leaf node pressure for a master group.
Definition: ReservoirCouplingSlaveReportStep.cpp:373
void markSlaveGroupsInSchedule(Schedule &schedule, int report_step_idx)
Mark slave groups in the Schedule as production/injection groups.
Definition: ReservoirCouplingSlaveReportStep.cpp:407
void setFirstSubstepOfSyncTimestep(bool value)
Set whether this is the first substep within a "sync" timestep.
Definition: ReservoirCouplingSlaveReportStep.hpp:227
Definition: ReservoirCoupling.hpp:42
void setLastSubstepOfSyncTimestep(bool value)
Set whether this is the last substep within a "sync" timestep.
Definition: ReservoirCouplingSlaveReportStep.hpp:232
bool hasMasterInjectionTarget(const std::string &gname, const Phase phase) const
Check if a master-imposed injection target exists for a group and phase.
Definition: ReservoirCouplingSlaveReportStep.cpp:63
Scalar masterGroupNodePressure(const std::string &gname) const
Get the master-computed network-leaf node pressure for a master group.
Definition: ReservoirCouplingSlaveReportStep.cpp:87
bool lastReceivedMasterGroupNodePressuresIsFinal() const
Whether the most recent master-group-node-pressures receive carried the is_final flag.
Definition: ReservoirCouplingSlaveReportStep.hpp:176
const MasterProductionLimits & masterProductionLimits(const std::string &gname) const
Get the master-imposed per-rate-type production limits for a group.
Definition: ReservoirCouplingSlaveReportStep.cpp:103
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
bool hasMasterGroupNodePressure(const std::string &gname) const
Check if a master-computed network-leaf node pressure exists for a master group.
Definition: ReservoirCouplingSlaveReportStep.cpp:55
ReservoirCoupling::Logger & logger() const
Get the logger for reservoir coupling operations.
Definition: ReservoirCouplingSlaveReportStep.hpp:118
const Parallel::Communication & comm() const
Get the MPI communicator for intra-slave communication.
Definition: ReservoirCouplingSlaveReportStep.hpp:73
std::pair< std::size_t, bool > receiveNumMasterGroupNodePressuresFromMaster()
Receive the master-group-node-pressures header from master.
Definition: ReservoirCouplingSlaveReportStep.cpp:269
MPI_Comm getSlaveMasterComm() const
Get the MPI communicator for slave-master communication.
Definition: ReservoirCouplingSlaveReportStep.hpp:77
std::pair< std::size_t, std::size_t > receiveNumGroupConstraintsFromMaster() const
Receive the number of injection and production constraints from master.
Definition: ReservoirCouplingSlaveReportStep.cpp:241
std::pair< Scalar, Group::InjectionCMode > masterInjectionTarget(const std::string &gname, const Phase phase) const
Get the master-imposed injection target and control mode for a group and phase.
Definition: ReservoirCouplingSlaveReportStep.cpp:95
void receiveProductionGroupConstraintsFromMaster(std::size_t num_targets)
Receive production group constraints from master and store them locally.
Definition: ReservoirCouplingSlaveReportStep.cpp:306
bool isLastSubstepOfSyncTimestep() const
Check if this is the last substep within a "sync" timestep.
Definition: ReservoirCouplingSlaveReportStep.hpp:114
void setMasterInjectionTarget(const std::string &gname, const Phase phase, const Scalar target, const Group::InjectionCMode cmode)
Store a master-imposed injection target for a group and phase.
Definition: ReservoirCouplingSlaveReportStep.cpp:381
bool hasMasterProductionLimits(const std::string &gname) const
Check if master-imposed per-rate-type production limits exist for a group.
Definition: ReservoirCouplingSlaveReportStep.cpp:71
const std::string & slaveName() const
Get the name of this slave process.
Definition: ReservoirCouplingSlaveReportStep.hpp:244
void setMasterProductionLimits(const std::string &gname, const MasterProductionLimits &limits)
Store master-imposed per-rate-type production limits for a group.
Definition: ReservoirCouplingSlaveReportStep.cpp:391
bool hasMasterProductionTarget(const std::string &gname) const
Check if a master-imposed production target exists for a group.
Definition: ReservoirCouplingSlaveReportStep.cpp:79
void receiveInjectionGroupTargetsFromMaster(std::size_t num_targets)
Receive injection group targets from master and store them locally.
Definition: ReservoirCouplingSlaveReportStep.cpp:161
Definition: ReservoirCouplingSlave.hpp:40
void setMasterProductionTarget(const std::string &gname, const Scalar target, const Group::ProductionCMode cmode)
Store a master-imposed production target for a group.
Definition: ReservoirCouplingSlaveReportStep.cpp:399
void receiveMasterGroupNodePressuresFromMaster(std::size_t num_pressures)
Receive master-computed network-leaf node pressures from master and store them locally.
Definition: ReservoirCouplingSlaveReportStep.cpp:202
void receiveCoupledNetworkActiveStatusFromMaster()
Receive the master&#39;s single-bool flag for the current sync timestep and mirror it into last_received_...
Definition: ReservoirCouplingSlaveReportStep.cpp:125
void sendInjectionDataToMaster(const std::vector< SlaveGroupInjectionData > &injection_data) const
Send injection data to the master process.
Definition: ReservoirCouplingSlaveReportStep.cpp:353
std::pair< Scalar, Group::ProductionCMode > masterProductionTarget(const std::string &gname) const
Get the master-imposed production target and control mode for a group.
Definition: ReservoirCouplingSlaveReportStep.cpp:111
bool isFirstSubstepOfSyncTimestep() const
Check if this is the first substep within a "sync" timestep.
Definition: ReservoirCouplingSlaveReportStep.hpp:105
const std::map< std::string, Scalar > & masterGroupNodePressures() const
Get the full map of master-computed network-leaf node pressures.
Definition: ReservoirCouplingSlaveReportStep.hpp:128
ReservoirCouplingSlaveReportStep(ReservoirCouplingSlave< Scalar > &slave)
Construct a report step manager for the slave process.
Definition: ReservoirCouplingSlaveReportStep.cpp:41