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