opm-common
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 <opm/common/utility/gpuDecorators.hpp>
24 #include <opm/common/utility/TimeService.hpp>
25 
26 #include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
27 #include <opm/input/eclipse/EclipseState/Runspec.hpp>
28 
29 #include <opm/input/eclipse/Schedule/BCProp.hpp>
30 #include <opm/input/eclipse/Schedule/Events.hpp>
31 #include <opm/input/eclipse/Schedule/Group/Group.hpp>
32 #include <opm/input/eclipse/Schedule/MessageLimits.hpp>
33 #include <opm/input/eclipse/Schedule/OilVaporizationProperties.hpp>
34 #include <opm/input/eclipse/Schedule/RSTConfig.hpp>
35 #include <opm/input/eclipse/Schedule/Source.hpp>
36 #include <opm/input/eclipse/Schedule/Tuning.hpp>
37 #include <opm/input/eclipse/Schedule/VFPInjTable.hpp>
38 #include <opm/input/eclipse/Schedule/VFPProdTable.hpp>
39 #include <opm/input/eclipse/Schedule/Well/PAvg.hpp>
40 #include <opm/input/eclipse/Schedule/Well/WCYCLE.hpp>
41 #include <opm/input/eclipse/Schedule/Well/WellEnums.hpp>
42 
43 #include <opm/input/eclipse/Deck/DeckKeyword.hpp>
44 
45 #include <array>
46 #include <cstddef>
47 #include <iterator>
48 #include <memory>
49 #include <optional>
50 #include <stdexcept>
51 #include <string>
52 #include <type_traits>
53 #include <unordered_map>
54 #include <utility>
55 #include <vector>
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 
69 namespace Opm {
70 
71  namespace Action {
72  class Actions;
73  }
74  class GasLiftOpt;
75  class GConSale;
76  class GConSump;
77  class GroupEconProductionLimits;
78  class GroupOrder;
79  class GroupSatelliteInjection;
80  class GSatProd;
81  class GuideRateConfig;
82  class NameOrder;
83  namespace Network {
84  class Balance;
85  class ExtNetwork;
86  }
87  namespace ReservoirCoupling {
88  class CouplingInfo;
89  }
90  class RFTConfig;
91  class RPTConfig;
92  class UDQActive;
93  class UDQConfig;
94  class Well;
95  class WellFractureSeeds;
96  class WellTestConfig;
97  class WListManager;
98 
99  /*
100  The purpose of the ScheduleState class is to hold the entire Schedule
101  information, i.e. wells and groups and so on, at exactly one point in
102  time. The ScheduleState class itself has no dynamic behavior, the dynamics
103  is handled by the Schedule instance owning the ScheduleState instance.
104  */
105 
107  public:
108  /*
109  In the SCHEDULE section typically all information is a function of
110  time, and the ScheduleState class is used to manage a snapshot of
111  state at one point in time. Typically a large part of the
112  configuration does not change between timesteps and consecutive
113  ScheduleState instances are very similar, to handle this many of the
114  ScheduleState members are implemented as std::shared_ptr<>s.
115 
116  The ptr_member<T> class is a small wrapper around the
117  std::shared_ptr<T>. The ptr_member<T> class is meant to be internal to
118  the Schedule implementation and downstream should only access this
119  indirectly like e.g.
120 
121  const auto& gconsum = sched_state.gconsump();
122 
123  The remaining details of the ptr_member<T> class are heavily
124  influenced by the code used to serialize the Schedule information.
125  */
126 
127 
128 
129  template <typename T>
130  class ptr_member {
131  public:
132  const T& get() const {
133  return *this->m_data;
134  }
135 
136  /*
137  This will allocate new storage and assign @object to the new
138  storage.
139  */
140  void update(T object)
141  {
142  this->m_data = std::make_shared<T>( std::move(object) );
143  }
144 
145  /*
146  Will reassign the pointer to point to existing shared instance
147  @other.
148  */
149  void update(const ptr_member<T>& other)
150  {
151  this->m_data = other.m_data;
152  }
153 
154  const T& operator()() const {
155  return *this->m_data;
156  }
157 
158  template<class Serializer>
159  void serializeOp(Serializer& serializer)
160  {
161  serializer(m_data);
162  }
163 
164  private:
165  std::shared_ptr<T> m_data;
166  };
167 
168 
169  /*
170  The map_member class is a quite specialized class used to internalize
171  the map variables managed in the ScheduleState. The actual value
172  objects will be stored as std::shared_ptr<T>, and only the unique
173  objects have dedicated storage. The class T must implement the method:
174 
175  const K& T::name() const;
176 
177  Which is used to get the storage key for the objects.
178  */
179 
180  template <typename K, typename T>
181  class map_member {
182  public:
183  std::vector<K> keys() const {
184  std::vector<K> key_vector;
185  std::ranges::transform(this->m_data, std::back_inserter(key_vector),
186  [](const auto& pair) { return pair.first; });
187  return key_vector;
188  }
189 
190 
191  template <typename Predicate>
192  const T* find(Predicate&& predicate) const {
193  const auto iter = std::ranges::find_if(this->m_data, std::forward<Predicate>(predicate));
194  if (iter == this->m_data.end()) {
195  return nullptr;
196  }
197 
198  return iter->second.get();
199  }
200 
201 
202  const std::shared_ptr<T> get_ptr(const K& key) const {
203  auto iter = this->m_data.find(key);
204  if (iter != this->m_data.end())
205  return iter->second;
206 
207  return {};
208  }
209 
210 
211  bool has(const K& key) const {
212  auto ptr = this->get_ptr(key);
213  return (ptr != nullptr);
214  }
215 
216  void update(const K& key, std::shared_ptr<T> value) {
217  this->m_data.insert_or_assign(key, std::move(value));
218  }
219 
220  void update(T object) {
221  auto key = object.name();
222  this->m_data[key] = std::make_shared<T>( std::move(object) );
223  }
224 
225  void update(const K& key, const map_member<K,T>& other) {
226  auto other_ptr = other.get_ptr(key);
227  if (other_ptr)
228  this->m_data[key] = other.get_ptr(key);
229  else
230  throw std::logic_error(std::string{"Tried to update member: "} + as_string(key) + std::string{"with uninitialized object"});
231  }
232 
233  const T& operator()(const K& key) const {
234  return this->get(key);
235  }
236 
237  const T& get(const K& key) const {
238  return *this->m_data.at(key);
239  }
240 
241  T& get(const K& key) {
242  return *this->m_data.at(key);
243  }
244 
245 
246  std::vector<std::reference_wrapper<const T>> operator()() const {
247  std::vector<std::reference_wrapper<const T>> as_vector;
248  for (const auto& [_, elm_ptr] : this->m_data) {
249  (void)_;
250  as_vector.push_back( std::cref(*elm_ptr));
251  }
252  return as_vector;
253  }
254 
255 
256  std::vector<std::reference_wrapper<T>> operator()() {
257  std::vector<std::reference_wrapper<T>> as_vector;
258  for (const auto& [_, elm_ptr] : this->m_data) {
259  (void)_;
260  as_vector.push_back( std::ref(*elm_ptr));
261  }
262  return as_vector;
263  }
264 
265 
266  bool operator==(const map_member<K,T>& other) const {
267  if (this->m_data.size() != other.m_data.size())
268  return false;
269 
270  for (const auto& [key1, ptr1] : this->m_data) {
271  const auto& ptr2 = other.get_ptr(key1);
272  if (!ptr2)
273  return false;
274 
275  if (!(*ptr1 == *ptr2))
276  return false;
277  }
278  return true;
279  }
280 
281 
282  std::size_t size() const {
283  return this->m_data.size();
284  }
285 
286  typename std::unordered_map<K, std::shared_ptr<T>>::const_iterator begin() const {
287  return this->m_data.begin();
288  }
289 
290  typename std::unordered_map<K, std::shared_ptr<T>>::const_iterator end() const {
291  return this->m_data.end();
292  }
293 
294 
295  static map_member<K,T> serializationTestObject() {
296  map_member<K,T> map_object;
297  T value_object = T::serializationTestObject();
298  K key = value_object.name();
299  map_object.m_data.emplace( key, std::make_shared<T>( std::move(value_object) ));
300  return map_object;
301  }
302 
303  template<class Serializer>
304  void serializeOp(Serializer& serializer)
305  {
306  serializer(m_data);
307  }
308 
309  private:
310  std::unordered_map<K, std::shared_ptr<T>> m_data;
311  };
312 
313  struct BHPDefaults {
314  std::optional<double> prod_target;
315  std::optional<double> inj_limit;
316 
317  static BHPDefaults serializationTestObject()
318  {
319  return BHPDefaults{1.0, 2.0};
320  }
321 
322  bool operator==(const BHPDefaults& rhs) const
323  {
324  return this->prod_target == rhs.prod_target
325  && this->inj_limit == rhs.inj_limit;
326  }
327 
328  template<class Serializer>
329  void serializeOp(Serializer& serializer)
330  {
331  serializer(prod_target);
332  serializer(inj_limit);
333  }
334  };
335 
338  {
339  private:
341  enum class Ix : std::size_t {
343  Static,
344 
346  Action,
347 
349  Num,
350  };
351 
357  static constexpr auto index(const Ix i)
358  {
359  return static_cast<std::underlying_type_t<Ix>>(i);
360  }
361 
362  public:
367  {
368  this->listsChanged_[ index(Ix::Static) ] = true;
369  }
370 
374  {
375  this->listsChanged_[ index(Ix::Action) ] = true;
376  }
377 
380  bool changedLists() const
381  {
382  return this->listsChanged_[ index(Ix::Static) ];
383  }
384 
391  void prepareNextReportStep();
392 
394  static WellListChangeTracker serializationTestObject();
395 
403  bool operator==(const WellListChangeTracker& that) const
404  {
405  return this->listsChanged_ == that.listsChanged_;
406  }
407 
413  template <class Serializer>
414  void serializeOp(Serializer& serializer)
415  {
416  serializer(this->listsChanged_);
417  }
418 
419  private:
421  using ListChangeStatus = std::array
422  <bool, static_cast<std::underlying_type_t<Ix>>(Ix::Num)>;
423 
428  ListChangeStatus listsChanged_{{false, false}};
429  };
430 
431  ScheduleState() = default;
432  explicit ScheduleState(const time_point& start_time);
433  ScheduleState(const time_point& start_time, const time_point& end_time);
434  ScheduleState(const ScheduleState& src, const time_point& start_time);
435  ScheduleState(const ScheduleState& src, const time_point& start_time, const time_point& end_time);
436 
437 
438  time_point start_time() const;
439  time_point end_time() const;
440  ScheduleState next(const time_point& next_start);
441 
442  // The sim_step() is the report step we are currently simulating on. The
443  // results when we have completed sim_step=N are stored in report_step
444  // N+1.
445  std::size_t sim_step() const;
446 
447  // The month_num and year_num() functions return the accumulated number
448  // of full months/years to the start of the current block.
449  std::size_t month_num() const;
450  std::size_t year_num() const;
451  bool first_in_month() const;
452  bool first_in_year() const;
453  bool well_group_contains_lgr(const Group& grp, const std::string& lgr_tag) const;
454  bool group_contains_lgr(const Group& grp, const std::string& lgr_tag) const;
455 
456  std::size_t num_lgr_well_in_group(const Group& grp, const std::string& lgr_tag) const;
457  std::size_t num_lgr_groups_in_group(const Group& grp, const std::string& lgr_tag) const;
458 
459 
460  bool operator==(const ScheduleState& other) const;
461  static ScheduleState serializationTestObject();
462 
463  // ---- TUNING ----
464  void update_tuning(Tuning tuning);
465  Tuning& tuning();
466  const Tuning& tuning() const;
467  double max_next_tstep(const bool enableTUNING = false) const;
468 
469  // ---- TUNINGDP ----
470  void update_tuning_dp(TuningDp tuningDp);
471  TuningDp& tuning_dp();
472  const TuningDp& tuning_dp() const;
473 
474  void init_nupcol(Nupcol nupcol);
475  void update_nupcol(int nupcol);
476  int nupcol() const;
477 
478  void update_events(Events events);
479  Events& events();
480  const Events& events() const;
481 
482  void update_wellgroup_events(WellGroupEvents wgevents);
483  WellGroupEvents& wellgroup_events();
484  const WellGroupEvents& wellgroup_events() const;
485 
486  void update_geo_keywords(std::vector<DeckKeyword> geo_keywords);
487  std::vector<DeckKeyword>& geo_keywords();
488  const std::vector<DeckKeyword>& geo_keywords() const;
489 
490  void update_message_limits(MessageLimits message_limits);
491  MessageLimits& message_limits();
492  const MessageLimits& message_limits() const;
493 
494  WellProducerCMode whistctl() const;
495  void update_whistctl(WellProducerCMode whistctl);
496 
497  bool rst_file(const RSTConfig& rst_config, const time_point& previous_restart_output_time) const;
498  void update_date(const time_point& prev_time);
499  void updateSAVE(bool save);
500  bool save() const;
501 
502  const std::optional<double>& sumthin() const;
503  void update_sumthin(double sumthin);
504 
505  bool rptonly() const;
506  void rptonly(const bool only);
507 
508  bool has_gpmaint() const;
509 
510  bool hasAnalyticalAquifers() const
511  {
512  return ! this->aqufluxs.empty();
513  }
514 
515  /*********************************************************************/
516 
517  ptr_member<GConSale> gconsale;
518  ptr_member<GConSump> gconsump;
519  ptr_member<GSatProd> gsatprod;
520  ptr_member<GroupEconProductionLimits> gecon;
521  ptr_member<GuideRateConfig> guide_rate;
522 
523  ptr_member<WListManager> wlist_manager;
524  ptr_member<NameOrder> well_order;
525  ptr_member<GroupOrder> group_order;
526 
527  ptr_member<Action::Actions> actions;
528  ptr_member<UDQConfig> udq;
529  ptr_member<UDQActive> udq_active;
530 
531  ptr_member<PAvg> pavg;
532  ptr_member<WellTestConfig> wtest_config;
533  ptr_member<GasLiftOpt> glo;
534  ptr_member<Network::ExtNetwork> network;
535  ptr_member<Network::Balance> network_balance;
536  ptr_member<ReservoirCoupling::CouplingInfo> rescoup;
537 
538  ptr_member<RPTConfig> rpt_config;
539  ptr_member<RFTConfig> rft_config;
540  ptr_member<RSTConfig> rst_config;
541 
542  ptr_member<OilVaporizationProperties> oilvap;
543 
544  ptr_member<BHPDefaults> bhp_defaults;
545  ptr_member<Source> source;
546  ptr_member<WCYCLE> wcycle;
547 
548  ptr_member<WellListChangeTracker> wlist_tracker;
549 
550  template <typename T>
551  ptr_member<T>& get() {
552  return const_cast<ptr_member<T>&>(std::as_const(*this).template get<T>());
553  }
554 
555  template <typename T>
556  const ptr_member<T>& get() const
557  {
558  struct always_false1 : std::false_type {};
559 
560  if constexpr ( std::is_same_v<T, PAvg> )
561  return this->pavg;
562  else if constexpr ( std::is_same_v<T, WellTestConfig> )
563  return this->wtest_config;
564  else if constexpr ( std::is_same_v<T, GConSale> )
565  return this->gconsale;
566  else if constexpr ( std::is_same_v<T, GConSump> )
567  return this->gconsump;
568  else if constexpr ( std::is_same_v<T, GSatProd> )
569  return this->gsatprod;
570  else if constexpr ( std::is_same_v<T, GroupEconProductionLimits> )
571  return this->gecon;
572  else if constexpr ( std::is_same_v<T, WListManager> )
573  return this->wlist_manager;
574  else if constexpr ( std::is_same_v<T, Network::ExtNetwork> )
575  return this->network;
576  else if constexpr ( std::is_same_v<T, Network::Balance> )
577  return this->network_balance;
578  else if constexpr ( std::is_same_v<T, ReservoirCoupling::CouplingInfo> )
579  return this->rescoup;
580  else if constexpr ( std::is_same_v<T, RPTConfig> )
581  return this->rpt_config;
582  else if constexpr ( std::is_same_v<T, Action::Actions> )
583  return this->actions;
584  else if constexpr ( std::is_same_v<T, UDQActive> )
585  return this->udq_active;
586  else if constexpr ( std::is_same_v<T, NameOrder> )
587  return this->well_order;
588  else if constexpr ( std::is_same_v<T, GroupOrder> )
589  return this->group_order;
590  else if constexpr ( std::is_same_v<T, UDQConfig> )
591  return this->udq;
592  else if constexpr ( std::is_same_v<T, GasLiftOpt> )
593  return this->glo;
594  else if constexpr ( std::is_same_v<T, GuideRateConfig> )
595  return this->guide_rate;
596  else if constexpr ( std::is_same_v<T, RFTConfig> )
597  return this->rft_config;
598  else if constexpr ( std::is_same_v<T, RSTConfig> )
599  return this->rst_config;
600  else if constexpr ( std::is_same_v<T, OilVaporizationProperties> )
601  return this->oilvap;
602  else if constexpr ( std::is_same_v<T, BHPDefaults> )
603  return this->bhp_defaults;
604  else if constexpr ( std::is_same_v<T, Source> )
605  return this->source;
606  else if constexpr ( std::is_same_v<T, WCYCLE> )
607  return this->wcycle;
608  else if constexpr ( std::is_same_v<T, WellListChangeTracker> )
609  return this->wlist_tracker;
610  else {
611  #if !OPM_IS_COMPILING_WITH_GPU_COMPILER // NVCC evaluates this branch for some reason
612  static_assert(always_false1::value, "Template type <T> not supported in get()");
613  #endif
614  }
615  }
616 
617  map_member<int, VFPProdTable> vfpprod;
618  map_member<int, VFPInjTable> vfpinj;
619  map_member<std::string, Group> groups;
620  map_member<std::string, Well> wells;
621 
624 
628 
629  // constant flux aquifers
630  std::unordered_map<int, SingleAquiferFlux> aqufluxs;
631  BCProp bcprop;
632  // injection streams for compostional STREAM injection using WINJGAS
634 
635  std::unordered_map<std::string, double> target_wellpi;
636  std::optional<NextStep> next_tstep;
637 
638  template<class Serializer>
639  void serializeOp(Serializer& serializer)
640  {
641  serializer(gconsale);
642  serializer(gconsump);
643  serializer(gsatprod);
644  serializer(gecon);
645  serializer(guide_rate);
646  serializer(wlist_manager);
647  serializer(well_order);
648  serializer(group_order);
649  serializer(actions);
650  serializer(udq);
651  serializer(udq_active);
652  serializer(pavg);
653  serializer(wtest_config);
654  serializer(glo);
655  serializer(network);
656  serializer(network_balance);
657  serializer(rescoup);
658  serializer(rpt_config);
659  serializer(rft_config);
660  serializer(rst_config);
661  serializer(this->oilvap);
662  serializer(bhp_defaults);
663  serializer(source);
664  serializer(wcycle);
665  serializer(this->wlist_tracker);
666  serializer(vfpprod);
667  serializer(vfpinj);
668  serializer(groups);
669  serializer(wells);
670  serializer(this->satelliteInjection);
671  serializer(wseed);
672  serializer(aqufluxs);
673  serializer(bcprop);
674  serializer(inj_streams);
675  serializer(target_wellpi);
676  serializer(this->next_tstep);
677  serializer(m_start_time);
678  serializer(m_end_time);
679  serializer(m_sim_step);
680  serializer(m_month_num);
681  serializer(m_year_num);
682  serializer(m_first_in_year);
683  serializer(m_first_in_month);
684  serializer(m_save_step);
685  serializer(m_tuning);
686  serializer(m_tuning_dp);
687  serializer(m_nupcol);
688  serializer(m_events);
689  serializer(m_wellgroup_events);
690  serializer(m_geo_keywords);
691  serializer(m_message_limits);
692  serializer(m_whistctl_mode);
693  serializer(m_sumthin);
694  serializer(this->m_rptonly);
695  }
696 
697  private:
698  time_point m_start_time{};
699  std::optional<time_point> m_end_time{};
700 
701  std::size_t m_sim_step = 0;
702  std::size_t m_month_num = 0;
703  std::size_t m_year_num = 0;
704  bool m_first_in_month{false};
705  bool m_first_in_year{false};
706  bool m_save_step{false};
707 
708  Tuning m_tuning{};
709  TuningDp m_tuning_dp{};
710  Nupcol m_nupcol{};
711  Events m_events{};
712  WellGroupEvents m_wellgroup_events{};
713  std::vector<DeckKeyword> m_geo_keywords{};
714  MessageLimits m_message_limits{};
715  WellProducerCMode m_whistctl_mode = WellProducerCMode::CMODE_UNDEFINED;
716  std::optional<double> m_sumthin{};
717  bool m_rptonly{false};
718  };
719 
720 } // namespace Opm
721 
722 #endif // SCHEDULE_TSTEP_HPP
bool changedLists() const
Report whether or not any well lists have changed since the previous report step. ...
Definition: ScheduleState.hpp:380
void recordActionChangedLists()
Record that one or more well lists have changed structurally in response to a WLIST keyword entered i...
Definition: ScheduleState.hpp:373
Definition: ScheduleState.hpp:130
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
void recordStaticChangedLists()
Record that one or more well lists have changed structurally in response to a WLIST keyword entered i...
Definition: ScheduleState.hpp:366
Definition: ScheduleState.hpp:181
Definition: ScheduleState.hpp:313
Definition: BCProp.hpp:91
bool operator==(const WellListChangeTracker &that) const
Equality predicate.
Definition: ScheduleState.hpp:403
map_member< std::string, GroupSatelliteInjection > satelliteInjection
Group level satellite injection rates.
Definition: ScheduleState.hpp:623
Definition: ScheduleState.hpp:106
Flag for structural changes to the run&#39;s well list.
Definition: ScheduleState.hpp:337
map_member< std::string, WellFractureSeeds > wseed
Well fracturing seed points and associate fracture plane normal vectors.
Definition: ScheduleState.hpp:627
void serializeOp(Serializer &serializer)
Convert between byte array and object representation.
Definition: ScheduleState.hpp:414
Class for (de-)serializing.
Definition: Serializer.hpp:94