My Project
ScheduleState.hpp
1 /*
2  Copyright 2021 Equinor 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 SCHEDULE_TSTEP_HPP
21 #define SCHEDULE_TSTEP_HPP
22 
23 #include <chrono>
24 #include <cstddef>
25 #include <memory>
26 #include <optional>
27 #include <unordered_map>
28 
29 #include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
30 #include <opm/common/utility/TimeService.hpp>
31 
32 #include <opm/parser/eclipse/EclipseState/Schedule/RPTConfig.hpp>
33 #include <opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp>
34 #include <opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp>
35 #include <opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.hpp>
36 #include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
37 #include <opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp>
38 #include <opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp>
39 #include <opm/parser/eclipse/EclipseState/Schedule/Well/NameOrder.hpp>
40 #include <opm/parser/eclipse/EclipseState/Schedule/Well/WListManager.hpp>
41 #include <opm/parser/eclipse/EclipseState/Schedule/MessageLimits.hpp>
42 #include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSump.hpp>
43 #include <opm/parser/eclipse/EclipseState/Schedule/Group/GConSale.hpp>
44 #include <opm/parser/eclipse/EclipseState/Schedule/Network/ExtNetwork.hpp>
45 #include <opm/parser/eclipse/EclipseState/Schedule/Network/Balance.hpp>
46 #include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
47 #include <opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp>
48 #include <opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp>
49 #include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
50 #include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
51 #include <opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateConfig.hpp>
52 #include <opm/parser/eclipse/EclipseState/Schedule/GasLiftOpt.hpp>
53 #include <opm/parser/eclipse/EclipseState/Schedule/RFTConfig.hpp>
54 #include <opm/parser/eclipse/EclipseState/Schedule/RSTConfig.hpp>
55 
56 
57 namespace {
58 
59 [[maybe_unused]] std::string as_string(int value) {
60  return std::to_string(value);
61 }
62 
63 [[maybe_unused]] std::string as_string(const std::string& value) {
64  return value;
65 }
66 
67 }
68 namespace Opm {
69 
70  /*
71  The purpose of the ScheduleState class is to hold the entire Schedule
72  information, i.e. wells and groups and so on, at exactly one point in
73  time. The ScheduleState class itself has no dynamic behavior, the dynamics
74  is handled by the Schedule instance owning the ScheduleState instance.
75  */
76 
77  class WellTestConfig;
78 
79 
80 
81  class ScheduleState {
82  public:
83  /*
84  In the SCHEDULE section typically all information is a function of
85  time, and the ScheduleState class is used to manage a snapshot of
86  state at one point in time. Typically a large part of the
87  configuration does not change between timesteps and consecutive
88  ScheduleState instances are very similar, to handle this many of the
89  ScheduleState members are implemented as std::shared_ptr<>s.
90 
91  The ptr_member<T> class is a small wrapper around the
92  std::shared_ptr<T>. The ptr_member<T> class is meant to be internal to
93  the Schedule implementation and downstream should only access this
94  indirectly like e.g.
95 
96  const auto& gconsum = sched_state.gconsump();
97 
98  The remaining details of the ptr_member<T> class are heavily
99  influenced by the code used to serialize the Schedule information.
100  */
101 
102 
103 
104  template <typename T>
105  class ptr_member {
106  public:
107  const T& get() const {
108  return *this->m_data;
109  }
110 
111  /*
112  This will allocate new storage and assign @object to the new
113  storage.
114  */
115  void update(T object)
116  {
117  this->m_data = std::make_shared<T>( std::move(object) );
118  }
119 
120  /*
121  Will reassign the pointer to point to existing shared instance
122  @other.
123  */
124  void update(const ptr_member<T>& other)
125  {
126  this->m_data = other.m_data;
127  }
128 
129  const T& operator()() const {
130  return *this->m_data;
131  }
132 
133  private:
134  std::shared_ptr<T> m_data;
135  };
136 
137 
138  /*
139  The map_member class is a quite specialized class used to internalize
140  the map variables managed in the ScheduleState. The actual value
141  objects will be stored as std::shared_ptr<T>, and only the unique
142  objects have dedicated storage. The class T must implement the method:
143 
144  const K& T::name() const;
145 
146  Which is used to get the storage key for the objects.
147  */
148 
149  template <typename K, typename T>
150  class map_member {
151  public:
152  std::vector<K> keys() const {
153  std::vector<K> key_vector;
154  std::transform( this->m_data.begin(), this->m_data.end(), std::back_inserter(key_vector), [](const auto& pair) { return pair.first; });
155  return key_vector;
156  }
157 
158 
159  template <typename Predicate>
160  const T* find(Predicate&& predicate) const {
161  auto iter = std::find_if( this->m_data.begin(), this->m_data.end(), std::forward<Predicate>(predicate));
162  if (iter == this->m_data.end())
163  return nullptr;
164 
165  return iter->second.get();
166  }
167 
168 
169  const std::shared_ptr<T> get_ptr(const K& key) const {
170  auto iter = this->m_data.find(key);
171  if (iter != this->m_data.end())
172  return iter->second;
173 
174  return {};
175  }
176 
177 
178  bool has(const K& key) const {
179  auto ptr = this->get_ptr(key);
180  return (ptr != nullptr);
181  }
182 
183 
184  void update(T object) {
185  auto key = object.name();
186  this->m_data[key] = std::make_shared<T>( std::move(object) );
187  }
188 
189  void update(const K& key, const map_member<K,T>& other) {
190  auto other_ptr = other.get_ptr(key);
191  if (other_ptr)
192  this->m_data[key] = other.get_ptr(key);
193  else
194  throw std::logic_error(std::string{"Tried to update member: "} + as_string(key) + std::string{"with uninitialized object"});
195  }
196 
197  const T& operator()(const K& key) const {
198  return this->get(key);
199  }
200 
201  const T& get(const K& key) const {
202  return *this->m_data.at(key);
203  }
204 
205  T& get(const K& key) {
206  return *this->m_data.at(key);
207  }
208 
209 
210  std::vector<std::reference_wrapper<const T>> operator()() const {
211  std::vector<std::reference_wrapper<const T>> as_vector;
212  for (const auto& [_, elm_ptr] : this->m_data) {
213  (void)_;
214  as_vector.push_back( std::cref(*elm_ptr));
215  }
216  return as_vector;
217  }
218 
219 
220  std::vector<std::reference_wrapper<T>> operator()() {
221  std::vector<std::reference_wrapper<T>> as_vector;
222  for (const auto& [_, elm_ptr] : this->m_data) {
223  (void)_;
224  as_vector.push_back( std::ref(*elm_ptr));
225  }
226  return as_vector;
227  }
228 
229 
230  bool operator==(const map_member<K,T>& other) const {
231  if (this->m_data.size() != other.m_data.size())
232  return false;
233 
234  for (const auto& [key1, ptr1] : this->m_data) {
235  const auto& ptr2 = other.get_ptr(key1);
236  if (!ptr2)
237  return false;
238 
239  if (!(*ptr1 == *ptr2))
240  return false;
241  }
242  return true;
243  }
244 
245 
246  std::size_t size() const {
247  return this->m_data.size();
248  }
249 
250  typename std::unordered_map<K, std::shared_ptr<T>>::const_iterator begin() const {
251  return this->m_data.begin();
252  }
253 
254  typename std::unordered_map<K, std::shared_ptr<T>>::const_iterator end() const {
255  return this->m_data.end();
256  }
257 
258 
259  static map_member<K,T> serializeObject() {
260  map_member<K,T> map_object;
261  T value_object = T::serializeObject();
262  K key = value_object.name();
263  map_object.m_data.emplace( key, std::make_shared<T>( std::move(value_object) ));
264  return map_object;
265  }
266 
267 
268  private:
269  std::unordered_map<K, std::shared_ptr<T>> m_data;
270  };
271 
272 
273 
274  ScheduleState() = default;
275  explicit ScheduleState(const time_point& start_time);
276  ScheduleState(const time_point& start_time, const time_point& end_time);
277  ScheduleState(const ScheduleState& src, const time_point& start_time);
278  ScheduleState(const ScheduleState& src, const time_point& start_time, const time_point& end_time);
279 
280 
281  time_point start_time() const;
282  time_point end_time() const;
283  ScheduleState next(const time_point& next_start);
284 
285  // The sim_step() is the report step we are currently simulating on. The
286  // results when we have completed sim_step=N are stored in report_step
287  // N+1.
288  std::size_t sim_step() const;
289 
290  // The month_num and year_num() functions return the accumulated number
291  // of full months/years to the start of the current block.
292  std::size_t month_num() const;
293  std::size_t year_num() const;
294  bool first_in_month() const;
295  bool first_in_year() const;
296 
297  bool operator==(const ScheduleState& other) const;
298  static ScheduleState serializeObject();
299 
300  void update_tuning(Tuning tuning);
301  Tuning& tuning();
302  const Tuning& tuning() const;
303 
304  void init_nupcol(Nupcol nupcol);
305  void update_nupcol(int nupcol);
306  int nupcol() const;
307 
308  void update_oilvap(OilVaporizationProperties oilvap);
309  const OilVaporizationProperties& oilvap() const;
310  OilVaporizationProperties& oilvap();
311 
312  void update_events(Events events);
313  Events& events();
314  const Events& events() const;
315 
316  void update_wellgroup_events(WellGroupEvents wgevents);
317  WellGroupEvents& wellgroup_events();
318  const WellGroupEvents& wellgroup_events() const;
319 
320  void update_geo_keywords(std::vector<DeckKeyword> geo_keywords);
321  std::vector<DeckKeyword>& geo_keywords();
322  const std::vector<DeckKeyword>& geo_keywords() const;
323 
324  void update_message_limits(MessageLimits message_limits);
325  MessageLimits& message_limits();
326  const MessageLimits& message_limits() const;
327 
328  Well::ProducerCMode whistctl() const;
329  void update_whistctl(Well::ProducerCMode whistctl);
330 
331  bool rst_file(const RSTConfig& rst_config, const time_point& previous_restart_output_time) const;
332  void update_date(const time_point& prev_time);
333  void updateSAVE(bool save);
334  bool save() const;
335 
336  const std::optional<double>& sumthin() const;
337  void update_sumthin(double sumthin);
338 
339  bool rptonly() const;
340  void rptonly(const bool only);
341 
342  bool has_gpmaint() const;
343 
344  /*********************************************************************/
345 
346  ptr_member<GConSale> gconsale;
347  ptr_member<GConSump> gconsump;
348  ptr_member<GuideRateConfig> guide_rate;
349 
350  ptr_member<WListManager> wlist_manager;
351  ptr_member<NameOrder> well_order;
352  ptr_member<GroupOrder> group_order;
353 
356  ptr_member<UDQActive> udq_active;
357 
358  ptr_member<PAvg> pavg;
359  ptr_member<WellTestConfig> wtest_config;
362  ptr_member<Network::Balance> network_balance;
363 
364  ptr_member<RPTConfig> rpt_config;
365  ptr_member<RFTConfig> rft_config;
366  ptr_member<RSTConfig> rst_config;
367 
368  template <typename T> struct always_false1 : std::false_type {};
369 
370  template <typename T>
371  ptr_member<T>& get() {
372  if constexpr ( std::is_same_v<T, PAvg> )
373  return this->pavg;
374  else if constexpr ( std::is_same_v<T, WellTestConfig> )
375  return this->wtest_config;
376  else if constexpr ( std::is_same_v<T, GConSale> )
377  return this->gconsale;
378  else if constexpr ( std::is_same_v<T, GConSump> )
379  return this->gconsump;
380  else if constexpr ( std::is_same_v<T, WListManager> )
381  return this->wlist_manager;
382  else if constexpr ( std::is_same_v<T, Network::ExtNetwork> )
383  return this->network;
384  else if constexpr ( std::is_same_v<T, Network::Balance> )
385  return this->network_balance;
386  else if constexpr ( std::is_same_v<T, RPTConfig> )
387  return this->rpt_config;
388  else if constexpr ( std::is_same_v<T, Action::Actions> )
389  return this->actions;
390  else if constexpr ( std::is_same_v<T, UDQActive> )
391  return this->udq_active;
392  else if constexpr ( std::is_same_v<T, NameOrder> )
393  return this->well_order;
394  else if constexpr ( std::is_same_v<T, GroupOrder> )
395  return this->group_order;
396  else if constexpr ( std::is_same_v<T, UDQConfig> )
397  return this->udq;
398  else if constexpr ( std::is_same_v<T, GasLiftOpt> )
399  return this->glo;
400  else if constexpr ( std::is_same_v<T, GuideRateConfig> )
401  return this->guide_rate;
402  else if constexpr ( std::is_same_v<T, RFTConfig> )
403  return this->rft_config;
404  else if constexpr ( std::is_same_v<T, RSTConfig> )
405  return this->rst_config;
406  else
407  static_assert(always_false1<T>::value, "Template type <T> not supported in get()");
408  }
409 
410  template <typename T>
411  const ptr_member<T>& get() const {
412  if constexpr ( std::is_same_v<T, PAvg> )
413  return this->pavg;
414  else if constexpr ( std::is_same_v<T, WellTestConfig> )
415  return this->wtest_config;
416  else if constexpr ( std::is_same_v<T, GConSale> )
417  return this->gconsale;
418  else if constexpr ( std::is_same_v<T, GConSump> )
419  return this->gconsump;
420  else if constexpr ( std::is_same_v<T, WListManager> )
421  return this->wlist_manager;
422  else if constexpr ( std::is_same_v<T, Network::ExtNetwork> )
423  return this->network;
424  else if constexpr ( std::is_same_v<T, Network::Balance> )
425  return this->network_balance;
426  else if constexpr ( std::is_same_v<T, RPTConfig> )
427  return this->rpt_config;
428  else if constexpr ( std::is_same_v<T, Action::Actions> )
429  return this->actions;
430  else if constexpr ( std::is_same_v<T, UDQActive> )
431  return this->udq_active;
432  else if constexpr ( std::is_same_v<T, NameOrder> )
433  return this->well_order;
434  else if constexpr ( std::is_same_v<T, GroupOrder> )
435  return this->group_order;
436  else if constexpr ( std::is_same_v<T, UDQConfig> )
437  return this->udq;
438  else if constexpr ( std::is_same_v<T, GasLiftOpt> )
439  return this->glo;
440  else if constexpr ( std::is_same_v<T, GuideRateConfig> )
441  return this->guide_rate;
442  else if constexpr ( std::is_same_v<T, RFTConfig> )
443  return this->rft_config;
444  else if constexpr ( std::is_same_v<T, RSTConfig> )
445  return this->rst_config;
446  else
447  static_assert(always_false1<T>::value, "Template type <T> not supported in get()");
448  }
449 
450 
451  template <typename K, typename T> struct always_false2 : std::false_type {};
452  template <typename K, typename T>
453  map_member<K,T>& get_map() {
454  if constexpr ( std::is_same_v<T, VFPProdTable> )
455  return this->vfpprod;
456  else if constexpr ( std::is_same_v<T, VFPInjTable> )
457  return this->vfpinj;
458  else if constexpr ( std::is_same_v<T, Group> )
459  return this->groups;
460  else if constexpr ( std::is_same_v<T, Well> )
461  return this->wells;
462  else
463  static_assert(always_false2<K,T>::value, "Template type <K,T> not supported in get_map()");
464  }
465 
466  map_member<int, VFPProdTable> vfpprod;
467  map_member<int, VFPInjTable> vfpinj;
468  map_member<std::string, Group> groups;
469  map_member<std::string, Well> wells;
470  std::unordered_map<std::string, double> target_wellpi;
471 
472 
473  using WellPIMapType = std::unordered_map<std::string, double>;
474  template<class Serializer>
475  void serializeOp(Serializer& serializer) {
476  serializer(m_start_time);
477  serializer(m_end_time);
478  serializer(m_sim_step);
479  serializer(m_month_num);
480  serializer(m_year_num);
481  serializer(m_first_in_year);
482  serializer(m_first_in_month);
483  serializer(m_save_step);
484  serializer(m_sumthin);
485  serializer(this->m_rptonly);
486  m_tuning.serializeOp(serializer);
487  m_nupcol.serializeOp(serializer);
488  m_oilvap.serializeOp(serializer);
489  m_events.serializeOp(serializer);
490  m_wellgroup_events.serializeOp(serializer);
491  serializer.vector(m_geo_keywords);
492  m_message_limits.serializeOp(serializer);
493  serializer(m_whistctl_mode);
494  serializer.template map<WellPIMapType, false>(target_wellpi);
495  }
496 
497 
498  private:
499  time_point m_start_time;
500  std::optional<time_point> m_end_time;
501 
502  std::size_t m_sim_step = 0;
503  std::size_t m_month_num = 0;
504  std::size_t m_year_num = 0;
505  bool m_first_in_month;
506  bool m_first_in_year;
507  bool m_save_step{false};
508 
509  Tuning m_tuning;
510  Nupcol m_nupcol;
511  OilVaporizationProperties m_oilvap;
512  Events m_events;
513  WellGroupEvents m_wellgroup_events;
514  std::vector<DeckKeyword> m_geo_keywords;
515  MessageLimits m_message_limits;
516  Well::ProducerCMode m_whistctl_mode = Well::ProducerCMode::CMODE_UNDEFINED;
517  std::optional<double> m_sumthin;
518  bool m_rptonly{false};
519  };
520 }
521 
522 #endif
Definition: Events.hpp:147
Definition: MessageLimits.hpp:28
Definition: Runspec.hpp:380
Definition: OilVaporizationProperties.hpp:34
Definition: RSTConfig.hpp:196
Definition: ScheduleState.hpp:150
Definition: ScheduleState.hpp:105
Definition: ScheduleState.hpp:81
Definition: Serializer.hpp:38
Definition: Events.hpp:169
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:29
Definition: ScheduleState.hpp:368
Definition: ScheduleState.hpp:451
Definition: Tuning.hpp:24