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 <initializer_list>
24 #include <map>
25 #include <algorithm>
26 #include <stdexcept>
27 #include <string>
28 #include <type_traits>
29 #include <vector>
30 
31 namespace Opm {
32 
33  namespace data {
34 
35  class Rates {
36  /* Methods are defined inline for performance, as the actual *work* done
37  * is trivial, but somewhat frequent (typically once per time step per
38  * completion per well).
39  *
40  * To add a new rate type, add an entry in the enum with the correct
41  * shift, and if needed, increase the size type. Add a member variable
42  * and a new case in get_ref.
43  */
44 
45  public:
46  Rates() = default;
47  enum class opt : uint32_t {
48  wat = (1 << 0),
49  oil = (1 << 1),
50  gas = (1 << 2),
51  polymer = (1 << 3),
52  solvent = (1 << 4),
53  };
54 
55  using enum_size = std::underlying_type< opt >::type;
56 
58  inline bool has( opt ) const;
59 
62  inline double get( opt m ) const;
65  inline double get( opt m, double default_value ) const;
69  inline Rates& set( opt m, double value );
70 
72  inline bool any() const noexcept;
73 
74  private:
75  double& get_ref( opt );
76  const double& get_ref( opt ) const;
77 
78  opt mask = static_cast< opt >( 0 );
79 
80  double wat = 0.0;
81  double oil = 0.0;
82  double gas = 0.0;
83  double polymer = 0.0;
84  double solvent = 0.0;
85  };
86 
87  struct Completion {
88  using active_index = size_t;
89  static const constexpr int restart_size = 2;
90 
91  active_index index;
92  Rates rates;
93  double pressure;
94  double reservoir_rate;
95  };
96 
97  struct Well {
98  Rates rates;
99  double bhp;
100  double thp;
101  double temperature;
102  int control;
103  std::vector< Completion > completions;
104 
105  inline bool flowing() const noexcept;
106  };
107 
108 
109  class WellRates : public std::map<std::string , Well> {
110  public:
111 
112  double get(const std::string& well_name , Rates::opt m) const {
113  const auto& well = this->find( well_name );
114  if( well == this->end() ) return 0.0;
115 
116  return well->second.rates.get( m, 0.0 );
117  }
118 
119 
120  double get(const std::string& well_name , Completion::active_index completion_grid_index, Rates::opt m) const {
121  const auto& witr = this->find( well_name );
122  if( witr == this->end() ) return 0.0;
123 
124  const auto& well = witr->second;
125  const auto& completion = std::find_if( well.completions.begin() ,
126  well.completions.end() ,
127  [=]( const Completion& c ) {
128  return c.index == completion_grid_index; });
129 
130  if( completion == well.completions.end() )
131  return 0.0;
132 
133  return completion->rates.get( m, 0.0 );
134  }
135 
136  };
137 
138  using Wells = WellRates;
139 
140  /* IMPLEMENTATIONS */
141 
142  inline bool Rates::has( opt m ) const {
143  const auto mand = static_cast< enum_size >( this->mask )
144  & static_cast< enum_size >( m );
145 
146  return static_cast< opt >( mand ) == m;
147  }
148 
149  inline double Rates::get( opt m ) const {
150  if( !this->has( m ) )
151  throw std::invalid_argument( "Uninitialized value." );
152 
153  return this->get_ref( m );
154  }
155 
156  inline double Rates::get( opt m, double default_value ) const {
157  if( !this->has( m ) ) return default_value;
158 
159  return this->get_ref( m );
160  }
161 
162  inline Rates& Rates::set( opt m, double value ) {
163  this->get_ref( m ) = value;
164  /* mask |= m */
165  this->mask = static_cast< opt >(
166  static_cast< enum_size >( this->mask ) |
167  static_cast< enum_size >( m )
168  );
169 
170  return *this;
171  }
172 
173 
174  /*
175  * To avoid error-prone and repetitve work when extending rates with new
176  * values, the get+set methods use this helper get_ref to determine what
177  * member to manipulate. To add a new option, just add another case
178  * corresponding to the enum entry in Rates to this function.
179  *
180  * This is an implementation detail and understanding this has no
181  * significant impact on correct use of the class.
182  */
183  inline const double& Rates::get_ref( opt m ) const {
184  switch( m ) {
185  case opt::wat: return this->wat;
186  case opt::oil: return this->oil;
187  case opt::gas: return this->gas;
188  case opt::polymer: return this->polymer;
189  case opt::solvent: return this->solvent;
190  }
191 
192  throw std::invalid_argument(
193  "Unknown value type '"
194  + std::to_string( static_cast< enum_size >( m ) )
195  + "'" );
196 
197  }
198 
199  inline double& Rates::get_ref( opt m ) {
200  return const_cast< double& >(
201  static_cast< const Rates* >( this )->get_ref( m )
202  );
203  }
204 
205  inline bool Rates::any() const noexcept {
206  return static_cast< enum_size >( this->mask ) != 0;
207  }
208 
209  inline bool Well::flowing() const noexcept {
210  return this->rates.any();
211  }
212 
213  }
214 }
215 
216 #endif //OPM_OUTPUT_WELLS_HPP
bool has(opt) const
Query if a value is set.
Definition: Wells.hpp:142
Rates & set(opt m, double value)
Set the value specified by m.
Definition: Wells.hpp:162
Definition: Wells.hpp:97
Definition: Cells.hpp:28
Definition: Wells.hpp:35
Definition: Wells.hpp:87
double get(opt m) const
Read the value indicated by m.
Definition: Wells.hpp:149
bool any() const noexcept
true if any option is set; false otherwise
Definition: Wells.hpp:205
Definition: Wells.hpp:109