20 #ifndef OPM_OUTPUT_WELLS_HPP
21 #define OPM_OUTPUT_WELLS_HPP
25 #include <initializer_list>
29 #include <type_traits>
30 #include <unordered_map>
33 #include <opm/json/JsonObject.hpp>
34 #include <opm/output/data/GuideRateValue.hpp>
35 #include <opm/input/eclipse/Schedule/Well/Well.hpp>
53 enum class opt : uint32_t {
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),
77 using enum_size = std::underlying_type< opt >::type;
80 inline bool has( opt )
const;
84 inline double get( opt m )
const;
87 inline double get( opt m,
double default_value )
const;
88 inline double get( opt m,
double default_value ,
const std::string& tracer_name )
const;
92 inline Rates&
set( opt m,
double value );
93 inline Rates&
set( opt m,
double value ,
const std::string& tracer_name );
98 template <
class MessageBufferType>
99 void write(MessageBufferType& buffer)
const;
100 template <
class MessageBufferType>
101 void read(MessageBufferType& buffer);
103 bool operator==(
const Rates& rat2)
const;
107 double& get_ref( opt );
108 double& get_ref( opt,
const std::string& tracer_name );
109 const double& get_ref( opt )
const;
110 const double& get_ref( opt,
const std::string& tracer_name )
const;
112 opt mask =
static_cast< opt
>( 0 );
117 double polymer = 0.0;
118 double solvent = 0.0;
120 double dissolved_gas = 0.0;
121 double vaporized_oil = 0.0;
122 double reservoir_water = 0.0;
123 double reservoir_oil = 0.0;
124 double reservoir_gas = 0.0;
125 double productivity_index_water = 0.0;
126 double productivity_index_oil = 0.0;
127 double productivity_index_gas = 0.0;
128 double well_potential_water = 0.0;
129 double well_potential_oil = 0.0;
130 double well_potential_gas = 0.0;
133 std::map<std::string, double> tracer;
138 using global_index = size_t;
139 static const constexpr
int restart_size = 6;
144 double reservoir_rate;
145 double cell_pressure;
146 double cell_saturation_water;
147 double cell_saturation_gas;
151 bool operator==(
const Connection& conn2)
const
153 return index == conn2.index &&
154 rates == conn2.rates &&
155 pressure == conn2.pressure &&
156 reservoir_rate == conn2.reservoir_rate &&
157 cell_pressure == conn2.cell_pressure &&
158 cell_saturation_water == conn2.cell_saturation_water &&
159 cell_saturation_gas == conn2.cell_saturation_gas &&
160 effective_Kh == conn2.effective_Kh;
163 template <
class MessageBufferType>
164 void write(MessageBufferType& buffer)
const;
165 template <
class MessageBufferType>
166 void read(MessageBufferType& buffer);
173 enum class Value : std::size_t {
174 Pressure, PDrop, PDropHydrostatic, PDropAccel, PDropFriction,
177 double& operator[](
const Value i)
179 return this->values_[this->index(i)];
182 double operator[](
const Value i)
const
184 return this->values_[this->index(i)];
189 return this->values_ == segpres2.values_;
192 template <
class MessageBufferType>
193 void write(MessageBufferType& buffer)
const
195 for (
const auto& value : this->values_) {
200 template <
class MessageBufferType>
201 void read(MessageBufferType& buffer)
203 for (
auto& value : this->values_) {
209 constexpr
static std::size_t numvals = 5;
211 std::array<double, numvals> values_ = {0};
213 std::size_t index(
const Value ix)
const
215 return static_cast<std::size_t
>(ix);
222 std::size_t segNumber;
224 bool operator==(
const Segment& seg2)
const
226 return rates == seg2.rates &&
227 pressures == seg2.pressures &&
228 segNumber == seg2.segNumber;
231 template <
class MessageBufferType>
232 void write(MessageBufferType& buffer)
const;
234 template <
class MessageBufferType>
235 void read(MessageBufferType& buffer);
239 bool isProducer{
true};
241 ::Opm::Well::ProducerCMode prod {
242 ::Opm::Well::ProducerCMode::CMODE_UNDEFINED
245 ::Opm::Well::InjectorCMode inj {
246 ::Opm::Well::InjectorCMode::CMODE_UNDEFINED
251 return (this->isProducer == rhs.isProducer)
252 && ((this->isProducer && (this->prod == rhs.prod)) ||
253 (!this->isProducer && (this->inj == rhs.inj)));
258 if (this->inj == ::Opm::Well::InjectorCMode::CMODE_UNDEFINED)
259 json_data.add_item(
"inj",
"CMODE_UNDEFINED");
261 json_data.add_item(
"inj", ::Opm::Well::InjectorCMode2String(this->inj));
263 if (this->prod == ::Opm::Well::ProducerCMode::CMODE_UNDEFINED)
264 json_data.add_item(
"prod",
"CMODE_UNDEFINED");
266 json_data.add_item(
"prod", ::Opm::Well::ProducerCMode2String(this->prod));
269 template <
class MessageBufferType>
270 void write(MessageBufferType& buffer)
const;
272 template <
class MessageBufferType>
273 void read(MessageBufferType& buffer);
280 double temperature{0.0};
283 ::Opm::Well::Status dynamicStatus { Opm::Well::Status::OPEN };
285 std::vector< Connection > connections{};
286 std::unordered_map<std::size_t, Segment> segments{};
290 inline bool flowing()
const noexcept;
291 template <
class MessageBufferType>
292 void write(MessageBufferType& buffer)
const;
293 template <
class MessageBufferType>
294 void read(MessageBufferType& buffer);
298 const Connection* find_connection(Connection::global_index connection_grid_index)
const {
299 const auto connection = std::find_if( this->connections.begin() ,
300 this->connections.end() ,
302 return c.index == connection_grid_index; });
304 if( connection == this->connections.end() )
310 Connection* find_connection(Connection::global_index connection_grid_index) {
311 auto connection = std::find_if( this->connections.begin() ,
312 this->connections.end() ,
314 return c.index == connection_grid_index; });
316 if( connection == this->connections.end() )
322 bool operator==(
const Well& well2)
const
324 return rates == well2.rates &&
327 temperature == well2.temperature &&
328 control == well2.control &&
329 connections == well2.connections &&
330 segments == well2.segments &&
331 current_control == well2.current_control &&
332 guide_rates == well2.guide_rates;
337 class Wells:
public std::map<std::string , Well> {
340 double get(
const std::string& well_name , Rates::opt m)
const {
341 const auto& well = this->find( well_name );
342 if( well == this->end() )
return 0.0;
344 return well->second.rates.get( m, 0.0 );
347 double get(
const std::string& well_name , Rates::opt m,
const std::string& tracer_name)
const {
348 const auto& well = this->find( well_name );
349 if( well == this->end() )
return 0.0;
351 return well->second.rates.get( m, 0.0, tracer_name);
354 double get(
const std::string& well_name , Connection::global_index connection_grid_index, Rates::opt m)
const {
355 const auto& witr = this->find( well_name );
356 if( witr == this->end() )
return 0.0;
358 const auto& well = witr->second;
359 const auto& connection = std::find_if( well.connections.begin() ,
360 well.connections.end() ,
362 return c.index == connection_grid_index; });
364 if( connection == well.connections.end() )
367 return connection->rates.get( m, 0.0 );
370 template <
class MessageBufferType>
371 void write(MessageBufferType& buffer)
const {
372 unsigned int size = this->size();
374 for (
const auto& witr : *
this) {
375 const std::string& name = witr.first;
377 const Well& well = witr.second;
382 template <
class MessageBufferType>
383 void read(MessageBufferType& buffer) {
386 for (
size_t i = 0; i < size; ++i) {
391 this->emplace(name, well);
396 for (
const auto& [wname, well] : *
this) {
397 auto json_well = json_data.add_object(wname);
398 well.init_json(json_well);
405 this->init_json(json_data);
415 const auto mand =
static_cast< enum_size
>( this->mask )
416 &
static_cast< enum_size
>( m );
418 return static_cast< opt
>( mand ) == m;
422 if( !this->
has( m ) )
423 throw std::invalid_argument(
"Uninitialized value." );
425 return this->get_ref( m );
428 inline double Rates::get( opt m,
double default_value )
const {
429 if( !this->
has( m ) )
return default_value;
431 return this->get_ref( m );
434 inline double Rates::get( opt m,
double default_value,
const std::string& tracer_name)
const {
435 if( !this->
has( m ) )
return default_value;
437 if( m == opt::tracer && this->tracer.find(tracer_name) == this->tracer.end())
return default_value;
439 return this->get_ref( m, tracer_name);
443 this->get_ref( m ) = value;
446 this->mask =
static_cast< opt
>(
447 static_cast< enum_size
>( this->mask ) |
448 static_cast< enum_size
>( m )
454 inline Rates&
Rates::set( opt m,
double value ,
const std::string& tracer_name ) {
455 this->get_ref( m , tracer_name) = value;
458 this->mask =
static_cast< opt
>(
459 static_cast< enum_size
>( this->mask ) |
460 static_cast< enum_size
>( m )
466 inline bool Rates::operator==(
const Rates& rate)
const
468 return mask == rate.mask &&
472 polymer == rate.polymer &&
473 solvent == rate.solvent &&
474 energy == rate.energy &&
475 dissolved_gas == rate.dissolved_gas &&
476 vaporized_oil == rate.vaporized_oil &&
477 reservoir_water == rate.reservoir_water &&
478 reservoir_oil == rate.reservoir_oil &&
479 reservoir_gas == rate.reservoir_gas &&
480 productivity_index_water == rate.productivity_index_water &&
481 productivity_index_gas == rate.productivity_index_gas &&
482 productivity_index_oil == rate.productivity_index_oil &&
483 well_potential_water == rate.well_potential_water &&
484 well_potential_oil == rate.well_potential_oil &&
485 well_potential_gas == rate.well_potential_gas &&
486 brine == rate.brine &&
488 tracer == rate.tracer &&
502 inline const double& Rates::get_ref( opt m )
const {
504 case opt::wat:
return this->wat;
505 case opt::oil:
return this->oil;
506 case opt::gas:
return this->gas;
507 case opt::polymer:
return this->polymer;
508 case opt::solvent:
return this->solvent;
509 case opt::energy:
return this->energy;
510 case opt::dissolved_gas:
return this->dissolved_gas;
511 case opt::vaporized_oil:
return this->vaporized_oil;
512 case opt::reservoir_water:
return this->reservoir_water;
513 case opt::reservoir_oil:
return this->reservoir_oil;
514 case opt::reservoir_gas:
return this->reservoir_gas;
515 case opt::productivity_index_water:
return this->productivity_index_water;
516 case opt::productivity_index_oil:
return this->productivity_index_oil;
517 case opt::productivity_index_gas:
return this->productivity_index_gas;
518 case opt::well_potential_water:
return this->well_potential_water;
519 case opt::well_potential_oil:
return this->well_potential_oil;
520 case opt::well_potential_gas:
return this->well_potential_gas;
521 case opt::brine:
return this->brine;
522 case opt::alq:
return this->alq;
525 case opt::micp:
return this->micp;
528 throw std::invalid_argument(
529 "Unknown value type '"
530 + std::to_string(
static_cast< enum_size
>( m ) )
535 inline const double& Rates::get_ref( opt m,
const std::string& tracer_name )
const {
536 if (m != opt::tracer)
537 throw std::logic_error(
"Logic error - should be called with tracer argument");
539 return this->tracer.at(tracer_name);
542 inline double& Rates::get_ref( opt m ) {
543 return const_cast< double&
>(
544 static_cast< const Rates*
>( this )->get_ref( m )
548 inline double& Rates::get_ref( opt m,
const std::string& tracer_name ) {
549 if (m == opt::tracer) this->tracer.emplace(tracer_name, 0.0);
550 return this->tracer.at(tracer_name);
555 if (this->
has(opt::wat))
556 json_data.add_item(
"wat", this->
get(opt::wat));
558 if (this->
has(opt::oil))
559 json_data.add_item(
"oil", this->
get(opt::oil));
561 if (this->
has(opt::gas))
562 json_data.add_item(
"gas", this->
get(opt::gas));
567 return ((this->wat != 0) ||
572 inline bool Well::flowing() const noexcept {
576 template <
class MessageBufferType>
577 void Rates::write(MessageBufferType& buffer)
const {
578 buffer.write(this->mask);
579 buffer.write(this->wat);
580 buffer.write(this->oil);
581 buffer.write(this->gas);
582 buffer.write(this->polymer);
583 buffer.write(this->solvent);
584 buffer.write(this->energy);
585 buffer.write(this->dissolved_gas);
586 buffer.write(this->vaporized_oil);
587 buffer.write(this->reservoir_water);
588 buffer.write(this->reservoir_oil);
589 buffer.write(this->reservoir_gas);
590 buffer.write(this->productivity_index_water);
591 buffer.write(this->productivity_index_oil);
592 buffer.write(this->productivity_index_gas);
593 buffer.write(this->well_potential_water);
594 buffer.write(this->well_potential_oil);
595 buffer.write(this->well_potential_gas);
596 buffer.write(this->brine);
597 buffer.write(this->alq);
599 unsigned int size = this->tracer.size();
601 for (
const auto& [name, rate] : this->tracer) {
605 buffer.write(this->micp);
608 template <
class MessageBufferType>
609 void Connection::write(MessageBufferType& buffer)
const {
610 buffer.write(this->index);
611 this->rates.write(buffer);
612 buffer.write(this->pressure);
613 buffer.write(this->reservoir_rate);
614 buffer.write(this->cell_pressure);
615 buffer.write(this->cell_saturation_water);
616 buffer.write(this->cell_saturation_gas);
617 buffer.write(this->effective_Kh);
618 buffer.write(this->trans_factor);
623 auto json_rates = json_data.add_object(
"rates");
624 this->rates.init_json(json_rates);
626 json_data.add_item(
"global_index",
static_cast<int>(this->index));
627 json_data.add_item(
"pressure", this->pressure);
628 json_data.add_item(
"reservoir_rate", this->reservoir_rate);
629 json_data.add_item(
"cell_pressure", this->cell_pressure);
630 json_data.add_item(
"swat", this->cell_saturation_water);
631 json_data.add_item(
"sgas", this->cell_saturation_gas);
632 json_data.add_item(
"Kh", this->effective_Kh);
633 json_data.add_item(
"trans_factor", this->trans_factor);
636 template <
class MessageBufferType>
637 void Segment::write(MessageBufferType& buffer)
const {
638 buffer.write(this->segNumber);
639 this->rates.write(buffer);
640 this->pressures.write(buffer);
643 template <
class MessageBufferType>
644 void CurrentControl::write(MessageBufferType& buffer)
const
646 buffer.write(this->isProducer);
647 if (this->isProducer) {
648 buffer.write(this->prod);
651 buffer.write(this->inj);
655 template <
class MessageBufferType>
656 void Well::write(MessageBufferType& buffer)
const {
657 this->rates.write(buffer);
658 buffer.write(this->bhp);
659 buffer.write(this->thp);
660 buffer.write(this->temperature);
661 buffer.write(this->control);
664 const auto status = ::Opm::Well::Status2String(this->dynamicStatus);
665 buffer.write(status);
668 unsigned int size = this->connections.size();
670 for (
const Connection& comp : this->connections)
675 static_cast<unsigned int>(this->segments.size());
678 for (
const auto& seg : this->segments) {
679 seg.second.write(buffer);
683 this->current_control.write(buffer);
684 this->guide_rates.write(buffer);
687 template <
class MessageBufferType>
688 void Rates::read(MessageBufferType& buffer) {
689 buffer.read(this->mask);
690 buffer.read(this->wat);
691 buffer.read(this->oil);
692 buffer.read(this->gas);
693 buffer.read(this->polymer);
694 buffer.read(this->solvent);
695 buffer.read(this->energy);
696 buffer.read(this->dissolved_gas);
697 buffer.read(this->vaporized_oil);
698 buffer.read(this->reservoir_water);
699 buffer.read(this->reservoir_oil);
700 buffer.read(this->reservoir_gas);
701 buffer.read(this->productivity_index_water);
702 buffer.read(this->productivity_index_oil);
703 buffer.read(this->productivity_index_gas);
704 buffer.read(this->well_potential_water);
705 buffer.read(this->well_potential_oil);
706 buffer.read(this->well_potential_gas);
707 buffer.read(this->brine);
708 buffer.read(this->alq);
712 for (
size_t i = 0; i < size; ++i) {
713 std::string tracer_name;
714 buffer.read(tracer_name);
716 buffer.read(tracer_rate);
717 this->tracer.emplace(tracer_name, tracer_rate);
719 buffer.read(this->micp);
722 template <
class MessageBufferType>
723 void Connection::read(MessageBufferType& buffer) {
724 buffer.read(this->index);
725 this->rates.read(buffer);
726 buffer.read(this->pressure);
727 buffer.read(this->reservoir_rate);
728 buffer.read(this->cell_pressure);
729 buffer.read(this->cell_saturation_water);
730 buffer.read(this->cell_saturation_gas);
731 buffer.read(this->effective_Kh);
732 buffer.read(this->trans_factor);
735 template <
class MessageBufferType>
736 void Segment::read(MessageBufferType& buffer) {
737 buffer.read(this->segNumber);
738 this->rates.read(buffer);
739 this->pressures.read(buffer);
742 template <
class MessageBufferType>
743 void CurrentControl::read(MessageBufferType& buffer)
745 buffer.read(this->isProducer);
746 if (this->isProducer) {
747 buffer.read(this->prod);
750 buffer.read(this->inj);
754 template <
class MessageBufferType>
755 void Well::read(MessageBufferType& buffer) {
756 this->rates.read(buffer);
757 buffer.read(this->bhp);
758 buffer.read(this->thp);
759 buffer.read(this->temperature);
760 buffer.read(this->control);
763 auto status = std::string{};
765 this->dynamicStatus = ::Opm::Well::StatusFromString(status);
769 unsigned int size = 0.0;
771 this->connections.resize(size);
772 for (
size_t i = 0; i < size; ++i)
774 auto& comp = this->connections[ i ];
779 const auto nSeg = [&buffer]() ->
unsigned int
787 for (
auto segID = 0*nSeg; segID < nSeg; ++segID) {
788 auto seg = Segment{};
791 const auto segNumber = seg.segNumber;
792 this->segments.emplace(segNumber, std::move(seg));
795 this->current_control.read(buffer);
796 this->guide_rates.read(buffer);
800 auto json_connections = json_data.add_array(
"connections");
801 for (
const auto& conn : this->connections) {
802 auto json_conn = json_connections.add_object();
803 conn.init_json(json_conn);
805 auto json_rates = json_data.add_object(
"rates");
806 this->rates.init_json(json_rates);
808 json_data.add_item(
"bhp", this->bhp);
809 json_data.add_item(
"thp", this->thp);
810 json_data.add_item(
"temperature", this->temperature);
811 json_data.add_item(
"status", ::Opm::Well::Status2String(this->dynamicStatus));
813 auto json_control = json_data.add_object(
"control");
814 this->current_control.init_json(json_control);
816 auto json_guiderate = json_data.add_object(
"guiderate");
817 this->guide_rates.init_json(json_guiderate);
Definition: JsonObject.hpp:32
Definition: GuideRateValue.hpp:32
bool flowing() const
Returns true if any of the rates oil, gas, water is nonzero.
Definition: Wells.hpp:566
double get(opt m) const
Read the value indicated by m.
Definition: Wells.hpp:421
Rates & set(opt m, double value)
Set the value specified by m.
Definition: Wells.hpp:442
bool has(opt) const
Query if a value is set.
Definition: Wells.hpp:414
Definition: Wells.hpp:171
Definition: Wells.hpp:337
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:29
Definition: Wells.hpp:137
Definition: Wells.hpp:238
Definition: Wells.hpp:219
Definition: Wells.hpp:276