Add Protocol to Linearise Connection Flow Rates Into Subrange
This commit introduces a wrapper for a linear subrange of consecutive elements of an arithmetic type that imposes an ordering of the elements when treated as directional component surface flow rates. The wrapper distinguishes negative from positive flow rate contributions and tracks those separately. This is a building block for accounting for the inter-region flows in a parallel context.
This commit is contained in:
parent
27da32d812
commit
7ef3d6c0b3
@ -460,6 +460,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
tests/test_EclipseIO.cpp
|
||||
tests/test_DoubHEAD.cpp
|
||||
tests/test_InteHEAD.cpp
|
||||
tests/test_data_InterRegFlow.cpp
|
||||
tests/test_LinearisedOutputTable.cpp
|
||||
tests/test_LogiHEAD.cpp
|
||||
tests/test_LGOData.cpp
|
||||
@ -935,6 +936,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
opm/output/data/Cells.hpp
|
||||
opm/output/data/GuideRateValue.hpp
|
||||
opm/output/data/Groups.hpp
|
||||
opm/output/data/InterRegFlow.hpp
|
||||
opm/output/data/Solution.hpp
|
||||
opm/output/data/Wells.hpp
|
||||
opm/output/eclipse/VectorItems/action.hpp
|
||||
|
361
opm/output/data/InterRegFlow.hpp
Normal file
361
opm/output/data/InterRegFlow.hpp
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
Copyright (c) 2022 Equinor ASA
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_OUTPUT_DATA_INTERREGFLOW_HPP
|
||||
#define OPM_OUTPUT_DATA_INTERREGFLOW_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace Opm { namespace data {
|
||||
|
||||
/// Intermediary Protocol to Linearise Per-Connection Flow Rates Into Subrange.
|
||||
///
|
||||
/// \tparam RandIt Random access iterator type of subrange.
|
||||
template <typename RandIt>
|
||||
class InterRegFlow
|
||||
{
|
||||
public:
|
||||
/// Subrange element type.
|
||||
///
|
||||
/// Typically \c double or \c float.
|
||||
using ElmT = std::remove_cv_t<
|
||||
std::remove_reference_t<
|
||||
typename std::iterator_traits<RandIt>::value_type
|
||||
>>;
|
||||
|
||||
/// Surface component flow type.
|
||||
enum class Component : char {
|
||||
Oil, Gas, Water, Disgas, Vapoil,
|
||||
|
||||
// Must be last enumerator
|
||||
NumComponents,
|
||||
};
|
||||
|
||||
/// Surface flow direction.
|
||||
enum class Direction : char {
|
||||
Positive, Negative,
|
||||
};
|
||||
|
||||
/// Connection Flow Rates
|
||||
class FlowRates
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
FlowRates()
|
||||
{
|
||||
this->rate_.fill(ElmT{});
|
||||
}
|
||||
|
||||
/// Element access.
|
||||
///
|
||||
/// \param[in] i Component ID for specific element.
|
||||
///
|
||||
/// \return Read/Write reference to internal flow rate element.
|
||||
ElmT& operator[](const Component i)
|
||||
{
|
||||
return this->rate_[this->index(i)];
|
||||
}
|
||||
|
||||
friend class InterRegFlow;
|
||||
|
||||
private:
|
||||
/// Internal storage.
|
||||
std::array<ElmT, static_cast<std::size_t>(Component::NumComponents)> rate_{};
|
||||
|
||||
/// Convert component ID into linear index.
|
||||
///
|
||||
/// \param[in] i Component ID for specific element.
|
||||
///
|
||||
/// \return Linear index to internal flow rate element identified by \p i.
|
||||
std::size_t index(const Component i) const
|
||||
{
|
||||
return static_cast<std::size_t>(i);
|
||||
}
|
||||
};
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param[in] begin Beginning of subrange viewd by this instance.
|
||||
/// \param[in] end One-past-the-end of subrange viewed by this instance.
|
||||
explicit InterRegFlow(RandIt begin, RandIt end)
|
||||
: elements_(begin, end)
|
||||
{}
|
||||
|
||||
/// Deleted copy constructor.
|
||||
InterRegFlow(const InterRegFlow&) = delete;
|
||||
|
||||
/// Move constructor.
|
||||
///
|
||||
/// Invalidates source range.
|
||||
///
|
||||
/// \param[in,out] rhs Source range.
|
||||
InterRegFlow(InterRegFlow&& rhs)
|
||||
: elements_(rhs.elements_.first, rhs.elements_.second)
|
||||
{
|
||||
rhs.elements_.second = rhs.elements_.first; // rhs -> empty
|
||||
}
|
||||
|
||||
/// Assignment operator.
|
||||
///
|
||||
/// \param[in] rhs Source range.
|
||||
///
|
||||
/// \return \code *this \endcode.
|
||||
InterRegFlow& operator=(const InterRegFlow& rhs)
|
||||
{
|
||||
this->copyIn(rhs);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move assignment operator.
|
||||
///
|
||||
/// Invalidates source range.
|
||||
///
|
||||
/// \param[in,out] rhs Source range.
|
||||
///
|
||||
/// \return \code *this \endcode.
|
||||
InterRegFlow& operator=(InterRegFlow&& rhs)
|
||||
{
|
||||
if (! this->isValid()) {
|
||||
this->elements_ = rhs.elements_;
|
||||
}
|
||||
else {
|
||||
this->copyIn(rhs);
|
||||
}
|
||||
|
||||
rhs.elements_.second = rhs.elements_.first; // rhs -> empty
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Addition operator
|
||||
///
|
||||
/// \tparam OtherRandIt Random access iterator, possibly different
|
||||
/// from \c RandIt.
|
||||
///
|
||||
/// \param[in] rhs Source subrange.
|
||||
///
|
||||
/// \return \code *this \endcode.
|
||||
template <typename OtherRandIt>
|
||||
std::enable_if_t<
|
||||
std::is_convertible_v<typename InterRegFlow<OtherRandIt>::ElmT, ElmT>,
|
||||
InterRegFlow&> operator+=(const InterRegFlow<OtherRandIt>& rhs)
|
||||
{
|
||||
std::transform(this->begin(),
|
||||
this->end(),
|
||||
rhs .begin(),
|
||||
this->begin(),
|
||||
std::plus<>{});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assignment operator from different, but compatible, subrange.
|
||||
///
|
||||
/// Enables assigning into a subrange of \code vector<double>
|
||||
/// \endcode from a subrange backed by \code array<float,N> \endcode
|
||||
/// of compatible size.
|
||||
///
|
||||
/// \tparam OtherRandIt Random access iterator different from \c RandIt.
|
||||
///
|
||||
/// \param[in] rhs Source subrange.
|
||||
///
|
||||
/// \return \code *this \endcode.
|
||||
template <typename OtherRandIt>
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<RandIt, OtherRandIt> &&
|
||||
std::is_convertible_v<typename InterRegFlow<OtherRandIt>::ElmT, ElmT>,
|
||||
InterRegFlow&> operator=(const InterRegFlow<OtherRandIt>& rhs)
|
||||
{
|
||||
this->copyIn(rhs.begin(), rhs.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Accumulate connection contribution into subrange.
|
||||
///
|
||||
/// \param[in] sign Flow rate sign--e.g., to flip direction if
|
||||
/// needed in calling context.
|
||||
///
|
||||
/// \param[in] q Connection flow rates.
|
||||
void addFlow(const ElmT sign, const FlowRates& q)
|
||||
{
|
||||
assert (this->isValid());
|
||||
|
||||
const auto numComp = static_cast<std::size_t>(Component::NumComponents);
|
||||
|
||||
for (auto component = 0*numComp; component < numComp; ++component) {
|
||||
this->add(sign * q.rate_[component], component);
|
||||
}
|
||||
}
|
||||
|
||||
/// Buffer size (number of elements)
|
||||
///
|
||||
/// Storage buffer backing the \c InterRegFlow object must have at
|
||||
/// least \code InterRegFlow::bufferSize() \endcode contiguous elements.
|
||||
constexpr static std::size_t bufferSize() noexcept
|
||||
{
|
||||
return InterRegFlow::index(Component::NumComponents, Direction::Positive);
|
||||
}
|
||||
|
||||
/// Total accumulated flow rate of particular surface rate component
|
||||
/// for this region.
|
||||
///
|
||||
/// \param[in] component Component ID for specific element.
|
||||
///
|
||||
/// \return Flow rate.
|
||||
constexpr ElmT flow(const Component component) const noexcept
|
||||
{
|
||||
// Add components since Positive and Negative are stored as
|
||||
// signed quantities. In other words flow(x, Negative) <= 0
|
||||
// while flow(x, Positive) >= 0).
|
||||
return this->flow(component, Direction::Positive)
|
||||
+ this->flow(component, Direction::Negative);
|
||||
}
|
||||
|
||||
/// Accumulated flow rate for this region par of particular surface
|
||||
/// rate component in particular direction.
|
||||
///
|
||||
/// Flow from source to destination is \c Positive while from from
|
||||
/// destination to source is \c Negative. Numerical value in the \c
|
||||
/// Positive direction is non-negative while the numerical value in
|
||||
/// the \c Negative direction is non-positive.
|
||||
///
|
||||
/// \param[in] component Component ID for specific element.
|
||||
///
|
||||
/// \param[in] direction Flow direction.
|
||||
///
|
||||
/// \return Component flow rate in specified direction.
|
||||
constexpr ElmT flow(const Component component,
|
||||
const Direction direction) const noexcept
|
||||
{
|
||||
return *(this->elements_.first + InterRegFlow::index(component, direction));
|
||||
}
|
||||
|
||||
/// Predicate for whether or not this \c InterRegFlow object is
|
||||
/// backed by an empty range.
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return this->begin() == this->end();
|
||||
}
|
||||
|
||||
/// Predicate for whether or not this \c InterRegFlow object is
|
||||
/// backed by a valid range (size \code InterRegFlow::bufferSize()
|
||||
/// \endcode).
|
||||
constexpr bool isValid() const noexcept
|
||||
{
|
||||
using sz_t = decltype(InterRegFlow::bufferSize());
|
||||
|
||||
const auto& [begin, end] = this->elements_;
|
||||
|
||||
return static_cast<sz_t>(std::distance(begin, end))
|
||||
== InterRegFlow::bufferSize();
|
||||
}
|
||||
|
||||
/// Iterator to beginning of subrange.
|
||||
RandIt begin() const noexcept
|
||||
{
|
||||
return this->elements_.first;
|
||||
}
|
||||
|
||||
/// Iterator to one-past-end of subrange.
|
||||
RandIt end() const noexcept
|
||||
{
|
||||
return this->elements_.second;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Element subrange.
|
||||
std::pair<RandIt, RandIt> elements_;
|
||||
|
||||
/// Convert directional component ID into linear index.
|
||||
///
|
||||
/// Overload for already converted component index.
|
||||
///
|
||||
/// \param[in] component Component index for specific element.
|
||||
/// \param[in] direction Flow direction.
|
||||
///
|
||||
/// \return Linear index of ordered pair of component ID and flow
|
||||
/// direction.
|
||||
constexpr static std::size_t
|
||||
index(const std::size_t component, const Direction direction)
|
||||
{
|
||||
return 2*component + (direction == Direction::Negative);
|
||||
}
|
||||
|
||||
/// Convert directional component ID into linear index.
|
||||
///
|
||||
/// \param[in] component Component ID for specific element.
|
||||
/// \param[in] direction Flow direction.
|
||||
///
|
||||
/// \return Linear index of ordered pair of component ID and flow
|
||||
/// direction.
|
||||
constexpr static std::size_t
|
||||
index(const Component component, const Direction direction)
|
||||
{
|
||||
return InterRegFlow::index(static_cast<std::size_t>(component), direction);
|
||||
}
|
||||
|
||||
/// Accumulate component flow rate into linearised subrange.
|
||||
///
|
||||
/// \param[in] rate Component flow rate.
|
||||
/// \param[in] component Component index.
|
||||
void add(const ElmT rate, const std::size_t component)
|
||||
{
|
||||
const auto direction = std::signbit(rate)
|
||||
? Direction::Negative : Direction::Positive;
|
||||
|
||||
auto* rateVec = &*this->elements_.first;
|
||||
rateVec[InterRegFlow::index(component, direction)] += rate;
|
||||
}
|
||||
|
||||
/// Backend for assignment operator
|
||||
///
|
||||
/// \param[in] rhs Source subrange.
|
||||
void copyIn(const InterRegFlow& rhs)
|
||||
{
|
||||
if (this->elements_ != rhs.elements_) {
|
||||
this->copyIn(rhs.elements_.first, rhs.elements_.second);
|
||||
}
|
||||
}
|
||||
|
||||
/// Backend for assignment operator
|
||||
///
|
||||
/// Activated for compatible ranges.
|
||||
///
|
||||
/// \param[in] begin Beginning of source subrange.
|
||||
/// \param[in] end One-past-end of source subrange.
|
||||
template <typename OtherRandIt>
|
||||
void copyIn(OtherRandIt begin, OtherRandIt end)
|
||||
{
|
||||
std::copy(begin, end, this->elements_.first);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace Opm::data
|
||||
|
||||
#endif // OPM_OUTPUT_DATA_INTERREGFLOW_HPP
|
494
tests/test_data_InterRegFlow.cpp
Normal file
494
tests/test_data_InterRegFlow.cpp
Normal file
@ -0,0 +1,494 @@
|
||||
/*
|
||||
Copyright (c) 2022 Equinor ASA
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE data_InterRegFlow
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <opm/output/data/InterRegFlow.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(InterReg_View)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Construct)
|
||||
{
|
||||
using IRegFlow = Opm::data::InterRegFlow<decltype(std::declval<std::vector<double>>().begin())>;
|
||||
using IRegRate = IRegFlow::FlowRates;
|
||||
using Component = IRegFlow::Component;
|
||||
using Direction = IRegFlow::Direction;
|
||||
|
||||
auto store = std::vector<double>(IRegFlow::bufferSize(), 0.0);
|
||||
|
||||
{
|
||||
auto iregFlow = IRegFlow{ store.begin(), store.begin() }; // empty
|
||||
BOOST_CHECK_MESSAGE(iregFlow.empty(), "[begin, begin) must be an empty range");
|
||||
}
|
||||
|
||||
{
|
||||
auto iregFlow = IRegFlow{ store.begin(), store.begin() + static_cast<std::size_t>(Component::NumComponents) };
|
||||
BOOST_CHECK_MESSAGE(!iregFlow.isValid(), "Small range must be invalid");
|
||||
}
|
||||
|
||||
auto iregFlow = IRegFlow{ store.begin(), store.end() };
|
||||
BOOST_REQUIRE_MESSAGE(iregFlow.isValid(), "Valid range must be valid");
|
||||
|
||||
auto rate = IRegRate{};
|
||||
rate[Component::Oil] = 1.0;
|
||||
rate[Component::Gas] = 2.0;
|
||||
rate[Component::Water] = 3.0;
|
||||
rate[Component::Disgas] = 4.0;
|
||||
rate[Component::Vapoil] = 5.0;
|
||||
|
||||
iregFlow.addFlow(1.0, rate); // 1->2
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil, Direction::Positive), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas, Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water, Direction::Positive), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas, Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil, Direction::Positive), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil, Direction::Negative), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas, Direction::Negative), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water, Direction::Negative), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas, Direction::Negative), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil, Direction::Negative), 0.0, 1.0e-6);
|
||||
|
||||
iregFlow.addFlow(-1.0, rate); // 2->1
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas), 0.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil), 0.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil, Direction::Positive), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas, Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water, Direction::Positive), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas, Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil, Direction::Positive), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil, Direction::Negative), -1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas, Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water, Direction::Negative), -3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas, Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil, Direction::Negative), -5.0, 1.0e-6);
|
||||
|
||||
iregFlow.addFlow(1.0, rate); // 1->2
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil, Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas, Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water, Direction::Positive), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas, Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil, Direction::Positive), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Oil, Direction::Negative), -1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Gas, Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Water, Direction::Negative), -3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Disgas, Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(Component::Vapoil, Direction::Negative), -5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(store[0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[9], - 5.0, 1.0e-6);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Copy_Move_Assign_Add)
|
||||
{
|
||||
using IRegFlow = Opm::data::InterRegFlow<decltype(std::declval<std::vector<double>>().begin())>;
|
||||
using IRegRate = IRegFlow::FlowRates;
|
||||
using Component = IRegFlow::Component;
|
||||
using Direction = IRegFlow::Direction;
|
||||
|
||||
auto store = std::vector<double>(2 * IRegFlow::bufferSize(), 0.0);
|
||||
|
||||
{
|
||||
auto iregFlow = IRegFlow{ store.begin(), store.begin() }; // empty
|
||||
BOOST_CHECK_MESSAGE(iregFlow.empty(), "[begin, begin) must be an empty range");
|
||||
}
|
||||
|
||||
{
|
||||
auto iregFlow = IRegFlow{ store.begin(), store.end() };
|
||||
BOOST_CHECK_MESSAGE(!iregFlow.isValid(), "Large range must be invalid");
|
||||
}
|
||||
|
||||
auto iregFlow_1 = IRegFlow{ store.begin(), store.begin() + IRegFlow::bufferSize() };
|
||||
auto iregFlow_2 = IRegFlow{ store.begin() + IRegFlow::bufferSize(), store.end() };
|
||||
BOOST_REQUIRE_MESSAGE(iregFlow_1.isValid(), "Valid range 1 must be valid");
|
||||
BOOST_REQUIRE_MESSAGE(iregFlow_2.isValid(), "Valid range 2 must be valid");
|
||||
|
||||
auto rate = IRegRate{};
|
||||
rate[Component::Oil] = 1.0;
|
||||
rate[Component::Gas] = 2.0;
|
||||
rate[Component::Water] = 3.0;
|
||||
rate[Component::Disgas] = 4.0;
|
||||
rate[Component::Vapoil] = 5.0;
|
||||
|
||||
iregFlow_1.addFlow( 1.0, rate); // 1->2
|
||||
iregFlow_1.addFlow(- 1.0, rate); // 2->1
|
||||
iregFlow_1.addFlow( 1.0, rate); // 1->2
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Oil), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Gas), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Water), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Disgas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Vapoil), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Oil, Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Gas, Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Water, Direction::Positive), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Disgas, Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Vapoil, Direction::Positive), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Oil, Direction::Negative), -1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Gas, Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Water, Direction::Negative), -3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Disgas, Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Vapoil, Direction::Negative), -5.0, 1.0e-6);
|
||||
|
||||
const auto iregFlow_3 = std::move(iregFlow_1);
|
||||
BOOST_CHECK_MESSAGE(! iregFlow_1.isValid(), "Moved-from range must be invalid");
|
||||
BOOST_CHECK_MESSAGE( iregFlow_3.isValid(), "Move-constructed range must be valid");
|
||||
|
||||
BOOST_CHECK_CLOSE(store[0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[9], - 5.0, 1.0e-6);
|
||||
|
||||
iregFlow_2 = iregFlow_3;
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Oil), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Gas), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Water), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Disgas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Vapoil), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Oil, Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Gas, Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Water, Direction::Positive), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Disgas, Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Vapoil, Direction::Positive), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Oil, Direction::Negative), -1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Gas, Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Water, Direction::Negative), -3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Disgas, Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Vapoil, Direction::Negative), -5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(store[10 + 0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 9], - 5.0, 1.0e-6);
|
||||
|
||||
iregFlow_2 += iregFlow_3;
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Oil), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Gas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Water), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Disgas), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Vapoil), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Oil, Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Gas, Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Water, Direction::Positive), 12.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Disgas, Direction::Positive), 16.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Vapoil, Direction::Positive), 20.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Oil, Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Gas, Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Water, Direction::Negative), -6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Disgas, Direction::Negative), -8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_2.flow(Component::Vapoil, Direction::Negative), -10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(store[0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[9], - 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(store[10 + 0], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 1], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 2], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 3], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 4], 12.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 5], - 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 6], 16.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 7], - 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 8], 20.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 9], -10.0, 1.0e-6);
|
||||
|
||||
iregFlow_1 = std::move(iregFlow_2);
|
||||
BOOST_CHECK_MESSAGE(! iregFlow_2.isValid(), "Moved-from source range must be invalid");
|
||||
BOOST_CHECK_MESSAGE( iregFlow_1.isValid(), "Moved-assigned destination range must be valid");
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Oil), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Gas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Water), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Disgas), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Vapoil), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Oil, Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Gas, Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Water, Direction::Positive), 12.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Disgas, Direction::Positive), 16.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Vapoil, Direction::Positive), 20.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Oil, Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Gas, Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Water, Direction::Negative), -6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Disgas, Direction::Negative), -8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow_1.flow(Component::Vapoil, Direction::Negative), -10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(store[0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[9], - 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(store[10 + 0], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 1], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 2], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 3], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 4], 12.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 5], - 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 6], 16.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 7], - 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 8], 20.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(store[10 + 9], -10.0, 1.0e-6);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Assign_Different_Iterator)
|
||||
{
|
||||
using IRegFlow = Opm::data::InterRegFlow<decltype(std::declval<std::vector<double>>().begin())>;
|
||||
|
||||
using ArrayBuffer = std::array<double, IRegFlow::bufferSize()>;
|
||||
using IRegFlow_ArrayBacked = Opm::data::InterRegFlow<decltype(std::declval<ArrayBuffer>().begin())>;
|
||||
using IRegRate = IRegFlow_ArrayBacked::FlowRates;
|
||||
using Component = IRegFlow_ArrayBacked::Component;
|
||||
|
||||
auto buffer = ArrayBuffer{};
|
||||
buffer.fill(0.0);
|
||||
|
||||
auto iregFlow_array = IRegFlow_ArrayBacked{ buffer.begin(), buffer.end() };
|
||||
|
||||
auto rate = IRegRate{};
|
||||
rate[Component::Oil] = 1.0;
|
||||
rate[Component::Gas] = 2.0;
|
||||
rate[Component::Water] = 3.0;
|
||||
rate[Component::Disgas] = 4.0;
|
||||
rate[Component::Vapoil] = 5.0;
|
||||
|
||||
iregFlow_array.addFlow( 1.0, rate); // 1->2
|
||||
iregFlow_array.addFlow(- 1.0, rate); // 2->1
|
||||
iregFlow_array.addFlow( 1.0, rate); // 1->2
|
||||
|
||||
auto range = std::vector<double>(IRegFlow::bufferSize(), 0.0);
|
||||
auto iregFlow = IRegFlow{ range.begin(), range.end() };
|
||||
|
||||
iregFlow = iregFlow_array;
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil, IRegFlow::Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas, IRegFlow::Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water, IRegFlow::Direction::Positive), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas, IRegFlow::Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil, IRegFlow::Direction::Positive), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil, IRegFlow::Direction::Negative), -1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas, IRegFlow::Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water, IRegFlow::Direction::Negative), -3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas, IRegFlow::Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil, IRegFlow::Direction::Negative), -5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(range[0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[9], - 5.0, 1.0e-6);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Assign_Different_ElmT)
|
||||
{
|
||||
using IRegFlow = Opm::data::InterRegFlow<decltype(std::declval<std::vector<double>>().begin())>;
|
||||
using IRegFlow_float = Opm::data::InterRegFlow<decltype(std::declval<std::vector<float>>().begin())>;
|
||||
|
||||
using IRegRate = IRegFlow_float::FlowRates;
|
||||
using Component = IRegFlow_float::Component;
|
||||
|
||||
auto buffer = std::vector<float>(IRegFlow_float::bufferSize(), 0.0f);
|
||||
auto iregFlow_float = IRegFlow_float{ buffer.begin(), buffer.end() };
|
||||
|
||||
auto rate = IRegRate{};
|
||||
rate[Component::Oil] = 1.0f;
|
||||
rate[Component::Gas] = 2.0f;
|
||||
rate[Component::Water] = 3.0f;
|
||||
rate[Component::Disgas] = 4.0f;
|
||||
rate[Component::Vapoil] = 5.0f;
|
||||
|
||||
iregFlow_float.addFlow( 1.0, rate); // 1->2
|
||||
iregFlow_float.addFlow(- 1.0, rate); // 2->1
|
||||
iregFlow_float.addFlow( 1.0, rate); // 1->2
|
||||
|
||||
auto range = std::vector<double>(IRegFlow::bufferSize(), 0.0);
|
||||
auto iregFlow = IRegFlow{ range.begin(), range.end() };
|
||||
|
||||
iregFlow = iregFlow_float;
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil, IRegFlow::Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas, IRegFlow::Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water, IRegFlow::Direction::Positive), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas, IRegFlow::Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil, IRegFlow::Direction::Positive), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil, IRegFlow::Direction::Negative), -1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas, IRegFlow::Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water, IRegFlow::Direction::Negative), -3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas, IRegFlow::Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil, IRegFlow::Direction::Negative), -5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(range[0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[9], - 5.0, 1.0e-6);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Assign_Different_ElmT_Different_Iterator)
|
||||
{
|
||||
using IRegFlow = Opm::data::InterRegFlow<decltype(std::declval<std::vector<double>>().begin())>;
|
||||
|
||||
using ArrayBuffer = std::array<float, IRegFlow::bufferSize()>;
|
||||
using IRegFlow_ArrayBacked = Opm::data::InterRegFlow<decltype(std::declval<ArrayBuffer>().begin())>;
|
||||
using IRegRate = IRegFlow_ArrayBacked::FlowRates;
|
||||
using Component = IRegFlow_ArrayBacked::Component;
|
||||
|
||||
auto buffer = ArrayBuffer{};
|
||||
buffer.fill(0.0f);
|
||||
auto iregFlow_array = IRegFlow_ArrayBacked{ buffer.begin(), buffer.end() };
|
||||
|
||||
auto rate = IRegRate{};
|
||||
rate[Component::Oil] = 1.0f;
|
||||
rate[Component::Gas] = 2.0f;
|
||||
rate[Component::Water] = 3.0f;
|
||||
rate[Component::Disgas] = 4.0f;
|
||||
rate[Component::Vapoil] = 5.0f;
|
||||
|
||||
iregFlow_array.addFlow( 1.0, rate); // 1->2
|
||||
iregFlow_array.addFlow(- 1.0, rate); // 2->1
|
||||
iregFlow_array.addFlow( 1.0, rate); // 1->2
|
||||
|
||||
auto range = std::vector<double>(IRegFlow::bufferSize(), 0.0);
|
||||
auto iregFlow = IRegFlow{ range.begin(), range.end() };
|
||||
|
||||
iregFlow = iregFlow_array;
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil), 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water), 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil), 5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil, IRegFlow::Direction::Positive), 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas, IRegFlow::Direction::Positive), 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water, IRegFlow::Direction::Positive), 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas, IRegFlow::Direction::Positive), 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil, IRegFlow::Direction::Positive), 10.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Oil, IRegFlow::Direction::Negative), -1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Gas, IRegFlow::Direction::Negative), -2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Water, IRegFlow::Direction::Negative), -3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Disgas, IRegFlow::Direction::Negative), -4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(iregFlow.flow(IRegFlow::Component::Vapoil, IRegFlow::Direction::Negative), -5.0, 1.0e-6);
|
||||
|
||||
BOOST_CHECK_CLOSE(range[0], 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[1], - 1.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[2], 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[3], - 2.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[4], 6.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[5], - 3.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[6], 8.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[7], - 4.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[8], 10.0, 1.0e-6);
|
||||
BOOST_CHECK_CLOSE(range[9], - 5.0, 1.0e-6);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // InterReg_View
|
Loading…
Reference in New Issue
Block a user