opm-simulators
WellContainer.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 OPM_WELL_CONTAINER_HEADER_INCLUDED
21 #define OPM_WELL_CONTAINER_HEADER_INCLUDED
22 
23 #include <initializer_list>
24 #include <optional>
25 #include <stdexcept>
26 #include <string>
27 #include <unordered_map>
28 #include <vector>
29 
30 namespace Opm {
31 
32 
33 /*
34  The WellContainer<T> class is a small utility class designed to manage the
35  dynamic state of per well quantities, like active control and phase rates. The
36  values are stored continously in a vector, but they are added with a name, and
37  can also be accessed and updated with the name.
38 
39  The class is created to facilitate safe and piecewise refactoring of the
40  WellState class, and might have a short life in the
41  development timeline.
42 */
43 
44 
45 template <class T>
47 public:
48  WellContainer() = default;
49 
50  WellContainer(std::initializer_list<std::pair<std::string,T>> init_list) {
51  for (const auto& [name, value] : init_list)
52  this->add(name, value);
53  }
54 
55  static WellContainer serializationTestObject(const T& data)
56  {
57  WellContainer<T> result;
58 
59  result.m_data = {data};
60  result.index_map = {{"test1", 1}, {"test2", 4}};
61 
62  return result;
63  }
64 
65  bool empty() const {
66  return this->index_map.empty();
67  }
68 
69  std::size_t size() const {
70  return this->m_data.size();
71  }
72 
73  T& add(const std::string& name, T&& value) {
74  if (index_map.count(name) != 0)
75  throw std::logic_error("An object with name: " + name + " already exists in container");
76 
77  this->index_map.emplace(name, this->m_data.size());
78  this->m_data.push_back(std::forward<T>(value));
79  return this->m_data.back();
80  }
81 
82  T& add(const std::string& name, const T& value) {
83  if (index_map.count(name) != 0)
84  throw std::logic_error("An object with name: " + name + " already exists in container");
85 
86  this->index_map.emplace(name, this->m_data.size());
87  this->m_data.push_back(value);
88  return this->m_data.back();
89  }
90 
91  bool has(const std::string& name) const {
92  return (index_map.count(name) != 0);
93  }
94 
95  /*
96  Will copy the value from other to this - for all wells which are present
97  in both containers.
98  */
99  void copy_welldata(const WellContainer<T>& other) {
100  if (this->index_map == other.index_map)
101  this->m_data = other.m_data;
102  else {
103  for (const auto& [name, index] : this->index_map)
104  this->update_if(index, name, other);
105  }
106  }
107 
108  /*
109  Will copy the value for well @name from other to this. The well @name must
110  exist in both containers, otherwise an exception is thrown.
111  */
112  void copy_welldata(const WellContainer<T>& other, const std::string& name) {
113  auto this_index = this->index_map.at(name);
114  auto other_index = other.index_map.at(name);
115  this->m_data[this_index] = other.m_data[other_index];
116  }
117 
118  T& operator[](std::size_t index) {
119  return this->m_data.at(index);
120  }
121 
122  const T& operator[](std::size_t index) const {
123  return this->m_data.at(index);
124  }
125 
126  T& operator[](const std::string& name) {
127  auto index = this->index_map.at(name);
128  return this->m_data[index];
129  }
130 
131  const T& operator[](const std::string& name) const {
132  auto index = this->index_map.at(name);
133  return this->m_data[index];
134  }
135 
136  void clear() {
137  this->m_data.clear();
138  this->index_map.clear();
139  }
140 
141  typename std::vector<T>::const_iterator begin() const {
142  return this->m_data.begin();
143  }
144 
145  typename std::vector<T>::const_iterator end() const {
146  return this->m_data.end();
147  }
148 
149  const std::vector<T>& data() const {
150  return this->m_data;
151  }
152 
153  std::optional<int> well_index(const std::string& wname) const {
154  auto index_iter = this->index_map.find(wname);
155  if (index_iter != this->index_map.end())
156  return index_iter->second;
157 
158  return std::nullopt;
159  }
160 
161  const std::string& well_name(std::size_t well_index) const {
162  for (const auto& [wname, windex] : this->index_map) {
163  if (windex == well_index)
164  return wname;
165  }
166  throw std::logic_error("No such well");
167  }
168 
169  std::vector<std::string> wells() const {
170  std::vector<std::string> wlist;
171  for (const auto& [wname, _] : this->index_map) {
172  (void)_;
173  wlist.push_back(wname);
174  }
175  return wlist;
176  }
177 
178  template<class Serializer>
179  void serializeOp(Serializer& serializer)
180  {
181  serializer(m_data);
182  serializer(index_map);
183  }
184 
185  bool operator==(const WellContainer<T>& rhs) const
186  {
187  return this->m_data == rhs.m_data &&
188  this->index_map == rhs.index_map;
189  }
190 
191 private:
192  void update_if(std::size_t index, const std::string& name, const WellContainer<T>& other) {
193  auto other_iter = other.index_map.find(name);
194  if (other_iter == other.index_map.end())
195  return;
196 
197  auto other_index = other_iter->second;
198  this->m_data[index] = other.m_data[other_index];
199  }
200 
201 
202  std::vector<T> m_data;
203  std::unordered_map<std::string, std::size_t> index_map;
204 };
205 
206 
207 }
208 
209 
210 #endif
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Definition: WellContainer.hpp:46