My Project
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::transform(this->begin(),
169  this->end(),
170  rhs .begin(),
171  this->begin(),
172  std::plus<>{});
173 
174  return *this;
175  }
176 
188  template <typename OtherRandIt>
189  std::enable_if_t<
190  !std::is_same_v<RandIt, OtherRandIt> &&
191  std::is_convertible_v<typename InterRegFlow<OtherRandIt>::ElmT, ElmT>,
192  InterRegFlow&> operator=(const InterRegFlow<OtherRandIt>& rhs)
193  {
194  this->copyIn(rhs.begin(), rhs.end());
195 
196  return *this;
197  }
198 
205  void addFlow(const ElmT sign, const FlowRates& q)
206  {
207  assert (this->isValid());
208 
209  const auto numComp = static_cast<std::size_t>(Component::NumComponents);
210 
211  for (auto component = 0*numComp; component < numComp; ++component) {
212  this->add(sign * q.rate_[component], component);
213  }
214  }
215 
220  constexpr static std::size_t bufferSize() noexcept
221  {
222  return InterRegFlow::index(Component::NumComponents, Direction::Positive);
223  }
224 
231  constexpr ElmT flow(const Component component) const noexcept
232  {
233  // Add components since Positive and Negative are stored as
234  // signed quantities. In other words flow(x, Negative) <= 0
235  // while flow(x, Positive) >= 0).
236  return this->flow(component, Direction::Positive)
237  + this->flow(component, Direction::Negative);
238  }
239 
253  constexpr ElmT flow(const Component component,
254  const Direction direction) const noexcept
255  {
256  return *(this->elements_.first + InterRegFlow::index(component, direction));
257  }
258 
261  constexpr bool empty() const noexcept
262  {
263  return this->begin() == this->end();
264  }
265 
269  constexpr bool isValid() const noexcept
270  {
271  using sz_t = decltype(InterRegFlow::bufferSize());
272 
273  const auto& [begin, end] = this->elements_;
274 
275  return static_cast<sz_t>(std::distance(begin, end))
276  == InterRegFlow::bufferSize();
277  }
278 
280  RandIt begin() const noexcept
281  {
282  return this->elements_.first;
283  }
284 
286  RandIt end() const noexcept
287  {
288  return this->elements_.second;
289  }
290 
291  private:
293  std::pair<RandIt, RandIt> elements_;
294 
304  constexpr static std::size_t
305  index(const std::size_t component, const Direction direction)
306  {
307  return 2*component + (direction == Direction::Negative);
308  }
309 
317  constexpr static std::size_t
318  index(const Component component, const Direction direction)
319  {
320  return InterRegFlow::index(static_cast<std::size_t>(component), direction);
321  }
322 
327  void add(const ElmT rate, const std::size_t component)
328  {
329  const auto direction = std::signbit(rate)
330  ? Direction::Negative : Direction::Positive;
331 
332  auto* rateVec = &*this->elements_.first;
333  rateVec[InterRegFlow::index(component, direction)] += rate;
334  }
335 
339  void copyIn(const InterRegFlow& rhs)
340  {
341  if (this->elements_ != rhs.elements_) {
342  this->copyIn(rhs.elements_.first, rhs.elements_.second);
343  }
344  }
345 
352  template <typename OtherRandIt>
353  void copyIn(OtherRandIt begin, OtherRandIt end)
354  {
355  std::copy(begin, end, this->elements_.first);
356  }
357  };
358 
359 }} // namespace Opm::data
360 
361 #endif // OPM_OUTPUT_DATA_INTERREGFLOW_HPP
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:29