My Project
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::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:30