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;
47  using MasterProductionLimits = typename ReservoirCoupling::MasterProductionLimits<Scalar>;
49 
51  const Parallel::Communication &comm, const Schedule &schedule, const SimulatorTimer &timer
52  );
53  bool activated() const { return activated_; }
54  void clearDeferredLogger() { logger_.clearDeferredLogger(); }
55  const Parallel::Communication& getComm() const { return comm_; }
56  MPI_Comm getMasterComm() const { return slave_master_comm_; }
57  const std::string& getSlaveName() const { return slave_name_; }
58  const std::map<std::string, std::string>& getSlaveToMasterGroupNameMap() const {
59  return slave_to_master_group_map_; }
62  bool hasMasterInjectionTarget(const std::string& gname, const Phase phase) const;
63 
66  bool hasMasterProductionLimits(const std::string& gname) const;
67 
70  bool hasMasterProductionTarget(const std::string& gname) const;
71  void initTimeStepping();
72  bool isFirstSubstepOfSyncTimestep() const;
80  bool isLastSubstepOfSyncTimestep() const;
81  bool isSlaveGroup(const std::string& group_name) const;
82  ReservoirCoupling::Logger& logger() { return this->logger_; }
83  ReservoirCoupling::Logger& logger() const { return this->logger_; }
86  std::pair<Scalar, Group::InjectionCMode> masterInjectionTarget(
87  const std::string& gname, const Phase phase) const;
88 
91  const MasterProductionLimits& masterProductionLimits(const std::string& gname) const;
92 
95  std::pair<Scalar, Group::ProductionCMode> masterProductionTarget(const std::string& gname) const;
96  void maybeActivate(int report_step);
97  std::size_t numSlaveGroups() const { return this->slave_group_order_.size(); }
98  double receiveNextTimeStepFromMaster();
99  std::pair<std::size_t, std::size_t> receiveNumGroupConstraintsFromMaster() const;
102  void receiveInjectionGroupTargetsFromMaster(std::size_t num_targets);
103 
106  void receiveProductionGroupConstraintsFromMaster(std::size_t num_targets);
107 
108  void sendAndReceiveInitialData();
109  void sendInjectionDataToMaster(const std::vector<SlaveGroupInjectionData> &injection_data) const;
110  void sendNextReportDateToMasterProcess() const;
111  void sendProductionDataToMaster(const std::vector<SlaveGroupProductionData> &production_data) const;
112  void setDeferredLogger(DeferredLogger *deferred_logger) {
113  this->logger_.setDeferredLogger(deferred_logger);
114  }
115  void setFirstSubstepOfSyncTimestep(bool value);
119  void setLastSubstepOfSyncTimestep(bool value);
120  const std::string& slaveGroupIdxToGroupName(std::size_t group_idx) const {
121  return this->slave_group_order_.at(group_idx);
122  }
123  bool terminated() const { return this->terminated_; }
124 
134 
145 
146 private:
147  void checkGrupSlavGroupNames_();
148  std::pair<double, bool> getGrupSlavActivationDateAndCheckHistoryMatchingMode_() const;
149  bool historyMatchingMode_() const { return this->history_matching_mode_; }
150  std::size_t numMasterGroups_() const { return this->slave_to_master_group_map_.size(); }
151  void receiveMasterGroupNamesFromMasterProcess_();
152  void receiveSlaveNameFromMasterProcess_();
153  void saveMasterGroupNamesAsMapAndEstablishOrder_(const std::vector<char>& group_names);
154  void sendActivationDateToMasterProcess_();
155  void sendActivationHandshakeToMasterProcess_() const;
156  void sendSimulationStartDateToMasterProcess_() const;
157 
158  const Parallel::Communication &comm_;
159  const Schedule& schedule_;
160  const SimulatorTimer &timer_;
161  // MPI parent communicator for a slave process
162  MPI_Comm slave_master_comm_{MPI_COMM_NULL};
163  std::map<std::string, std::string> slave_to_master_group_map_;
164  bool activated_{false};
165  // True if the slave was terminated by the master process
166  bool terminated_{false};
167  // True if no GRUPMAST keyword in the master schedule and no GRUPSLAV keyword in the slave schedule
168  bool history_matching_mode_{false};
169  std::string slave_name_; // This is the slave name as defined in the master process
170  mutable ReservoirCoupling::Logger logger_;
171  // Order of the slave groups. A mapping from slave group index to slave group name.
172  // The indices are determined by the order the master process sends us the group names, see
173  // receiveMasterGroupNamesFromMasterProcess_()
174  // Later, the master process will send us group name indices, and not the group names themselves,
175  // so we use this mapping to recover the slave group names from the indices.
176  std::map<std::size_t, std::string> slave_group_order_;
177  // Stores data that changes for a single report step or for timesteps within a report step.
178  std::unique_ptr<ReservoirCouplingSlaveReportStep<Scalar>> report_step_data_{nullptr};
179 };
180 
181 } // namespace Opm
182 
183 #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:258
bool hasMasterProductionLimits(const std::string &gname) const
Check if master-imposed per-rate-type production limits exist for a group.
Definition: ReservoirCouplingSlave.cpp:77
const MasterProductionLimits & masterProductionLimits(const std::string &gname) const
Get the master-imposed per-rate-type production limits for a group.
Definition: ReservoirCouplingSlave.cpp:138
Definition: ReservoirCoupling.hpp:42
Definition: ReservoirCoupling.hpp:229
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
bool isLastSubstepOfSyncTimestep() const
Check if this is the last substep within a "sync" timestep.
Definition: ReservoirCouplingSlave.cpp:113
void receiveInjectionGroupTargetsFromMaster(std::size_t num_targets)
Receive injection group targets from master and store them locally.
Definition: ReservoirCouplingSlave.cpp:215
Definition: ReservoirCoupling.hpp:187
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:147
Definition: DeferredLogger.hpp:56
bool maybeReceiveTerminateSignalFromMaster()
Blocking receive for terminate/continue signal from master.
Definition: ReservoirCouplingSlave.cpp:181
void receiveTerminateAndDisconnect()
Receive terminate signal from master and disconnect the intercommunicator.
Definition: ReservoirCouplingSlave.cpp:267
bool hasMasterProductionTarget(const std::string &gname) const
Check if a master-imposed production target exists for a group.
Definition: ReservoirCouplingSlave.cpp:86
Definition: ReservoirCoupling.hpp:245
Definition: ReservoirCouplingSlave.hpp:40
void setLastSubstepOfSyncTimestep(bool value)
Set whether this is the last substep within a "sync" timestep.
Definition: ReservoirCouplingSlave.cpp:366
Per-rate-type production limits received from master hierarchy.
Definition: ReservoirCoupling.hpp:263
Definition: ReservoirCoupling.hpp:235
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:129
Definition: ReservoirCoupling.hpp:211
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:68
Manages slave-side reservoir coupling operations for a single report step.
Definition: ReservoirCouplingSlave.hpp:37