opm-common
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/common/ErrorMacros.hpp>
24 #include <opm/common/OpmLog/OpmLog.hpp>
25 #include <opm/output/data/GuideRateValue.hpp>
26 #include <opm/input/eclipse/Schedule/Well/WellEnums.hpp>
27 
28 #include <algorithm>
29 #include <array>
30 #include <climits>
31 #include <cstddef>
32 #include <cstdint>
33 #include <map>
34 #include <stdexcept>
35 #include <string>
36 #include <type_traits>
37 #include <unordered_map>
38 #include <vector>
39 
40 namespace Opm { namespace data {
41 
42  class Rates {
43  /* Methods are defined inline for performance, as the actual *work* done
44  * is trivial, but somewhat frequent (typically once per time step per
45  * completion per well).
46  *
47  * To add a new rate type, add an entry in the enum with the correct
48  * shift, and if needed, increase the size type. Add a member variable
49  * and a new case in get_ref.
50  */
51 
52  public:
53  Rates() = default;
54  enum class opt : std::uint32_t {
55  wat = (1 << 0),
56  oil = (1 << 1),
57  gas = (1 << 2),
58  polymer = (1 << 3),
59  solvent = (1 << 4),
60  energy = (1 << 5),
61  dissolved_gas = (1 << 6),
62  vaporized_oil = (1 << 7),
63  reservoir_water = (1 << 8),
64  reservoir_oil = (1 << 9),
65  reservoir_gas = (1 << 10),
66  productivity_index_water = (1 << 11),
67  productivity_index_oil = (1 << 12),
68  productivity_index_gas = (1 << 13),
69  well_potential_water = (1 << 14),
70  well_potential_oil = (1 << 15),
71  well_potential_gas = (1 << 16),
72  brine = (1 << 17),
73  alq = (1 << 18),
74  tracer = (1 << 19),
75  microbial = (1 << 20),
76  oxygen = (1 << 21),
77  urea = (1 << 22),
78  vaporized_water = (1 << 23),
79  mass_gas = (1 << 24),
80  mass_wat = (1 << 25),
81  wat_frac = (1 << 26),
82  };
83 
84  using enum_size = std::underlying_type< opt >::type;
85 
87  inline bool has( opt ) const;
88 
91  inline double get( opt m ) const;
94  inline double get( opt m, double default_value ) const;
95  inline double get( opt m, double default_value , const std::string& tracer_name ) const;
99  inline Rates& set( opt m, double value );
100  inline Rates& set( opt m, double value , const std::string& tracer_name );
101 
103  inline bool flowing() const;
104 
105  template <class MessageBufferType>
106  void write(MessageBufferType& buffer) const;
107  template <class MessageBufferType>
108  void read(MessageBufferType& buffer);
109 
110  bool operator==(const Rates& rat2) const;
111 
112  template<class Serializer>
113  void serializeOp(Serializer& serializer)
114  {
115  serializer(mask);
116  serializer(wat);
117  serializer(oil);
118  serializer(gas);
119  serializer(polymer);
120  serializer(solvent);
121  serializer(energy);
122  serializer(dissolved_gas);
123  serializer(vaporized_oil);
124  serializer(reservoir_water);
125  serializer(reservoir_oil);
126  serializer(reservoir_gas);
127  serializer(productivity_index_water);
128  serializer(productivity_index_oil);
129  serializer(productivity_index_gas);
130  serializer(well_potential_water);
131  serializer(well_potential_oil);
132  serializer(well_potential_gas);
133  serializer(brine);
134  serializer(alq);
135  serializer(tracer);
136  serializer(microbial);
137  serializer(oxygen);
138  serializer(urea);
139  serializer(vaporized_water);
140  serializer(mass_gas);
141  serializer(mass_wat);
142  serializer(wat_frac);
143  }
144 
145  static Rates serializationTestObject()
146  {
147  Rates rat1;
148  rat1.set(opt::wat, 1.0);
149  rat1.set(opt::oil, 2.0);
150  rat1.set(opt::gas, 3.0);
151  rat1.set(opt::polymer, 4.0);
152  rat1.set(opt::solvent, 5.0);
153  rat1.set(opt::energy, 6.0);
154  rat1.set(opt::dissolved_gas, 7.0);
155  rat1.set(opt::vaporized_oil, 8.0);
156  rat1.set(opt::reservoir_water, 9.0);
157  rat1.set(opt::reservoir_oil, 10.0);
158  rat1.set(opt::reservoir_gas, 11.0);
159  rat1.set(opt::productivity_index_water, 12.0);
160  rat1.set(opt::productivity_index_oil, 13.0);
161  rat1.set(opt::productivity_index_gas, 14.0);
162  rat1.set(opt::well_potential_water, 15.0);
163  rat1.set(opt::well_potential_oil, 16.0);
164  rat1.set(opt::well_potential_gas, 17.0);
165  rat1.set(opt::brine, 18.0);
166  rat1.set(opt::alq, 19.0);
167  rat1.set(opt::microbial, 20.0);
168  rat1.set(opt::oxygen, 21.0);
169  rat1.set(opt::urea, 22.0);
170  rat1.set(opt::vaporized_water, 23.0);
171  rat1.set(opt::mass_gas, 24.0);
172  rat1.set(opt::mass_wat, 25.0);
173  rat1.set(opt::wat_frac, 26.0);
174  rat1.tracer.insert({"test_tracer", 1.0});
175 
176  return rat1;
177  }
178 
179  private:
180  double& get_ref( opt );
181  double& get_ref( opt, const std::string& tracer_name );
182  const double& get_ref( opt ) const;
183  const double& get_ref( opt, const std::string& tracer_name ) const;
184 
185  opt mask = static_cast< opt >( 0 );
186 
187  double wat = 0.0;
188  double oil = 0.0;
189  double gas = 0.0;
190  double polymer = 0.0;
191  double solvent = 0.0;
192  double energy = 0.0;
193  double dissolved_gas = 0.0;
194  double vaporized_oil = 0.0;
195  double reservoir_water = 0.0;
196  double reservoir_oil = 0.0;
197  double reservoir_gas = 0.0;
198  double productivity_index_water = 0.0;
199  double productivity_index_oil = 0.0;
200  double productivity_index_gas = 0.0;
201  double well_potential_water = 0.0;
202  double well_potential_oil = 0.0;
203  double well_potential_gas = 0.0;
204  double brine = 0.0;
205  double alq = 0.0;
206  std::map<std::string, double> tracer{};
207  double microbial = 0.0;
208  double oxygen = 0.0;
209  double urea = 0.0;
210  double vaporized_water = 0.0;
211  double mass_gas = 0.0;
212  double mass_wat = 0.0;
213  double wat_frac = 0.0;
214  };
215 
217  {
218  double rate{};
219  double total{};
220  double skin_factor{};
221  double thickness{};
222  double perm{};
223  double poro{};
224  double radius{};
225  double area_of_flow{};
226  double flow_factor{};
227  double fracture_rate{};
228 
229  template <class Serializer>
230  void serializeOp(Serializer& serializer)
231  {
232  serializer(rate);
233  serializer(total);
234  serializer(skin_factor);
235  serializer(thickness);
236  serializer(perm);
237  serializer(poro);
238  serializer(radius);
239  serializer(area_of_flow);
240  serializer(flow_factor);
241  serializer(fracture_rate);
242  }
243 
244  bool operator==(const ConnectionFiltrate& filtrate) const
245  {
246  return (this->rate == filtrate.rate)
247  && (this->total == filtrate.total)
248  && (this->skin_factor == filtrate.skin_factor)
249  && (this->thickness == filtrate.thickness)
250  && (this->perm == filtrate.perm)
251  && (this->poro == filtrate.poro)
252  && (this->radius == filtrate.radius)
253  && (this->area_of_flow == filtrate.area_of_flow)
254  && (this->flow_factor == filtrate.flow_factor)
255  && (this->fracture_rate == filtrate.fracture_rate)
256  ;
257  }
258 
259  static ConnectionFiltrate serializationTestObject()
260  {
261  return {0.8, 100.0, -1.0, 2.0, 1.0e-9,
262  0.3, 0.05, 0.8, 0.1, 0.7};
263  }
264 
265  template <class MessageBufferType>
266  void write(MessageBufferType& buffer) const;
267 
268  template <class MessageBufferType>
269  void read(MessageBufferType& buffer);
270  };
271 
273  {
274  double area{};
275  double flux{};
276  double height{};
277  double length{};
278  double WI{};
279  double volume{};
280  double filter_volume{};
281  double avg_width{};
282  double avg_filter_width{};
283  double inj_pressure{};
284  double inj_bhp{};
285  double inj_wellrate{};
286 
287  template <class Serializer>
288  void serializeOp(Serializer& serializer)
289  {
290  serializer(area);
291  serializer(flux);
292  serializer(height);
293  serializer(length);
294  serializer(WI);
295  serializer(volume);
296  serializer(filter_volume);
297  serializer(avg_width);
298  serializer(avg_filter_width);
299  serializer(inj_pressure);
300  serializer(inj_bhp);
301  serializer(inj_wellrate);
302  }
303 
304  bool operator==(const ConnectionFracture& fraccon) const
305  {
306  return (this->area == fraccon.area)
307  && (this->flux == fraccon.flux)
308  && (this->height == fraccon.height)
309  && (this->length == fraccon.length)
310  && (this->WI == fraccon.WI)
311  && (this->volume == fraccon.volume)
312  && (this->filter_volume == fraccon.filter_volume)
313  && (this->avg_width == fraccon.avg_width)
314  && (this->avg_filter_width == fraccon.avg_filter_width)
315  && (this->inj_pressure == fraccon.inj_pressure)
316  && (this->inj_bhp == fraccon.inj_bhp)
317  && (this->inj_wellrate == fraccon.inj_wellrate)
318  ;
319  }
320 
321  static ConnectionFracture serializationTestObject()
322  {
323  return {0.8, 100.0, 1.3, 1.4, 10.0, 4.0, 0.4, 0.5, 0.05, 200.0, 150.0, 500.0};
324  }
325 
326  template <class MessageBufferType>
327  void write(MessageBufferType& buffer) const
328  {
329  buffer.write(this->area);
330  buffer.write(this->flux);
331  buffer.write(this->height);
332  buffer.write(this->length);
333  buffer.write(this->WI);
334  buffer.write(this->volume);
335  buffer.write(this->filter_volume);
336  buffer.write(this->avg_width);
337  buffer.write(this->avg_filter_width);
338  buffer.write(this->inj_pressure);
339  buffer.write(this->inj_bhp);
340  buffer.write(this->inj_wellrate);
341  }
342 
343  template <class MessageBufferType>
344  void read(MessageBufferType& buffer)
345  {
346  buffer.read(this->area);
347  buffer.read(this->flux);
348  buffer.read(this->height);
349  buffer.read(this->length);
350  buffer.read(this->WI);
351  buffer.read(this->volume);
352  buffer.read(this->filter_volume);
353  buffer.read(this->avg_width);
354  buffer.read(this->avg_filter_width);
355  buffer.read(this->inj_pressure);
356  buffer.read(this->inj_bhp);
357  buffer.read(this->inj_wellrate);
358  }
359  };
360 
363  {
365  struct Statistics
366  {
368  double avg{};
369 
371  double max{};
372 
374  double min{};
375 
379  double stdev{};
380 
383  {
384  return {
385  12.34, 56.78, 9.10, 11.12
386  };
387  }
388 
394  template <class Serializer>
395  void serializeOp(Serializer& serializer)
396  {
397  serializer(this->avg);
398  serializer(this->max);
399  serializer(this->min);
400  serializer(this->stdev);
401  }
402 
410  bool operator==(const Statistics& that) const
411  {
412  return (this->avg == that.avg)
413  && (this->max == that.max)
414  && (this->min == that.min)
415  && (this->stdev == that.stdev)
416  ;
417  }
418 
420  template <class MessageBufferType>
421  void write(MessageBufferType& buffer) const
422  {
423  buffer.write(this->avg);
424  buffer.write(this->max);
425  buffer.write(this->min);
426  buffer.write(this->stdev);
427  }
428 
430  template <class MessageBufferType>
431  void read(MessageBufferType& buffer)
432  {
433  buffer.read(this->avg);
434  buffer.read(this->max);
435  buffer.read(this->min);
436  buffer.read(this->stdev);
437  }
438  };
439 
443  std::size_t numCells{};
444 
447 
450 
453 
456  {
457  auto fract = ConnectionFracturing{};
458 
459  fract.numCells = 123;
460  fract.press = Statistics::serializationTestObject();
462  fract.width = Statistics::serializationTestObject();
463 
464  return fract;
465  }
466 
472  template <class Serializer>
473  void serializeOp(Serializer& serializer)
474  {
475  serializer(this->numCells);
476  serializer(this->press);
477  serializer(this->rate);
478  serializer(this->width);
479  }
480 
488  bool operator==(const ConnectionFracturing& that) const
489  {
490  return (this->numCells == that.numCells)
491  && (this->press == that.press)
492  && (this->rate == that.rate)
493  && (this->width == that.width)
494  ;
495  }
496 
498  template <class MessageBufferType>
499  void write(MessageBufferType& buffer) const
500  {
501  buffer.write(this->numCells);
502  buffer.write(this->press);
503  buffer.write(this->rate);
504  buffer.write(this->width);
505  }
506 
508  template <class MessageBufferType>
509  void read(MessageBufferType& buffer)
510  {
511  buffer.read(this->numCells);
512  buffer.read(this->press);
513  buffer.read(this->rate);
514  buffer.read(this->width);
515  }
516  };
517 
518  struct Connection
519  {
520  using global_index = std::size_t;
521  static const constexpr int restart_size = 6;
522 
523  global_index index{};
524  Rates rates{};
525  double pressure{};
526  double reservoir_rate{};
527  double cell_pressure{};
528  double cell_saturation_water{};
529  double cell_saturation_gas{};
530  double effective_Kh{};
531  double trans_factor{};
532  double d_factor{};
533  double compact_mult{1.0}; // Rock compaction transmissibility multiplier (ROCKTAB)
534 
535  int lgr_grid{0}; // LGR grid index, 0 if not in LGR
536 
537  ConnectionFiltrate filtrate{};
538 
539  ConnectionFracture fracture{};
540 
543 
544  bool operator==(const Connection& conn2) const
545  {
546  return (index == conn2.index)
547  && (rates == conn2.rates)
548  && (pressure == conn2.pressure)
549  && (reservoir_rate == conn2.reservoir_rate)
550  && (cell_pressure == conn2.cell_pressure)
551  && (cell_saturation_water == conn2.cell_saturation_water)
552  && (cell_saturation_gas == conn2.cell_saturation_gas)
553  && (effective_Kh == conn2.effective_Kh)
554  && (trans_factor == conn2.trans_factor)
555  && (d_factor == conn2.d_factor)
556  && (compact_mult == conn2.compact_mult)
557  && (lgr_grid == conn2.lgr_grid)
558  && (filtrate == conn2.filtrate)
559  && (fracture == conn2.fracture)
560  && (this->fract == conn2.fract)
561  ;
562  }
563 
564  template <class MessageBufferType>
565  void write(MessageBufferType& buffer) const;
566  template <class MessageBufferType>
567  void read(MessageBufferType& buffer);
568 
569  template<class Serializer>
570  void serializeOp(Serializer& serializer)
571  {
572  serializer(index);
573  serializer(rates);
574  serializer(pressure);
575  serializer(reservoir_rate);
576  serializer(cell_pressure);
577  serializer(cell_saturation_water);
578  serializer(cell_saturation_gas);
579  serializer(effective_Kh);
580  serializer(trans_factor);
581  serializer(d_factor);
582  serializer(compact_mult);
583  serializer(lgr_grid);
584  serializer(filtrate);
585  serializer(fracture);
586  serializer(this->fract);
587  }
588 
589  static Connection serializationTestObject()
590  {
591  return Connection {
592  1, Rates::serializationTestObject(),
593  2.0, 3.0, 4.0, 5.0,
594  6.0, 7.0, 8.0, 9.0, 0.987,
595  3, // lgr_grid
596  ConnectionFiltrate::serializationTestObject(),
597  ConnectionFracture::serializationTestObject(),
599  };
600  }
601  };
602 
604  {
605  public:
606  enum class Value : std::size_t {
607  Pressure, PDrop, PDropHydrostatic, PDropAccel, PDropFriction,
608  };
609 
610  double& operator[](const Value i)
611  {
612  return this->values_[this->index(i)];
613  }
614 
615  double operator[](const Value i) const
616  {
617  return this->values_[this->index(i)];
618  }
619 
620  bool operator==(const SegmentPressures& segpres2) const
621  {
622  return this->values_ == segpres2.values_;
623  }
624 
625  template <class MessageBufferType>
626  void write(MessageBufferType& buffer) const
627  {
628  for (const auto& value : this->values_) {
629  buffer.write(value);
630  }
631  }
632 
633  template <class MessageBufferType>
634  void read(MessageBufferType& buffer)
635  {
636  for (auto& value : this->values_) {
637  buffer.read(value);
638  }
639  }
640 
641  template<class Serializer>
642  void serializeOp(Serializer& serializer)
643  {
644  serializer(values_);
645  }
646 
647  static SegmentPressures serializationTestObject()
648  {
649  SegmentPressures spres;
650  spres[Value::Pressure] = 1.0;
651  spres[Value::PDrop] = 2.0;
652  spres[Value::PDropHydrostatic] = 3.0;
653  spres[Value::PDropAccel] = 4.0;
654  spres[Value::PDropFriction] = 5.0;
655 
656  return spres;
657  }
658 
659  private:
660  constexpr static std::size_t numvals = 5;
661 
662  std::array<double, numvals> values_ = {0};
663 
664  std::size_t index(const Value ix) const
665  {
666  return static_cast<std::size_t>(ix);
667  }
668  };
669 
670  template <typename Items>
672  {
673  public:
674  using Item = typename Items::Item;
675 
676  void clear()
677  {
678  this->has_ = static_cast<unsigned char>(0);
679  this->value_.fill(0.0);
680  }
681 
682  constexpr bool has(const Item p) const
683  {
684  const auto i = this->index(p);
685 
686  return (i < Size) && this->hasItem(i);
687  }
688 
689  bool operator==(const QuantityCollection& that) const
690  {
691  return (this->has_ == that.has_)
692  && (this->value_ == that.value_);
693  }
694 
695  double get(const Item p) const
696  {
697  if (! this->has(p)) {
698  throw std::invalid_argument {
699  "Request for Unset Item Value for " + Items::itemName(p)
700  };
701  }
702 
703  return this->value_[ this->index(p) ];
704  }
705 
706  QuantityCollection& set(const Item p, const double value)
707  {
708  const auto i = this->index(p);
709 
710  if (i >= Size) {
711  throw std::invalid_argument {
712  "Cannot Assign Item Value for Unsupported Item '"
713  + Items::itemName(p) + '\''
714  };
715  }
716 
717  this->has_ |= 1 << i;
718  this->value_[i] = value;
719 
720  return *this;
721  }
722 
723  template <class MessageBufferType>
724  void write(MessageBufferType& buffer) const
725  {
726  buffer.write(this->has_);
727 
728  for (const auto& x : this->value_) {
729  buffer.write(x);
730  }
731  }
732 
733  template <class MessageBufferType>
734  void read(MessageBufferType& buffer)
735  {
736  this->clear();
737  buffer.read(this->has_);
738 
739  for (auto& x : this->value_) {
740  buffer.read(x);
741  }
742  }
743 
744  template <class Serializer>
745  void serializeOp(Serializer& serializer)
746  {
747  serializer(this->has_);
748  serializer(this->value_);
749  }
750 
751  static QuantityCollection serializationTestObject()
752  {
753  auto quant = QuantityCollection{};
754 
755  for (const auto& [item, value] : Items::serializationTestItems()) {
756  quant.set(item, value);
757  }
758 
759  return quant;
760  }
761 
762  private:
763  enum { Size = static_cast<std::size_t>(Item::NumItems) };
764 
765  static_assert(Size <= static_cast<std::size_t>(CHAR_BIT),
766  "Number of items must not exceed CHAR_BIT");
767 
770  unsigned char has_{};
771 
773  std::array<double, Size> value_{};
774 
775  constexpr std::size_t index(const Item p) const noexcept
776  {
777  return static_cast<std::size_t>(p);
778  }
779 
780  bool hasItem(const std::size_t i) const
781  {
782  return (this->has_ & (1 << i)) != 0;
783  }
784  };
785 
786  struct PhaseItems
787  {
788  enum class Item {
789  Oil, Gas, Water,
790 
791  // -- Must be last enumerator --
792  NumItems,
793  };
794 
795  static std::string itemName(const Item p)
796  {
797  switch (p) {
798  case Item::Oil: return "Oil";
799  case Item::Gas: return "Gas";
800  case Item::Water: return "Water";
801 
802  case Item::NumItems:
803  return "Out of bounds (NumItems)";
804  }
805 
806  return "Unknown (" + std::to_string(static_cast<int>(p)) + ')';
807  }
808 
809  static auto serializationTestItems()
810  {
811  return std::vector {
812  std::pair { Item::Oil , 1.0 },
813  std::pair { Item::Gas , 7.0 },
814  std::pair { Item::Water, 2.9 },
815  };
816  }
817  };
818 
820  {
821  enum class Item {
822  Oil, Gas, Water, Mixture, MixtureWithExponents,
823 
824  // -- Must be last enumerator --
825  NumItems,
826  };
827 
828  static std::string itemName(const Item p)
829  {
830  switch (p) {
831  case Item::Oil: return "Oil";
832  case Item::Gas: return "Gas";
833  case Item::Water: return "Water";
834  case Item::Mixture: return "Mixture";
835  case Item::MixtureWithExponents: return "MixtureWithExponents";
836 
837  case Item::NumItems:
838  return "Out of bounds (NumItems)";
839  }
840 
841  return "Unknown (" + std::to_string(static_cast<int>(p)) + ')';
842  }
843 
844  static auto serializationTestItems()
845  {
846  return std::vector {
847  std::pair { Item::Oil , 876.54 },
848  std::pair { Item::Gas , 321.09 },
849  std::pair { Item::Water , 987.65 },
850  std::pair { Item::Mixture , 975.31 },
851  std::pair { Item::MixtureWithExponents, 765.43 },
852  };
853  }
854  };
855 
858 
859  struct Segment
860  {
861  Rates rates{};
862  SegmentPressures pressures{};
863  SegmentPhaseQuantity velocity{};
864  SegmentPhaseQuantity holdup{};
865  SegmentPhaseQuantity viscosity{};
866  SegmentPhaseDensity density{};
867  std::size_t segNumber{};
868 
869  bool operator==(const Segment& seg2) const
870  {
871  return (rates == seg2.rates)
872  && (pressures == seg2.pressures)
873  && (velocity == seg2.velocity)
874  && (holdup == seg2.holdup)
875  && (viscosity == seg2.viscosity)
876  && (density == seg2.density)
877  && (segNumber == seg2.segNumber);
878  }
879 
880  template <class MessageBufferType>
881  void write(MessageBufferType& buffer) const;
882 
883  template <class MessageBufferType>
884  void read(MessageBufferType& buffer);
885 
886  template <class Serializer>
887  void serializeOp(Serializer& serializer)
888  {
889  serializer(this->rates);
890  serializer(this->pressures);
891  serializer(this->velocity);
892  serializer(this->holdup);
893  serializer(this->viscosity);
894  serializer(this->density);
895  serializer(this->segNumber);
896  }
897 
898  static Segment serializationTestObject()
899  {
900  return {
901  Rates::serializationTestObject(),
902  SegmentPressures::serializationTestObject(),
903  SegmentPhaseQuantity::serializationTestObject(), // velocity
904  SegmentPhaseQuantity::serializationTestObject(), // holdup
905  SegmentPhaseQuantity::serializationTestObject(), // viscosity
906  SegmentPhaseDensity::serializationTestObject(), // density
907  10
908  };
909  }
910  };
911 
913  {
914  bool isProducer{true};
915 
916  ::Opm::WellProducerCMode prod {
917  ::Opm::WellProducerCMode::CMODE_UNDEFINED
918  };
919 
920  ::Opm::WellInjectorCMode inj {
921  ::Opm::WellInjectorCMode::CMODE_UNDEFINED
922  };
923 
924  bool operator==(const CurrentControl& rhs) const
925  {
926  return (this->isProducer == rhs.isProducer)
927  && ((this->isProducer && (this->prod == rhs.prod)) ||
928  (!this->isProducer && (this->inj == rhs.inj)));
929  }
930 
931  template <class MessageBufferType>
932  void write(MessageBufferType& buffer) const;
933 
934  template <class MessageBufferType>
935  void read(MessageBufferType& buffer);
936 
937  template<class Serializer>
938  void serializeOp(Serializer& serializer)
939  {
940  serializer(isProducer);
941  serializer(prod);
942  serializer(inj);
943  }
944 
945  static CurrentControl serializationTestObject()
946  {
947  return CurrentControl{false,
948  ::Opm::WellProducerCMode::BHP,
949  ::Opm::WellInjectorCMode::GRUP
950  };
951  }
952  };
953 
955  {
956  public:
957  enum class Quantity { WBP, WBP4, WBP5, WBP9 };
958 
959  double& operator[](const Quantity q)
960  {
961  return this->wbp_[static_cast<std::size_t>(q)];
962  }
963 
964  double operator[](const Quantity q) const
965  {
966  return this->wbp_[static_cast<std::size_t>(q)];
967  }
968 
969  bool operator==(const WellBlockAvgPress& that) const
970  {
971  return this->wbp_ == that.wbp_;
972  }
973 
974  template <class MessageBufferType>
975  void write(MessageBufferType& buffer) const;
976 
977  template <class MessageBufferType>
978  void read(MessageBufferType& buffer);
979 
980  template <class Serializer>
981  void serializeOp(Serializer& serializer)
982  {
983  serializer(this->wbp_);
984  }
985 
986  static WellBlockAvgPress serializationTestObject()
987  {
988  auto wbp = WellBlockAvgPress{};
989 
990  wbp[Quantity::WBP] = 17.29;
991  wbp[Quantity::WBP4] = 2.718;
992  wbp[Quantity::WBP5] = 3.1415;
993  wbp[Quantity::WBP9] = 1.618;
994 
995  return wbp;
996  }
997 
998  private:
999  static constexpr auto NumQuantities =
1000  static_cast<std::size_t>(Quantity::WBP9) + 1;
1001 
1002  std::array<double, NumQuantities> wbp_{};
1003  };
1004 
1006  {
1007  double rate{0.};
1008  double total{0.};
1009  double concentration{0.};
1010 
1011  template<class Serializer>
1012  void serializeOp(Serializer& serializer) {
1013  serializer(rate);
1014  serializer(total);
1015  serializer(concentration);
1016  }
1017 
1018  bool operator==(const WellFiltrate& filtrate) const {
1019  return this->rate == filtrate.rate
1020  && this->total == filtrate.total
1021  && this->concentration == filtrate.concentration;
1022  }
1023 
1024  static WellFiltrate serializationTestObject() {
1025  WellFiltrate res;
1026  res.rate = 1.;
1027  res.total = 10.;
1028  res.concentration = 0.;
1029  return res;
1030  }
1031 
1032  template <class MessageBufferType>
1033  void write(MessageBufferType& buffer) const;
1034 
1035  template <class MessageBufferType>
1036  void read(MessageBufferType& buffer);
1037  };
1038 
1040  {
1041  enum class Item {
1042  Bhp, OilRate, WaterRate, GasRate, ResVRate, LiquidRate,
1043 
1044  // -- Must be last enumerator --
1045  NumItems,
1046  };
1047 
1048  static std::string itemName(const Item p)
1049  {
1050  switch (p) {
1051  case Item::Bhp: return "Bhp";
1052  case Item::OilRate: return "OilRate";
1053  case Item::WaterRate: return "WaterRate";
1054  case Item::GasRate: return "GasRate";
1055  case Item::ResVRate: return "ResVRate";
1056  case Item::LiquidRate: return "LiquidRate";
1057 
1058  case Item::NumItems:
1059  return "Out of bounds (NumItems)";
1060  }
1061 
1062  return "Unknown (" + std::to_string(static_cast<int>(p)) + ')';
1063  }
1064 
1065  static auto serializationTestItems()
1066  {
1067  return std::vector {
1068  std::pair { Item::Bhp , 321.09 },
1069  std::pair { Item::OilRate , 987.65 },
1070  std::pair { Item::WaterRate , 975.31 },
1071  std::pair { Item::GasRate , 765.43 },
1072  std::pair { Item::ResVRate , 876.54 },
1073  std::pair { Item::LiquidRate, 54.32 },
1074  };
1075  }
1076  };
1077 
1079 
1080  struct Well
1081  {
1082  Rates rates{};
1083 
1084  double bhp{0.0};
1085  double thp{0.0};
1086  double temperature{0.0};
1087  int control{0};
1088  double efficiency_scaling_factor{1.0};
1089 
1090  WellFiltrate filtrate;
1091 
1092  ::Opm::WellStatus dynamicStatus { Opm::WellStatus::OPEN };
1093 
1094  std::vector<Connection> connections{};
1095  std::unordered_map<std::size_t, Segment> segments{};
1096  CurrentControl current_control{};
1097  GuideRateValue guide_rates{};
1098  WellControlLimits limits{};
1099 
1100  inline bool flowing() const noexcept;
1101 
1102  template <class MessageBufferType>
1103  void write(MessageBufferType& buffer) const;
1104 
1105  template <class MessageBufferType>
1106  void read(MessageBufferType& buffer);
1107 
1108  const Connection*
1109  find_connection(const Connection::global_index connection_grid_index) const
1110  {
1111  const auto connection =
1112  std::ranges::find_if(this->connections,
1113  [connection_grid_index](const Connection& c)
1114  { return c.index == connection_grid_index; });
1115 
1116  if (connection == this->connections.end()) {
1117  return nullptr;
1118  }
1119 
1120  return &*connection;
1121  }
1122 
1123  Connection*
1124  find_connection(const Connection::global_index connection_grid_index)
1125  {
1126  const auto connection =
1127  std::ranges::find_if(this->connections,
1128  [connection_grid_index](const Connection& c)
1129  { return c.index == connection_grid_index; });
1130 
1131  if (connection == this->connections.end()) {
1132  return nullptr;
1133  }
1134 
1135  return &*connection;
1136  }
1137 
1138  bool operator==(const Well& well2) const
1139  {
1140  return (this->rates == well2.rates)
1141  && (this->bhp == well2.bhp)
1142  && (this->thp == well2.thp)
1143  && (this->temperature == well2.temperature)
1144  && (this->filtrate == well2.filtrate)
1145  && (this->control == well2.control)
1146  && (this->dynamicStatus == well2.dynamicStatus)
1147  && (this->connections == well2.connections)
1148  && (this->segments == well2.segments)
1149  && (this->current_control == well2.current_control)
1150  && (this->guide_rates == well2.guide_rates)
1151  && (this->limits == well2.limits)
1152  ;
1153  }
1154 
1155  bool operator!=(const Well& well2) const
1156  {
1157  return !(*this == well2);
1158  }
1159 
1160  template<class Serializer>
1161  void serializeOp(Serializer& serializer)
1162  {
1163  serializer(rates);
1164  serializer(bhp);
1165  serializer(thp);
1166  serializer(temperature);
1167  serializer(control);
1168  serializer(efficiency_scaling_factor);
1169  serializer(filtrate);
1170  serializer(dynamicStatus);
1171  serializer(connections);
1172  serializer(segments);
1173  serializer(current_control);
1174  serializer(guide_rates);
1175  serializer(limits);
1176  }
1177 
1178  static Well serializationTestObject()
1179  {
1180  return Well {
1181  Rates::serializationTestObject(),
1182  1.0,
1183  2.0,
1184  3.0,
1185  4,
1186  5.0,
1187  WellFiltrate::serializationTestObject(),
1188  ::Opm::WellStatus::SHUT,
1189  {Connection::serializationTestObject()},
1190  {{0, Segment::serializationTestObject()}},
1191  CurrentControl::serializationTestObject(),
1192  GuideRateValue::serializationTestObject(),
1193  WellControlLimits::serializationTestObject()
1194  };
1195  }
1196  };
1197 
1198  class Wells: public std::map<std::string , Well> {
1199  public:
1200 
1201  double get(const std::string& well_name , Rates::opt m) const {
1202  const auto& well = this->find( well_name );
1203  if( well == this->end() ) return 0.0;
1204 
1205  return well->second.rates.get( m, 0.0 );
1206  }
1207 
1208  double get(const std::string& well_name , Rates::opt m, const std::string& tracer_name) const {
1209  const auto& well = this->find( well_name );
1210  if( well == this->end() ) return 0.0;
1211 
1212  return well->second.rates.get( m, 0.0, tracer_name);
1213  }
1214 
1215  double get(const std::string& well_name , Connection::global_index connection_grid_index, Rates::opt m) const {
1216  const auto& witr = this->find( well_name );
1217  if( witr == this->end() ) return 0.0;
1218 
1219  const auto& well = witr->second;
1220  const auto connection =
1221  std::ranges::find_if(well.connections,
1222  [connection_grid_index](const Connection& c)
1223  { return c.index == connection_grid_index; });
1224 
1225  if (connection == well.connections.end()) {
1226  return 0.0;
1227  }
1228 
1229  return connection->rates.get(m, 0.0);
1230  }
1231 
1232  template <class MessageBufferType>
1233  void write(MessageBufferType& buffer) const {
1234  unsigned int size = this->size();
1235  buffer.write(size);
1236  for (const auto& witr : *this) {
1237  const std::string& name = witr.first;
1238  buffer.write(name);
1239  const Well& well = witr.second;
1240  well.write(buffer);
1241  }
1242  }
1243 
1244  template <class MessageBufferType>
1245  void read(MessageBufferType& buffer) {
1246  unsigned int size;
1247  buffer.read(size);
1248  for (std::size_t i = 0; i < size; ++i) {
1249  std::string name;
1250  buffer.read(name);
1251  Well well;
1252  well.read(buffer);
1253  auto result = this->emplace(name, well);
1254  // In case there was already an entry for the well we want to insert, then result.second == false.
1255  // Then we check if this entry is the same as the one we want to insert.
1256  if (!result.second && result.first->second != well) {
1257  OPM_THROW(std::runtime_error, "Received different output data for well " + name + " from more than one process, the output of this simulation will be wrong!");
1258  } else if (!result.second) {
1259  OpmLog::warning("Received consistently duplicated output data for well " + name + " from more than one process - this might be problematic!");
1260  }
1261  }
1262  }
1263 
1264  template<class Serializer>
1265  void serializeOp(Serializer& serializer)
1266  {
1267  serializer(static_cast<std::map<std::string,Well>&>(*this));
1268  }
1269 
1270  static Wells serializationTestObject()
1271  {
1272  Wells w;
1273  w.insert({"test_well", Well::serializationTestObject()});
1274 
1275  return w;
1276  }
1277  };
1278 
1280  {
1281  std::unordered_map<std::string, WellBlockAvgPress> values{};
1282 
1283  template <class MessageBufferType>
1284  void write(MessageBufferType& buffer) const;
1285 
1286  template <class MessageBufferType>
1287  void read(MessageBufferType& buffer);
1288 
1289  bool operator==(const WellBlockAveragePressures& that) const
1290  {
1291  return this->values == that.values;
1292  }
1293 
1294  template <class Serializer>
1295  void serializeOp(Serializer& serializer)
1296  {
1297  serializer(this->values);
1298  }
1299 
1300  static WellBlockAveragePressures serializationTestObject()
1301  {
1302  return {
1303  { { "I-45", WellBlockAvgPress::serializationTestObject() } },
1304  };
1305  }
1306  };
1307 
1308  /* IMPLEMENTATIONS */
1309 
1310  inline bool Rates::has( opt m ) const {
1311  const auto mand = static_cast< enum_size >( this->mask )
1312  & static_cast< enum_size >( m );
1313 
1314  return static_cast< opt >( mand ) == m;
1315  }
1316 
1317  inline double Rates::get( opt m ) const {
1318  if( !this->has( m ) )
1319  throw std::invalid_argument( "Uninitialized value." );
1320 
1321  return this->get_ref( m );
1322  }
1323 
1324  inline double Rates::get( opt m, double default_value ) const {
1325  if( !this->has( m ) ) return default_value;
1326 
1327  return this->get_ref( m );
1328  }
1329 
1330  inline double Rates::get( opt m, double default_value, const std::string& tracer_name) const {
1331  if( !this->has( m ) ) return default_value;
1332 
1333  if( m == opt::tracer && this->tracer.find(tracer_name) == this->tracer.end()) return default_value;
1334 
1335  return this->get_ref( m, tracer_name);
1336  }
1337 
1338  inline Rates& Rates::set( opt m, double value ) {
1339  this->get_ref( m ) = value;
1340 
1341  /* mask |= m */
1342  this->mask = static_cast< opt >(
1343  static_cast< enum_size >( this->mask ) |
1344  static_cast< enum_size >( m )
1345  );
1346 
1347  return *this;
1348  }
1349 
1350  inline Rates& Rates::set( opt m, double value , const std::string& tracer_name ) {
1351  this->get_ref( m , tracer_name) = value;
1352 
1353  /* mask |= m */
1354  this->mask = static_cast< opt >(
1355  static_cast< enum_size >( this->mask ) |
1356  static_cast< enum_size >( m )
1357  );
1358 
1359  return *this;
1360  }
1361 
1362  inline bool Rates::operator==(const Rates& rate) const
1363  {
1364  return mask == rate.mask &&
1365  wat == rate.wat &&
1366  oil == rate.oil &&
1367  gas == rate.gas &&
1368  polymer == rate.polymer &&
1369  solvent == rate.solvent &&
1370  energy == rate.energy &&
1371  dissolved_gas == rate.dissolved_gas &&
1372  vaporized_oil == rate.vaporized_oil &&
1373  reservoir_water == rate.reservoir_water &&
1374  reservoir_oil == rate.reservoir_oil &&
1375  reservoir_gas == rate.reservoir_gas &&
1376  productivity_index_water == rate.productivity_index_water &&
1377  productivity_index_gas == rate.productivity_index_gas &&
1378  productivity_index_oil == rate.productivity_index_oil &&
1379  well_potential_water == rate.well_potential_water &&
1380  well_potential_oil == rate.well_potential_oil &&
1381  well_potential_gas == rate.well_potential_gas &&
1382  brine == rate.brine &&
1383  alq == rate.alq &&
1384  tracer == rate.tracer &&
1385  microbial == rate.microbial &&
1386  oxygen == rate.oxygen &&
1387  urea == rate.urea &&
1388  vaporized_water == rate.vaporized_water &&
1389  mass_gas == rate.mass_gas &&
1390  mass_wat == rate.mass_wat &&
1391  wat_frac == rate.wat_frac;
1392  }
1393 
1394 
1395  /*
1396  * To avoid error-prone and repetitve work when extending rates with new
1397  * values, the get+set methods use this helper get_ref to determine what
1398  * member to manipulate. To add a new option, just add another case
1399  * corresponding to the enum entry in Rates to this function.
1400  *
1401  * This is an implementation detail and understanding this has no
1402  * significant impact on correct use of the class.
1403  */
1404  inline const double& Rates::get_ref( opt m ) const {
1405  switch( m ) {
1406  case opt::wat: return this->wat;
1407  case opt::oil: return this->oil;
1408  case opt::gas: return this->gas;
1409  case opt::polymer: return this->polymer;
1410  case opt::solvent: return this->solvent;
1411  case opt::energy: return this->energy;
1412  case opt::dissolved_gas: return this->dissolved_gas;
1413  case opt::vaporized_oil: return this->vaporized_oil;
1414  case opt::reservoir_water: return this->reservoir_water;
1415  case opt::reservoir_oil: return this->reservoir_oil;
1416  case opt::reservoir_gas: return this->reservoir_gas;
1417  case opt::productivity_index_water: return this->productivity_index_water;
1418  case opt::productivity_index_oil: return this->productivity_index_oil;
1419  case opt::productivity_index_gas: return this->productivity_index_gas;
1420  case opt::well_potential_water: return this->well_potential_water;
1421  case opt::well_potential_oil: return this->well_potential_oil;
1422  case opt::well_potential_gas: return this->well_potential_gas;
1423  case opt::brine: return this->brine;
1424  case opt::alq: return this->alq;
1425  case opt::tracer: /* Should _not_ be called with tracer argument */
1426  break;
1427  case opt::microbial: return this->microbial;
1428  case opt::oxygen: return this->oxygen;
1429  case opt::urea: return this->urea;
1430  case opt::vaporized_water: return this->vaporized_water;
1431  case opt::mass_gas: return this->mass_gas;
1432  case opt::mass_wat: return this->mass_wat;
1433  case opt::wat_frac: return this->wat_frac;
1434  }
1435 
1436  throw std::invalid_argument(
1437  "Unknown value type '"
1438  + std::to_string( static_cast< enum_size >( m ) )
1439  + "'" );
1440 
1441  }
1442 
1443  inline const double& Rates::get_ref( opt m, const std::string& tracer_name ) const {
1444  if (m != opt::tracer)
1445  throw std::logic_error("Logic error - should be called with tracer argument");
1446 
1447  return this->tracer.at(tracer_name);
1448  }
1449 
1450  inline double& Rates::get_ref( opt m ) {
1451  return const_cast< double& >(
1452  static_cast< const Rates* >( this )->get_ref( m )
1453  );
1454  }
1455 
1456  inline double& Rates::get_ref( opt m, const std::string& tracer_name ) {
1457  if (m == opt::tracer) this->tracer.emplace(tracer_name, 0.0);
1458  return this->tracer.at(tracer_name);
1459  }
1460 
1461  bool inline Rates::flowing() const {
1462  return ((this->wat != 0) ||
1463  (this->oil != 0) ||
1464  (this->gas != 0));
1465  }
1466 
1467  inline bool Well::flowing() const noexcept {
1468  return this->rates.flowing();
1469  }
1470 
1471  template <class MessageBufferType>
1472  void Rates::write(MessageBufferType& buffer) const {
1473  buffer.write(this->mask);
1474  buffer.write(this->wat);
1475  buffer.write(this->oil);
1476  buffer.write(this->gas);
1477  buffer.write(this->polymer);
1478  buffer.write(this->solvent);
1479  buffer.write(this->energy);
1480  buffer.write(this->dissolved_gas);
1481  buffer.write(this->vaporized_oil);
1482  buffer.write(this->reservoir_water);
1483  buffer.write(this->reservoir_oil);
1484  buffer.write(this->reservoir_gas);
1485  buffer.write(this->productivity_index_water);
1486  buffer.write(this->productivity_index_oil);
1487  buffer.write(this->productivity_index_gas);
1488  buffer.write(this->well_potential_water);
1489  buffer.write(this->well_potential_oil);
1490  buffer.write(this->well_potential_gas);
1491  buffer.write(this->brine);
1492  buffer.write(this->alq);
1493 
1494  //tracer:
1495  unsigned int size = this->tracer.size();
1496  buffer.write(size);
1497  for (const auto& [name, rate] : this->tracer) {
1498  buffer.write(name);
1499  buffer.write(rate);
1500  }
1501 
1502  buffer.write(this->microbial);
1503  buffer.write(this->oxygen);
1504  buffer.write(this->urea);
1505  buffer.write(this->vaporized_water);
1506  buffer.write(this->mass_gas);
1507  buffer.write(this->mass_wat);
1508  buffer.write(this->wat_frac);
1509  }
1510 
1511  template <class MessageBufferType>
1512  void ConnectionFiltrate::write(MessageBufferType& buffer) const {
1513  buffer.write(this->rate);
1514  buffer.write(this->total);
1515  buffer.write(this->skin_factor);
1516  buffer.write(this->thickness);
1517  buffer.write(this->perm);
1518  buffer.write(this->poro);
1519  buffer.write(this->radius);
1520  buffer.write(this->area_of_flow);
1521  buffer.write(this->flow_factor);
1522  buffer.write(this->fracture_rate);
1523  }
1524 
1525  template <class MessageBufferType>
1526  void Connection::write(MessageBufferType& buffer) const {
1527  buffer.write(this->index);
1528  this->rates.write(buffer);
1529  buffer.write(this->pressure);
1530  buffer.write(this->reservoir_rate);
1531  buffer.write(this->cell_pressure);
1532  buffer.write(this->cell_saturation_water);
1533  buffer.write(this->cell_saturation_gas);
1534  buffer.write(this->effective_Kh);
1535  buffer.write(this->trans_factor);
1536  buffer.write(this->d_factor);
1537  buffer.write(this->compact_mult);
1538  buffer.write(this->lgr_grid);
1539  this->filtrate.write(buffer);
1540  this->fracture.write(buffer);
1541  this->fract.write(buffer);
1542  }
1543 
1544  template <class MessageBufferType>
1545  void Segment::write(MessageBufferType& buffer) const
1546  {
1547  buffer.write(this->segNumber);
1548  this->rates.write(buffer);
1549  this->pressures.write(buffer);
1550  this->velocity.write(buffer);
1551  this->holdup.write(buffer);
1552  this->viscosity.write(buffer);
1553  this->density.write(buffer);
1554  }
1555 
1556  template <class MessageBufferType>
1557  void CurrentControl::write(MessageBufferType& buffer) const
1558  {
1559  buffer.write(this->isProducer);
1560  if (this->isProducer) {
1561  buffer.write(this->prod);
1562  }
1563  else {
1564  buffer.write(this->inj);
1565  }
1566  }
1567 
1568  template <class MessageBufferType>
1569  void WellBlockAvgPress::write(MessageBufferType& buffer) const
1570  {
1571  for (const auto& quantity : this->wbp_) {
1572  buffer.write(quantity);
1573  }
1574  }
1575 
1576  template <class MessageBufferType>
1577  void WellFiltrate::write(MessageBufferType& buffer) const
1578  {
1579  buffer.write(this->rate);
1580  buffer.write(this->total);
1581  buffer.write(this->concentration);
1582  }
1583 
1584  template <class MessageBufferType>
1585  void Well::write(MessageBufferType& buffer) const
1586  {
1587  this->rates.write(buffer);
1588 
1589  buffer.write(this->bhp);
1590  buffer.write(this->thp);
1591  buffer.write(this->temperature);
1592  buffer.write(this->control);
1593  buffer.write(this->efficiency_scaling_factor);
1594 
1595  this->filtrate.write(buffer);
1596 
1597  {
1598  const auto status = ::Opm::WellStatus2String(this->dynamicStatus);
1599  buffer.write(status);
1600  }
1601 
1602  {
1603  const unsigned int size = this->connections.size();
1604  buffer.write(size);
1605 
1606  for (const Connection& comp : this->connections) {
1607  comp.write(buffer);
1608  }
1609  }
1610 
1611  {
1612  const auto nSeg =
1613  static_cast<unsigned int>(this->segments.size());
1614  buffer.write(nSeg);
1615 
1616  for (const auto& seg : this->segments) {
1617  seg.second.write(buffer);
1618  }
1619  }
1620 
1621  this->current_control.write(buffer);
1622  this->guide_rates.write(buffer);
1623  this->limits.write(buffer);
1624  }
1625 
1626  template <class MessageBufferType>
1627  void WellBlockAveragePressures::write(MessageBufferType& buffer) const
1628  {
1629  buffer.write(this->values.size());
1630 
1631  for (const auto& [well, value] : this->values) {
1632  buffer.write(well);
1633  value.write(buffer);
1634  }
1635  }
1636 
1637  template <class MessageBufferType>
1638  void Rates::read(MessageBufferType& buffer) {
1639  buffer.read(this->mask);
1640  buffer.read(this->wat);
1641  buffer.read(this->oil);
1642  buffer.read(this->gas);
1643  buffer.read(this->polymer);
1644  buffer.read(this->solvent);
1645  buffer.read(this->energy);
1646  buffer.read(this->dissolved_gas);
1647  buffer.read(this->vaporized_oil);
1648  buffer.read(this->reservoir_water);
1649  buffer.read(this->reservoir_oil);
1650  buffer.read(this->reservoir_gas);
1651  buffer.read(this->productivity_index_water);
1652  buffer.read(this->productivity_index_oil);
1653  buffer.read(this->productivity_index_gas);
1654  buffer.read(this->well_potential_water);
1655  buffer.read(this->well_potential_oil);
1656  buffer.read(this->well_potential_gas);
1657  buffer.read(this->brine);
1658  buffer.read(this->alq);
1659 
1660  //tracer:
1661  unsigned int size;
1662  buffer.read(size);
1663  for (std::size_t i = 0; i < size; ++i) {
1664  std::string tracer_name;
1665  buffer.read(tracer_name);
1666  double tracer_rate;
1667  buffer.read(tracer_rate);
1668  this->tracer.emplace(tracer_name, tracer_rate);
1669  }
1670 
1671  buffer.read(this->microbial);
1672  buffer.read(this->oxygen);
1673  buffer.read(this->urea);
1674  buffer.read(this->vaporized_water);
1675  buffer.read(this->mass_gas);
1676  buffer.read(this->mass_wat);
1677  buffer.read(this->wat_frac);
1678  }
1679 
1680  template <class MessageBufferType>
1681  void ConnectionFiltrate::read(MessageBufferType& buffer) {
1682  buffer.read(this->rate);
1683  buffer.read(this->total);
1684  buffer.read(this->skin_factor);
1685  buffer.read(this->thickness);
1686  buffer.read(this->perm);
1687  buffer.read(this->poro);
1688  buffer.read(this->radius);
1689  buffer.read(this->area_of_flow);
1690  buffer.read(this->flow_factor);
1691  buffer.read(this->fracture_rate);
1692  }
1693 
1694  template <class MessageBufferType>
1695  void Connection::read(MessageBufferType& buffer) {
1696  buffer.read(this->index);
1697  this->rates.read(buffer);
1698  buffer.read(this->pressure);
1699  buffer.read(this->reservoir_rate);
1700  buffer.read(this->cell_pressure);
1701  buffer.read(this->cell_saturation_water);
1702  buffer.read(this->cell_saturation_gas);
1703  buffer.read(this->effective_Kh);
1704  buffer.read(this->trans_factor);
1705  buffer.read(this->d_factor);
1706  buffer.read(this->compact_mult);
1707  buffer.read(this->lgr_grid);
1708  this->filtrate.read(buffer);
1709  this->fracture.read(buffer);
1710  this->fract.read(buffer);
1711  }
1712 
1713  template <class MessageBufferType>
1714  void Segment::read(MessageBufferType& buffer)
1715  {
1716  buffer.read(this->segNumber);
1717  this->rates.read(buffer);
1718  this->pressures.read(buffer);
1719  this->velocity.read(buffer);
1720  this->holdup.read(buffer);
1721  this->viscosity.read(buffer);
1722  this->density.read(buffer);
1723  }
1724 
1725  template <class MessageBufferType>
1726  void CurrentControl::read(MessageBufferType& buffer)
1727  {
1728  buffer.read(this->isProducer);
1729  if (this->isProducer) {
1730  buffer.read(this->prod);
1731  }
1732  else {
1733  buffer.read(this->inj);
1734  }
1735  }
1736 
1737  template <class MessageBufferType>
1738  void WellBlockAvgPress::read(MessageBufferType& buffer)
1739  {
1740  for (auto& quantity : this->wbp_) {
1741  buffer.read(quantity);
1742  }
1743  }
1744 
1745  template <class MessageBufferType>
1746  void WellFiltrate::read(MessageBufferType& buffer)
1747  {
1748  buffer.read(this->rate);
1749  buffer.read(this->total);
1750  buffer.read(this->concentration);
1751  }
1752 
1753  template <class MessageBufferType>
1754  void Well::read(MessageBufferType& buffer)
1755  {
1756  this->rates.read(buffer);
1757 
1758  buffer.read(this->bhp);
1759  buffer.read(this->thp);
1760  buffer.read(this->temperature);
1761  buffer.read(this->control);
1762  buffer.read(this->efficiency_scaling_factor);
1763 
1764  this->filtrate.read(buffer);
1765 
1766  {
1767  auto status = std::string{};
1768  buffer.read(status);
1769  this->dynamicStatus = ::Opm::WellStatusFromString(status);
1770  }
1771 
1772  // Connection information
1773  {
1774  unsigned int size = 0;
1775  buffer.read(size);
1776 
1777  this->connections.resize(size);
1778  for (auto& connection : this->connections) {
1779  connection.read(buffer);
1780  }
1781  }
1782 
1783  // Segment information (if applicable)
1784  const auto nSeg = [&buffer]() -> unsigned int
1785  {
1786  auto n = 0u;
1787  buffer.read(n);
1788 
1789  return n;
1790  }();
1791 
1792  for (auto segID = 0*nSeg; segID < nSeg; ++segID) {
1793  auto seg = Segment{};
1794  seg.read(buffer);
1795 
1796  const auto segNumber = seg.segNumber;
1797  this->segments.emplace(segNumber, std::move(seg));
1798  }
1799 
1800  this->current_control.read(buffer);
1801  this->guide_rates.read(buffer);
1802  this->limits.read(buffer);
1803  }
1804 
1805  template <class MessageBufferType>
1806  void WellBlockAveragePressures::read(MessageBufferType& buffer)
1807  {
1808  const auto numWells = [&buffer, this]()
1809  {
1810  auto size = 0*this->values.size();
1811  buffer.read(size);
1812 
1813  return size;
1814  }();
1815 
1816  auto wellName = std::string{};
1817  for (auto well = 0*numWells; well < numWells; ++well) {
1818  buffer.read(wellName);
1819 
1820  this->values[wellName].read(buffer);
1821  }
1822  }
1823 
1824 }} // Opm::data
1825 
1826 #endif // OPM_OUTPUT_WELLS_HPP
Definition: Wells.hpp:671
double avg
Arithmetic average.
Definition: Wells.hpp:368
Statistics collection for a single quantity.
Definition: Wells.hpp:365
Definition: UDQActive.cpp:79
bool has(opt) const
Query if a value is set.
Definition: Wells.hpp:1310
void write(MessageBufferType &buffer) const
MPI communication protocol–serialisation operation.
Definition: Wells.hpp:499
bool operator==(const ConnectionFracturing &that) const
Equality predicate.
Definition: Wells.hpp:488
Rates & set(opt m, double value)
Set the value specified by m.
Definition: Wells.hpp:1338
void serializeOp(Serializer &serializer)
Convert between byte array and object representation.
Definition: Wells.hpp:473
Definition: Wells.hpp:603
static ConnectionFracturing serializationTestObject()
Create a serialisation test object.
Definition: Wells.hpp:455
Definition: Wells.hpp:1005
Definition: Wells.hpp:1279
bool operator==(const Statistics &that) const
Equality predicate.
Definition: Wells.hpp:410
std::size_t numCells
Sample size.
Definition: Wells.hpp:443
double max
Maximum value.
Definition: Wells.hpp:371
Definition: Wells.hpp:1080
Statistics width
Statistical measures for connection&#39;s fracture fracture width.
Definition: Wells.hpp:452
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Definition: Wells.hpp:272
Definition: Wells.hpp:216
Definition: Wells.hpp:42
Definition: GuideRateValue.hpp:31
double get(opt m) const
Read the value indicated by m.
Definition: Wells.hpp:1317
Definition: Wells.hpp:859
ConnectionFracturing fract
Connection level fracturing statistics.
Definition: Wells.hpp:542
Definition: Wells.hpp:819
Definition: UDQActive.cpp:103
Definition: Wells.hpp:954
Definition: Wells.hpp:786
void read(MessageBufferType &buffer)
MPI communication protocol–deserialisation operation.
Definition: Wells.hpp:509
Connection Level Fracturing Statistics.
Definition: Wells.hpp:362
double stdev
Unbiased sample standard deviation.
Definition: Wells.hpp:379
Definition: Wells.hpp:912
Definition: Wells.hpp:518
Statistics rate
Statistical measures for connection&#39;s fracture fracture flow rate.
Definition: Wells.hpp:449
Statistics press
Statistical measures for connection&#39;s fracture pressures.
Definition: Wells.hpp:446
void serializeOp(Serializer &serializer)
Convert between byte array and object representation.
Definition: Wells.hpp:395
Definition: Wells.hpp:1039
static Statistics serializationTestObject()
Create a serialization test object.
Definition: Wells.hpp:382
void read(MessageBufferType &buffer)
MPI communication protocol–deserialisation operation.
Definition: Wells.hpp:431
double min
Minimum value.
Definition: Wells.hpp:374
Definition: Wells.hpp:1198
bool flowing() const
Returns true if any of the rates oil, gas, water is nonzero.
Definition: Wells.hpp:1461
Class for (de-)serializing.
Definition: Serializer.hpp:95
void write(MessageBufferType &buffer) const
MPI communication protocol–serialisation operation.
Definition: Wells.hpp:421