Wells.hpp
Go to the documentation of this file.
1/*
2 Copyright 2016 Statoil 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_OUTPUT_WELLS_HPP
21#define OPM_OUTPUT_WELLS_HPP
22
23#include <algorithm>
24#include <cstddef>
25#include <initializer_list>
26#include <map>
27#include <stdexcept>
28#include <string>
29#include <type_traits>
30#include <unordered_map>
31#include <vector>
32
34
35namespace Opm {
36
37 namespace data {
38
39 class Rates {
40 /* Methods are defined inline for performance, as the actual *work* done
41 * is trivial, but somewhat frequent (typically once per time step per
42 * completion per well).
43 *
44 * To add a new rate type, add an entry in the enum with the correct
45 * shift, and if needed, increase the size type. Add a member variable
46 * and a new case in get_ref.
47 */
48
49 public:
50 Rates() = default;
51 enum class opt : uint32_t {
52 wat = (1 << 0),
53 oil = (1 << 1),
54 gas = (1 << 2),
55 polymer = (1 << 3),
56 solvent = (1 << 4),
57 energy = (1 << 5),
58 dissolved_gas = (1 << 6),
59 vaporized_oil = (1 << 7),
60 reservoir_water = (1 << 8),
61 reservoir_oil = (1 << 9),
62 reservoir_gas = (1 << 10),
63 productivity_index_water = (1 << 11),
64 productivity_index_oil = (1 << 12),
65 productivity_index_gas = (1 << 13),
66 well_potential_water = (1 << 14),
67 well_potential_oil = (1 << 15),
68 well_potential_gas = (1 << 16),
69 };
70
71 using enum_size = std::underlying_type< opt >::type;
72
74 inline bool has( opt ) const;
75
78 inline double get( opt m ) const;
81 inline double get( opt m, double default_value ) const;
85 inline Rates& set( opt m, double value );
86
88 inline bool flowing() const;
89
90 template <class MessageBufferType>
91 void write(MessageBufferType& buffer) const;
92 template <class MessageBufferType>
93 void read(MessageBufferType& buffer);
94
95 bool operator==(const Rates& rat2) const;
96
97 private:
98 double& get_ref( opt );
99 const double& get_ref( opt ) const;
100
101 opt mask = static_cast< opt >( 0 );
102
103 double wat = 0.0;
104 double oil = 0.0;
105 double gas = 0.0;
106 double polymer = 0.0;
107 double solvent = 0.0;
108 double energy = 0.0;
109 double dissolved_gas = 0.0;
110 double vaporized_oil = 0.0;
111 double reservoir_water = 0.0;
112 double reservoir_oil = 0.0;
113 double reservoir_gas = 0.0;
114 double productivity_index_water = 0.0;
115 double productivity_index_oil = 0.0;
116 double productivity_index_gas = 0.0;
117 double well_potential_water = 0.0;
118 double well_potential_oil = 0.0;
119 double well_potential_gas = 0.0;
120 };
121
122 struct Connection {
123 using global_index = size_t;
124 static const constexpr int restart_size = 6;
125
128 double pressure;
134
135 bool operator==(const Connection& conn2) const
136 {
137 return index == conn2.index &&
138 rates == conn2.rates &&
139 pressure == conn2.pressure &&
141 cell_pressure == conn2.cell_pressure &&
144 effective_Kh == conn2.effective_Kh;
145 }
146
147 template <class MessageBufferType>
148 void write(MessageBufferType& buffer) const;
149 template <class MessageBufferType>
150 void read(MessageBufferType& buffer);
151 };
152
154 public:
155 enum class Value : std::size_t {
156 Pressure, PDrop, PDropHydrostatic, PDropAccel, PDropFriction,
157 };
158
159 double& operator[](const Value i)
160 {
161 return this->values_[this->index(i)];
162 }
163
164 double operator[](const Value i) const
165 {
166 return this->values_[this->index(i)];
167 }
168
169 bool operator==(const SegmentPressures& segpres2) const
170 {
171 return this->values_ == segpres2.values_;
172 }
173
174 template <class MessageBufferType>
175 void write(MessageBufferType& buffer) const
176 {
177 for (const auto& value : this->values_) {
178 buffer.write(value);
179 }
180 }
181
182 template <class MessageBufferType>
183 void read(MessageBufferType& buffer)
184 {
185 for (auto& value : this->values_) {
186 buffer.read(value);
187 }
188 }
189
190 private:
191 constexpr static std::size_t numvals = 5;
192
193 std::array<double, numvals> values_;
194
195 std::size_t index(const Value ix) const
196 {
197 return static_cast<std::size_t>(ix);
198 }
199 };
200
201 struct Segment {
204 std::size_t segNumber;
205
206 bool operator==(const Segment& seg2) const
207 {
208 return rates == seg2.rates &&
209 pressures == seg2.pressures &&
210 segNumber == seg2.segNumber;
211 }
212
213 template <class MessageBufferType>
214 void write(MessageBufferType& buffer) const;
215
216 template <class MessageBufferType>
217 void read(MessageBufferType& buffer);
218 };
219
221 bool isProducer{true};
222
225 };
226
229 };
230
231 bool operator==(const CurrentControl& rhs) const
232 {
233 return (this->isProducer == rhs.isProducer)
234 && ((this->isProducer && (this->prod == rhs.prod)) ||
235 (!this->isProducer && (this->inj == rhs.inj)));
236 }
237
238 template <class MessageBufferType>
239 void write(MessageBufferType& buffer) const;
240
241 template <class MessageBufferType>
242 void read(MessageBufferType& buffer);
243 };
244
245 struct Well {
247 double bhp;
248 double thp;
251 std::vector< Connection > connections;
252 std::unordered_map<std::size_t, Segment> segments;
254
255 inline bool flowing() const noexcept;
256 template <class MessageBufferType>
257 void write(MessageBufferType& buffer) const;
258 template <class MessageBufferType>
259 void read(MessageBufferType& buffer);
260
261 const Connection* find_connection(Connection::global_index connection_grid_index) const {
262 const auto connection = std::find_if( this->connections.begin() ,
263 this->connections.end() ,
264 [=]( const Connection& c ) {
265 return c.index == connection_grid_index; });
266
267 if( connection == this->connections.end() )
268 return nullptr;
269
270 return &*connection;
271 }
272
274 auto connection = std::find_if( this->connections.begin() ,
275 this->connections.end() ,
276 [=]( const Connection& c ) {
277 return c.index == connection_grid_index; });
278
279 if( connection == this->connections.end() )
280 return nullptr;
281
282 return &*connection;
283 }
284
285 bool operator==(const Well& well2) const
286 {
287 return rates == well2.rates &&
288 bhp == well2.bhp &&
289 thp == well2.thp &&
290 temperature == well2.temperature &&
291 control == well2.control &&
292 connections == well2.connections &&
293 segments == well2.segments &&
295 }
296 };
297
298
299 class WellRates : public std::map<std::string , Well> {
300 public:
301
302 double get(const std::string& well_name , Rates::opt m) const {
303 const auto& well = this->find( well_name );
304 if( well == this->end() ) return 0.0;
305
306 return well->second.rates.get( m, 0.0 );
307 }
308
309
310 double get(const std::string& well_name , Connection::global_index connection_grid_index, Rates::opt m) const {
311 const auto& witr = this->find( well_name );
312 if( witr == this->end() ) return 0.0;
313
314 const auto& well = witr->second;
315 const auto& connection = std::find_if( well.connections.begin() ,
316 well.connections.end() ,
317 [=]( const Connection& c ) {
318 return c.index == connection_grid_index; });
319
320 if( connection == well.connections.end() )
321 return 0.0;
322
323 return connection->rates.get( m, 0.0 );
324 }
325
326 template <class MessageBufferType>
327 void write(MessageBufferType& buffer) const {
328 unsigned int size = this->size();
329 buffer.write(size);
330 for (const auto& witr : *this) {
331 const std::string& name = witr.first;
332 buffer.write(name);
333 const Well& well = witr.second;
334 well.write(buffer);
335 }
336 }
337
338 template <class MessageBufferType>
339 void read(MessageBufferType& buffer) {
340 unsigned int size;
341 buffer.read(size);
342 for (size_t i = 0; i < size; ++i) {
344 buffer.read(name);
345 Well well;
346 well.read(buffer);
347 this->emplace(name, well);
348 }
349 }
350 };
351
353
354
355 /* IMPLEMENTATIONS */
356
357 inline bool Rates::has( opt m ) const {
358 const auto mand = static_cast< enum_size >( this->mask )
359 & static_cast< enum_size >( m );
360
361 return static_cast< opt >( mand ) == m;
362 }
363
364 inline double Rates::get( opt m ) const {
365 if( !this->has( m ) )
366 throw std::invalid_argument( "Uninitialized value." );
367
368 return this->get_ref( m );
369 }
370
371 inline double Rates::get( opt m, double default_value ) const {
372 if( !this->has( m ) ) return default_value;
373
374 return this->get_ref( m );
375 }
376
377 inline Rates& Rates::set( opt m, double value ) {
378 this->get_ref( m ) = value;
379 /* mask |= m */
380 this->mask = static_cast< opt >(
381 static_cast< enum_size >( this->mask ) |
382 static_cast< enum_size >( m )
383 );
384
385 return *this;
386 }
387
388 inline bool Rates::operator==(const Rates& rate) const
389 {
390 return mask == rate.mask &&
391 wat == rate.wat &&
392 oil == rate.oil &&
393 gas == rate.gas &&
394 polymer == rate.polymer &&
395 solvent == rate.solvent &&
396 energy == rate.energy &&
397 dissolved_gas == rate.dissolved_gas &&
398 vaporized_oil == rate.vaporized_oil &&
399 reservoir_water == rate.reservoir_water &&
400 reservoir_oil == rate.reservoir_oil &&
401 reservoir_gas == rate.reservoir_gas &&
402 productivity_index_water == rate.productivity_index_water &&
403 productivity_index_gas == rate.productivity_index_gas &&
404 productivity_index_oil == rate.productivity_index_oil &&
405 well_potential_water == rate.well_potential_water &&
406 well_potential_oil == rate.well_potential_oil &&
407 well_potential_gas == rate.well_potential_gas;
408 }
409
410
411 /*
412 * To avoid error-prone and repetitve work when extending rates with new
413 * values, the get+set methods use this helper get_ref to determine what
414 * member to manipulate. To add a new option, just add another case
415 * corresponding to the enum entry in Rates to this function.
416 *
417 * This is an implementation detail and understanding this has no
418 * significant impact on correct use of the class.
419 */
420 inline const double& Rates::get_ref( opt m ) const {
421 switch( m ) {
422 case opt::wat: return this->wat;
423 case opt::oil: return this->oil;
424 case opt::gas: return this->gas;
425 case opt::polymer: return this->polymer;
426 case opt::solvent: return this->solvent;
427 case opt::energy: return this->energy;
428 case opt::dissolved_gas: return this->dissolved_gas;
429 case opt::vaporized_oil: return this->vaporized_oil;
430 case opt::reservoir_water: return this->reservoir_water;
431 case opt::reservoir_oil: return this->reservoir_oil;
432 case opt::reservoir_gas: return this->reservoir_gas;
433 case opt::productivity_index_water: return this->productivity_index_water;
434 case opt::productivity_index_oil: return this->productivity_index_oil;
435 case opt::productivity_index_gas: return this->productivity_index_gas;
436 case opt::well_potential_water: return this->well_potential_water;
437 case opt::well_potential_oil: return this->well_potential_oil;
438 case opt::well_potential_gas: return this->well_potential_gas;
439 }
440
441 throw std::invalid_argument(
442 "Unknown value type '"
443 + std::to_string( static_cast< enum_size >( m ) )
444 + "'" );
445
446 }
447
448 inline double& Rates::get_ref( opt m ) {
449 return const_cast< double& >(
450 static_cast< const Rates* >( this )->get_ref( m )
451 );
452 }
453
454
455 bool inline Rates::flowing() const {
456 return ((this->wat != 0) ||
457 (this->oil != 0) ||
458 (this->gas != 0));
459 }
460
461 inline bool Well::flowing() const noexcept {
462 return this->rates.flowing();
463 }
464
465 template <class MessageBufferType>
466 void Rates::write(MessageBufferType& buffer) const {
467 buffer.write(this->mask);
468 buffer.write(this->wat);
469 buffer.write(this->oil);
470 buffer.write(this->gas);
471 buffer.write(this->polymer);
472 buffer.write(this->solvent);
473 buffer.write(this->energy);
474 buffer.write(this->dissolved_gas);
475 buffer.write(this->vaporized_oil);
476 buffer.write(this->reservoir_water);
477 buffer.write(this->reservoir_oil);
478 buffer.write(this->reservoir_gas);
479 buffer.write(this->productivity_index_water);
480 buffer.write(this->productivity_index_oil);
481 buffer.write(this->productivity_index_gas);
482 buffer.write(this->well_potential_water);
483 buffer.write(this->well_potential_oil);
484 buffer.write(this->well_potential_gas);
485 }
486
487 template <class MessageBufferType>
488 void Connection::write(MessageBufferType& buffer) const {
489 buffer.write(this->index);
490 this->rates.write(buffer);
491 buffer.write(this->pressure);
492 buffer.write(this->reservoir_rate);
493 buffer.write(this->cell_pressure);
494 buffer.write(this->cell_saturation_water);
495 buffer.write(this->cell_saturation_gas);
496 buffer.write(this->effective_Kh);
497 }
498
499 template <class MessageBufferType>
500 void Segment::write(MessageBufferType& buffer) const {
501 buffer.write(this->segNumber);
502 this->rates.write(buffer);
503 this->pressures.write(buffer);
504 }
505
506 template <class MessageBufferType>
507 void CurrentControl::write(MessageBufferType& buffer) const
508 {
509 buffer.write(this->isProducer);
510 if (this->isProducer) {
511 buffer.write(this->prod);
512 }
513 else {
514 buffer.write(this->inj);
515 }
516 }
517
518 template <class MessageBufferType>
519 void Well::write(MessageBufferType& buffer) const {
520 this->rates.write(buffer);
521 buffer.write(this->bhp);
522 buffer.write(this->thp);
523 buffer.write(this->temperature);
524 buffer.write(this->control);
525 unsigned int size = this->connections.size();
526 buffer.write(size);
527 for (const Connection& comp : this->connections)
528 comp.write(buffer);
529
530 {
531 const auto nSeg =
532 static_cast<unsigned int>(this->segments.size());
533 buffer.write(nSeg);
534
535 for (const auto& seg : this->segments) {
536 seg.second.write(buffer);
537 }
538 }
539
540 this->current_control.write(buffer);
541 }
542
543 template <class MessageBufferType>
544 void Rates::read(MessageBufferType& buffer) {
545 buffer.read(this->mask);
546 buffer.read(this->wat);
547 buffer.read(this->oil);
548 buffer.read(this->gas);
549 buffer.read(this->polymer);
550 buffer.read(this->solvent);
551 buffer.read(this->energy);
552 buffer.read(this->dissolved_gas);
553 buffer.read(this->vaporized_oil);
554 buffer.read(this->reservoir_water);
555 buffer.read(this->reservoir_oil);
556 buffer.read(this->reservoir_gas);
557 buffer.read(this->productivity_index_water);
558 buffer.read(this->productivity_index_oil);
559 buffer.read(this->productivity_index_gas);
560 buffer.read(this->well_potential_water);
561 buffer.read(this->well_potential_oil);
562 buffer.read(this->well_potential_gas);
563 }
564
565 template <class MessageBufferType>
566 void Connection::read(MessageBufferType& buffer) {
567 buffer.read(this->index);
568 this->rates.read(buffer);
569 buffer.read(this->pressure);
570 buffer.read(this->reservoir_rate);
571 buffer.read(this->cell_pressure);
572 buffer.read(this->cell_saturation_water);
573 buffer.read(this->cell_saturation_gas);
574 buffer.read(this->effective_Kh);
575 }
576
577 template <class MessageBufferType>
578 void Segment::read(MessageBufferType& buffer) {
579 buffer.read(this->segNumber);
580 this->rates.read(buffer);
581 this->pressures.read(buffer);
582 }
583
584 template <class MessageBufferType>
585 void CurrentControl::read(MessageBufferType& buffer)
586 {
587 buffer.read(this->isProducer);
588 if (this->isProducer) {
589 buffer.read(this->prod);
590 }
591 else {
592 buffer.read(this->inj);
593 }
594 }
595
596 template <class MessageBufferType>
597 void Well::read(MessageBufferType& buffer) {
598 this->rates.read(buffer);
599 buffer.read(this->bhp);
600 buffer.read(this->thp);
601 buffer.read(this->temperature);
602 buffer.read(this->control);
603
604 // Connection information
605 unsigned int size = 0.0; //this->connections.size();
606 buffer.read(size);
607 this->connections.resize(size);
608 for (size_t i = 0; i < size; ++i)
609 {
610 auto& comp = this->connections[ i ];
611 comp.read(buffer);
612 }
613
614 // Segment information (if applicable)
615 const auto nSeg = [&buffer]() -> unsigned int
616 {
617 auto n = 0u;
618 buffer.read(n);
619
620 return n;
621 }();
622
623 for (auto segID = 0*nSeg; segID < nSeg; ++segID) {
624 auto seg = Segment{};
625 seg.read(buffer);
626
627 const auto segNumber = seg.segNumber;
628 this->segments.emplace(segNumber, std::move(seg));
629 }
630
631 this->current_control.read(buffer);
632 }
633
634}} // Opm::data
635
636#endif //OPM_OUTPUT_WELLS_HPP
const char *const name
Definition: cJSON.h:258
const char *const string
Definition: cJSON.h:170
char * buffer
Definition: cJSON.h:161
Definition: Value.hpp:39
ProducerCMode
Definition: custom-opm-common/opm-common/opm/parser/eclipse/EclipseState/Schedule/Well/well.hpp:101
InjectorCMode
Definition: custom-opm-common/opm-common/opm/parser/eclipse/EclipseState/Schedule/Well/well.hpp:78
Definition: Wells.hpp:39
bool flowing() const
Returns true if any of the rates oil, gas, water is nonzero.
Definition: Wells.hpp:455
double get(opt m) const
Definition: Wells.hpp:364
void read(MessageBufferType &buffer)
Definition: Wells.hpp:544
bool operator==(const Rates &rat2) const
Definition: Wells.hpp:388
Rates & set(opt m, double value)
Definition: Wells.hpp:377
std::underlying_type< opt >::type enum_size
Definition: Wells.hpp:71
void write(MessageBufferType &buffer) const
Definition: Wells.hpp:466
opt
Definition: Wells.hpp:51
bool has(opt) const
Query if a value is set.
Definition: Wells.hpp:357
Definition: Wells.hpp:153
bool operator==(const SegmentPressures &segpres2) const
Definition: Wells.hpp:169
Value
Definition: Wells.hpp:155
double operator[](const Value i) const
Definition: Wells.hpp:164
double & operator[](const Value i)
Definition: Wells.hpp:159
void read(MessageBufferType &buffer)
Definition: Wells.hpp:183
void write(MessageBufferType &buffer) const
Definition: Wells.hpp:175
Definition: Wells.hpp:299
double get(const std::string &well_name, Rates::opt m) const
Definition: Wells.hpp:302
void write(MessageBufferType &buffer) const
Definition: Wells.hpp:327
double get(const std::string &well_name, Connection::global_index connection_grid_index, Rates::opt m) const
Definition: Wells.hpp:310
void read(MessageBufferType &buffer)
Definition: Wells.hpp:339
std::vector< typename std::result_of< F(typename C::const_iterator::value_type &) >::type > map(F f, const C &src)
Definition: Functional.hpp:84
Definition: A.hpp:4
@ end
Definition: ActionValue.hpp:20
T value(details::expression_node< T > *n)
Definition: exprtk.hpp:12955
static std::string data()
Definition: exprtk.hpp:40022
Definition: Wells.hpp:122
double cell_saturation_water
Definition: Wells.hpp:131
bool operator==(const Connection &conn2) const
Definition: Wells.hpp:135
Rates rates
Definition: Wells.hpp:127
void write(MessageBufferType &buffer) const
Definition: Wells.hpp:488
double effective_Kh
Definition: Wells.hpp:133
double cell_pressure
Definition: Wells.hpp:130
size_t global_index
Definition: Wells.hpp:123
void read(MessageBufferType &buffer)
Definition: Wells.hpp:566
static const constexpr int restart_size
Definition: Wells.hpp:124
double cell_saturation_gas
Definition: Wells.hpp:132
double reservoir_rate
Definition: Wells.hpp:129
global_index index
Definition: Wells.hpp:126
double pressure
Definition: Wells.hpp:128
Definition: Wells.hpp:220
void write(MessageBufferType &buffer) const
Definition: Wells.hpp:507
bool operator==(const CurrentControl &rhs) const
Definition: Wells.hpp:231
::Opm::Well::InjectorCMode inj
Definition: Wells.hpp:227
void read(MessageBufferType &buffer)
Definition: Wells.hpp:585
bool isProducer
Definition: Wells.hpp:221
::Opm::Well::ProducerCMode prod
Definition: Wells.hpp:223
Definition: Wells.hpp:201
bool operator==(const Segment &seg2) const
Definition: Wells.hpp:206
SegmentPressures pressures
Definition: Wells.hpp:203
Rates rates
Definition: Wells.hpp:202
std::size_t segNumber
Definition: Wells.hpp:204
void read(MessageBufferType &buffer)
Definition: Wells.hpp:578
void write(MessageBufferType &buffer) const
Definition: Wells.hpp:500
Definition: Wells.hpp:245
double bhp
Definition: Wells.hpp:247
Connection * find_connection(Connection::global_index connection_grid_index)
Definition: Wells.hpp:273
bool operator==(const Well &well2) const
Definition: Wells.hpp:285
Rates rates
Definition: Wells.hpp:246
std::vector< Connection > connections
Definition: Wells.hpp:251
const Connection * find_connection(Connection::global_index connection_grid_index) const
Definition: Wells.hpp:261
double thp
Definition: Wells.hpp:248
int control
Definition: Wells.hpp:250
bool flowing() const noexcept
Definition: Wells.hpp:461
std::unordered_map< std::size_t, Segment > segments
Definition: Wells.hpp:252
void write(MessageBufferType &buffer) const
Definition: Wells.hpp:519
void read(MessageBufferType &buffer)
Definition: Wells.hpp:597
CurrentControl current_control
Definition: Wells.hpp:253
double temperature
Definition: Wells.hpp:249