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