My Project
Loading...
Searching...
No Matches
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
200 double rate;
201 double total;
202 double skin_factor;
203 double thickness;
204 double perm;
205 double poro;
206 double radius;
207 double area_of_flow;
208
209 template<class Serializer>
210 void serializeOp(Serializer& serializer) {
211 serializer(rate);
212 serializer(total);
213 serializer(skin_factor);
214 serializer(thickness);
215 serializer(perm);
216 serializer(poro);
217 serializer(radius);
218 serializer(area_of_flow);
219 }
220
221 bool operator==(const ConnectionFiltrate& filtrate) const
222 {
223 return this->rate == filtrate.rate &&
224 this->total == filtrate.total &&
225 this->skin_factor == filtrate.skin_factor &&
226 this->thickness == filtrate.thickness &&
227 this->perm == filtrate.perm &&
228 this->poro == filtrate.poro &&
229 this->radius == filtrate.radius &&
230 this->area_of_flow == filtrate.area_of_flow;
231 }
232
233 static ConnectionFiltrate serializationTestObject()
234 {
235 return {0.8, 100., -1., 2., 1.e-9,
236 0.3, 0.05, 0.8};
237 }
238
239 template <class MessageBufferType>
240 void write(MessageBufferType& buffer) const;
241
242 template <class MessageBufferType>
243 void read(MessageBufferType& buffer);
244 };
245
246 struct Connection {
247 using global_index = size_t;
248 static const constexpr int restart_size = 6;
249
250 global_index index;
251 Rates rates;
252 double pressure;
253 double reservoir_rate;
254 double cell_pressure;
255 double cell_saturation_water;
256 double cell_saturation_gas;
257 double effective_Kh;
258 double trans_factor;
259
260 ConnectionFiltrate filtrate;
261
262 bool operator==(const Connection& conn2) const
263 {
264 return index == conn2.index &&
265 rates == conn2.rates &&
266 pressure == conn2.pressure &&
267 reservoir_rate == conn2.reservoir_rate &&
268 cell_pressure == conn2.cell_pressure &&
269 cell_saturation_water == conn2.cell_saturation_water &&
270 cell_saturation_gas == conn2.cell_saturation_gas &&
271 effective_Kh == conn2.effective_Kh &&
272 trans_factor == conn2.trans_factor &&
273 filtrate == conn2.filtrate;
274 }
275
276 template <class MessageBufferType>
277 void write(MessageBufferType& buffer) const;
278 template <class MessageBufferType>
279 void read(MessageBufferType& buffer);
280
281 inline void init_json(Json::JsonObject& json_data) const;
282
283 template<class Serializer>
284 void serializeOp(Serializer& serializer)
285 {
286 serializer(index);
287 serializer(rates);
288 serializer(pressure);
289 serializer(reservoir_rate);
290 serializer(cell_pressure);
291 serializer(cell_saturation_water);
292 serializer(cell_saturation_gas);
293 serializer(effective_Kh);
294 serializer(trans_factor);
295 serializer(filtrate);
296 }
297
298 static Connection serializationTestObject()
299 {
300 return Connection{1, Rates::serializationTestObject(),
301 2.0, 3.0, 4.0, 5.0,
302 6.0, 7.0, 8.0,
303 ConnectionFiltrate::serializationTestObject() };
304 }
305 };
306
308 public:
309 enum class Value : std::size_t {
310 Pressure, PDrop, PDropHydrostatic, PDropAccel, PDropFriction,
311 };
312
313 double& operator[](const Value i)
314 {
315 return this->values_[this->index(i)];
316 }
317
318 double operator[](const Value i) const
319 {
320 return this->values_[this->index(i)];
321 }
322
323 bool operator==(const SegmentPressures& segpres2) const
324 {
325 return this->values_ == segpres2.values_;
326 }
327
328 template <class MessageBufferType>
329 void write(MessageBufferType& buffer) const
330 {
331 for (const auto& value : this->values_) {
332 buffer.write(value);
333 }
334 }
335
336 template <class MessageBufferType>
337 void read(MessageBufferType& buffer)
338 {
339 for (auto& value : this->values_) {
340 buffer.read(value);
341 }
342 }
343
344 template<class Serializer>
345 void serializeOp(Serializer& serializer)
346 {
347 serializer(values_);
348 }
349
350 static SegmentPressures serializationTestObject()
351 {
352 SegmentPressures spres;
353 spres[Value::Pressure] = 1.0;
354 spres[Value::PDrop] = 2.0;
355 spres[Value::PDropHydrostatic] = 3.0;
356 spres[Value::PDropAccel] = 4.0;
357 spres[Value::PDropFriction] = 5.0;
358
359 return spres;
360 }
361
362 private:
363 constexpr static std::size_t numvals = 5;
364
365 std::array<double, numvals> values_ = {0};
366
367 std::size_t index(const Value ix) const
368 {
369 return static_cast<std::size_t>(ix);
370 }
371 };
372
373 template <typename Items>
375 {
376 public:
377 using Item = typename Items::Item;
378
379 void clear()
380 {
381 this->has_ = static_cast<unsigned char>(0);
382 this->value_.fill(0.0);
383 }
384
385 constexpr bool has(const Item p) const
386 {
387 const auto i = this->index(p);
388
389 return (i < Size) && this->hasItem(i);
390 }
391
392 bool operator==(const SegmentQuantity& vec) const
393 {
394 return (this->has_ == vec.has_)
395 && (this->value_ == vec.value_);
396 }
397
398 double get(const Item p) const
399 {
400 if (! this->has(p)) {
401 throw std::invalid_argument {
402 "Request for Unset Item Value for " + Items::itemName(p)
403 };
404 }
405
406 return this->value_[ this->index(p) ];
407 }
408
409 SegmentQuantity& set(const Item p, const double value)
410 {
411 const auto i = this->index(p);
412
413 if (i >= Size) {
414 throw std::invalid_argument {
415 "Cannot Assign Item Value for Unsupported Item '"
416 + Items::itemName(p) + '\''
417 };
418 }
419
420 this->has_ |= 1 << i;
421 this->value_[i] = value;
422
423 return *this;
424 }
425
426 template <class MessageBufferType>
427 void write(MessageBufferType& buffer) const
428 {
429 buffer.write(this->has_);
430
431 for (const auto& x : this->value_) {
432 buffer.write(x);
433 }
434 }
435
436 template <class MessageBufferType>
437 void read(MessageBufferType& buffer)
438 {
439 this->clear();
440 buffer.read(this->has_);
441
442 for (auto& x : this->value_) {
443 buffer.read(x);
444 }
445 }
446
447 template <class Serializer>
448 void serializeOp(Serializer& serializer)
449 {
450 serializer(this->has_);
451 serializer(this->value_);
452 }
453
454 static SegmentQuantity serializationTestObject()
455 {
456 auto quant = SegmentQuantity{};
457
458 for (const auto& [item, value] : Items::serializationTestItems()) {
459 quant.set(item, value);
460 }
461
462 return quant;
463 }
464
465 private:
466 enum { Size = static_cast<std::size_t>(Item::NumItems) };
467
470 unsigned char has_{};
471
473 std::array<double, Size> value_{};
474
475 constexpr std::size_t index(const Item p) const noexcept
476 {
477 return static_cast<std::size_t>(p);
478 }
479
480 bool hasItem(const std::size_t i) const
481 {
482 return (this->has_ & (1 << i)) != 0;
483 }
484 };
485
487 {
488 enum class Item {
489 Oil, Gas, Water,
490
491 // -- Must be last enumerator --
492 NumItems,
493 };
494
495 static std::string itemName(const Item p)
496 {
497 switch (p) {
498 case Item::Oil: return "Oil";
499 case Item::Gas: return "Gas";
500 case Item::Water: return "Water";
501
502 case Item::NumItems:
503 return "Out of bounds (NumItems)";
504 }
505
506 return "Unknown (" + std::to_string(static_cast<int>(p)) + ')';
507 }
508
509 static auto serializationTestItems()
510 {
511 return std::vector {
512 std::pair { Item::Oil , 1.0 },
513 std::pair { Item::Gas , 7.0 },
514 std::pair { Item::Water, 2.9 },
515 };
516 }
517 };
518
520 {
521 enum class Item {
522 Oil, Gas, Water, Mixture, MixtureWithExponents,
523
524 // -- Must be last enumerator --
525 NumItems,
526 };
527
528 static std::string itemName(const Item p)
529 {
530 switch (p) {
531 case Item::Oil: return "Oil";
532 case Item::Gas: return "Gas";
533 case Item::Water: return "Water";
534 case Item::Mixture: return "Mixture";
535 case Item::MixtureWithExponents: return "MixtureWithExponents";
536
537 case Item::NumItems:
538 return "Out of bounds (NumItems)";
539 }
540
541 return "Unknown (" + std::to_string(static_cast<int>(p)) + ')';
542 }
543
544 static auto serializationTestItems()
545 {
546 return std::vector {
547 std::pair { Item::Oil , 876.54 },
548 std::pair { Item::Gas , 321.09 },
549 std::pair { Item::Water , 987.65 },
550 std::pair { Item::Mixture , 975.31 },
551 std::pair { Item::MixtureWithExponents, 765.43 },
552 };
553 }
554 };
555
558
559 struct Segment
560 {
561 Rates rates{};
562 SegmentPressures pressures{};
563 SegmentPhaseQuantity velocity{};
564 SegmentPhaseQuantity holdup{};
565 SegmentPhaseQuantity viscosity{};
566 SegmentPhaseDensity density{};
567 std::size_t segNumber{};
568
569 bool operator==(const Segment& seg2) const
570 {
571 return (rates == seg2.rates)
572 && (pressures == seg2.pressures)
573 && (velocity == seg2.velocity)
574 && (holdup == seg2.holdup)
575 && (viscosity == seg2.viscosity)
576 && (density == seg2.density)
577 && (segNumber == seg2.segNumber);
578 }
579
580 template <class MessageBufferType>
581 void write(MessageBufferType& buffer) const;
582
583 template <class MessageBufferType>
584 void read(MessageBufferType& buffer);
585
586 template <class Serializer>
587 void serializeOp(Serializer& serializer)
588 {
589 serializer(this->rates);
590 serializer(this->pressures);
591 serializer(this->velocity);
592 serializer(this->holdup);
593 serializer(this->viscosity);
594 serializer(this->density);
595 serializer(this->segNumber);
596 }
597
598 static Segment serializationTestObject()
599 {
600 return {
601 Rates::serializationTestObject(),
602 SegmentPressures::serializationTestObject(),
603 SegmentPhaseQuantity::serializationTestObject(), // velocity
604 SegmentPhaseQuantity::serializationTestObject(), // holdup
605 SegmentPhaseQuantity::serializationTestObject(), // viscosity
606 SegmentPhaseDensity::serializationTestObject(), // density
607 10
608 };
609 }
610 };
611
613 bool isProducer{true};
614
615 ::Opm::WellProducerCMode prod {
616 ::Opm::WellProducerCMode::CMODE_UNDEFINED
617 };
618
619 ::Opm::WellInjectorCMode inj {
620 ::Opm::WellInjectorCMode::CMODE_UNDEFINED
621 };
622
623 bool operator==(const CurrentControl& rhs) const
624 {
625 return (this->isProducer == rhs.isProducer)
626 && ((this->isProducer && (this->prod == rhs.prod)) ||
627 (!this->isProducer && (this->inj == rhs.inj)));
628 }
629
630 void init_json(Json::JsonObject& json_data) const
631 {
632 if (this->inj == ::Opm::WellInjectorCMode::CMODE_UNDEFINED)
633 json_data.add_item("inj", "CMODE_UNDEFINED");
634 else
635 json_data.add_item("inj", ::Opm::WellInjectorCMode2String(this->inj));
636
637 if (this->prod == ::Opm::WellProducerCMode::CMODE_UNDEFINED)
638 json_data.add_item("prod", "CMODE_UNDEFINED");
639 else
640 json_data.add_item("prod", ::Opm::WellProducerCMode2String(this->prod));
641 }
642
643 template <class MessageBufferType>
644 void write(MessageBufferType& buffer) const;
645
646 template <class MessageBufferType>
647 void read(MessageBufferType& buffer);
648
649 template<class Serializer>
650 void serializeOp(Serializer& serializer)
651 {
652 serializer(isProducer);
653 serializer(prod);
654 serializer(inj);
655 }
656
657 static CurrentControl serializationTestObject()
658 {
659 return CurrentControl{false,
660 ::Opm::WellProducerCMode::BHP,
661 ::Opm::WellInjectorCMode::GRUP
662 };
663 }
664 };
665
667 {
668 public:
669 enum class Quantity { WBP, WBP4, WBP5, WBP9 };
670
671 double& operator[](const Quantity q)
672 {
673 return this->wbp_[static_cast<std::size_t>(q)];
674 }
675
676 double operator[](const Quantity q) const
677 {
678 return this->wbp_[static_cast<std::size_t>(q)];
679 }
680
681 bool operator==(const WellBlockAvgPress& that) const
682 {
683 return this->wbp_ == that.wbp_;
684 }
685
686 template <class MessageBufferType>
687 void write(MessageBufferType& buffer) const;
688
689 template <class MessageBufferType>
690 void read(MessageBufferType& buffer);
691
692 template <class Serializer>
693 void serializeOp(Serializer& serializer)
694 {
695 serializer(this->wbp_);
696 }
697
698 static WellBlockAvgPress serializationTestObject()
699 {
700 auto wbp = WellBlockAvgPress{};
701
702 wbp[Quantity::WBP] = 17.29;
703 wbp[Quantity::WBP4] = 2.718;
704 wbp[Quantity::WBP5] = 3.1415;
705 wbp[Quantity::WBP9] = 1.618;
706
707 return wbp;
708 }
709
710 private:
711 static constexpr auto NumQuantities =
712 static_cast<std::size_t>(Quantity::WBP9) + 1;
713
714 std::array<double, NumQuantities> wbp_{};
715 };
716
718 double rate{0.};
719 double total{0.};
720 double concentration{0.};
721
722 template<class Serializer>
723 void serializeOp(Serializer& serializer) {
724 serializer(rate);
725 serializer(total);
726 serializer(concentration);
727 }
728
729 bool operator==(const WellFiltrate& filtrate) const {
730 return this->rate == filtrate.rate
731 && this->total == filtrate.total
732 && this->concentration == filtrate.concentration;
733 }
734
735 static WellFiltrate serializationTestObject() {
736 WellFiltrate res;
737 res.rate = 1.;
738 res.total = 10.;
739 res.concentration = 0.;
740 return res;
741 }
742
743 template <class MessageBufferType>
744 void write(MessageBufferType& buffer) const;
745
746 template <class MessageBufferType>
747 void read(MessageBufferType& buffer);
748 };
749
750 struct Well {
751 Rates rates{};
752 double bhp{0.0};
753 double thp{0.0};
754 double temperature{0.0};
755 int control{0};
756
757 WellFiltrate filtrate;
758
759 ::Opm::WellStatus dynamicStatus { Opm::WellStatus::OPEN };
760
761 std::vector< Connection > connections{};
762 std::unordered_map<std::size_t, Segment> segments{};
763 CurrentControl current_control{};
764 GuideRateValue guide_rates{};
765
766 inline bool flowing() const noexcept;
767 template <class MessageBufferType>
768 void write(MessageBufferType& buffer) const;
769 template <class MessageBufferType>
770 void read(MessageBufferType& buffer);
771
772 inline void init_json(Json::JsonObject& json_data) const;
773
774 const Connection* find_connection(Connection::global_index connection_grid_index) const {
775 const auto connection = std::find_if( this->connections.begin() ,
776 this->connections.end() ,
777 [=]( const Connection& c ) {
778 return c.index == connection_grid_index; });
779
780 if( connection == this->connections.end() )
781 return nullptr;
782
783 return &*connection;
784 }
785
786 Connection* find_connection(Connection::global_index connection_grid_index) {
787 auto connection = std::find_if( this->connections.begin() ,
788 this->connections.end() ,
789 [=]( const Connection& c ) {
790 return c.index == connection_grid_index; });
791
792 if( connection == this->connections.end() )
793 return nullptr;
794
795 return &*connection;
796 }
797
798 bool operator==(const Well& well2) const
799 {
800 return (this->rates == well2.rates)
801 && (this->bhp == well2.bhp)
802 && (this->thp == well2.thp)
803 && (this->temperature == well2.temperature)
804 && (this->filtrate == well2.filtrate)
805 && (this->control == well2.control)
806 && (this->dynamicStatus == well2.dynamicStatus)
807 && (this->connections == well2.connections)
808 && (this->segments == well2.segments)
809 && (this->current_control == well2.current_control)
810 && (this->guide_rates == well2.guide_rates)
811 ;
812 }
813
814 template<class Serializer>
815 void serializeOp(Serializer& serializer)
816 {
817 serializer(rates);
818 serializer(bhp);
819 serializer(thp);
820 serializer(temperature);
821 serializer(control);
822 serializer(filtrate);
823 serializer(dynamicStatus);
824 serializer(connections);
825 serializer(segments);
826 serializer(current_control);
827 serializer(guide_rates);
828 }
829
830 static Well serializationTestObject()
831 {
832 return Well {
833 Rates::serializationTestObject(),
834 1.0,
835 2.0,
836 3.0,
837 4,
838 WellFiltrate::serializationTestObject(),
839 ::Opm::WellStatus::SHUT,
840 {Connection::serializationTestObject()},
841 {{0, Segment::serializationTestObject()}},
842 CurrentControl::serializationTestObject(),
843 GuideRateValue::serializationTestObject()
844 };
845 }
846 };
847
848 class Wells: public std::map<std::string , Well> {
849 public:
850
851 double get(const std::string& well_name , Rates::opt m) const {
852 const auto& well = this->find( well_name );
853 if( well == this->end() ) return 0.0;
854
855 return well->second.rates.get( m, 0.0 );
856 }
857
858 double get(const std::string& well_name , Rates::opt m, const std::string& tracer_name) const {
859 const auto& well = this->find( well_name );
860 if( well == this->end() ) return 0.0;
861
862 return well->second.rates.get( m, 0.0, tracer_name);
863 }
864
865 double get(const std::string& well_name , Connection::global_index connection_grid_index, Rates::opt m) const {
866 const auto& witr = this->find( well_name );
867 if( witr == this->end() ) return 0.0;
868
869 const auto& well = witr->second;
870 const auto& connection = std::find_if( well.connections.begin() ,
871 well.connections.end() ,
872 [=]( const Connection& c ) {
873 return c.index == connection_grid_index; });
874
875 if( connection == well.connections.end() )
876 return 0.0;
877
878 return connection->rates.get( m, 0.0 );
879 }
880
881 template <class MessageBufferType>
882 void write(MessageBufferType& buffer) const {
883 unsigned int size = this->size();
884 buffer.write(size);
885 for (const auto& witr : *this) {
886 const std::string& name = witr.first;
887 buffer.write(name);
888 const Well& well = witr.second;
889 well.write(buffer);
890 }
891 }
892
893 template <class MessageBufferType>
894 void read(MessageBufferType& buffer) {
895 unsigned int size;
896 buffer.read(size);
897 for (size_t i = 0; i < size; ++i) {
898 std::string name;
899 buffer.read(name);
900 Well well;
901 well.read(buffer);
902 this->emplace(name, well);
903 }
904 }
905
906 void init_json(Json::JsonObject& json_data) const {
907 for (const auto& [wname, well] : *this) {
908 auto json_well = json_data.add_object(wname);
909 well.init_json(json_well);
910 }
911 }
912
913
914 Json::JsonObject json() const {
915 Json::JsonObject json_data;
916 this->init_json(json_data);
917 return json_data;
918 }
919
920 template<class Serializer>
921 void serializeOp(Serializer& serializer)
922 {
923 serializer(static_cast<std::map<std::string,Well>&>(*this));
924 }
925
926 static Wells serializationTestObject()
927 {
928 Wells w;
929 w.insert({"test_well", Well::serializationTestObject()});
930
931 return w;
932 }
933 };
934
936 {
937 std::unordered_map<std::string, WellBlockAvgPress> values{};
938
939 template <class MessageBufferType>
940 void write(MessageBufferType& buffer) const;
941
942 template <class MessageBufferType>
943 void read(MessageBufferType& buffer);
944
945 bool operator==(const WellBlockAveragePressures& that) const
946 {
947 return this->values == that.values;
948 }
949
950 template <class Serializer>
951 void serializeOp(Serializer& serializer)
952 {
953 serializer(this->values);
954 }
955
956 static WellBlockAveragePressures serializationTestObject()
957 {
958 return {
959 { { "I-45", WellBlockAvgPress::serializationTestObject() } },
960 };
961 }
962 };
963
964 /* IMPLEMENTATIONS */
965
966 inline bool Rates::has( opt m ) const {
967 const auto mand = static_cast< enum_size >( this->mask )
968 & static_cast< enum_size >( m );
969
970 return static_cast< opt >( mand ) == m;
971 }
972
973 inline double Rates::get( opt m ) const {
974 if( !this->has( m ) )
975 throw std::invalid_argument( "Uninitialized value." );
976
977 return this->get_ref( m );
978 }
979
980 inline double Rates::get( opt m, double default_value ) const {
981 if( !this->has( m ) ) return default_value;
982
983 return this->get_ref( m );
984 }
985
986 inline double Rates::get( opt m, double default_value, const std::string& tracer_name) const {
987 if( !this->has( m ) ) return default_value;
988
989 if( m == opt::tracer && this->tracer.find(tracer_name) == this->tracer.end()) return default_value;
990
991 return this->get_ref( m, tracer_name);
992 }
993
994 inline Rates& Rates::set( opt m, double value ) {
995 this->get_ref( m ) = value;
996
997 /* mask |= m */
998 this->mask = static_cast< opt >(
999 static_cast< enum_size >( this->mask ) |
1000 static_cast< enum_size >( m )
1001 );
1002
1003 return *this;
1004 }
1005
1006 inline Rates& Rates::set( opt m, double value , const std::string& tracer_name ) {
1007 this->get_ref( m , tracer_name) = value;
1008
1009 /* mask |= m */
1010 this->mask = static_cast< opt >(
1011 static_cast< enum_size >( this->mask ) |
1012 static_cast< enum_size >( m )
1013 );
1014
1015 return *this;
1016 }
1017
1018 inline bool Rates::operator==(const Rates& rate) const
1019 {
1020 return mask == rate.mask &&
1021 wat == rate.wat &&
1022 oil == rate.oil &&
1023 gas == rate.gas &&
1024 polymer == rate.polymer &&
1025 solvent == rate.solvent &&
1026 energy == rate.energy &&
1027 dissolved_gas == rate.dissolved_gas &&
1028 vaporized_oil == rate.vaporized_oil &&
1029 reservoir_water == rate.reservoir_water &&
1030 reservoir_oil == rate.reservoir_oil &&
1031 reservoir_gas == rate.reservoir_gas &&
1032 productivity_index_water == rate.productivity_index_water &&
1033 productivity_index_gas == rate.productivity_index_gas &&
1034 productivity_index_oil == rate.productivity_index_oil &&
1035 well_potential_water == rate.well_potential_water &&
1036 well_potential_oil == rate.well_potential_oil &&
1037 well_potential_gas == rate.well_potential_gas &&
1038 brine == rate.brine &&
1039 alq == rate.alq &&
1040 tracer == rate.tracer &&
1041 micp == rate.micp &&
1042 vaporized_water == rate.vaporized_water;
1043 }
1044
1045
1046 /*
1047 * To avoid error-prone and repetitve work when extending rates with new
1048 * values, the get+set methods use this helper get_ref to determine what
1049 * member to manipulate. To add a new option, just add another case
1050 * corresponding to the enum entry in Rates to this function.
1051 *
1052 * This is an implementation detail and understanding this has no
1053 * significant impact on correct use of the class.
1054 */
1055 inline const double& Rates::get_ref( opt m ) const {
1056 switch( m ) {
1057 case opt::wat: return this->wat;
1058 case opt::oil: return this->oil;
1059 case opt::gas: return this->gas;
1060 case opt::polymer: return this->polymer;
1061 case opt::solvent: return this->solvent;
1062 case opt::energy: return this->energy;
1063 case opt::dissolved_gas: return this->dissolved_gas;
1064 case opt::vaporized_oil: return this->vaporized_oil;
1065 case opt::reservoir_water: return this->reservoir_water;
1066 case opt::reservoir_oil: return this->reservoir_oil;
1067 case opt::reservoir_gas: return this->reservoir_gas;
1068 case opt::productivity_index_water: return this->productivity_index_water;
1069 case opt::productivity_index_oil: return this->productivity_index_oil;
1070 case opt::productivity_index_gas: return this->productivity_index_gas;
1071 case opt::well_potential_water: return this->well_potential_water;
1072 case opt::well_potential_oil: return this->well_potential_oil;
1073 case opt::well_potential_gas: return this->well_potential_gas;
1074 case opt::brine: return this->brine;
1075 case opt::alq: return this->alq;
1076 case opt::tracer: /* Should _not_ be called with tracer argument */
1077 break;
1078 case opt::micp: return this->micp;
1079 case opt::vaporized_water: return this->vaporized_water;
1080 }
1081
1082 throw std::invalid_argument(
1083 "Unknown value type '"
1084 + std::to_string( static_cast< enum_size >( m ) )
1085 + "'" );
1086
1087 }
1088
1089 inline const double& Rates::get_ref( opt m, const std::string& tracer_name ) const {
1090 if (m != opt::tracer)
1091 throw std::logic_error("Logic error - should be called with tracer argument");
1092
1093 return this->tracer.at(tracer_name);
1094 }
1095
1096 inline double& Rates::get_ref( opt m ) {
1097 return const_cast< double& >(
1098 static_cast< const Rates* >( this )->get_ref( m )
1099 );
1100 }
1101
1102 inline double& Rates::get_ref( opt m, const std::string& tracer_name ) {
1103 if (m == opt::tracer) this->tracer.emplace(tracer_name, 0.0);
1104 return this->tracer.at(tracer_name);
1105 }
1106
1107 void Rates::init_json(Json::JsonObject& json_data) const {
1108
1109 if (this->has(opt::wat))
1110 json_data.add_item("wat", this->get(opt::wat));
1111
1112 if (this->has(opt::oil))
1113 json_data.add_item("oil", this->get(opt::oil));
1114
1115 if (this->has(opt::gas))
1116 json_data.add_item("gas", this->get(opt::gas));
1117
1118 }
1119
1120 bool inline Rates::flowing() const {
1121 return ((this->wat != 0) ||
1122 (this->oil != 0) ||
1123 (this->gas != 0));
1124 }
1125
1126 inline bool Well::flowing() const noexcept {
1127 return this->rates.flowing();
1128 }
1129
1130 template <class MessageBufferType>
1131 void Rates::write(MessageBufferType& buffer) const {
1132 buffer.write(this->mask);
1133 buffer.write(this->wat);
1134 buffer.write(this->oil);
1135 buffer.write(this->gas);
1136 buffer.write(this->polymer);
1137 buffer.write(this->solvent);
1138 buffer.write(this->energy);
1139 buffer.write(this->dissolved_gas);
1140 buffer.write(this->vaporized_oil);
1141 buffer.write(this->reservoir_water);
1142 buffer.write(this->reservoir_oil);
1143 buffer.write(this->reservoir_gas);
1144 buffer.write(this->productivity_index_water);
1145 buffer.write(this->productivity_index_oil);
1146 buffer.write(this->productivity_index_gas);
1147 buffer.write(this->well_potential_water);
1148 buffer.write(this->well_potential_oil);
1149 buffer.write(this->well_potential_gas);
1150 buffer.write(this->brine);
1151 buffer.write(this->alq);
1152 //tracer:
1153 unsigned int size = this->tracer.size();
1154 buffer.write(size);
1155 for (const auto& [name, rate] : this->tracer) {
1156 buffer.write(name);
1157 buffer.write(rate);
1158 }
1159 buffer.write(this->micp);
1160 buffer.write(this->vaporized_water);
1161 }
1162
1163 template <class MessageBufferType>
1164 void ConnectionFiltrate::write(MessageBufferType& buffer) const {
1165 buffer.write(this->rate);
1166 buffer.write(this->total);
1167 buffer.write(this->skin_factor);
1168 buffer.write(this->thickness);
1169 buffer.write(this->perm);
1170 buffer.write(this->poro);
1171 buffer.write(this->radius);
1172 buffer.write(this->area_of_flow);
1173 }
1174
1175 template <class MessageBufferType>
1176 void Connection::write(MessageBufferType& buffer) const {
1177 buffer.write(this->index);
1178 this->rates.write(buffer);
1179 buffer.write(this->pressure);
1180 buffer.write(this->reservoir_rate);
1181 buffer.write(this->cell_pressure);
1182 buffer.write(this->cell_saturation_water);
1183 buffer.write(this->cell_saturation_gas);
1184 buffer.write(this->effective_Kh);
1185 buffer.write(this->trans_factor);
1186 this->filtrate.write(buffer);
1187 }
1188
1189 void Connection::init_json(Json::JsonObject& json_data) const {
1190 auto json_rates = json_data.add_object("rates");
1191 this->rates.init_json(json_rates);
1192
1193 json_data.add_item("global_index", static_cast<int>(this->index));
1194 json_data.add_item("pressure", this->pressure);
1195 json_data.add_item("reservoir_rate", this->reservoir_rate);
1196 json_data.add_item("cell_pressure", this->cell_pressure);
1197 json_data.add_item("swat", this->cell_saturation_water);
1198 json_data.add_item("sgas", this->cell_saturation_gas);
1199 json_data.add_item("Kh", this->effective_Kh);
1200 json_data.add_item("trans_factor", this->trans_factor);
1201 }
1202
1203 template <class MessageBufferType>
1204 void Segment::write(MessageBufferType& buffer) const
1205 {
1206 buffer.write(this->segNumber);
1207 this->rates.write(buffer);
1208 this->pressures.write(buffer);
1209 this->velocity.write(buffer);
1210 this->holdup.write(buffer);
1211 this->viscosity.write(buffer);
1212 this->density.write(buffer);
1213 }
1214
1215 template <class MessageBufferType>
1216 void CurrentControl::write(MessageBufferType& buffer) const
1217 {
1218 buffer.write(this->isProducer);
1219 if (this->isProducer) {
1220 buffer.write(this->prod);
1221 }
1222 else {
1223 buffer.write(this->inj);
1224 }
1225 }
1226
1227 template <class MessageBufferType>
1228 void WellBlockAvgPress::write(MessageBufferType& buffer) const
1229 {
1230 for (const auto& quantity : this->wbp_) {
1231 buffer.write(quantity);
1232 }
1233 }
1234
1235 template <class MessageBufferType>
1236 void WellFiltrate::write(MessageBufferType& buffer) const
1237 {
1238 buffer.write(this->rate);
1239 buffer.write(this->total);
1240 buffer.write(this->concentration);
1241 }
1242
1243 template <class MessageBufferType>
1244 void Well::write(MessageBufferType& buffer) const {
1245 this->rates.write(buffer);
1246 buffer.write(this->bhp);
1247 buffer.write(this->thp);
1248 buffer.write(this->temperature);
1249 buffer.write(this->control);
1250 this->filtrate.write(buffer);
1251
1252 {
1253 const auto status = ::Opm::WellStatus2String(this->dynamicStatus);
1254 buffer.write(status);
1255 }
1256
1257 unsigned int size = this->connections.size();
1258 buffer.write(size);
1259 for (const Connection& comp : this->connections)
1260 comp.write(buffer);
1261
1262 {
1263 const auto nSeg =
1264 static_cast<unsigned int>(this->segments.size());
1265 buffer.write(nSeg);
1266
1267 for (const auto& seg : this->segments) {
1268 seg.second.write(buffer);
1269 }
1270 }
1271
1272 this->current_control.write(buffer);
1273 this->guide_rates.write(buffer);
1274 }
1275
1276 template <class MessageBufferType>
1277 void WellBlockAveragePressures::write(MessageBufferType& buffer) const
1278 {
1279 buffer.write(this->values.size());
1280
1281 for (const auto& [well, value] : this->values) {
1282 buffer.write(well);
1283 value.write(buffer);
1284 }
1285 }
1286
1287 template <class MessageBufferType>
1288 void Rates::read(MessageBufferType& buffer) {
1289 buffer.read(this->mask);
1290 buffer.read(this->wat);
1291 buffer.read(this->oil);
1292 buffer.read(this->gas);
1293 buffer.read(this->polymer);
1294 buffer.read(this->solvent);
1295 buffer.read(this->energy);
1296 buffer.read(this->dissolved_gas);
1297 buffer.read(this->vaporized_oil);
1298 buffer.read(this->reservoir_water);
1299 buffer.read(this->reservoir_oil);
1300 buffer.read(this->reservoir_gas);
1301 buffer.read(this->productivity_index_water);
1302 buffer.read(this->productivity_index_oil);
1303 buffer.read(this->productivity_index_gas);
1304 buffer.read(this->well_potential_water);
1305 buffer.read(this->well_potential_oil);
1306 buffer.read(this->well_potential_gas);
1307 buffer.read(this->brine);
1308 buffer.read(this->alq);
1309 //tracer:
1310 unsigned int size;
1311 buffer.read(size);
1312 for (size_t i = 0; i < size; ++i) {
1313 std::string tracer_name;
1314 buffer.read(tracer_name);
1315 double tracer_rate;
1316 buffer.read(tracer_rate);
1317 this->tracer.emplace(tracer_name, tracer_rate);
1318 }
1319 buffer.read(this->micp);
1320 buffer.read(this->vaporized_water);
1321 }
1322
1323 template <class MessageBufferType>
1324 void ConnectionFiltrate::read(MessageBufferType& buffer) {
1325 buffer.read(this->rate);
1326 buffer.read(this->total);
1327 buffer.read(this->skin_factor);
1328 buffer.read(this->thickness);
1329 buffer.read(this->perm);
1330 buffer.read(this->poro);
1331 buffer.read(this->radius);
1332 buffer.read(this->area_of_flow);
1333 }
1334
1335 template <class MessageBufferType>
1336 void Connection::read(MessageBufferType& buffer) {
1337 buffer.read(this->index);
1338 this->rates.read(buffer);
1339 buffer.read(this->pressure);
1340 buffer.read(this->reservoir_rate);
1341 buffer.read(this->cell_pressure);
1342 buffer.read(this->cell_saturation_water);
1343 buffer.read(this->cell_saturation_gas);
1344 buffer.read(this->effective_Kh);
1345 buffer.read(this->trans_factor);
1346 this->filtrate.read(buffer);
1347 }
1348
1349 template <class MessageBufferType>
1350 void Segment::read(MessageBufferType& buffer)
1351 {
1352 buffer.read(this->segNumber);
1353 this->rates.read(buffer);
1354 this->pressures.read(buffer);
1355 this->velocity.read(buffer);
1356 this->holdup.read(buffer);
1357 this->viscosity.read(buffer);
1358 this->density.read(buffer);
1359 }
1360
1361 template <class MessageBufferType>
1362 void CurrentControl::read(MessageBufferType& buffer)
1363 {
1364 buffer.read(this->isProducer);
1365 if (this->isProducer) {
1366 buffer.read(this->prod);
1367 }
1368 else {
1369 buffer.read(this->inj);
1370 }
1371 }
1372
1373 template <class MessageBufferType>
1374 void WellBlockAvgPress::read(MessageBufferType& buffer)
1375 {
1376 for (auto& quantity : this->wbp_) {
1377 buffer.read(quantity);
1378 }
1379 }
1380
1381 template <class MessageBufferType>
1382 void WellFiltrate::read(MessageBufferType& buffer)
1383 {
1384 buffer.read(this->rate);
1385 buffer.read(this->total);
1386 buffer.read(this->concentration);
1387 }
1388
1389 template <class MessageBufferType>
1390 void Well::read(MessageBufferType& buffer) {
1391 this->rates.read(buffer);
1392 buffer.read(this->bhp);
1393 buffer.read(this->thp);
1394 buffer.read(this->temperature);
1395 buffer.read(this->control);
1396 this->filtrate.read(buffer);
1397
1398 {
1399 auto status = std::string{};
1400 buffer.read(status);
1401 this->dynamicStatus = ::Opm::WellStatusFromString(status);
1402 }
1403
1404 // Connection information
1405 unsigned int size = 0.0; //this->connections.size();
1406 buffer.read(size);
1407 this->connections.resize(size);
1408 for (size_t i = 0; i < size; ++i)
1409 {
1410 auto& comp = this->connections[ i ];
1411 comp.read(buffer);
1412 }
1413
1414 // Segment information (if applicable)
1415 const auto nSeg = [&buffer]() -> unsigned int
1416 {
1417 auto n = 0u;
1418 buffer.read(n);
1419
1420 return n;
1421 }();
1422
1423 for (auto segID = 0*nSeg; segID < nSeg; ++segID) {
1424 auto seg = Segment{};
1425 seg.read(buffer);
1426
1427 const auto segNumber = seg.segNumber;
1428 this->segments.emplace(segNumber, std::move(seg));
1429 }
1430
1431 this->current_control.read(buffer);
1432 this->guide_rates.read(buffer);
1433 }
1434
1435 template <class MessageBufferType>
1436 void WellBlockAveragePressures::read(MessageBufferType& buffer)
1437 {
1438 const auto numWells = [&buffer, this]()
1439 {
1440 auto size = 0*this->values.size();
1441 buffer.read(size);
1442
1443 return size;
1444 }();
1445
1446 auto wellName = std::string{};
1447 for (auto well = 0*numWells; well < numWells; ++well) {
1448 buffer.read(wellName);
1449
1450 this->values[wellName].read(buffer);
1451 }
1452 }
1453
1454 void Well::init_json(Json::JsonObject& json_data) const {
1455 auto json_connections = json_data.add_array("connections");
1456 for (const auto& conn : this->connections) {
1457 auto json_conn = json_connections.add_object();
1458 conn.init_json(json_conn);
1459 }
1460 auto json_rates = json_data.add_object("rates");
1461 this->rates.init_json(json_rates);
1462
1463 json_data.add_item("bhp", this->bhp);
1464 json_data.add_item("thp", this->thp);
1465 json_data.add_item("temperature", this->temperature);
1466 json_data.add_item("status", ::Opm::WellStatus2String(this->dynamicStatus));
1467
1468 auto json_control = json_data.add_object("control");
1469 this->current_control.init_json(json_control);
1470
1471 auto json_guiderate = json_data.add_object("guiderate");
1472 this->guide_rates.init_json(json_guiderate);
1473 }
1474
1475}} // Opm::data
1476
1477#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:1120
double get(opt m) const
Read the value indicated by m.
Definition Wells.hpp:973
Rates & set(opt m, double value)
Set the value specified by m.
Definition Wells.hpp:994
bool has(opt) const
Query if a value is set.
Definition Wells.hpp:966
Definition Wells.hpp:307
Definition Wells.hpp:375
Definition Wells.hpp:667
Definition Wells.hpp:848
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:246
Definition Wells.hpp:612
Definition Wells.hpp:520
Definition Wells.hpp:487
Definition Wells.hpp:560
Definition Wells.hpp:936
Definition Wells.hpp:717
Definition Wells.hpp:750