opm-common
FieldData.hpp
1 /*
2  Copyright 2020 Equinor AS.
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 FIELD_DATA_HPP
21 #define FIELD_DATA_HPP
22 
23 #include <opm/input/eclipse/EclipseState/Grid/Box.hpp>
24 #include <opm/input/eclipse/EclipseState/Grid/Keywords.hpp>
25 
26 #include <opm/input/eclipse/Deck/value_status.hpp>
27 
28 #include <algorithm>
29 #include <array>
30 #include <cstddef>
31 #include <functional>
32 #include <optional>
33 #include <stdexcept>
34 #include <string>
35 #include <vector>
36 
37 namespace Opm {
38  class KeywordLocation;
39 } // namespace Opm
40 
41 namespace Opm::Fieldprops {
42 
43  template <typename T>
44  static void compress(std::vector<T>& data,
45  const std::vector<bool>& active_map,
46  const std::size_t values_per_cell = 1)
47  {
48  const std::size_t num_cells = active_map.size();
49  if (data.size() != num_cells * values_per_cell) {
50  throw std::invalid_argument("Data size does not match the size of active_map times values_per_cell.");
51  }
52 
53  std::size_t shift = 0;
54  for (std::size_t value_index = 0; value_index < values_per_cell; ++value_index) {
55  for (std::size_t g = 0; g < active_map.size(); ++g) {
56  if (active_map[g] && shift > 0) {
57  const std::size_t orig_index = value_index * num_cells + g;
58  data[orig_index - shift] = data[orig_index];
59  continue;
60  }
61  if (!active_map[g]) {
62  shift += 1;
63  }
64  }
65  }
66 
67  data.resize(data.size() - shift);
68  }
69 
70  template <typename T>
71  struct FieldData
72  {
73  std::vector<T> data{};
74  std::vector<value::status> value_status{};
75  keywords::keyword_info<T> kw_info{};
76  std::optional<std::vector<T>> global_data{};
77  std::optional<std::vector<value::status>> global_value_status{std::nullopt};
78  mutable bool all_set{false};
79 
80  bool operator==(const FieldData& other) const
81  {
82  return this->data == other.data &&
83  this->value_status == other.value_status &&
84  this->kw_info == other.kw_info &&
85  this->global_data == other.global_data &&
86  this->global_value_status == other.global_value_status;
87  }
88 
89  FieldData() = default;
90 
92  const std::size_t active_size,
93  const std::size_t global_size)
94  : data (active_size * info.num_value)
95  , value_status(active_size * info.num_value, value::status::uninitialized)
96  , kw_info (info)
97  , all_set (false)
98  {
99  if (global_size != 0) {
100  this->global_data.emplace(global_size * this->numValuePerCell());
101  this->global_value_status.emplace(global_size * this->numValuePerCell(), value::status::uninitialized);
102  }
103 
104  if (info.scalar_init) {
105  this->default_assign(*info.scalar_init);
106  }
107  }
108 
109  std::size_t numCells() const
110  {
111  return this->data.size() / this->numValuePerCell();
112  }
113 
114  std::size_t dataSize() const
115  {
116  return this->data.size();
117  }
118 
119  std::size_t numValuePerCell() const
120  {
121  return this->kw_info.num_value;
122  }
123 
124  bool valid() const
125  {
126  if (this->all_set) {
127  return true;
128  }
129 
130  // Object is "valid" if the 'value_status' of every element is
131  // neither uninitialised nor empty.
132  return this->all_set =
133  std::ranges::none_of(this->value_status,
134  [](const value::status& status)
135  {
136  return (status == value::status::uninitialized)
137  || (status == value::status::empty_default);
138  });
139  }
140 
141  bool valid_default() const
142  {
143  return std::ranges::all_of(this->value_status,
144  [](const value::status& status)
145  { return status == value::status::valid_default; });
146  }
147 
148  void compress(const std::vector<bool>& active_map)
149  {
150  Fieldprops::compress(this->data, active_map, this->numValuePerCell());
151  Fieldprops::compress(this->value_status, active_map, this->numValuePerCell());
152  }
153 
154  void checkInitialisedCopy(const FieldData& src,
155  const std::vector<Box::cell_index>& index_list,
156  const std::string& from,
157  const std::string& to,
158  const KeywordLocation& loc,
159  const bool global = false);
160 
161  void default_assign(T value)
162  {
163  std::ranges::fill(this->data, value);
164  std::ranges::fill(this->value_status, value::status::valid_default);
165 
166  if (this->global_data) {
167  std::ranges::fill(*this->global_data, value);
168 
169  std::ranges::fill(*this->global_value_status, value::status::valid_default);
170  }
171  }
172 
173  void default_assign(const std::vector<T>& src)
174  {
175  if (src.size() != this->dataSize()) {
176  throw std::invalid_argument {
177  "Size mismatch got: " + std::to_string(src.size()) +
178  ", expected: " + std::to_string(this->dataSize())
179  };
180  }
181 
182  std::ranges::copy(src, this->data.begin());
183  std::ranges::fill(this->value_status, value::status::valid_default);
184  }
185 
186  void default_assign_global(const std::vector<T>& src)
187  {
188  if (!global_data) {
189  throw std::invalid_argument {
190  "Cannot call default_assign_global on keyword with local storage"
191  };
192  }
193 
194  if (src.size() != this->global_data->size()) {
195  throw std::invalid_argument {
196  "Size mismatch got: " + std::to_string(src.size()) +
197  ", expected: " + std::to_string(this->dataSize())
198  };
199  }
200 
201  std::ranges::copy(src, this->global_data->begin());
202  std::ranges::fill(*this->global_value_status, value::status::valid_default);
203  }
204 
205  void update_local_from_global(std::function<std::size_t(std::size_t)> local_to_global)
206  {
207  if (!global_data) {
208  throw std::invalid_argument {
209  "Cannot call update_local_from_gloabl on keyword with local storage"
210  };
211  }
212  std::size_t i{};
213  auto current_status = this->value_status.begin();
214  for(auto current = this->data.begin(); current != this->data.end(); ++current, ++current_status, ++i)
215  {
216  const auto& global = local_to_global(i);
217  *current = (*global_data)[global];
218  *current_status = (*global_value_status)[global];
219  }
220  }
221 
222  void default_update(const std::vector<T>& src)
223  {
224  if (src.size() != this->dataSize()) {
225  throw std::invalid_argument {
226  "Size mismatch got: " + std::to_string(src.size()) +
227  ", expected: " + std::to_string(this->dataSize())
228  };
229  }
230 
231  for (std::size_t i = 0; i < src.size(); ++i) {
232  if (!value::has_value(this->value_status[i])) {
233  this->value_status[i] = value::status::valid_default;
234  this->data[i] = src[i];
235  }
236  }
237  }
238 
239  void update(const std::size_t index,
240  T value,
241  const value::status status)
242  {
243  this->data[index] = value;
244  this->value_status[index] = status;
245  }
246  };
247 
248 } // namespace Opm::Fieldprops
249 
250 #endif // FIELD_DATA_HPP
Definition: KeywordLocation.hpp:27
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Definition: Keywords.hpp:31
Definition: FieldData.hpp:41
Definition: FieldData.hpp:71