mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-24 16:30:02 -06:00
211 lines
5.8 KiB
C++
211 lines
5.8 KiB
C++
/*
|
|
Copyright 2021 Equinor ASA
|
|
|
|
This file is part of the Open Porous Media project (OPM).
|
|
|
|
OPM is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OPM is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef OPM_WELL_CONTAINER_HEADER_INCLUDED
|
|
#define OPM_WELL_CONTAINER_HEADER_INCLUDED
|
|
|
|
#include <initializer_list>
|
|
#include <optional>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace Opm {
|
|
|
|
|
|
/*
|
|
The WellContainer<T> class is a small utility class designed to manage the
|
|
dynamic state of per well quantities, like active control and phase rates. The
|
|
values are stored continously in a vector, but they are added with a name, and
|
|
can also be accessed and updated with the name.
|
|
|
|
The class is created to facilitate safe and piecewise refactoring of the
|
|
WellState class, and might have a short life in the
|
|
development timeline.
|
|
*/
|
|
|
|
|
|
template <class T>
|
|
class WellContainer {
|
|
public:
|
|
WellContainer() = default;
|
|
|
|
WellContainer(std::initializer_list<std::pair<std::string,T>> init_list) {
|
|
for (const auto& [name, value] : init_list)
|
|
this->add(name, value);
|
|
}
|
|
|
|
static WellContainer serializationTestObject(const T& data)
|
|
{
|
|
WellContainer<T> result;
|
|
|
|
result.m_data = {data};
|
|
result.index_map = {{"test1", 1}, {"test2", 4}};
|
|
|
|
return result;
|
|
}
|
|
|
|
bool empty() const {
|
|
return this->index_map.empty();
|
|
}
|
|
|
|
std::size_t size() const {
|
|
return this->m_data.size();
|
|
}
|
|
|
|
T& add(const std::string& name, T&& value) {
|
|
if (index_map.count(name) != 0)
|
|
throw std::logic_error("An object with name: " + name + " already exists in container");
|
|
|
|
this->index_map.emplace(name, this->m_data.size());
|
|
this->m_data.push_back(std::forward<T>(value));
|
|
return this->m_data.back();
|
|
}
|
|
|
|
T& add(const std::string& name, const T& value) {
|
|
if (index_map.count(name) != 0)
|
|
throw std::logic_error("An object with name: " + name + " already exists in container");
|
|
|
|
this->index_map.emplace(name, this->m_data.size());
|
|
this->m_data.push_back(value);
|
|
return this->m_data.back();
|
|
}
|
|
|
|
bool has(const std::string& name) const {
|
|
return (index_map.count(name) != 0);
|
|
}
|
|
|
|
/*
|
|
Will copy the value from other to this - for all wells which are present
|
|
in both containers.
|
|
*/
|
|
void copy_welldata(const WellContainer<T>& other) {
|
|
if (this->index_map == other.index_map)
|
|
this->m_data = other.m_data;
|
|
else {
|
|
for (const auto& [name, index] : this->index_map)
|
|
this->update_if(index, name, other);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Will copy the value for well @name from other to this. The well @name must
|
|
exist in both containers, otherwise an exception is thrown.
|
|
*/
|
|
void copy_welldata(const WellContainer<T>& other, const std::string& name) {
|
|
auto this_index = this->index_map.at(name);
|
|
auto other_index = other.index_map.at(name);
|
|
this->m_data[this_index] = other.m_data[other_index];
|
|
}
|
|
|
|
T& operator[](std::size_t index) {
|
|
return this->m_data.at(index);
|
|
}
|
|
|
|
const T& operator[](std::size_t index) const {
|
|
return this->m_data.at(index);
|
|
}
|
|
|
|
T& operator[](const std::string& name) {
|
|
auto index = this->index_map.at(name);
|
|
return this->m_data[index];
|
|
}
|
|
|
|
const T& operator[](const std::string& name) const {
|
|
auto index = this->index_map.at(name);
|
|
return this->m_data[index];
|
|
}
|
|
|
|
void clear() {
|
|
this->m_data.clear();
|
|
this->index_map.clear();
|
|
}
|
|
|
|
typename std::vector<T>::const_iterator begin() const {
|
|
return this->m_data.begin();
|
|
}
|
|
|
|
typename std::vector<T>::const_iterator end() const {
|
|
return this->m_data.end();
|
|
}
|
|
|
|
const std::vector<T>& data() const {
|
|
return this->m_data;
|
|
}
|
|
|
|
std::optional<int> well_index(const std::string& wname) const {
|
|
auto index_iter = this->index_map.find(wname);
|
|
if (index_iter != this->index_map.end())
|
|
return index_iter->second;
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
const std::string& well_name(std::size_t well_index) const {
|
|
for (const auto& [wname, windex] : this->index_map) {
|
|
if (windex == well_index)
|
|
return wname;
|
|
}
|
|
throw std::logic_error("No such well");
|
|
}
|
|
|
|
std::vector<std::string> wells() const {
|
|
std::vector<std::string> wlist;
|
|
for (const auto& [wname, _] : this->index_map) {
|
|
(void)_;
|
|
wlist.push_back(wname);
|
|
}
|
|
return wlist;
|
|
}
|
|
|
|
template<class Serializer>
|
|
void serializeOp(Serializer& serializer)
|
|
{
|
|
serializer(m_data);
|
|
serializer(index_map);
|
|
}
|
|
|
|
bool operator==(const WellContainer<T>& rhs) const
|
|
{
|
|
return this->m_data == rhs.m_data &&
|
|
this->index_map == rhs.index_map;
|
|
}
|
|
|
|
private:
|
|
void update_if(std::size_t index, const std::string& name, const WellContainer<T>& other) {
|
|
auto other_iter = other.index_map.find(name);
|
|
if (other_iter == other.index_map.end())
|
|
return;
|
|
|
|
auto other_index = other_iter->second;
|
|
this->m_data[index] = other.m_data[other_index];
|
|
}
|
|
|
|
|
|
std::vector<T> m_data;
|
|
std::unordered_map<std::string, std::size_t> index_map;
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|