opm-simulators
Loading...
Searching...
No Matches
ReservoirCoupling.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_HPP
21#define OPM_RESERVOIR_COUPLING_HPP
22#include <opm/simulators/utils/DeferredLogger.hpp>
23#include <opm/simulators/utils/ParallelCommunication.hpp>
24#include <opm/input/eclipse/Schedule/Group/Group.hpp>
25#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
26#include <opm/input/eclipse/Units/Units.hpp>
27
28#include <dune/common/parallel/mpitraits.hh>
29
30#include <fmt/format.h>
31
32#include <mpi.h>
33#include <cmath>
34#include <iostream>
35#include <memory>
36#include <stdexcept>
37#include <vector>
38
39namespace Opm {
40namespace ReservoirCoupling {
41
42class Logger {
43public:
44 Logger() = delete; // No default constructor - must have comm
45 explicit Logger(const Parallel::Communication& comm) : comm_(comm) {}
46
47 void clearDeferredLogger() { deferred_logger_ = nullptr; }
48 void debug(const std::string &msg) const;
49 DeferredLogger& deferredLogger() { return *deferred_logger_; }
50 DeferredLogger& deferredLogger() const { return *deferred_logger_; }
51 bool haveDeferredLogger() const { return deferred_logger_ != nullptr; }
52 void info(const std::string &msg) const;
53 void warning(const std::string &msg) const;
54 void setDeferredLogger(DeferredLogger *deferred_logger) { deferred_logger_ = deferred_logger; }
55
56private:
57 const Parallel::Communication& comm_;
58 DeferredLogger *deferred_logger_ = nullptr;
59};
60
88class ScopedLoggerGuard {
89public:
90 explicit ScopedLoggerGuard(Logger& logger, DeferredLogger* deferred_logger)
91 : logger_(&logger)
92 {
93 logger_->setDeferredLogger(deferred_logger);
94 }
95
96 ~ScopedLoggerGuard() {
97 // Only clear if we still own the logger (not moved-from)
98 if (logger_) {
99 logger_->clearDeferredLogger();
100 }
101 }
102
103 // Prevent copying to ensure single ownership
104 ScopedLoggerGuard(const ScopedLoggerGuard&) = delete;
105 ScopedLoggerGuard& operator=(const ScopedLoggerGuard&) = delete;
106
107 // Enable moving - required for returning from functions and std::optional
108 ScopedLoggerGuard(ScopedLoggerGuard&& other) noexcept
109 : logger_(other.logger_)
110 {
111 // Transfer ownership: moved-from object becomes inactive and won't clear the logger
112 other.logger_ = nullptr;
113 }
114
115 ScopedLoggerGuard& operator=(ScopedLoggerGuard&& other) noexcept {
116 if (this != &other) {
117 // Clean up current logger before taking ownership of new one
118 if (logger_) {
119 logger_->clearDeferredLogger();
120 }
121 // Transfer ownership from other
122 logger_ = other.logger_;
123 other.logger_ = nullptr;
124 }
125 return *this;
126 }
127
128private:
129 // Use pointer instead of reference to enable move semantics
130 // (references cannot be reassigned, which is required for move operations)
131 Logger* logger_{nullptr};
132};
133
134enum class MessageTag : int {
135 InjectionGroupTargets,
136 MasterGroupNames,
137 MasterGroupNamesSize,
138 MasterStartOfReportStep,
139 NumSlaveGroupConstraints,
141 SlaveActivationDate,
142 SlaveActivationHandshake,
143 SlaveInjectionData,
144 SlaveProcessTermination,
145 SlaveName,
146 SlaveNameSize,
147 SlaveNextReportDate,
148 SlaveNextTimeStep,
149 SlaveProductionData,
150 SlaveSimulationStartDate,
151 SlaveStartOfReportStep,
152};
153
156enum class Phase : std::size_t {
157 Oil = 0, // Matches Opm::Phase::OIL
158 Gas, // Matches Opm::Phase::GAS
159 Water, // Matches Opm::Phase::WATER
160 Count
161};
162
168enum class RateKind {
169 InjectionSurface,
170 InjectionReservoir,
171 ProductionSurface,
172 ProductionNetworkSurface,
173 ProductionReservoir
174};
175
176template <class Scalar>
177struct InjectionRates {
178 InjectionRates() = default;
179
180 std::array<Scalar, static_cast<std::size_t>(Phase::Count)> rate{};
181 [[nodiscard]] Scalar& operator[](Phase p) noexcept { return rate[static_cast<std::size_t>(p)]; }
182 [[nodiscard]] Scalar operator[](Phase p) const noexcept { return rate[static_cast<std::size_t>(p)]; }
183};
184
185// Used to communicate potentials for oil, gas, and water rates between slave and master processes
186template <class Scalar>
188 std::array<Scalar, static_cast<std::size_t>(Phase::Count)> rate{};
189
190 [[nodiscard]] Scalar& operator[](Phase p) noexcept { return rate[static_cast<std::size_t>(p)]; }
191 [[nodiscard]] Scalar operator[](Phase p) const noexcept { return rate[static_cast<std::size_t>(p)]; }
192};
193
194template <class Scalar>
195struct ProductionRates {
196 ProductionRates() = default;
197
198 explicit ProductionRates(const GuideRate::RateVector& rate_vector)
199 : rate{static_cast<Scalar>(rate_vector.oil_rat),
200 static_cast<Scalar>(rate_vector.gas_rat),
201 static_cast<Scalar>(rate_vector.wat_rat)}
202 {}
203
204 std::array<Scalar, static_cast<std::size_t>(Phase::Count)> rate{};
205 [[nodiscard]] Scalar& operator[](Phase p) noexcept { return rate[static_cast<std::size_t>(p)]; }
206 [[nodiscard]] Scalar operator[](Phase p) const noexcept { return rate[static_cast<std::size_t>(p)]; }
207};
208
209// Slave group production data sent to the corresponding master group for target calculation.
210template <class Scalar>
212 // Group production potentials are used by the master group for guiderate calculations
213 Potentials<Scalar> potentials;
214 // Production rates are used by the master group in guiderate calculations
215 // when converting the guide rate target to the phase of the master group.
216 ProductionRates<Scalar> surface_rates; // Surface production rates by phase (network=false)
217 // Network surface rates - computed with network=true, meaning efficiency factors
218 // are 1.0 for groups/wells with GEFAC/WEFAC item 3 = "NO"
219 ProductionRates<Scalar> network_surface_rates; // Surface rates for network calculations
220 // Individual phase reservoir production rates - needed when master's parent group
221 // has RESV control mode, so the conversion uses slave's PVT properties
222 ProductionRates<Scalar> reservoir_rates; // Reservoir production rates by phase
223 Scalar voidage_rate{0.0}; // Reservoir voidage replacement rate
224 Scalar gas_reinjection_rate{0.0}; // Reinjection (surface) rate for the gas phase
225};
226
227// Slave group injection data sent to the corresponding master group for target calculation.
228template <class Scalar>
230 InjectionRates<Scalar> surface_rates; // Surface injection rates by phase
231 InjectionRates<Scalar> reservoir_rates; // Reservoir injection rates by phase
232};
233
234template <class Scalar>
236 // To save memory and avoid varying size of the struct when serializing
237 // and deserializing the group name, we use an index instead of the full name.
238 std::size_t group_name_idx; // Index of group name in the master group names vector
239 Scalar target; // Target rate for the group
240 Group::InjectionCMode cmode; // Control mode for the group
241 Phase phase; // Phase the target applies to
242};
243
244template <class Scalar>
246 // To save memory and avoid varying size of the struct when serializing
247 // and deserializing the group name, we use an index instead of the full name.
248 std::size_t group_name_idx; // Index of group name in the master group names vector
249 Scalar target; // Target rate for the active control mode
250 Group::ProductionCMode cmode; // Active control mode for the group
251 // Per-rate-type effective limits (-1 = no limit defined in hierarchy).
252 // These are guide-rate-distributed limits from the group hierarchy.
253 Scalar oil_limit;
254 Scalar water_limit;
255 Scalar gas_limit;
256 Scalar liquid_limit;
257 Scalar resv_limit;
258};
259
262template <class Scalar>
264 Scalar oil_limit{-1};
265 Scalar water_limit{-1};
266 Scalar gas_limit{-1};
267 Scalar liquid_limit{-1};
268 Scalar resv_limit{-1};
269};
270
271// Helper functions
272Phase convertPhaseToReservoirCouplingPhase(::Opm::Phase phase);
273::Opm::Phase convertToOpmPhase(const Phase phase);
274void customErrorHandler_(MPI_Comm* comm, int* err, const std::string &msg);
275void customErrorHandlerSlave_(MPI_Comm* comm, int* err, ...);
276void customErrorHandlerMaster_(MPI_Comm* comm, int* err, ...);
277void setErrhandler(MPI_Comm comm, bool is_master);
278std::pair<std::vector<char>, std::size_t> serializeStrings(const std::vector<std::string>& data);
279
283inline std::string formatDays(double seconds) {
284 double days = seconds / unit::day;
285 return fmt::format(fmt::runtime("{:.0f}s ({:.2f} days)"), seconds, days);
286}
287
305struct Seconds {
307 static constexpr double abstol = 1e-15;
308
310 static constexpr double reltol = 1e-15;
311
330 static bool compare_eq(double a, double b);
331
337 static bool compare_gt(double a, double b);
338
344 static bool compare_gt_or_eq(double a, double b);
345
351 static bool compare_lt(double a, double b);
352
358 static bool compare_lt_or_eq(double a, double b);
359};
360
361} // namespace ReservoirCoupling
362} // namespace Opm
363
364#endif // OPM_RESERVOIR_COUPLING_HPP
Definition DeferredLogger.hpp:57
Definition ReservoirCoupling.hpp:42
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilbioeffectsmodules.hh:45
Definition ReservoirCoupling.hpp:235
Definition ReservoirCoupling.hpp:177
Per-rate-type production limits received from master hierarchy.
Definition ReservoirCoupling.hpp:263
Definition ReservoirCoupling.hpp:187
Definition ReservoirCoupling.hpp:245
Definition ReservoirCoupling.hpp:195
Utility class for comparing double values representing epoch dates or elapsed time.
Definition ReservoirCoupling.hpp:305
static bool compare_eq(double a, double b)
Determines if two double values are equal within a specified tolerance.
Definition ReservoirCoupling.cpp:173
static bool compare_gt(double a, double b)
Determines if a is greater than b within the specified tolerance.
Definition ReservoirCoupling.cpp:194
static bool compare_lt_or_eq(double a, double b)
Determines if a is less than or equal to b within the specified tolerance.
Definition ReservoirCoupling.cpp:200
static constexpr double reltol
Relative tolerance used for comparisons.
Definition ReservoirCoupling.hpp:310
static bool compare_gt_or_eq(double a, double b)
Determines if a is greater than b within the specified tolerance.
Definition ReservoirCoupling.cpp:179
static bool compare_lt(double a, double b)
Determines if a is less than b within the specified tolerance.
Definition ReservoirCoupling.cpp:188
static constexpr double abstol
Absolute tolerance used for comparisons.
Definition ReservoirCoupling.hpp:307
Definition ReservoirCoupling.hpp:229
Definition ReservoirCoupling.hpp:211