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