opm-simulators
ReservoirCouplingSlave.hpp
1 /*
2  Copyright 2024 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_HPP
21 #define OPM_RESERVOIR_COUPLING_SLAVE_HPP
22 
23 #include <opm/simulators/flow/rescoup/ReservoirCoupling.hpp>
24 #include <opm/simulators/flow/rescoup/ReservoirCouplingSlaveReportStep.hpp>
25 #include <opm/input/eclipse/Schedule/Schedule.hpp>
26 #include <opm/simulators/utils/ParallelCommunication.hpp>
27 #include <opm/simulators/timestepping/SimulatorTimer.hpp>
28 #include <opm/common/OpmLog/OpmLog.hpp>
29 
30 #include <mpi.h>
31 
32 #include <vector>
33 
34 namespace Opm {
35 
36 template <class Scalar>
38 
39 template <class Scalar>
41 public:
42  using MessageTag = ReservoirCoupling::MessageTag;
48  using MasterProductionLimits = typename ReservoirCoupling::MasterProductionLimits<Scalar>;
50 
52  const Parallel::Communication &comm, const Schedule &schedule, const SimulatorTimer &timer
53  );
54  bool activated() const { return activated_; }
55  void clearDeferredLogger() { logger_.clearDeferredLogger(); }
56  const Parallel::Communication& getComm() const { return comm_; }
57  MPI_Comm getMasterComm() const { return slave_master_comm_; }
58  const std::string& getSlaveName() const { return slave_name_; }
59  const std::map<std::string, std::string>& getSlaveToMasterGroupNameMap() const {
60  return slave_to_master_group_map_; }
63  bool hasMasterGroupNodePressure(const std::string& gname) const;
64 
67  bool hasMasterInjectionTarget(const std::string& gname, const Phase phase) const;
68 
71  bool hasMasterProductionLimits(const std::string& gname) const;
72 
75  bool hasMasterProductionTarget(const std::string& gname) const;
76  void initTimeStepping();
77  bool isFirstSubstepOfSyncTimestep() const;
85  bool isLastSubstepOfSyncTimestep() const;
86  bool isSlaveGroup(const std::string& group_name) const;
87 
92 
97 
98  ReservoirCoupling::Logger& logger() { return this->logger_; }
99  ReservoirCoupling::Logger& logger() const { return this->logger_; }
102  Scalar masterGroupNodePressure(const std::string& gname) const;
103 
106  const std::map<std::string, Scalar>& masterGroupNodePressures() const;
107 
110  std::pair<Scalar, Group::InjectionCMode> masterInjectionTarget(
111  const std::string& gname, const Phase phase) const;
112 
115  const MasterProductionLimits& masterProductionLimits(const std::string& gname) const;
116 
119  std::pair<Scalar, Group::ProductionCMode> masterProductionTarget(const std::string& gname) const;
120  void maybeActivate(int report_step);
121  std::size_t numSlaveGroups() const { return this->slave_group_order_.size(); }
128  double receiveNextTimeStepFromMaster();
129  std::pair<std::size_t, std::size_t> receiveNumGroupConstraintsFromMaster() const;
132  void receiveInjectionGroupTargetsFromMaster(std::size_t num_targets);
133 
136  void receiveMasterGroupNodePressuresFromMaster(std::size_t num_pressures);
137 
141  std::pair<std::size_t, bool> receiveNumMasterGroupNodePressuresFromMaster();
142 
145  void receiveProductionGroupConstraintsFromMaster(std::size_t num_targets);
146 
147  void sendAndReceiveInitialData();
148  void sendInjectionDataToMaster(const std::vector<SlaveGroupInjectionData> &injection_data) const;
149  void sendNextReportDateToMasterProcess() const;
150  void sendProductionDataToMaster(const std::vector<SlaveGroupProductionData> &production_data) const;
151  void setDeferredLogger(DeferredLogger *deferred_logger) {
152  this->logger_.setDeferredLogger(deferred_logger);
153  }
154  void setFirstSubstepOfSyncTimestep(bool value);
158  void setLastSubstepOfSyncTimestep(bool value);
159 
162  void markSlaveGroupsInSchedule(Schedule& schedule, int report_step_idx);
163 
164  const std::string& slaveGroupIdxToGroupName(std::size_t group_idx) const {
165  return this->slave_group_order_.at(group_idx);
166  }
167  bool terminated() const { return this->terminated_; }
168 
178 
189 
190 private:
191  void checkGrupSlavGroupNames_();
192  std::pair<double, bool> getGrupSlavActivationDateAndCheckHistoryMatchingMode_() const;
193  bool historyMatchingMode_() const { return this->history_matching_mode_; }
194  std::size_t numMasterGroups_() const { return this->slave_to_master_group_map_.size(); }
201  void receiveInitStatusFromMasterProcess_();
202  void receiveMasterGroupNamesFromMasterProcess_();
203  void receiveSlaveNameFromMasterProcess_();
204  void saveMasterGroupNamesAsMapAndEstablishOrder_(const std::vector<char>& group_names);
205  void sendActivationDateToMasterProcess_();
206  void sendActivationHandshakeToMasterProcess_() const;
207  void sendSimulationStartDateToMasterProcess_() const;
208  void sendStatusToMasterProcess_(bool ok);
209 
210  const Parallel::Communication &comm_;
211  const Schedule& schedule_;
212  const SimulatorTimer &timer_;
213  // MPI parent communicator for a slave process
214  MPI_Comm slave_master_comm_{MPI_COMM_NULL};
215  std::map<std::string, std::string> slave_to_master_group_map_;
216  bool activated_{false};
217  // True if the slave was terminated by the master process
218  bool terminated_{false};
219  // True if no GRUPMAST keyword in the master schedule and no GRUPSLAV keyword in the slave schedule
220  bool history_matching_mode_{false};
221  std::string slave_name_; // This is the slave name as defined in the master process
222  mutable ReservoirCoupling::Logger logger_;
223  // Order of the slave groups. A mapping from slave group index to slave group name.
224  // The indices are determined by the order the master process sends us the group names, see
225  // receiveMasterGroupNamesFromMasterProcess_()
226  // Later, the master process will send us group name indices, and not the group names themselves,
227  // so we use this mapping to recover the slave group names from the indices.
228  std::map<std::size_t, std::string> slave_group_order_;
229  // Stores data that changes for a single report step or for timesteps within a report step.
230  std::unique_ptr<ReservoirCouplingSlaveReportStep<Scalar>> report_step_data_{nullptr};
231 };
232 
233 } // namespace Opm
234 
235 #endif // OPM_RESERVOIR_COUPLING_SLAVE_HPP
void receiveProductionGroupConstraintsFromMaster(std::size_t num_targets)
Receive production group constraints from master and store them locally.
Definition: ReservoirCouplingSlave.cpp:332
Master-computed network-leaf node pressure for a single master group.
Definition: ReservoirCoupling.hpp:287
void markSlaveGroupsInSchedule(Schedule &schedule, int report_step_idx)
Mark slave groups in the Schedule as production/injection groups.
Definition: ReservoirCouplingSlave.cpp:457
bool hasMasterProductionLimits(const std::string &gname) const
Check if master-imposed per-rate-type production limits exist for a group.
Definition: ReservoirCouplingSlave.cpp:87
const MasterProductionLimits & masterProductionLimits(const std::string &gname) const
Get the master-imposed per-rate-type production limits for a group.
Definition: ReservoirCouplingSlave.cpp:184
Scalar masterGroupNodePressure(const std::string &gname) const
Get the master-computed network-leaf node pressure for a master group.
Definition: ReservoirCouplingSlave.cpp:157
Definition: ReservoirCoupling.hpp:42
void receiveCoupledNetworkActiveStatusFromMaster()
Receive the master&#39;s single-bool flag for the current sync timestep and mirror it into the slave&#39;s lo...
Definition: ReservoirCouplingSlave.cpp:306
bool hasMasterGroupNodePressure(const std::string &gname) const
Check if a master-computed network-leaf node pressure exists for a master group.
Definition: ReservoirCouplingSlave.cpp:69
Definition: ReservoirCoupling.hpp:238
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
bool isLastSubstepOfSyncTimestep() const
Check if this is the last substep within a "sync" timestep.
Definition: ReservoirCouplingSlave.cpp:141
void receiveInjectionGroupTargetsFromMaster(std::size_t num_targets)
Receive injection group targets from master and store them locally.
Definition: ReservoirCouplingSlave.cpp:261
Definition: ReservoirCoupling.hpp:196
bool connectedToMasterCoupledNetwork() const
Whether this slave is connected to the master&#39;s cross-rescoup network this sync step.
Definition: ReservoirCouplingSlave.cpp:132
std::pair< Scalar, Group::ProductionCMode > masterProductionTarget(const std::string &gname) const
Get the master-imposed production target and control mode for a group.
Definition: ReservoirCouplingSlave.cpp:193
Definition: DeferredLogger.hpp:56
bool maybeReceiveTerminateSignalFromMaster()
Blocking receive for terminate/continue signal from master.
Definition: ReservoirCouplingSlave.cpp:227
void receiveTerminateAndDisconnect()
Receive terminate signal from master and disconnect the intercommunicator.
Definition: ReservoirCouplingSlave.cpp:341
bool lastReceivedMasterGroupNodePressuresIsFinal() const
Whether the most recent master-group-node-pressures receive carried the is_final flag.
Definition: ReservoirCouplingSlave.cpp:123
bool hasMasterProductionTarget(const std::string &gname) const
Check if a master-imposed production target exists for a group.
Definition: ReservoirCouplingSlave.cpp:96
Definition: ReservoirCoupling.hpp:254
void receiveMasterGroupNodePressuresFromMaster(std::size_t num_pressures)
Receive master-computed network-leaf node pressures from master.
Definition: ReservoirCouplingSlave.cpp:270
Definition: ReservoirCouplingSlave.hpp:40
void setLastSubstepOfSyncTimestep(bool value)
Set whether this is the last substep within a "sync" timestep.
Definition: ReservoirCouplingSlave.cpp:448
const std::map< std::string, Scalar > & masterGroupNodePressures() const
Get the full map of master-computed network-leaf node pressures.
Definition: ReservoirCouplingSlave.cpp:166
Per-rate-type production limits received from master hierarchy.
Definition: ReservoirCoupling.hpp:272
Definition: ReservoirCoupling.hpp:244
std::pair< std::size_t, bool > receiveNumMasterGroupNodePressuresFromMaster()
Receive the master-group-node-pressures header from master.
Definition: ReservoirCouplingSlave.cpp:323
Definition: SimulatorTimer.hpp:38
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: ReservoirCouplingSlave.cpp:175
Definition: ReservoirCoupling.hpp:220
bool hasMasterInjectionTarget(const std::string &gname, const Phase phase) const
Check if a master-imposed injection target exists for a group and phase.
Definition: ReservoirCouplingSlave.cpp:78
Manages slave-side reservoir coupling operations for a single report step.
Definition: ReservoirCouplingSlave.hpp:37