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