Add Container for Dynamic WBPn Source Values
This commit adds a new container class, PAvgDynamicSourceData which wraps a single vector<double> which in turn backs source data items for - pressure values - fluid mixture densities - dynamic pore-volumes at a collection of source locations-active cells or well reservoir connections. We provide read-only and read-write accessors to the underlying data items for a single source location through subscript operator (read only) and named assignment (set(), read-write) member functions. The latter is available only when the underlying range of data values is mutable (e.g., SourceDataSpan<double>) as opposed to immutable (e.g., SourceDataSpan<const double>).
This commit is contained in:
parent
46415cebed
commit
c7d6604d98
@ -204,6 +204,7 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/input/eclipse/Schedule/Well/PAvg.cpp
|
||||
src/opm/input/eclipse/Schedule/Well/PAvgCalculator.cpp
|
||||
src/opm/input/eclipse/Schedule/Well/PAvgCalculatorCollection.cpp
|
||||
src/opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.cpp
|
||||
src/opm/input/eclipse/Schedule/Well/Well.cpp
|
||||
src/opm/input/eclipse/Schedule/Well/WellConnections.cpp
|
||||
src/opm/input/eclipse/Schedule/Well/WellMatcher.cpp
|
||||
@ -460,11 +461,12 @@ if(ENABLE_ECL_INPUT)
|
||||
tests/test_RestartFileView.cpp
|
||||
tests/test_EclIO.cpp
|
||||
tests/test_EGrid.cpp
|
||||
tests/test_EInit.cpp
|
||||
tests/test_ERft.cpp
|
||||
tests/test_ERst.cpp
|
||||
tests/test_ESmry.cpp
|
||||
tests/test_EInit.cpp
|
||||
tests/test_ExtESmry.cpp
|
||||
tests/test_PAvgDynamicSourceData.cpp
|
||||
tests/test_Serialization.cpp
|
||||
tests/material/test_co2brinepvt.cpp
|
||||
tests/material/test_eclblackoilfluidsystem.cpp
|
||||
@ -1212,6 +1214,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/input/eclipse/Schedule/Well/PAvg.hpp
|
||||
opm/input/eclipse/Schedule/Well/PAvgCalculator.hpp
|
||||
opm/input/eclipse/Schedule/Well/PAvgCalculatorCollection.hpp
|
||||
opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.hpp
|
||||
opm/input/eclipse/Schedule/Well/Well.hpp
|
||||
opm/input/eclipse/Schedule/Well/WellEnums.hpp
|
||||
opm/input/eclipse/Schedule/Well/WellInjectionControls.hpp
|
||||
|
256
opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.hpp
Normal file
256
opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.hpp
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
Copyright 2023 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 PAVE_DYNAMIC_SOURCE_DATA_HPP
|
||||
#define PAVE_DYNAMIC_SOURCE_DATA_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/// Dynamic source data for block-average pressure calculations
|
||||
class PAvgDynamicSourceData
|
||||
{
|
||||
public:
|
||||
/// Ad hoc implementation of fixed-width span/view of an underlying
|
||||
/// contiguous range of elements.
|
||||
///
|
||||
/// \tparam T Element type. Const or non-const as needed. Typically \c
|
||||
/// double or \code const double \endcode.
|
||||
template <typename T>
|
||||
class SourceDataSpan
|
||||
{
|
||||
private:
|
||||
friend class PAvgDynamicSourceData;
|
||||
|
||||
public:
|
||||
/// Supported items of dynamic data per source location
|
||||
enum class Item
|
||||
{
|
||||
Pressure, //< Dynamic pressure value
|
||||
MixtureDensity, //< Dynamic mixture density
|
||||
PoreVol, //< Dynamic pore volume
|
||||
|
||||
// ----------------------------------------
|
||||
|
||||
Last_Do_Not_Use, //< Simplifies item count
|
||||
};
|
||||
|
||||
using ElmT = std::remove_cv_t<T>;
|
||||
|
||||
/// Read-only access to numerical value of specified item
|
||||
///
|
||||
/// \param[in] i Item of dynamic source data.
|
||||
/// \return Numerical value of specified item.
|
||||
[[nodiscard]] constexpr ElmT operator[](const Item i) const
|
||||
{
|
||||
return this->begin_[this->index(i)];
|
||||
}
|
||||
|
||||
/// Assign specified item
|
||||
///
|
||||
/// Availble only if underlying range is non-const.
|
||||
///
|
||||
/// \param[in] i Item of dynamic source data.
|
||||
/// \param[in] value Numerical value of specified item.
|
||||
/// \return \code *this \endcode to enable chaining.
|
||||
template <typename Ret = SourceDataSpan&>
|
||||
constexpr std::enable_if_t<! std::is_const_v<T>, Ret>
|
||||
set(const Item i, const ElmT value)
|
||||
{
|
||||
this->begin_[this->index(i)] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assign all items
|
||||
///
|
||||
/// Availble only if underlying range is non-const.
|
||||
///
|
||||
/// \param[in] i Item of dynamic source data.
|
||||
/// \param[in] value Numerical value of specified item.
|
||||
/// \return \code *this \endcode to enable chaining.
|
||||
template <typename U, typename Ret = SourceDataSpan&>
|
||||
constexpr std::enable_if_t<! std::is_const_v<T>, Ret>
|
||||
operator=(const SourceDataSpan<U> src)
|
||||
{
|
||||
std::copy_n(src.begin_, NumItems, this->begin_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Number of data items per source location
|
||||
static constexpr auto NumItems =
|
||||
static_cast<std::size_t>(Item::Last_Do_Not_Use);
|
||||
|
||||
/// Beginning of items associated to a single source location.
|
||||
T* begin_{nullptr};
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param[in] begin Beginning of items associated to a single
|
||||
/// source location.
|
||||
explicit SourceDataSpan(T* begin)
|
||||
: begin_{begin}
|
||||
{}
|
||||
|
||||
/// Translate item into linear index
|
||||
///
|
||||
/// \param[in] i Item of dynamic source data
|
||||
/// \return Linear index into span corresponding to specified item.
|
||||
constexpr std::size_t index(const Item i) const
|
||||
{
|
||||
const auto ix = static_cast<std::size_t>(i);
|
||||
if (ix >= NumItems) {
|
||||
throw std::invalid_argument {
|
||||
"Index out of bounds"
|
||||
};
|
||||
}
|
||||
|
||||
return ix;
|
||||
}
|
||||
};
|
||||
|
||||
/// Constructor
|
||||
///
|
||||
/// \param[in] sourceLocations Known locations, typically linearised
|
||||
/// global call IDs, for which to enable collecting/reporting dynamic
|
||||
/// source data.
|
||||
explicit PAvgDynamicSourceData(const std::vector<std::size_t>& sourceLocations);
|
||||
|
||||
/// Destructor
|
||||
///
|
||||
/// Marked virtual because this type is intended for inheritance.
|
||||
virtual ~PAvgDynamicSourceData() {}
|
||||
|
||||
/// Acquire read/write span of data items corresponding to a single
|
||||
/// source location.
|
||||
///
|
||||
/// Mostly intended for assigning values.
|
||||
///
|
||||
/// \param[in] source Source location. Function will \c throw if \p
|
||||
/// source is not one of the known locations registered in the object
|
||||
/// constructor.
|
||||
///
|
||||
/// \return Read/write span of data items.
|
||||
[[nodiscard]] SourceDataSpan<double>
|
||||
operator[](const std::size_t source);
|
||||
|
||||
/// Acquire read-only span of data items corresponding to a single
|
||||
/// source location.
|
||||
///
|
||||
/// Intended for extracting previously assigned data items.
|
||||
///
|
||||
/// \param[in] source Source location. Function will \c throw if \p
|
||||
/// source is not one of the known locations registered in the object
|
||||
/// constructor.
|
||||
///
|
||||
/// \return Read-only span of data items.
|
||||
[[nodiscard]] SourceDataSpan<const double>
|
||||
operator[](const std::size_t source) const;
|
||||
|
||||
protected:
|
||||
/// Contiguous array of data items for all source locations.
|
||||
///
|
||||
/// Intentionally accessible to derived classes for use in parallel
|
||||
/// runs.
|
||||
std::vector<double> src_{};
|
||||
|
||||
/// Form mutable data span into non-default backing store.
|
||||
///
|
||||
/// Mainly intended for constructing span objects in backing store for
|
||||
/// local (on-rank) sources in parallel runs.
|
||||
///
|
||||
/// \param[in] ix Logical element index into source term backing store.
|
||||
///
|
||||
/// \param[in,out] src Source term backing store.
|
||||
///
|
||||
/// \return Mutable view into \p src.
|
||||
[[nodiscard]] SourceDataSpan<double>
|
||||
sourceTerm(const std::size_t ix, std::vector<double>& src);
|
||||
|
||||
/// Reconstruct Source Data backing storage and internal mapping tables
|
||||
///
|
||||
/// Effectively replaces the original object formed by the constructor.
|
||||
/// Mainly intended for updating objects as new wells and/or new
|
||||
/// reservoir connections are introduced.
|
||||
///
|
||||
/// \param[in] sourceLocations Known locations, typically linearised
|
||||
/// global call IDs, for which to enable collecting/reporting dynamic
|
||||
/// source data.
|
||||
void reconstruct(const std::vector<std::size_t>& sourceLocations);
|
||||
|
||||
/// Provide number of span items using function syntax
|
||||
///
|
||||
/// Marked 'protected' because derived classes might need this
|
||||
/// information too.
|
||||
///
|
||||
/// \return Number of span items.
|
||||
static constexpr std::size_t numSpanItems() noexcept
|
||||
{
|
||||
return SourceDataSpan<const double>::NumItems;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Translate non-contiguous source locations to starting indices in \c
|
||||
/// src_.
|
||||
std::unordered_map<std::size_t, std::vector<double>::size_type> ix_{};
|
||||
|
||||
/// Form source location to index translation table.
|
||||
///
|
||||
/// \param[in] sourceLocations Known locations, typically linearised
|
||||
/// global call IDs, for which to enable collecting/reporting dynamic
|
||||
/// source data.
|
||||
///
|
||||
/// \return Whether or not table formation succeeded. Typical reasons
|
||||
/// for failure is repeated source locations.
|
||||
void buildLocationMapping(const std::vector<std::size_t>& sourceLocations);
|
||||
|
||||
/// Translate source location to starting index in \c src_.
|
||||
///
|
||||
/// \param[in] source Source location.
|
||||
///
|
||||
/// \return Starting index. Nullopt if no index exists for \p source.
|
||||
[[nodiscard]] std::optional<std::vector<double>::size_type>
|
||||
index(const std::size_t source) const;
|
||||
|
||||
/// Translate element index into storage index.
|
||||
///
|
||||
/// This is a customisation point to simplify usage in parallel contexts.
|
||||
///
|
||||
/// Default implementation, identity mapping.
|
||||
///
|
||||
/// \param[in] elemIndex Source element index.
|
||||
///
|
||||
/// \return Storage (starting) index in \c src_.
|
||||
[[nodiscard]] virtual std::vector<double>::size_type
|
||||
storageIndex(std::vector<double>::size_type elemIndex) const
|
||||
{
|
||||
return elemIndex;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif // PAVE_DYNAMIC_SOURCE_DATA_HPP
|
107
src/opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.cpp
Normal file
107
src/opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2023 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/>.
|
||||
*/
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.hpp>
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
Opm::PAvgDynamicSourceData::PAvgDynamicSourceData(const std::vector<std::size_t>& sourceLocations)
|
||||
: src_(numSpanItems() * sourceLocations.size(), 0.0)
|
||||
{
|
||||
this->buildLocationMapping(sourceLocations);
|
||||
}
|
||||
|
||||
Opm::PAvgDynamicSourceData::SourceDataSpan<double>
|
||||
Opm::PAvgDynamicSourceData::operator[](const std::size_t source)
|
||||
{
|
||||
const auto i = this->index(source);
|
||||
if (! i.has_value()) {
|
||||
OPM_THROW_NOLOG(std::invalid_argument,
|
||||
fmt::format("Dynamic source location "
|
||||
"'{}' is not registered", source));
|
||||
}
|
||||
|
||||
return SourceDataSpan<double>{ &this->src_[*i] };
|
||||
}
|
||||
|
||||
Opm::PAvgDynamicSourceData::SourceDataSpan<const double>
|
||||
Opm::PAvgDynamicSourceData::operator[](const std::size_t source) const
|
||||
{
|
||||
const auto i = this->index(source);
|
||||
if (! i.has_value()) {
|
||||
OPM_THROW_NOLOG(std::invalid_argument,
|
||||
fmt::format("Dynamic source location "
|
||||
"'{}' is not registered", source));
|
||||
}
|
||||
|
||||
return SourceDataSpan<const double>{ &this->src_[*i] };
|
||||
}
|
||||
|
||||
Opm::PAvgDynamicSourceData::SourceDataSpan<double>
|
||||
Opm::PAvgDynamicSourceData::sourceTerm(const std::size_t ix, std::vector<double>& src)
|
||||
{
|
||||
return SourceDataSpan<double> { &src[ix*numSpanItems() + 0] };
|
||||
}
|
||||
|
||||
void
|
||||
Opm::PAvgDynamicSourceData::
|
||||
reconstruct(const std::vector<std::size_t>& sourceLocations)
|
||||
{
|
||||
this->src_.assign(numSpanItems() * sourceLocations.size(), 0.0);
|
||||
|
||||
this->buildLocationMapping(sourceLocations);
|
||||
}
|
||||
|
||||
void
|
||||
Opm::PAvgDynamicSourceData::
|
||||
buildLocationMapping(const std::vector<std::size_t>& sourceLocations)
|
||||
{
|
||||
this->ix_.clear();
|
||||
|
||||
auto ix = std::vector<double>::size_type{0};
|
||||
for (const auto& srcLoc : sourceLocations) {
|
||||
auto elm = this->ix_.emplace(srcLoc, ix++);
|
||||
if (! elm.second) {
|
||||
OPM_THROW_NOLOG(std::invalid_argument,
|
||||
fmt::format("Failed to set up internal mapping table, "
|
||||
"single location {} entered multiple times.",
|
||||
srcLoc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::vector<double>::size_type>
|
||||
Opm::PAvgDynamicSourceData::index(const std::size_t source) const
|
||||
{
|
||||
auto pos = this->ix_.find(source);
|
||||
if (pos == this->ix_.end()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return numSpanItems() * this->storageIndex(pos->second);
|
||||
}
|
151
tests/test_PAvgDynamicSourceData.cpp
Normal file
151
tests/test_PAvgDynamicSourceData.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright (c) 2023 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 test_PAvgDynamicSourceData
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Dynamic_Source_Data)
|
||||
|
||||
namespace {
|
||||
std::vector<std::size_t> small()
|
||||
{
|
||||
return { 1, 2, 3, 5, };
|
||||
}
|
||||
|
||||
std::vector<std::size_t> repeated()
|
||||
{
|
||||
return { 1, 2, 3, 5, 3, };
|
||||
}
|
||||
|
||||
Opm::PAvgDynamicSourceData smallResult()
|
||||
{
|
||||
using S = decltype(std::declval<Opm::PAvgDynamicSourceData>()[0]);
|
||||
using I = typename S::Item;
|
||||
|
||||
auto src = Opm::PAvgDynamicSourceData { small() };
|
||||
|
||||
src[1].set(I::Pressure, 123.4).set(I::MixtureDensity, 121.2).set(I::PoreVol, 543.21);
|
||||
src[2].set(I::Pressure, 12.34).set(I::MixtureDensity, 12.12).set(I::PoreVol, 54.321);
|
||||
src[3].set(I::Pressure, 1.234).set(I::MixtureDensity, 1.212).set(I::PoreVol, 5.4321);
|
||||
src[5].set(I::Pressure, 1234) .set(I::MixtureDensity, 1212.).set(I::PoreVol, 5432.1);
|
||||
|
||||
return src;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Mutable)
|
||||
{
|
||||
using S = decltype(std::declval<Opm::PAvgDynamicSourceData>()[0]);
|
||||
using I = typename S::Item;
|
||||
|
||||
auto src = Opm::PAvgDynamicSourceData { small() };
|
||||
|
||||
src[1].set(I::Pressure, 123.4).set(I::MixtureDensity, 121.2).set(I::PoreVol, 543.21);
|
||||
|
||||
{
|
||||
const auto s1 = src[1];
|
||||
BOOST_CHECK_CLOSE(s1[I::Pressure], 123.4, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s1[I::MixtureDensity], 121.2, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s1[I::PoreVol], 543.21, 1.0e-10);
|
||||
}
|
||||
|
||||
{
|
||||
const auto s2 = src[2];
|
||||
BOOST_CHECK_CLOSE(s2[I::Pressure], 0.0, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s2[I::MixtureDensity], 0.0, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s2[I::PoreVol], 0.0, 1.0e-10);
|
||||
}
|
||||
|
||||
src[2].set(I::Pressure, 123.4).set(I::MixtureDensity, 121.2).set(I::PoreVol, 543.21);
|
||||
|
||||
{
|
||||
const auto s2 = src[2];
|
||||
BOOST_CHECK_CLOSE(s2[I::Pressure], 123.4, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s2[I::MixtureDensity], 121.2, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s2[I::PoreVol], 543.21, 1.0e-10);
|
||||
}
|
||||
|
||||
BOOST_CHECK_THROW(src[4].set(I::Pressure, 0.5), std::invalid_argument);
|
||||
|
||||
src[5].set(I::Pressure, 123.4).set(I::MixtureDensity, 121.2).set(I::PoreVol, 543.21);
|
||||
|
||||
{
|
||||
const auto s5 = src[5];
|
||||
BOOST_CHECK_CLOSE(s5[I::Pressure], 123.4, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s5[I::MixtureDensity], 121.2, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s5[I::PoreVol], 543.21, 1.0e-10);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Immutable)
|
||||
{
|
||||
const auto src = smallResult();
|
||||
|
||||
using S = decltype(src[0]);
|
||||
using I = typename S::Item;
|
||||
|
||||
{
|
||||
const auto s1 = src[1];
|
||||
BOOST_CHECK_CLOSE(s1[I::Pressure], 123.4, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s1[I::MixtureDensity], 121.2, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s1[I::PoreVol], 543.21, 1.0e-10);
|
||||
}
|
||||
|
||||
{
|
||||
const auto s2 = src[2];
|
||||
BOOST_CHECK_CLOSE(s2[I::Pressure], 12.34, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s2[I::MixtureDensity], 12.12, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s2[I::PoreVol], 54.321, 1.0e-10);
|
||||
}
|
||||
|
||||
{
|
||||
const auto s3 = src[3];
|
||||
BOOST_CHECK_CLOSE(s3[I::Pressure], 1.234, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s3[I::MixtureDensity], 1.212, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s3[I::PoreVol], 5.4321, 1.0e-10);
|
||||
}
|
||||
|
||||
{
|
||||
const auto s5 = src[5];
|
||||
BOOST_CHECK_CLOSE(s5[I::Pressure], 1234., 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s5[I::MixtureDensity], 1212., 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(s5[I::PoreVol], 5432.1, 1.0e-10);
|
||||
}
|
||||
|
||||
BOOST_CHECK_THROW(std::ignore = src[1729], std::invalid_argument);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Repeated)
|
||||
{
|
||||
BOOST_CHECK_THROW(std::ignore = Opm::PAvgDynamicSourceData{ repeated() },
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // Dynamic_Source_Data
|
Loading…
Reference in New Issue
Block a user