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
29namespace 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
44template <class T>
46public:
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 std::vector<std::string> wells() const {
161 std::vector<std::string> wlist;
162 for (const auto& [wname, _] : this->index_map) {
163 (void)_;
164 wlist.push_back(wname);
165 }
166 return wlist;
167 }
168
169
170private:
171 void update_if(std::size_t index, const std::string& name, const WellContainer<T>& other) {
172 auto other_iter = other.index_map.find(name);
173 if (other_iter == other.index_map.end())
174 return;
175
176 auto other_index = other_iter->second;
177 this->m_data[index] = other.m_data[other_index];
178 }
179
180
181 std::vector<T> m_data;
182 std::unordered_map<std::string, std::size_t> index_map;
183};
184
185
186}
187
188
189#endif
Definition: WellContainer.hpp:45
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27