My Project
Wells.hpp
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 <opm/output/data/GuideRateValue.hpp>
24#include <opm/input/eclipse/Schedule/Well/WellEnums.hpp>
25
26#include <opm/json/JsonObject.hpp>
27
28#include <algorithm>
29#include <array>
30#include <cstddef>
31#include <initializer_list>
32#include <map>
33#include <stdexcept>
34#include <string>
35#include <type_traits>
36#include <unordered_map>
37#include <vector>
38
39namespace Opm {
40
41 namespace data {
42
43 class Rates {
44 /* Methods are defined inline for performance, as the actual *work* done
45 * is trivial, but somewhat frequent (typically once per time step per
46 * completion per well).
47 *
48 * To add a new rate type, add an entry in the enum with the correct
49 * shift, and if needed, increase the size type. Add a member variable
50 * and a new case in get_ref.
51 */
52
53 public:
54 Rates() = default;
55 enum class opt : uint32_t {
56 wat = (1 << 0),
57 oil = (1 << 1),
58 gas = (1 << 2),
59 polymer = (1 << 3),
60 solvent = (1 << 4),
61 energy = (1 << 5),
62 dissolved_gas = (1 << 6),
63 vaporized_oil = (1 << 7),
64 reservoir_water = (1 << 8),
65 reservoir_oil = (1 << 9),
66 reservoir_gas = (1 << 10),
67 productivity_index_water = (1 << 11),
68 productivity_index_oil = (1 << 12),
69 productivity_index_gas = (1 << 13),
70 well_potential_water = (1 << 14),
71 well_potential_oil = (1 << 15),
72 well_potential_gas = (1 << 16),
73 brine = (1 << 17),
74 alq = (1 << 18),
75 tracer = (1 << 19),
76 micp = (1 << 20),
77 vaporized_water = (1 << 21)
78 };
79
80 using enum_size = std::underlying_type< opt >::type;
81
83 inline bool has( opt ) const;
84
87 inline double get( opt m ) const;
90 inline double get( opt m, double default_value ) const;
91 inline double get( opt m, double default_value , const std::string& tracer_name ) const;
95 inline Rates& set( opt m, double value );
96 inline Rates& set( opt m, double value , const std::string& tracer_name );
97
99 inline bool flowing() const;
100
101 template <class MessageBufferType>
102 void write(MessageBufferType& buffer) const;
103 template <class MessageBufferType>
104 void read(MessageBufferType& buffer);
105
106 bool operator==(const Rates& rat2) const;
107
108 inline void init_json(Json::JsonObject& json_data) const;
109
110 template<class Serializer>
111 void serializeOp(Serializer& serializer)
112 {
113 serializer(mask);
114 serializer(wat);
115 serializer(oil);
116 serializer(gas);
117 serializer(polymer);
118 serializer(solvent);
119 serializer(energy);
120 serializer(dissolved_gas);
121 serializer(vaporized_oil);
122 serializer(reservoir_water);
123 serializer(reservoir_oil);
124 serializer(reservoir_gas);
125 serializer(productivity_index_water);
126 serializer(productivity_index_oil);
127 serializer(productivity_index_gas);
128 serializer(well_potential_water);
129 serializer(well_potential_oil);
130 serializer(well_potential_gas);
131 serializer(brine);
132 serializer(alq);
133 serializer(tracer);
134 serializer(micp);
135 serializer(vaporized_water);
136 }
137
138 static Rates serializationTestObject()
139 {
140 Rates rat1;
141 rat1.set(opt::wat, 1.0);
142 rat1.set(opt::oil, 2.0);
143 rat1.set(opt::gas, 3.0);
144 rat1.set(opt::polymer, 4.0);
145 rat1.set(opt::solvent, 5.0);
146 rat1.set(opt::energy, 6.0);
147 rat1.set(opt::dissolved_gas, 7.0);
148 rat1.set(opt::vaporized_oil, 8.0);
149 rat1.set(opt::reservoir_water, 9.0);
150 rat1.set(opt::reservoir_oil, 10.0);
151 rat1.set(opt::reservoir_gas, 11.0);
152 rat1.set(opt::productivity_index_water, 12.0);
153 rat1.set(opt::productivity_index_oil, 13.0);
154 rat1.set(opt::productivity_index_gas, 14.0);
155 rat1.set(opt::well_potential_water, 15.0);
156 rat1.set(opt::well_potential_oil, 16.0);
157 rat1.set(opt::well_potential_gas, 17.0);
158 rat1.set(opt::brine, 18.0);
159 rat1.set(opt::alq, 19.0);
160 rat1.set(opt::micp, 21.0);
161 rat1.set(opt::vaporized_water, 22.0);
162 rat1.tracer.insert({"test_tracer", 1.0});
163
164 return rat1;
165 }
166
167 private:
168 double& get_ref( opt );
169 double& get_ref( opt, const std::string& tracer_name );
170 const double& get_ref( opt ) const;
171 const double& get_ref( opt, const std::string& tracer_name ) const;
172
173 opt mask = static_cast< opt >( 0 );
174
175 double wat = 0.0;
176 double oil = 0.0;
177 double gas = 0.0;
178 double polymer = 0.0;
179 double solvent = 0.0;
180 double energy = 0.0;
181 double dissolved_gas = 0.0;
182 double vaporized_oil = 0.0;
183 double reservoir_water = 0.0;
184 double reservoir_oil = 0.0;
185 double reservoir_gas = 0.0;
186 double productivity_index_water = 0.0;
187 double productivity_index_oil = 0.0;
188 double productivity_index_gas = 0.0;
189 double well_potential_water = 0.0;
190 double well_potential_oil = 0.0;
191 double well_potential_gas = 0.0;
192 double brine = 0.0;
193 double alq = 0.0;
194 std::map<std::string, double> tracer;
195 double micp = 0.0;
196 double vaporized_water = 0.0;
197 };
198
199 struct Connection {
200 using global_index = size_t;
201 static const constexpr int restart_size = 6;
202
203 global_index index;
204 Rates rates;
205 double pressure;
206 double reservoir_rate;
207 double cell_pressure;
208 double cell_saturation_water;
209 double cell_saturation_gas;
210 double effective_Kh;
211 double trans_factor;
212
213 bool operator==(const Connection& conn2) const
214 {
215 return index == conn2.index &&
216 rates == conn2.rates &&
217 pressure == conn2.pressure &&
218 reservoir_rate == conn2.reservoir_rate &&
219 cell_pressure == conn2.cell_pressure &&
220 cell_saturation_water == conn2.cell_saturation_water &&
221 cell_saturation_gas == conn2.cell_saturation_gas &&
222 effective_Kh == conn2.effective_Kh &&
223 trans_factor == conn2.trans_factor;
224 }
225
226 template <class MessageBufferType>
227 void write(MessageBufferType& buffer) const;
228 template <class MessageBufferType>
229 void read(MessageBufferType& buffer);
230
231 inline void init_json(Json::JsonObject& json_data) const;
232
233 template<class Serializer>
234 void serializeOp(Serializer& serializer)
235 {
236 serializer(index);
237 serializer(rates);
238 serializer(pressure);
239 serializer(reservoir_rate);
240 serializer(cell_pressure);
241 serializer(cell_saturation_water);
242 serializer(cell_saturation_gas);
243 serializer(effective_Kh);
244 serializer(trans_factor);
245 }
246
247 static Connection serializationTestObject()
248 {
249 return Connection{1, Rates::serializationTestObject(),
250 2.0, 3.0, 4.0, 5.0,
251 6.0, 7.0, 8.0};
252 }
253 };
254
256 public:
257 enum class Value : std::size_t {
258 Pressure, PDrop, PDropHydrostatic, PDropAccel, PDropFriction,
259 };
260
261 double& operator[](const Value i)
262 {
263 return this->values_[this->index(i)];
264 }
265
266 double operator[](const Value i) const
267 {
268 return this->values_[this->index(i)];
269 }
270
271 bool operator==(const SegmentPressures& segpres2) const
272 {
273 return this->values_ == segpres2.values_;
274 }
275
276 template <class MessageBufferType>
277 void write(MessageBufferType& buffer) const
278 {
279 for (const auto& value : this->values_) {
280 buffer.write(value);
281 }
282 }
283
284 template <class MessageBufferType>
285 void read(MessageBufferType& buffer)
286 {
287 for (auto& value : this->values_) {
288 buffer.read(value);
289 }
290 }
291
292 template<class Serializer>
293 void serializeOp(Serializer& serializer)
294 {
295 serializer(values_);
296 }
297
298 static SegmentPressures serializationTestObject()
299 {
300 SegmentPressures spres;
301 spres[Value::Pressure] = 1.0;
302 spres[Value::PDrop] = 2.0;
303 spres[Value::PDropHydrostatic] = 3.0;
304 spres[Value::PDropAccel] = 4.0;
305 spres[Value::PDropFriction] = 5.0;
306
307 return spres;
308 }
309
310 private:
311 constexpr static std::size_t numvals = 5;
312
313 std::array<double, numvals> values_ = {0};
314
315 std::size_t index(const Value ix) const
316 {
317 return static_cast<std::size_t>(ix);
318 }
319 };
320
322 {
323 public:
324 enum class Item : std::size_t {
325 Oil, Gas, Water,
326
327 // -- Must be last enumerator --
328 NumItems,
329 };
330
331 void clear()
332 {
333 this->has_ = static_cast<unsigned char>(0);
334 this->value_.fill(0.0);
335 }
336
337 constexpr bool has(const Item p) const
338 {
339 const auto i = this->index(p);
340
341 return (i < Size) && this->hasItem(i);
342 }
343
344 bool operator==(const SegmentPhaseQuantity& vec) const
345 {
346 return (this->has_ == vec.has_)
347 && (this->value_ == vec.value_);
348 }
349
350 double get(const Item p) const
351 {
352 if (! this->has(p)) {
353 throw std::invalid_argument {
354 "Request for Unset Item Value for " + this->itemName(p)
355 };
356 }
357
358 return this->value_[ this->index(p) ];
359 }
360
361 SegmentPhaseQuantity& set(const Item p, const double value)
362 {
363 const auto i = this->index(p);
364
365 if (i >= Size) {
366 throw std::invalid_argument {
367 "Cannot Assign Item Value for Unsupported Item '"
368 + this->itemName(p) + '\''
369 };
370 }
371
372 this->has_ |= 1 << i;
373 this->value_[i] = value;
374
375 return *this;
376 }
377
378 template <class MessageBufferType>
379 void write(MessageBufferType& buffer) const
380 {
381 buffer.write(this->has_);
382
383 for (const auto& x : this->value_) {
384 buffer.write(x);
385 }
386 }
387
388 template <class MessageBufferType>
389 void read(MessageBufferType& buffer)
390 {
391 this->clear();
392 buffer.read(this->has_);
393
394 for (auto& x : this->value_) {
395 buffer.read(x);
396 }
397 }
398
399 template <class Serializer>
400 void serializeOp(Serializer& serializer)
401 {
402 serializer(this->has_);
403 serializer(this->value_);
404 }
405
406 static SegmentPhaseQuantity serializationTestObject()
407 {
408 return SegmentPhaseQuantity{}
409 .set(Item::Oil , 1.0)
410 .set(Item::Gas , 7.0)
411 .set(Item::Water, 2.9);
412 }
413
414 private:
415 enum { Size = static_cast<std::size_t>(Item::NumItems) };
416
419 unsigned char has_{};
420
422 std::array<double, Size> value_{};
423
424 constexpr std::size_t index(const Item p) const noexcept
425 {
426 return static_cast<std::size_t>(p);
427 }
428
429 bool hasItem(const std::size_t i) const
430 {
431 return (this->has_ & (1 << i)) != 0;
432 }
433
434 std::string itemName(const Item p) const
435 {
436 switch (p) {
437 case Item::Oil: return "Oil";
438 case Item::Gas: return "Gas";
439 case Item::Water: return "Water";
440
441 case Item::NumItems:
442 return "Out of bounds (NumItems)";
443 }
444
445 return "Unknown (" + std::to_string(this->index(p)) + ')';
446 }
447 };
448
449 struct Segment
450 {
451 Rates rates{};
452 SegmentPressures pressures{};
453 SegmentPhaseQuantity velocity{};
454 SegmentPhaseQuantity holdup{};
455 SegmentPhaseQuantity viscosity{};
456 std::size_t segNumber{};
457
458 bool operator==(const Segment& seg2) const
459 {
460 return (rates == seg2.rates)
461 && (pressures == seg2.pressures)
462 && (velocity == seg2.velocity)
463 && (holdup == seg2.holdup)
464 && (viscosity == seg2.viscosity)
465 && (segNumber == seg2.segNumber);
466 }
467
468 template <class MessageBufferType>
469 void write(MessageBufferType& buffer) const;
470
471 template <class MessageBufferType>
472 void read(MessageBufferType& buffer);
473
474 template <class Serializer>
475 void serializeOp(Serializer& serializer)
476 {
477 serializer(this->rates);
478 serializer(this->pressures);
479 serializer(this->velocity);
480 serializer(this->holdup);
481 serializer(this->viscosity);
482 serializer(this->segNumber);
483 }
484
485 static Segment serializationTestObject()
486 {
487 return {
488 Rates::serializationTestObject(),
489 SegmentPressures::serializationTestObject(),
490 SegmentPhaseQuantity::serializationTestObject(), // velocity
491 SegmentPhaseQuantity::serializationTestObject(), // holdup
492 SegmentPhaseQuantity::serializationTestObject(), // viscosity
493 10
494 };
495 }
496 };
497
499 bool isProducer{true};
500
501 ::Opm::WellProducerCMode prod {
502 ::Opm::WellProducerCMode::CMODE_UNDEFINED
503 };
504
505 ::Opm::WellInjectorCMode inj {
506 ::Opm::WellInjectorCMode::CMODE_UNDEFINED
507 };
508
509 bool operator==(const CurrentControl& rhs) const
510 {
511 return (this->isProducer == rhs.isProducer)
512 && ((this->isProducer && (this->prod == rhs.prod)) ||
513 (!this->isProducer && (this->inj == rhs.inj)));
514 }
515
516 void init_json(Json::JsonObject& json_data) const
517 {
518 if (this->inj == ::Opm::WellInjectorCMode::CMODE_UNDEFINED)
519 json_data.add_item("inj", "CMODE_UNDEFINED");
520 else
521 json_data.add_item("inj", ::Opm::WellInjectorCMode2String(this->inj));
522
523 if (this->prod == ::Opm::WellProducerCMode::CMODE_UNDEFINED)
524 json_data.add_item("prod", "CMODE_UNDEFINED");
525 else
526 json_data.add_item("prod", ::Opm::WellProducerCMode2String(this->prod));
527 }
528
529 template <class MessageBufferType>
530 void write(MessageBufferType& buffer) const;
531
532 template <class MessageBufferType>
533 void read(MessageBufferType& buffer);
534
535 template<class Serializer>
536 void serializeOp(Serializer& serializer)
537 {
538 serializer(isProducer);
539 serializer(prod);
540 serializer(inj);
541 }
542
543 static CurrentControl serializationTestObject()
544 {
545 return CurrentControl{false,
546 ::Opm::WellProducerCMode::BHP,
547 ::Opm::WellInjectorCMode::GRUP
548 };
549 }
550 };
551
552 struct Well {
553 Rates rates{};
554 double bhp{0.0};
555 double thp{0.0};
556 double temperature{0.0};
557 int control{0};
558
559 ::Opm::WellStatus dynamicStatus { Opm::WellStatus::OPEN };
560
561 std::vector< Connection > connections{};
562 std::unordered_map<std::size_t, Segment> segments{};
563 CurrentControl current_control{};
564 GuideRateValue guide_rates{};
565
566 inline bool flowing() const noexcept;
567 template <class MessageBufferType>
568 void write(MessageBufferType& buffer) const;
569 template <class MessageBufferType>
570 void read(MessageBufferType& buffer);
571
572 inline void init_json(Json::JsonObject& json_data) const;
573
574 const Connection* find_connection(Connection::global_index connection_grid_index) const {
575 const auto connection = std::find_if( this->connections.begin() ,
576 this->connections.end() ,
577 [=]( const Connection& c ) {
578 return c.index == connection_grid_index; });
579
580 if( connection == this->connections.end() )
581 return nullptr;
582
583 return &*connection;
584 }
585
586 Connection* find_connection(Connection::global_index connection_grid_index) {
587 auto connection = std::find_if( this->connections.begin() ,
588 this->connections.end() ,
589 [=]( const Connection& c ) {
590 return c.index == connection_grid_index; });
591
592 if( connection == this->connections.end() )
593 return nullptr;
594
595 return &*connection;
596 }
597
598 bool operator==(const Well& well2) const
599 {
600 return rates == well2.rates &&
601 bhp == well2.bhp &&
602 thp == well2.thp &&
603 temperature == well2.temperature &&
604 control == well2.control &&
605 dynamicStatus == well2.dynamicStatus &&
606 connections == well2.connections &&
607 segments == well2.segments &&
608 current_control == well2.current_control &&
609 guide_rates == well2.guide_rates;
610 }
611
612 template<class Serializer>
613 void serializeOp(Serializer& serializer)
614 {
615 serializer(rates);
616 serializer(bhp);
617 serializer(thp);
618 serializer(temperature);
619 serializer(control);
620 serializer(dynamicStatus);
621 serializer(connections);
622 serializer(segments);
623 serializer(current_control);
624 serializer(guide_rates);
625 }
626
627 static Well serializationTestObject()
628 {
629 return Well{Rates::serializationTestObject(),
630 1.0,
631 2.0,
632 3.0,
633 4,
634 ::Opm::WellStatus::SHUT,
635 {Connection::serializationTestObject()},
636 {{0, Segment::serializationTestObject()}},
637 CurrentControl::serializationTestObject(),
638 GuideRateValue::serializationTestObject()
639 };
640 }
641 };
642
643
644 class Wells: public std::map<std::string , Well> {
645 public:
646
647 double get(const std::string& well_name , Rates::opt m) const {
648 const auto& well = this->find( well_name );
649 if( well == this->end() ) return 0.0;
650
651 return well->second.rates.get( m, 0.0 );
652 }
653
654 double get(const std::string& well_name , Rates::opt m, const std::string& tracer_name) const {
655 const auto& well = this->find( well_name );
656 if( well == this->end() ) return 0.0;
657
658 return well->second.rates.get( m, 0.0, tracer_name);
659 }
660
661 double get(const std::string& well_name , Connection::global_index connection_grid_index, Rates::opt m) const {
662 const auto& witr = this->find( well_name );
663 if( witr == this->end() ) return 0.0;
664
665 const auto& well = witr->second;
666 const auto& connection = std::find_if( well.connections.begin() ,
667 well.connections.end() ,
668 [=]( const Connection& c ) {
669 return c.index == connection_grid_index; });
670
671 if( connection == well.connections.end() )
672 return 0.0;
673
674 return connection->rates.get( m, 0.0 );
675 }
676
677 template <class MessageBufferType>
678 void write(MessageBufferType& buffer) const {
679 unsigned int size = this->size();
680 buffer.write(size);
681 for (const auto& witr : *this) {
682 const std::string& name = witr.first;
683 buffer.write(name);
684 const Well& well = witr.second;
685 well.write(buffer);
686 }
687 }
688
689 template <class MessageBufferType>
690 void read(MessageBufferType& buffer) {
691 unsigned int size;
692 buffer.read(size);
693 for (size_t i = 0; i < size; ++i) {
694 std::string name;
695 buffer.read(name);
696 Well well;
697 well.read(buffer);
698 this->emplace(name, well);
699 }
700 }
701
702 void init_json(Json::JsonObject& json_data) const {
703 for (const auto& [wname, well] : *this) {
704 auto json_well = json_data.add_object(wname);
705 well.init_json(json_well);
706 }
707 }
708
709
710 Json::JsonObject json() const {
711 Json::JsonObject json_data;
712 this->init_json(json_data);
713 return json_data;
714 }
715
716 template<class Serializer>
717 void serializeOp(Serializer& serializer)
718 {
719 serializer(static_cast<std::map<std::string,Well>&>(*this));
720 }
721
722 static Wells serializationTestObject()
723 {
724 Wells w;
725 w.insert({"test_well", Well::serializationTestObject()});
726
727 return w;
728 }
729 };
730
731
732 /* IMPLEMENTATIONS */
733
734 inline bool Rates::has( opt m ) const {
735 const auto mand = static_cast< enum_size >( this->mask )
736 & static_cast< enum_size >( m );
737
738 return static_cast< opt >( mand ) == m;
739 }
740
741 inline double Rates::get( opt m ) const {
742 if( !this->has( m ) )
743 throw std::invalid_argument( "Uninitialized value." );
744
745 return this->get_ref( m );
746 }
747
748 inline double Rates::get( opt m, double default_value ) const {
749 if( !this->has( m ) ) return default_value;
750
751 return this->get_ref( m );
752 }
753
754 inline double Rates::get( opt m, double default_value, const std::string& tracer_name) const {
755 if( !this->has( m ) ) return default_value;
756
757 if( m == opt::tracer && this->tracer.find(tracer_name) == this->tracer.end()) return default_value;
758
759 return this->get_ref( m, tracer_name);
760 }
761
762 inline Rates& Rates::set( opt m, double value ) {
763 this->get_ref( m ) = value;
764
765 /* mask |= m */
766 this->mask = static_cast< opt >(
767 static_cast< enum_size >( this->mask ) |
768 static_cast< enum_size >( m )
769 );
770
771 return *this;
772 }
773
774 inline Rates& Rates::set( opt m, double value , const std::string& tracer_name ) {
775 this->get_ref( m , tracer_name) = value;
776
777 /* mask |= m */
778 this->mask = static_cast< opt >(
779 static_cast< enum_size >( this->mask ) |
780 static_cast< enum_size >( m )
781 );
782
783 return *this;
784 }
785
786 inline bool Rates::operator==(const Rates& rate) const
787 {
788 return mask == rate.mask &&
789 wat == rate.wat &&
790 oil == rate.oil &&
791 gas == rate.gas &&
792 polymer == rate.polymer &&
793 solvent == rate.solvent &&
794 energy == rate.energy &&
795 dissolved_gas == rate.dissolved_gas &&
796 vaporized_oil == rate.vaporized_oil &&
797 reservoir_water == rate.reservoir_water &&
798 reservoir_oil == rate.reservoir_oil &&
799 reservoir_gas == rate.reservoir_gas &&
800 productivity_index_water == rate.productivity_index_water &&
801 productivity_index_gas == rate.productivity_index_gas &&
802 productivity_index_oil == rate.productivity_index_oil &&
803 well_potential_water == rate.well_potential_water &&
804 well_potential_oil == rate.well_potential_oil &&
805 well_potential_gas == rate.well_potential_gas &&
806 brine == rate.brine &&
807 alq == rate.alq &&
808 tracer == rate.tracer &&
809 micp == rate.micp &&
810 vaporized_water == rate.vaporized_water;
811 }
812
813
814 /*
815 * To avoid error-prone and repetitve work when extending rates with new
816 * values, the get+set methods use this helper get_ref to determine what
817 * member to manipulate. To add a new option, just add another case
818 * corresponding to the enum entry in Rates to this function.
819 *
820 * This is an implementation detail and understanding this has no
821 * significant impact on correct use of the class.
822 */
823 inline const double& Rates::get_ref( opt m ) const {
824 switch( m ) {
825 case opt::wat: return this->wat;
826 case opt::oil: return this->oil;
827 case opt::gas: return this->gas;
828 case opt::polymer: return this->polymer;
829 case opt::solvent: return this->solvent;
830 case opt::energy: return this->energy;
831 case opt::dissolved_gas: return this->dissolved_gas;
832 case opt::vaporized_oil: return this->vaporized_oil;
833 case opt::reservoir_water: return this->reservoir_water;
834 case opt::reservoir_oil: return this->reservoir_oil;
835 case opt::reservoir_gas: return this->reservoir_gas;
836 case opt::productivity_index_water: return this->productivity_index_water;
837 case opt::productivity_index_oil: return this->productivity_index_oil;
838 case opt::productivity_index_gas: return this->productivity_index_gas;
839 case opt::well_potential_water: return this->well_potential_water;
840 case opt::well_potential_oil: return this->well_potential_oil;
841 case opt::well_potential_gas: return this->well_potential_gas;
842 case opt::brine: return this->brine;
843 case opt::alq: return this->alq;
844 case opt::tracer: /* Should _not_ be called with tracer argument */
845 break;
846 case opt::micp: return this->micp;
847 case opt::vaporized_water: return this->vaporized_water;
848 }
849
850 throw std::invalid_argument(
851 "Unknown value type '"
852 + std::to_string( static_cast< enum_size >( m ) )
853 + "'" );
854
855 }
856
857 inline const double& Rates::get_ref( opt m, const std::string& tracer_name ) const {
858 if (m != opt::tracer)
859 throw std::logic_error("Logic error - should be called with tracer argument");
860
861 return this->tracer.at(tracer_name);
862 }
863
864 inline double& Rates::get_ref( opt m ) {
865 return const_cast< double& >(
866 static_cast< const Rates* >( this )->get_ref( m )
867 );
868 }
869
870 inline double& Rates::get_ref( opt m, const std::string& tracer_name ) {
871 if (m == opt::tracer) this->tracer.emplace(tracer_name, 0.0);
872 return this->tracer.at(tracer_name);
873 }
874
875 void Rates::init_json(Json::JsonObject& json_data) const {
876
877 if (this->has(opt::wat))
878 json_data.add_item("wat", this->get(opt::wat));
879
880 if (this->has(opt::oil))
881 json_data.add_item("oil", this->get(opt::oil));
882
883 if (this->has(opt::gas))
884 json_data.add_item("gas", this->get(opt::gas));
885
886 }
887
888 bool inline Rates::flowing() const {
889 return ((this->wat != 0) ||
890 (this->oil != 0) ||
891 (this->gas != 0));
892 }
893
894 inline bool Well::flowing() const noexcept {
895 return this->rates.flowing();
896 }
897
898 template <class MessageBufferType>
899 void Rates::write(MessageBufferType& buffer) const {
900 buffer.write(this->mask);
901 buffer.write(this->wat);
902 buffer.write(this->oil);
903 buffer.write(this->gas);
904 buffer.write(this->polymer);
905 buffer.write(this->solvent);
906 buffer.write(this->energy);
907 buffer.write(this->dissolved_gas);
908 buffer.write(this->vaporized_oil);
909 buffer.write(this->reservoir_water);
910 buffer.write(this->reservoir_oil);
911 buffer.write(this->reservoir_gas);
912 buffer.write(this->productivity_index_water);
913 buffer.write(this->productivity_index_oil);
914 buffer.write(this->productivity_index_gas);
915 buffer.write(this->well_potential_water);
916 buffer.write(this->well_potential_oil);
917 buffer.write(this->well_potential_gas);
918 buffer.write(this->brine);
919 buffer.write(this->alq);
920 //tracer:
921 unsigned int size = this->tracer.size();
922 buffer.write(size);
923 for (const auto& [name, rate] : this->tracer) {
924 buffer.write(name);
925 buffer.write(rate);
926 }
927 buffer.write(this->micp);
928 buffer.write(this->vaporized_water);
929 }
930
931 template <class MessageBufferType>
932 void Connection::write(MessageBufferType& buffer) const {
933 buffer.write(this->index);
934 this->rates.write(buffer);
935 buffer.write(this->pressure);
936 buffer.write(this->reservoir_rate);
937 buffer.write(this->cell_pressure);
938 buffer.write(this->cell_saturation_water);
939 buffer.write(this->cell_saturation_gas);
940 buffer.write(this->effective_Kh);
941 buffer.write(this->trans_factor);
942 }
943
944 void Connection::init_json(Json::JsonObject& json_data) const {
945 auto json_rates = json_data.add_object("rates");
946 this->rates.init_json(json_rates);
947
948 json_data.add_item("global_index", static_cast<int>(this->index));
949 json_data.add_item("pressure", this->pressure);
950 json_data.add_item("reservoir_rate", this->reservoir_rate);
951 json_data.add_item("cell_pressure", this->cell_pressure);
952 json_data.add_item("swat", this->cell_saturation_water);
953 json_data.add_item("sgas", this->cell_saturation_gas);
954 json_data.add_item("Kh", this->effective_Kh);
955 json_data.add_item("trans_factor", this->trans_factor);
956 }
957
958 template <class MessageBufferType>
959 void Segment::write(MessageBufferType& buffer) const
960 {
961 buffer.write(this->segNumber);
962 this->rates.write(buffer);
963 this->pressures.write(buffer);
964 this->velocity.write(buffer);
965 this->holdup.write(buffer);
966 this->viscosity.write(buffer);
967 }
968
969 template <class MessageBufferType>
970 void CurrentControl::write(MessageBufferType& buffer) const
971 {
972 buffer.write(this->isProducer);
973 if (this->isProducer) {
974 buffer.write(this->prod);
975 }
976 else {
977 buffer.write(this->inj);
978 }
979 }
980
981 template <class MessageBufferType>
982 void Well::write(MessageBufferType& buffer) const {
983 this->rates.write(buffer);
984 buffer.write(this->bhp);
985 buffer.write(this->thp);
986 buffer.write(this->temperature);
987 buffer.write(this->control);
988
989 {
990 const auto status = ::Opm::WellStatus2String(this->dynamicStatus);
991 buffer.write(status);
992 }
993
994 unsigned int size = this->connections.size();
995 buffer.write(size);
996 for (const Connection& comp : this->connections)
997 comp.write(buffer);
998
999 {
1000 const auto nSeg =
1001 static_cast<unsigned int>(this->segments.size());
1002 buffer.write(nSeg);
1003
1004 for (const auto& seg : this->segments) {
1005 seg.second.write(buffer);
1006 }
1007 }
1008
1009 this->current_control.write(buffer);
1010 this->guide_rates.write(buffer);
1011 }
1012
1013 template <class MessageBufferType>
1014 void Rates::read(MessageBufferType& buffer) {
1015 buffer.read(this->mask);
1016 buffer.read(this->wat);
1017 buffer.read(this->oil);
1018 buffer.read(this->gas);
1019 buffer.read(this->polymer);
1020 buffer.read(this->solvent);
1021 buffer.read(this->energy);
1022 buffer.read(this->dissolved_gas);
1023 buffer.read(this->vaporized_oil);
1024 buffer.read(this->reservoir_water);
1025 buffer.read(this->reservoir_oil);
1026 buffer.read(this->reservoir_gas);
1027 buffer.read(this->productivity_index_water);
1028 buffer.read(this->productivity_index_oil);
1029 buffer.read(this->productivity_index_gas);
1030 buffer.read(this->well_potential_water);
1031 buffer.read(this->well_potential_oil);
1032 buffer.read(this->well_potential_gas);
1033 buffer.read(this->brine);
1034 buffer.read(this->alq);
1035 //tracer:
1036 unsigned int size;
1037 buffer.read(size);
1038 for (size_t i = 0; i < size; ++i) {
1039 std::string tracer_name;
1040 buffer.read(tracer_name);
1041 double tracer_rate;
1042 buffer.read(tracer_rate);
1043 this->tracer.emplace(tracer_name, tracer_rate);
1044 }
1045 buffer.read(this->micp);
1046 buffer.read(this->vaporized_water);
1047 }
1048
1049 template <class MessageBufferType>
1050 void Connection::read(MessageBufferType& buffer) {
1051 buffer.read(this->index);
1052 this->rates.read(buffer);
1053 buffer.read(this->pressure);
1054 buffer.read(this->reservoir_rate);
1055 buffer.read(this->cell_pressure);
1056 buffer.read(this->cell_saturation_water);
1057 buffer.read(this->cell_saturation_gas);
1058 buffer.read(this->effective_Kh);
1059 buffer.read(this->trans_factor);
1060 }
1061
1062 template <class MessageBufferType>
1063 void Segment::read(MessageBufferType& buffer)
1064 {
1065 buffer.read(this->segNumber);
1066 this->rates.read(buffer);
1067 this->pressures.read(buffer);
1068 this->velocity.read(buffer);
1069 this->holdup.read(buffer);
1070 this->viscosity.read(buffer);
1071 }
1072
1073 template <class MessageBufferType>
1074 void CurrentControl::read(MessageBufferType& buffer)
1075 {
1076 buffer.read(this->isProducer);
1077 if (this->isProducer) {
1078 buffer.read(this->prod);
1079 }
1080 else {
1081 buffer.read(this->inj);
1082 }
1083 }
1084
1085 template <class MessageBufferType>
1086 void Well::read(MessageBufferType& buffer) {
1087 this->rates.read(buffer);
1088 buffer.read(this->bhp);
1089 buffer.read(this->thp);
1090 buffer.read(this->temperature);
1091 buffer.read(this->control);
1092
1093 {
1094 auto status = std::string{};
1095 buffer.read(status);
1096 this->dynamicStatus = ::Opm::WellStatusFromString(status);
1097 }
1098
1099 // Connection information
1100 unsigned int size = 0.0; //this->connections.size();
1101 buffer.read(size);
1102 this->connections.resize(size);
1103 for (size_t i = 0; i < size; ++i)
1104 {
1105 auto& comp = this->connections[ i ];
1106 comp.read(buffer);
1107 }
1108
1109 // Segment information (if applicable)
1110 const auto nSeg = [&buffer]() -> unsigned int
1111 {
1112 auto n = 0u;
1113 buffer.read(n);
1114
1115 return n;
1116 }();
1117
1118 for (auto segID = 0*nSeg; segID < nSeg; ++segID) {
1119 auto seg = Segment{};
1120 seg.read(buffer);
1121
1122 const auto segNumber = seg.segNumber;
1123 this->segments.emplace(segNumber, std::move(seg));
1124 }
1125
1126 this->current_control.read(buffer);
1127 this->guide_rates.read(buffer);
1128 }
1129
1130 void Well::init_json(Json::JsonObject& json_data) const {
1131 auto json_connections = json_data.add_array("connections");
1132 for (const auto& conn : this->connections) {
1133 auto json_conn = json_connections.add_object();
1134 conn.init_json(json_conn);
1135 }
1136 auto json_rates = json_data.add_object("rates");
1137 this->rates.init_json(json_rates);
1138
1139 json_data.add_item("bhp", this->bhp);
1140 json_data.add_item("thp", this->thp);
1141 json_data.add_item("temperature", this->temperature);
1142 json_data.add_item("status", ::Opm::WellStatus2String(this->dynamicStatus));
1143
1144 auto json_control = json_data.add_object("control");
1145 this->current_control.init_json(json_control);
1146
1147 auto json_guiderate = json_data.add_object("guiderate");
1148 this->guide_rates.init_json(json_guiderate);
1149 }
1150
1151}} // Opm::data
1152
1153#endif //OPM_OUTPUT_WELLS_HPP
Definition: JsonObject.hpp:32
Class for (de-)serializing.
Definition: Serializer.hpp:84
Definition: GuideRateValue.hpp:32
Definition: Wells.hpp:43
bool flowing() const
Returns true if any of the rates oil, gas, water is nonzero.
Definition: Wells.hpp:888
double get(opt m) const
Read the value indicated by m.
Definition: Wells.hpp:741
Rates & set(opt m, double value)
Set the value specified by m.
Definition: Wells.hpp:762
bool has(opt) const
Query if a value is set.
Definition: Wells.hpp:734
Definition: Wells.hpp:322
Definition: Wells.hpp:255
Definition: Wells.hpp:644
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Definition: Wells.hpp:199
Definition: Wells.hpp:498
Definition: Wells.hpp:450
Definition: Wells.hpp:552