opm-common
InterRegFlow.hpp
1 /*
2  Copyright (c) 2022 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_OUTPUT_DATA_INTERREGFLOW_HPP
21 #define OPM_OUTPUT_DATA_INTERREGFLOW_HPP
22 
23 #include <algorithm>
24 #include <cassert>
25 #include <array>
26 #include <cmath>
27 #include <cstddef>
28 #include <functional>
29 #include <iterator>
30 #include <type_traits>
31 #include <utility>
32 
33 namespace Opm { namespace data {
34 
38  template <typename RandIt>
39  class InterRegFlow
40  {
41  public:
45  using ElmT = std::remove_cv_t<
46  std::remove_reference_t<
47  typename std::iterator_traits<RandIt>::value_type
48  >>;
49 
51  enum class Component : char {
52  Oil, Gas, Water, Disgas, Vapoil,
53 
54  // Must be last enumerator
55  NumComponents,
56  };
57 
59  enum class Direction : char {
60  Positive, Negative,
61  };
62 
64  class FlowRates
65  {
66  public:
68  FlowRates()
69  {
70  this->rate_.fill(ElmT{});
71  }
72 
78  ElmT& operator[](const Component i)
79  {
80  return this->rate_[this->index(i)];
81  }
82 
83  friend class InterRegFlow;
84 
85  private:
87  std::array<ElmT, static_cast<std::size_t>(Component::NumComponents)> rate_{};
88 
94  std::size_t index(const Component i) const
95  {
96  return static_cast<std::size_t>(i);
97  }
98  };
99 
104  explicit InterRegFlow(RandIt begin, RandIt end)
105  : elements_(begin, end)
106  {}
107 
109  InterRegFlow(const InterRegFlow&) = delete;
110 
116  InterRegFlow(InterRegFlow&& rhs)
117  : elements_(rhs.elements_.first, rhs.elements_.second)
118  {
119  rhs.elements_.second = rhs.elements_.first; // rhs -> empty
120  }
121 
127  InterRegFlow& operator=(const InterRegFlow& rhs)
128  {
129  this->copyIn(rhs);
130 
131  return *this;
132  }
133 
141  InterRegFlow& operator=(InterRegFlow&& rhs)
142  {
143  if (! this->isValid()) {
144  this->elements_ = rhs.elements_;
145  }
146  else {
147  this->copyIn(rhs);
148  }
149 
150  rhs.elements_.second = rhs.elements_.first; // rhs -> empty
151 
152  return *this;
153  }
154 
163  template <typename OtherRandIt>
164  std::enable_if_t<
165  std::is_convertible_v<typename InterRegFlow<OtherRandIt>::ElmT, ElmT>,
166  InterRegFlow&> operator+=(const InterRegFlow<OtherRandIt>& rhs)
167  {
168  std::ranges::transform(*this, rhs, this->begin(), std::plus<>{});
169 
170  return *this;
171  }
172 
184  template <typename OtherRandIt>
185  std::enable_if_t<
186  !std::is_same_v<RandIt, OtherRandIt> &&
187  std::is_convertible_v<typename InterRegFlow<OtherRandIt>::ElmT, ElmT>,
188  InterRegFlow&> operator=(const InterRegFlow<OtherRandIt>& rhs)
189  {
190  this->copyIn(rhs.begin(), rhs.end());
191 
192  return *this;
193  }
194 
201  void addFlow(const ElmT sign, const FlowRates& q)
202  {
203  assert (this->isValid());
204 
205  const auto numComp = static_cast<std::size_t>(Component::NumComponents);
206 
207  for (auto component = 0*numComp; component < numComp; ++component) {
208  this->add(sign * q.rate_[component], component);
209  }
210  }
211 
216  constexpr static std::size_t bufferSize() noexcept
217  {
218  return InterRegFlow::index(Component::NumComponents, Direction::Positive);
219  }
220 
227  constexpr ElmT flow(const Component component) const noexcept
228  {
229  // Add components since Positive and Negative are stored as
230  // signed quantities. In other words flow(x, Negative) <= 0
231  // while flow(x, Positive) >= 0).
232  return this->flow(component, Direction::Positive)
233  + this->flow(component, Direction::Negative);
234  }
235 
249  constexpr ElmT flow(const Component component,
250  const Direction direction) const noexcept
251  {
252  return *(this->elements_.first + InterRegFlow::index(component, direction));
253  }
254 
257  constexpr bool empty() const noexcept
258  {
259  return this->begin() == this->end();
260  }
261 
265  constexpr bool isValid() const noexcept
266  {
267  using sz_t = decltype(InterRegFlow::bufferSize());
268 
269  const auto& [begin, end] = this->elements_;
270 
271  return static_cast<sz_t>(std::distance(begin, end))
272  == InterRegFlow::bufferSize();
273  }
274 
276  RandIt begin() const noexcept
277  {
278  return this->elements_.first;
279  }
280 
282  RandIt end() const noexcept
283  {
284  return this->elements_.second;
285  }
286 
287  private:
289  std::pair<RandIt, RandIt> elements_;
290 
300  constexpr static std::size_t
301  index(const std::size_t component, const Direction direction)
302  {
303  return 2*component + (direction == Direction::Negative);
304  }
305 
313  constexpr static std::size_t
314  index(const Component component, const Direction direction)
315  {
316  return InterRegFlow::index(static_cast<std::size_t>(component), direction);
317  }
318 
323  void add(const ElmT rate, const std::size_t component)
324  {
325  const auto direction = std::signbit(rate)
326  ? Direction::Negative : Direction::Positive;
327 
328  auto* rateVec = &*this->elements_.first;
329  rateVec[InterRegFlow::index(component, direction)] += rate;
330  }
331 
335  void copyIn(const InterRegFlow& rhs)
336  {
337  if (this->elements_ != rhs.elements_) {
338  this->copyIn(rhs.elements_.first, rhs.elements_.second);
339  }
340  }
341 
348  template <typename OtherRandIt>
349  void copyIn(OtherRandIt begin, OtherRandIt end)
350  {
351  std::copy(begin, end, this->elements_.first);
352  }
353  };
354 
355 }} // namespace Opm::data
356 
357 #endif // OPM_OUTPUT_DATA_INTERREGFLOW_HPP
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30