20#ifndef OPM_ECLPVTCOMMON_HEADER_INCLUDED
21#define OPM_ECLPVTCOMMON_HEADER_INCLUDED
35#include <initializer_list>
49 class ECLInitFileData;
52namespace Opm {
namespace ECLPVT {
83 density(const ::Opm::ECLUnits::UnitSystem& usys);
94 pressure(const ::Opm::ECLUnits::UnitSystem& usys);
116 disGas(const ::Opm::ECLUnits::UnitSystem& usys);
127 vapOil(const ::Opm::ECLUnits::UnitSystem& usys);
320 template <std::
size_t N>
333 std::plus<double>());
344 std::minus<double>());
354 [rhs](
const double xi)
367 [rhs](
const double xi)
375 const std::array<double, N>&
array()
const
381 std::array<double, N> x_;
384 template <std::
size_t N>
390 template <std::
size_t N>
396 template <std::
size_t N>
402 template <std::
size_t N>
408 template <std::
size_t N>
414 template <
class Extrapolation,
bool IsAscendingRange>
423 ? std::size_t{0} : std::size_t{1};
428 assert ((
x.size() == y.size()) &&
"Setup Error");
444 assert ((
b.size() == y.size()) &&
"Setup Error");
446 for (
auto n = y.size(), i = 0*n; i < n; ++i) {
482 std::vector<ElemIt>& colIt);
517 using Extrap = ::Opm::Interp1D::PiecewisePolynomial::
518 ExtrapolationPolicy::Linearly;
525 using EvalPt = std::decay<
526 decltype(std::declval<Backend>().classifyPoint(0.0))
539 EvalPt getInterpPoint(
const double p)
const
545 double fvf_recip(
const EvalPt& pt)
const
547 const auto col = std::size_t{0};
549 return this->interp_.evaluate(col, pt);
554 double fvf_mu_recip(
const EvalPt& pt)
const
556 const auto col = std::size_t{1};
558 return this->interp_.evaluate(col, pt);
563 template <
class EvalDynamicQuant>
565 computeQuantity(
const std::vector<double>& p,
566 EvalDynamicQuant&& eval)
const
568 auto result = std::vector<double>{};
569 result.reserve(p.size());
571 for (
const auto&
pi : p) {
572 result.push_back(eval(this->getInterpPoint(
pi)));
582 template <
class SubtableInterpolant>
587 std::vector<SubtableInterpolant> propInterp)
588 : key_ (std::move(key))
589 , propInterp_(std::move(propInterp))
591 if (this->key_.size() != this->propInterp_.size()) {
592 throw std::invalid_argument {
593 "Size of Key Table Does Not Match "
594 "Number of Sub-Table Interpolants"
598 if (this->key_.size() < 2) {
599 throw std::invalid_argument {
600 "Mixing-Dependent Property Evaluator "
601 "Must Have At Least Two Inner Tables"
608 const std::vector<double>&
data;
613 const std::vector<double>&
data;
620 const auto col = std::size_t{0};
622 return this->computeQuantity(key,
x,
623 [
this, col](
const std::size_t curve,
624 const InnerEvalPoint& pt) ->
double
626 return this->propInterp_[curve].evaluate(col, pt);
628 [](
const double recipFvF) ->
double
631 return 1.0 / recipFvF;
639 return this->computeQuantity(key,
x,
640 [
this](
const std::size_t curve,
644 const auto& I = this->propInterp_[curve];
646 const auto fvf_recip = I.evaluate(0, pt);
647 const auto fvf_mu_recip = I.evaluate(1, pt);
651 std::array<double,2>{
652 { fvf_recip, fvf_mu_recip }
661 const auto& v = recipFvFVisc.
array();
686 std::vector<PVTGraph>
690 return this->saturatedStateCurve();
693 return this->mainPvtCurve(curve);
697 using InnerEvalPoint =
typename std::decay<
698 decltype(std::declval<SubtableInterpolant>().classifyPoint(0.0))
701 using OuterInterpPoint =
702 ::Opm::Interp1D::PiecewisePolynomial::LocalInterpPoint;
704 struct InnerInterpPoint {
706 InnerEvalPoint right;
709 std::vector<double> key_;
710 std::vector<SubtableInterpolant> propInterp_;
712 InnerInterpPoint getInterpPoint(
const std::size_t i,
713 const double x)
const
715 assert ((i + 1) < this->propInterp_.size());
718 this->propInterp_[i + 0].classifyPoint(
x),
719 this->propInterp_[i + 1].classifyPoint(
x)
723 template <
class Function>
724 auto interpolate(Function&& func,
725 const OuterInterpPoint& outer,
726 const double x)
const
727 ->
decltype(func(outer.interval, std::declval<InnerEvalPoint>()))
729 assert (outer.cat == ::Opm::Interp1D::PointCategory::InRange);
732 this->getInterpPoint(outer.interval,
x);
734 const auto yLeft = func(outer.interval + 0, pt.left);
735 const auto yRight = func(outer.interval + 1, pt.right);
737 const auto t = outer.t / (this->key_[outer.interval + 1] -
738 this->key_[outer.interval + 0]);
741 return t*yRight + (1.0 -
t)*yLeft;
744 template <
class Function>
745 auto extrapLeft(Function&& func,
746 const OuterInterpPoint& outer,
747 const double x)
const
748 ->
decltype(func(outer.interval, std::declval<InnerEvalPoint>()))
750 assert (outer.cat == ::Opm::Interp1D::PointCategory::LeftOfRange);
751 assert (outer.interval == 0*this->key_.size());
754 this->getInterpPoint(outer.interval,
x);
756 const auto yLeft = func(0, pt.left);
757 const auto yRight = func(1, pt.right);
760 (yRight - yLeft) / (this->key_[1] - this->key_[0]);
762 return yLeft + outer.t*dydk;
765 template <
class Function>
766 auto extrapRight(Function&& func,
767 const OuterInterpPoint& outer,
768 const double x)
const
769 ->
decltype(func(outer.interval, std::declval<InnerEvalPoint>()))
771 const auto nIntervals = this->key_.size() - 1;
773 assert (outer.cat == ::Opm::Interp1D::PointCategory::RightOfRange);
774 assert (outer.interval == nIntervals);
776 const auto pt = this->getInterpPoint(nIntervals - 1,
x);
778 const auto yLeft = func(nIntervals - 1, pt.left);
779 const auto yRight = func(nIntervals - 0, pt.right);
782 (yRight - yLeft) / (this->key_[nIntervals - 0] -
783 this->key_[nIntervals - 1]);
785 return yRight + outer.t*dydk;
788 template <
class Function>
789 auto evaluate(
const double key,
791 Function&& func)
const
792 ->
decltype(func(std::declval<OuterInterpPoint>().interval,
793 std::declval<InnerEvalPoint>()))
795 const auto outer = ::Opm::Interp1D::PiecewisePolynomial::
796 LocalInterpPoint::identify(this->key_, key);
799 case ::Opm::Interp1D::PointCategory::InRange:
800 return this->interpolate(std::forward<Function>(func),
803 case ::Opm::Interp1D::PointCategory::LeftOfRange:
804 return this->extrapLeft(std::forward<Function>(func),
807 case ::Opm::Interp1D::PointCategory::RightOfRange:
808 return this->extrapRight(std::forward<Function>(func),
812 throw std::logic_error {
813 "Outer/Primary Key Cannot Be Classified"
817 template <
class InnerFunction,
class OuterFunction>
819 computeQuantity(
const PrimaryKey& key,
820 const InnerVariate&
x,
821 InnerFunction&& ifunc,
822 OuterFunction ofunc)
const
824 auto result = std::vector<double>{};
826 const auto nVals = key.data.size();
828 if (
x.data.size() != nVals) {
829 throw std::invalid_argument {
830 "Number of Inner Sampling Points Does Not Match "
831 "Number of Outer Sampling Points"
835 result.reserve(nVals);
837 for (
auto i = 0*nVals; i < nVals; ++i) {
839 this->evaluate(key.data[i],
x.data[i],
840 std::forward<InnerFunction>(ifunc));
842 result.push_back(ofunc(q));
848 std::vector<PVTGraph>
849 mainPvtCurve(
const RawCurve curve)
const
854 auto ret = std::vector<PVTGraph>{};
855 ret.reserve(this->propInterp_.size());
857 auto i =
static_cast<std::vector<double>::size_type
>(0);
859 for (
const auto& interp : this->propInterp_) {
863 auto& pvtgraph = ret.back();
865 pvtgraph.mixRat.assign(basic.first.size(), this->key_[i]);
867 pvtgraph.press = std::move(basic.first);
868 pvtgraph.value = std::move(basic.second);
876 std::vector<PVTGraph> saturatedStateCurve()
const
881 auto curve = PVTGraph{};
883 curve.press.reserve(this->propInterp_.size());
884 curve.mixRat = this->key_;
885 curve.value = this->key_;
887 for (
const auto& interp : this->propInterp_) {
888 const auto& yi = interp.independentVariable();
890 curve.press.push_back(yi[0]);
const cJSON *const b
Definition: cJSON.h:251
Definition: ECLResultData.hpp:177
Definition: ECLPvtCommon.hpp:321
DenseVector & operator/=(const double rhs)
Definition: ECLPvtCommon.hpp:362
DenseVector & operator-=(const DenseVector &rhs)
Definition: ECLPvtCommon.hpp:338
DenseVector(const std::array< double, N > &other)
Definition: ECLPvtCommon.hpp:323
const std::array< double, N > & array() const
Definition: ECLPvtCommon.hpp:375
DenseVector & operator+=(const DenseVector &rhs)
Definition: ECLPvtCommon.hpp:327
DenseVector & operator*=(const double rhs)
Definition: ECLPvtCommon.hpp:349
Definition: ECLPvtCommon.hpp:459
PVTGraph getPvtCurve(const RawCurve curve) const
std::vector< double > formationVolumeFactor(const std::vector< double > &p) const
ECLPropTableRawData::ElementIterator ElemIt
Convenience type alias.
Definition: ECLPvtCommon.hpp:462
PVDx(ElemIt xBegin, ElemIt xEnd, const ConvertUnits &convert, std::vector< ElemIt > &colIt)
std::vector< double > viscosity(const std::vector< double > &p) const
Definition: ECLPvtCommon.hpp:584
PVTx(std::vector< double > key, std::vector< SubtableInterpolant > propInterp)
Definition: ECLPvtCommon.hpp:586
std::vector< double > viscosity(const PrimaryKey &key, const InnerVariate &x) const
Definition: ECLPvtCommon.hpp:636
std::vector< double > formationVolumeFactor(const PrimaryKey &key, const InnerVariate &x) const
Definition: ECLPvtCommon.hpp:617
std::vector< PVTGraph > getPvtCurve(const RawCurve curve) const
Definition: ECLPvtCommon.hpp:687
Definition: ECLPiecewiseLinearInterpolant.hpp:52
std::vector< double > resultVariable(const std::size_t col) const
Definition: ECLPiecewiseLinearInterpolant.hpp:181
const std::vector< double > & independentVariable() const
Retrieve abscissas of interpolant's independent variate.
Definition: ECLPiecewiseLinearInterpolant.hpp:168
LocalInterpPoint classifyPoint(const double x) const
Definition: ECLPiecewiseLinearInterpolant.hpp:123
DenseVector< N > operator-(DenseVector< N > u, const DenseVector< N > &v)
Definition: ECLPvtCommon.hpp:409
RawCurve
Definition: ECLPvtCommon.hpp:293
@ SaturatedState
Enveloping curve for saturated state (wet gas or live oil)
@ FVF
Formation volume factor (B_\alpha)
std::vector< double > surfaceMassDensity(const ECLInitFileData &init, const ECLPhaseIndex phase)
DenseVector< N > operator+(DenseVector< N > u, const DenseVector< N > &v)
Definition: ECLPvtCommon.hpp:403
DenseVector< N > operator/(DenseVector< N > v, const double a)
Definition: ECLPvtCommon.hpp:385
FlowDiagnostics::Graph extractRawPVTCurve(const Interp1D::PiecewisePolynomial::Linear< Extrapolation, IsAscendingRange > &interpolant, const RawCurve curve)
Definition: ECLPvtCommon.hpp:416
DenseVector< N > operator*(const double a, DenseVector< N > v)
Definition: ECLPvtCommon.hpp:391
std::pair< std::vector< double >, std::vector< double > > Graph
Definition: DerivedQuantities.hpp:37
std::function< double(double, double)> function
Definition: Operate.hpp:28
std::vector< double > init(const std::string &kewyord, const TableManager &tables, const Phases &phases, const std::vector< double > &cell_depth, const std::vector< int > &num, const std::vector< int > &endnum)
ECLPhaseIndex
Definition: ECLPhaseIndex.hpp:28
@ end
Definition: ActionValue.hpp:20
static const double pi
Definition: exprtk.hpp:759
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t t(t+t)") define_sfop3(16
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y+z)
Definition: ECLPvtCommon.hpp:57
Converter indep
How to convert the independent variate (1st column)
Definition: ECLPvtCommon.hpp:62
std::vector< Converter > column
How to convert the dependent variates (2nd... columns).
Definition: ECLPvtCommon.hpp:65
std::function< double(const double)> Converter
Convenience type alias for a value transformation.
Definition: ECLPvtCommon.hpp:59
Definition: ECLPvtCommon.hpp:73
static ConvertUnits::Converter recipFvf(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter pressure(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfDerivVapOil(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfViscDerivVapOil(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter vapOil(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter disGas(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfGas(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfGasViscDerivPress(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfGasDerivVapOil(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter density(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter compressibility(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfGasDerivPress(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfGasVisc(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfGasViscDerivVapOil(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfVisc(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfViscDerivPress(const ::Opm::ECLUnits::UnitSystem &usys)
static ConvertUnits::Converter recipFvfDerivPress(const ::Opm::ECLUnits::UnitSystem &usys)
Definition: ECLPvtCommon.hpp:70
Definition: ECLPvtCommon.hpp:308
std::vector< double > mixRat
Mixing ratio. Typically Rs or Rv.
Definition: ECLPvtCommon.hpp:313
std::vector< double > press
Pressure values.
Definition: ECLPvtCommon.hpp:310
std::vector< double > value
Definition: ECLPvtCommon.hpp:317
Definition: ECLPvtCommon.hpp:612
const std::vector< double > & data
Definition: ECLPvtCommon.hpp:613
Definition: ECLPvtCommon.hpp:607
const std::vector< double > & data
Definition: ECLPvtCommon.hpp:608
DataVector::const_iterator ElementIterator
Iterator to table elements. Must be random access.
Definition: ECLPropTable.hpp:46