WellState.hpp
Go to the documentation of this file.
1/*
2 Copyright 2014 SINTEF ICT, Applied Mathematics.
3 Copyright 2017 IRIS AS
4
5 This file is part of the Open Porous Media project (OPM).
6
7 OPM is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 OPM is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with OPM. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifndef OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
22#define OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
23
24#include <dune/common/version.hh>
25#include <dune/common/parallel/mpihelper.hh>
26
27#include <opm/common/ErrorMacros.hpp>
28
29#include <opm/material/fluidsystems/PhaseUsageInfo.hpp>
30
31#include <opm/input/eclipse/Schedule/Events.hpp>
32
33#include <opm/output/data/Wells.hpp>
34
40
42
43#include <algorithm>
44#include <cstddef>
45#include <cstdint>
46#include <functional>
47#include <map>
48#include <optional>
49#include <string>
50#include <utility>
51#include <vector>
52
53namespace Opm
54{
55
56template<class Scalar> class ParallelWellInfo;
57template<class Scalar> struct PerforationData;
58template<class Scalar> class ConnFracStatistics;
59class Schedule;
60enum class WellStatus : std::uint8_t;
61
64template<typename Scalar, typename IndexTraits>
66{
67public:
69 {
70 RsConstInfo() = default;
71 RsConstInfo(const bool en, const Scalar val)
72 : enabled { en }
73 , value { val }
74 {}
75
76 // True when RSCONST-based reporting should be applied.
77 bool enabled {false};
78
79 // Constant Rs value (surface gas volume per surface oil volume).
80 Scalar value {};
81 };
82
83 static const std::uint64_t event_mask = ScheduleEvents::WELL_STATUS_CHANGE
84 | ScheduleEvents::PRODUCTION_UPDATE
85 | ScheduleEvents::INJECTION_UPDATE;
86
87 // TODO: same definition with WellInterface, eventually they should go to a common header file.
88
89 // TODO: trying to PhasedIdx to make it more explicit as phase index, will evaluate how it goes.
90 // TODO: eventually, we should distinguish phase index and component index
91 static const int waterPhaseIdx = IndexTraits::waterPhaseIdx;
92 static const int oilPhaseIdx = IndexTraits::oilPhaseIdx;
93 static const int gasPhaseIdx = IndexTraits::gasPhaseIdx;
94
95 // Only usable for testing purposes
96 explicit WellState(const ParallelWellInfo<Scalar>& pinfo);
97
99 : phaseUsageInfo_(pu)
100 {}
101
103
104 std::size_t size() const
105 {
106 return this->wells_.size();
107 }
108
109 std::vector<std::string> wells() const
110 {
111 return this->wells_.wells();
112 }
113
114 int numWells() const
115 {
116 return this->size();
117 }
118
119 // TODO: temporary naming during development, will change to phaseUsage() later
121 {
122 return this->phaseUsageInfo_;
123 }
124
125 const ParallelWellInfo<Scalar>& parallelWellInfo(std::size_t well_index) const;
126
130 void init(const std::vector<Scalar>& cellPressures,
131 const std::vector<Scalar>& cellTemperatures,
132 const Schedule& schedule,
133 const std::vector<Well>& wells_ecl,
134 const std::vector<std::reference_wrapper<ParallelWellInfo<Scalar>>>& parallel_well_info,
135 const int report_step,
136 const WellState* prevState,
137 const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
138 const SummaryState& summary_state,
139 const bool enableDistributedWells);
140
141 void resize(const std::vector<Well>& wells_ecl,
142 const std::vector<std::reference_wrapper<ParallelWellInfo<Scalar>>>& parallel_well_info,
143 const Schedule& schedule,
144 const bool handle_ms_well,
145 const std::size_t numCells,
146 const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
147 const SummaryState& summary_state,
148 const bool enable_distributed_wells);
149
150 void setCurrentWellRates(const std::string& wellName,
151 const std::vector<Scalar>& new_rates)
152 {
153 auto& [owner, rates] = this->well_rates.at(wellName);
154 if (owner)
155 rates = new_rates;
156 }
157
158 const std::vector<Scalar>& currentWellRates(const std::string& wellName) const;
159
160 bool hasWellRates(const std::string& wellName) const
161 {
162 return this->well_rates.find(wellName) != this->well_rates.end();
163 }
164
166 {
167 this->well_rates.clear();
168 }
169
170 void gatherVectorsOnRoot(const std::vector<data::Connection>& from_connections,
171 std::vector<data::Connection>& to_connections,
172 const Parallel::Communication& comm) const;
173
174 data::Wells
175 report(const int* globalCellIdxMap,
176 const std::function<bool(const int)>& wasDynamicallyClosed,
177 const RsConstInfo& rsConst = RsConstInfo{}) const;
178
179 void reportConnections(std::vector<data::Connection>& connections,
180 std::size_t well_index,
181 const int* globalCellIdxMap) const;
182
184 void initWellStateMSWell(const std::vector<Well>& wells_ecl,
185 const WellState* prev_well_state);
186
188 const std::vector<std::vector<int>>& segment_inlets,
189 const std::vector<std::vector<int>>& segment_perforations,
190 const std::vector<Scalar>& perforation_rates,
191 const int np,
192 const int segment,
193 std::vector<Scalar>& segment_rates);
194
195
197
199 const std::vector<WellStatus>& well_status);
200 void updateEfficiencyScalingFactor(const std::string& wellName,
201 const Scalar value);
202
203 bool isInjectionGrup(const std::string& name) const
204 {
205 return this->global_well_info.value().in_injecting_group(name);
206 }
207
208 bool isProductionGrup(const std::string& name) const
209 {
210 return this->global_well_info.value().in_producing_group(name);
211 }
212
213 bool isOpen(const std::string& name) const
214 {
215 return this->global_well_info.value().is_open(name);
216 }
217
218 Scalar getGlobalEfficiencyScalingFactor(const std::string& name) const
219 {
220 return this->global_well_info.value().efficiency_scaling_factor(name);
221 }
222
223 // If the ALQ has changed since the previous time step,
224 // reset current_alq and update default_alq. ALQ is used for
225 // constant lift gas injection and for gas lift optimization
226 // (THP controlled wells).
227 void updateWellsDefaultALQ(const Schedule& schedule,
228 const int report_step,
229 const SummaryState& summary_state);
230
232 {
233 for (size_t i = 0; i < this->size(); ++i) {
234 this->wells_[i].alq_state.reset_count();
235 }
236 }
237
238
239 int wellNameToGlobalIdx(const std::string& name)
240 {
241 return this->global_well_info.value().well_index(name);
242 }
243
244 std::string globalIdxToWellName(const int index)
245 {
246 return this->global_well_info.value().well_name(index);
247 }
248
249 bool wellIsOwned(std::size_t well_index,
250 const std::string& wellName) const;
251
252 bool wellIsOwned(const std::string& wellName) const;
253
254 bool isRank0() const {
255 return this->global_well_info.value().isRank0();
256 }
257
258 void updateStatus(int well_index, WellStatus status);
259
260 void openWell(int well_index);
261 void shutWell(int well_index);
262 void stopWell(int well_index);
263
265 constexpr int numPhases() const
266 {
267 return phaseUsageInfo_.numActivePhases();
268 }
269
271 std::vector<Scalar>& wellRates(std::size_t well_index)
272 { return this->wells_[well_index].surface_rates; }
273 const std::vector<Scalar>& wellRates(std::size_t well_index) const
274 { return this->wells_[well_index].surface_rates; }
275
276 const std::string& name(std::size_t well_index) const
277 {
278 return this->wells_.well_name(well_index);
279 }
280
281 std::optional<std::size_t> index(const std::string& well_name) const
282 {
283 return this->wells_.well_index(well_name);
284 }
285
286 const SingleWellState<Scalar, IndexTraits>& operator[](std::size_t well_index) const
287 {
288 return this->wells_[well_index];
289 }
290
291 const SingleWellState<Scalar, IndexTraits>& operator[](const std::string& well_name) const
292 {
293 return this->wells_[well_name];
294 }
295
297 {
298 return this->wells_[well_index];
299 }
300
302 {
303 return this->wells_[well_name];
304 }
305
306 const SingleWellState<Scalar, IndexTraits>& well(std::size_t well_index) const
307 {
308 return this->operator[](well_index);
309 }
310
311 const SingleWellState<Scalar, IndexTraits>& well(const std::string& well_name) const
312 {
313 return this->operator[](well_name);
314 }
315
317 {
318 return this->operator[](well_index);
319 }
320
321 SingleWellState<Scalar, IndexTraits>& well(const std::string& well_name)
322 {
323 return this->operator[](well_name);
324 }
325
326 bool has(const std::string& well_name) const
327 {
328 return this->wells_.has(well_name);
329 }
330
331 bool operator==(const WellState&) const;
332
333 template<class Serializer>
334 void serializeOp(Serializer& serializer)
335 {
336 serializer(well_rates);
337 if (serializer.isSerializing()) {
338 serializer(wells_.size());
339 } else {
340 std::size_t size = 0;
341 serializer(size);
342 if (size != wells_.size()) {
343 OPM_THROW(std::runtime_error, "Error deserializing WellState: size mismatch");
344 }
345 }
346 for (auto& w : wells_) {
347 serializer(w);
348 }
349 serializer(permanently_inactive_well_names_);
350 }
351
352 bool is_permanently_inactive_well(const std::string& wname) const {
353 return std::ranges::find(this->permanently_inactive_well_names_, wname) !=
354 this->permanently_inactive_well_names_.end();
355 }
356
357private:
358 bool enableDistributedWells_ = false;
359
360 PhaseUsageInfo<IndexTraits> phaseUsageInfo_;
361
362 // The wells_ variable is essentially a map of all the wells on the current
363 // process. Observe that since a well can be split over several processes a
364 // well might appear in the WellContainer on different processes.
366
367 // The members global_well_info and well_rates are map like
368 // structures which will have entries for *all* the wells in the system.
369
370 // Use of std::optional<> here is a technical crutch, the
371 // WellStateFullyImplicitBlackoil class should be default constructible,
372 // whereas the GlobalWellInfo is not.
373 std::optional<GlobalWellInfo<Scalar>> global_well_info;
374
375 // The well_rates variable is defined for all wells on all processors. The
376 // bool in the value pair is whether the current process owns the well or
377 // not.
378 std::map<std::string, std::pair<bool, std::vector<Scalar>>> well_rates;
379
380 // Keep track of permanently inactive well names
381 std::vector<std::string> permanently_inactive_well_names_;
382
383 data::Segment
384 reportSegmentResults(const int well_id,
385 const int seg_ix,
386 const int seg_no) const;
387
388
394 void base_init(const std::vector<Scalar>& cellPressures,
395 const std::vector<Scalar>& cellTemperatures,
396 const std::vector<Well>& wells_ecl,
397 const std::vector<std::reference_wrapper<ParallelWellInfo<Scalar>>>& parallel_well_info,
398 const std::vector<std::vector<PerforationData<Scalar>>>& well_perf_data,
399 const SummaryState& summary_state);
400
401 void initSingleWell(const std::vector<Scalar>& cellPressures,
402 const std::vector<Scalar>& cellTemperatures,
403 const Well& well,
404 const std::vector<PerforationData<Scalar>>& well_perf_data,
405 const ParallelWellInfo<Scalar>& well_info,
406 const SummaryState& summary_state);
407
408 void initSingleProducer(const Well& well,
409 const ParallelWellInfo<Scalar>& well_info,
410 Scalar pressure_first_connection,
411 const std::vector<PerforationData<Scalar>>& well_perf_data,
412 const SummaryState& summary_state);
413
414 void initSingleInjector(const Well& well,
415 const ParallelWellInfo<Scalar>& well_info,
416 Scalar pressure_first_connection,
417 Scalar temperature_first_connection,
418 const std::vector<PerforationData<Scalar>>& well_perf_data,
419 const SummaryState& summary_state);
420
421 static void calculateSegmentRatesBeforeSum(const ParallelWellInfo<Scalar>& pw_info,
422 const std::vector<std::vector<int>>& segment_inlets,
423 const std::vector<std::vector<int>>& segment_perforations,
424 const std::vector<Scalar>& perforation_rates,
425 const int np,
426 const int segment,
427 std::vector<Scalar>& segment_rates);
428
429 void reportConnectionFactors(const std::size_t well_index,
430 std::vector<data::Connection>& connections) const;
431
432 void reportConnectionPressuresAndRates(const std::size_t well_index,
433 std::vector<data::Connection>& connections) const;
434
435 void reportConnectionFilterCake(const std::size_t well_index,
436 std::vector<data::Connection>& connections) const;
437
438 void reportFractureStatistics(const std::vector<ConnFracStatistics<Scalar>>& stats,
439 std::vector<data::Connection>& connections) const;
440};
441
442} // namespace Opm
443
444// TODO: we are missing pu, while it was not there in the first place
445#endif // OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
Definition: ConnFracStatistics.hpp:37
Class encapsulating some information about parallel wells.
Definition: ParallelWellInfo.hpp:198
Definition: GasLiftGroupInfo.hpp:38
Definition: SingleWellState.hpp:44
Definition: WellContainer.hpp:46
Definition: WellState.hpp:66
bool has(const std::string &well_name) const
Definition: WellState.hpp:326
void reportConnections(std::vector< data::Connection > &connections, std::size_t well_index, const int *globalCellIdxMap) const
void resize(const std::vector< Well > &wells_ecl, const std::vector< std::reference_wrapper< ParallelWellInfo< Scalar > > > &parallel_well_info, const Schedule &schedule, const bool handle_ms_well, const std::size_t numCells, const std::vector< std::vector< PerforationData< Scalar > > > &well_perf_data, const SummaryState &summary_state, const bool enable_distributed_wells)
void clearWellRates()
Definition: WellState.hpp:165
bool isProductionGrup(const std::string &name) const
Definition: WellState.hpp:208
bool wellIsOwned(std::size_t well_index, const std::string &wellName) const
void openWell(int well_index)
SingleWellState< Scalar, IndexTraits > & operator[](std::size_t well_index)
Definition: WellState.hpp:296
constexpr int numPhases() const
The number of phases present.
Definition: WellState.hpp:265
SingleWellState< Scalar, IndexTraits > & well(std::size_t well_index)
Definition: WellState.hpp:316
bool hasWellRates(const std::string &wellName) const
Definition: WellState.hpp:160
bool is_permanently_inactive_well(const std::string &wname) const
Definition: WellState.hpp:352
std::string globalIdxToWellName(const int index)
Definition: WellState.hpp:244
const ParallelWellInfo< Scalar > & parallelWellInfo(std::size_t well_index) const
void updateGlobalIsGrup(const Parallel::Communication &comm, const std::vector< WellStatus > &well_status)
void communicateGroupRates(const Parallel::Communication &comm)
data::Wells report(const int *globalCellIdxMap, const std::function< bool(const int)> &wasDynamicallyClosed, const RsConstInfo &rsConst=RsConstInfo{}) const
static const int gasPhaseIdx
Definition: WellState.hpp:93
bool isInjectionGrup(const std::string &name) const
Definition: WellState.hpp:203
void initWellStateMSWell(const std::vector< Well > &wells_ecl, const WellState *prev_well_state)
init the MS well related.
int wellNameToGlobalIdx(const std::string &name)
Definition: WellState.hpp:239
static const int waterPhaseIdx
Definition: WellState.hpp:91
void stopWell(int well_index)
void gatherVectorsOnRoot(const std::vector< data::Connection > &from_connections, std::vector< data::Connection > &to_connections, const Parallel::Communication &comm) const
void gliftTimeStepInit()
Definition: WellState.hpp:231
const SingleWellState< Scalar, IndexTraits > & operator[](const std::string &well_name) const
Definition: WellState.hpp:291
bool operator==(const WellState &) const
WellState(const ParallelWellInfo< Scalar > &pinfo)
void setCurrentWellRates(const std::string &wellName, const std::vector< Scalar > &new_rates)
Definition: WellState.hpp:150
int numWells() const
Definition: WellState.hpp:114
static const int oilPhaseIdx
Definition: WellState.hpp:92
Scalar getGlobalEfficiencyScalingFactor(const std::string &name) const
Definition: WellState.hpp:218
const std::vector< Scalar > & currentWellRates(const std::string &wellName) const
const PhaseUsageInfo< IndexTraits > & phaseUsageInfo() const
Definition: WellState.hpp:120
std::vector< std::string > wells() const
Definition: WellState.hpp:109
bool isRank0() const
Definition: WellState.hpp:254
const SingleWellState< Scalar, IndexTraits > & well(const std::string &well_name) const
Definition: WellState.hpp:311
static const std::uint64_t event_mask
Definition: WellState.hpp:83
static WellState serializationTestObject(const ParallelWellInfo< Scalar > &pinfo)
std::size_t size() const
Definition: WellState.hpp:104
WellState(const PhaseUsageInfo< IndexTraits > &pu)
Definition: WellState.hpp:98
void updateStatus(int well_index, WellStatus status)
static void calculateSegmentRates(const ParallelWellInfo< Scalar > &pw_info, const std::vector< std::vector< int > > &segment_inlets, const std::vector< std::vector< int > > &segment_perforations, const std::vector< Scalar > &perforation_rates, const int np, const int segment, std::vector< Scalar > &segment_rates)
void updateEfficiencyScalingFactor(const std::string &wellName, const Scalar value)
const SingleWellState< Scalar, IndexTraits > & well(std::size_t well_index) const
Definition: WellState.hpp:306
const SingleWellState< Scalar, IndexTraits > & operator[](std::size_t well_index) const
Definition: WellState.hpp:286
bool isOpen(const std::string &name) const
Definition: WellState.hpp:213
bool wellIsOwned(const std::string &wellName) const
const std::vector< Scalar > & wellRates(std::size_t well_index) const
Definition: WellState.hpp:273
std::vector< Scalar > & wellRates(std::size_t well_index)
One rate per well and phase.
Definition: WellState.hpp:271
void updateWellsDefaultALQ(const Schedule &schedule, const int report_step, const SummaryState &summary_state)
void serializeOp(Serializer &serializer)
Definition: WellState.hpp:334
SingleWellState< Scalar, IndexTraits > & operator[](const std::string &well_name)
Definition: WellState.hpp:301
std::optional< std::size_t > index(const std::string &well_name) const
Definition: WellState.hpp:281
void shutWell(int well_index)
void init(const std::vector< Scalar > &cellPressures, const std::vector< Scalar > &cellTemperatures, const Schedule &schedule, const std::vector< Well > &wells_ecl, const std::vector< std::reference_wrapper< ParallelWellInfo< Scalar > > > &parallel_well_info, const int report_step, const WellState *prevState, const std::vector< std::vector< PerforationData< Scalar > > > &well_perf_data, const SummaryState &summary_state, const bool enableDistributedWells)
SingleWellState< Scalar, IndexTraits > & well(const std::string &well_name)
Definition: WellState.hpp:321
const std::string & name(std::size_t well_index) const
Definition: WellState.hpp:276
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: blackoilbioeffectsmodules.hh:45
Static data associated with a well perforation.
Definition: PerforationData.hpp:30
Definition: WellState.hpp:69
Scalar value
Definition: WellState.hpp:80
RsConstInfo(const bool en, const Scalar val)
Definition: WellState.hpp:71
bool enabled
Definition: WellState.hpp:77