opm-common
Loading...
Searching...
No Matches
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
33namespace 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