mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #5353 from akva2/vfp_template_scalar
VFP classes: template Scalar type
This commit is contained in:
+10
-8
@@ -46,7 +46,7 @@ struct Setup
|
|||||||
std::shared_ptr<Python> python;
|
std::shared_ptr<Python> python;
|
||||||
std::unique_ptr<const Schedule> schedule;
|
std::unique_ptr<const Schedule> schedule;
|
||||||
std::unique_ptr<SummaryState> summary_state;
|
std::unique_ptr<SummaryState> summary_state;
|
||||||
std::unique_ptr<VFPProperties> vfp_properties;
|
std::unique_ptr<VFPProperties<double>> vfp_properties;
|
||||||
|
|
||||||
Setup(const std::string& file)
|
Setup(const std::string& file)
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,9 @@ struct Setup
|
|||||||
const int step = 0;
|
const int step = 0;
|
||||||
const auto& sched_state = schedule->operator[](step);
|
const auto& sched_state = schedule->operator[](step);
|
||||||
WellState<double> well_state(phaseUsage(runspec.phases()));
|
WellState<double> well_state(phaseUsage(runspec.phases()));
|
||||||
vfp_properties = std::make_unique<VFPProperties>(sched_state.vfpinj(), sched_state.vfpprod(), well_state);
|
vfp_properties = std::make_unique<VFPProperties<double>>(sched_state.vfpinj(),
|
||||||
|
sched_state.vfpprod(),
|
||||||
|
well_state);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,13 +83,13 @@ double computeBhp(const VFPProdTable& table,
|
|||||||
// First, find the values to interpolate between.
|
// First, find the values to interpolate between.
|
||||||
// Assuming positive flo here!
|
// Assuming positive flo here!
|
||||||
assert(flo > 0.0);
|
assert(flo > 0.0);
|
||||||
auto flo_i = detail::findInterpData(flo, table.getFloAxis());
|
auto flo_i = VFPHelpers<double>::findInterpData(flo, table.getFloAxis());
|
||||||
auto thp_i = detail::findInterpData(thp, table.getTHPAxis()); // assume constant
|
auto thp_i = VFPHelpers<double>::findInterpData(thp, table.getTHPAxis()); // assume constant
|
||||||
auto wfr_i = detail::findInterpData(wfr, table.getWFRAxis());
|
auto wfr_i = VFPHelpers<double>::findInterpData(wfr, table.getWFRAxis());
|
||||||
auto gfr_i = detail::findInterpData(gfr, table.getGFRAxis());
|
auto gfr_i = VFPHelpers<double>::findInterpData(gfr, table.getGFRAxis());
|
||||||
auto alq_i = detail::findInterpData(alq, table.getALQAxis()); //assume constant
|
auto alq_i = VFPHelpers<double>::findInterpData(alq, table.getALQAxis()); //assume constant
|
||||||
|
|
||||||
return detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i).value;
|
return VFPHelpers<double>::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace Opm {
|
|||||||
class Schedule;
|
class Schedule;
|
||||||
struct SimulatorUpdate;
|
struct SimulatorUpdate;
|
||||||
class SummaryConfig;
|
class SummaryConfig;
|
||||||
class VFPProperties;
|
template<class Scalar> class VFPProperties;
|
||||||
template<class Scalar> class WellInterfaceGeneric;
|
template<class Scalar> class WellInterfaceGeneric;
|
||||||
template<class Scalar> class WellState;
|
template<class Scalar> class WellState;
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
@@ -557,7 +557,7 @@ protected:
|
|||||||
mutable std::unordered_set<std::string> closed_this_step_;
|
mutable std::unordered_set<std::string> closed_this_step_;
|
||||||
|
|
||||||
GuideRate guideRate_;
|
GuideRate guideRate_;
|
||||||
std::unique_ptr<VFPProperties> vfp_properties_{};
|
std::unique_ptr<VFPProperties<Scalar>> vfp_properties_{};
|
||||||
std::map<std::string, Scalar> node_pressures_; // Storing network pressures for output.
|
std::map<std::string, Scalar> node_pressures_; // Storing network pressures for output.
|
||||||
|
|
||||||
// previous injection multiplier, it is used in the injection multiplier calculation for WINJMULT keyword
|
// previous injection multiplier, it is used in the injection multiplier calculation for WINJMULT keyword
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ namespace Opm {
|
|||||||
{
|
{
|
||||||
const auto& sched_state = this->schedule()[timeStepIdx];
|
const auto& sched_state = this->schedule()[timeStepIdx];
|
||||||
|
|
||||||
this->vfp_properties_ = std::make_unique<VFPProperties>
|
this->vfp_properties_ = std::make_unique<VFPProperties<Scalar>>
|
||||||
(sched_state.vfpinj(), sched_state.vfpprod(), this->wellState());
|
(sched_state.vfpinj(), sched_state.vfpprod(), this->wellState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+191
-171
@@ -38,14 +38,15 @@ namespace {
|
|||||||
* Helper function that finds x for a given value of y for a line
|
* Helper function that finds x for a given value of y for a line
|
||||||
* *NOTE ORDER OF ARGUMENTS*
|
* *NOTE ORDER OF ARGUMENTS*
|
||||||
*/
|
*/
|
||||||
double findX(const double x0,
|
template<class Scalar>
|
||||||
const double x1,
|
Scalar findX(const Scalar x0,
|
||||||
const double y0,
|
const Scalar x1,
|
||||||
const double y1,
|
const Scalar y0,
|
||||||
const double y)
|
const Scalar y1,
|
||||||
|
const Scalar y)
|
||||||
{
|
{
|
||||||
const double dx = x1 - x0;
|
const Scalar dx = x1 - x0;
|
||||||
const double dy = y1 - y0;
|
const Scalar dy = y1 - y0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* y = y0 + (dy / dx) * (x - x0)
|
* y = y0 + (dy / dx) * (x - x0)
|
||||||
@@ -54,7 +55,7 @@ double findX(const double x0,
|
|||||||
* If dy is zero, use x1 as the value.
|
* If dy is zero, use x1 as the value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double x = 0.0;
|
Scalar x = 0.0;
|
||||||
|
|
||||||
if (dy != 0.0) {
|
if (dy != 0.0) {
|
||||||
x = x0 + (y-y0) * (dx/dy);
|
x = x0 + (y-y0) * (dx/dy);
|
||||||
@@ -77,17 +78,18 @@ static T chopNegativeValues(const T& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
InterpData findInterpData(const double value_in, const std::vector<double>& values)
|
template<class Scalar>
|
||||||
|
detail::InterpData<Scalar> VFPHelpers<Scalar>::findInterpData(const Scalar value_in,
|
||||||
|
const std::vector<double>& values)
|
||||||
{
|
{
|
||||||
InterpData retval;
|
detail::InterpData<Scalar> retval;
|
||||||
|
|
||||||
const int nvalues = values.size();
|
const int nvalues = values.size();
|
||||||
|
|
||||||
// chopping the value to be zero, which means we do not
|
// chopping the value to be zero, which means we do not
|
||||||
// extrapolate the table towards nagative ranges
|
// extrapolate the table towards nagative ranges
|
||||||
const double value = value_in < 0.? 0. : value_in;
|
const Scalar value = value_in < 0.? 0. : value_in;
|
||||||
|
|
||||||
//If we only have one value in our vector, return that
|
//If we only have one value in our vector, return that
|
||||||
if (values.size() == 1) {
|
if (values.size() == 1) {
|
||||||
@@ -119,8 +121,8 @@ InterpData findInterpData(const double value_in, const std::vector<double>& valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const double start = values[retval.ind_[0]];
|
const Scalar start = values[retval.ind_[0]];
|
||||||
const double end = values[retval.ind_[1]];
|
const Scalar end = values[retval.ind_[1]];
|
||||||
|
|
||||||
//Find interpolation ratio
|
//Find interpolation ratio
|
||||||
if (end > start) {
|
if (end > start) {
|
||||||
@@ -138,50 +140,17 @@ InterpData findInterpData(const double value_in, const std::vector<double>& valu
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFPEvaluation operator+(VFPEvaluation lhs, const VFPEvaluation& rhs)
|
template<class Scalar>
|
||||||
{
|
detail::VFPEvaluation<Scalar> VFPHelpers<Scalar>::
|
||||||
lhs.value += rhs.value;
|
interpolate(const VFPProdTable& table,
|
||||||
lhs.dthp += rhs.dthp;
|
const detail::InterpData<Scalar>& flo_i,
|
||||||
lhs.dwfr += rhs.dwfr;
|
const detail::InterpData<Scalar>& thp_i,
|
||||||
lhs.dgfr += rhs.dgfr;
|
const detail::InterpData<Scalar>& wfr_i,
|
||||||
lhs.dalq += rhs.dalq;
|
const detail::InterpData<Scalar>& gfr_i,
|
||||||
lhs.dflo += rhs.dflo;
|
const detail::InterpData<Scalar>& alq_i)
|
||||||
return lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFPEvaluation operator-(VFPEvaluation lhs, const VFPEvaluation& rhs)
|
|
||||||
{
|
|
||||||
lhs.value -= rhs.value;
|
|
||||||
lhs.dthp -= rhs.dthp;
|
|
||||||
lhs.dwfr -= rhs.dwfr;
|
|
||||||
lhs.dgfr -= rhs.dgfr;
|
|
||||||
lhs.dalq -= rhs.dalq;
|
|
||||||
lhs.dflo -= rhs.dflo;
|
|
||||||
return lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFPEvaluation operator*(double lhs, const VFPEvaluation& rhs)
|
|
||||||
{
|
|
||||||
VFPEvaluation retval;
|
|
||||||
retval.value = rhs.value * lhs;
|
|
||||||
retval.dthp = rhs.dthp * lhs;
|
|
||||||
retval.dwfr = rhs.dwfr * lhs;
|
|
||||||
retval.dgfr = rhs.dgfr * lhs;
|
|
||||||
retval.dalq = rhs.dalq * lhs;
|
|
||||||
retval.dflo = rhs.dflo * lhs;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFPEvaluation interpolate(const VFPProdTable& table,
|
|
||||||
const InterpData& flo_i,
|
|
||||||
const InterpData& thp_i,
|
|
||||||
const InterpData& wfr_i,
|
|
||||||
const InterpData& gfr_i,
|
|
||||||
const InterpData& alq_i)
|
|
||||||
{
|
{
|
||||||
//Values and derivatives in a 5D hypercube
|
//Values and derivatives in a 5D hypercube
|
||||||
VFPEvaluation nn[2][2][2][2][2];
|
detail::VFPEvaluation<Scalar> nn[2][2][2][2][2];
|
||||||
|
|
||||||
|
|
||||||
//Pick out nearest neighbors (nn) to our evaluation point
|
//Pick out nearest neighbors (nn) to our evaluation point
|
||||||
//This is not really required, but performance-wise it may pay off, since the 32-elements
|
//This is not really required, but performance-wise it may pay off, since the 32-elements
|
||||||
@@ -231,7 +200,7 @@ VFPEvaluation interpolate(const VFPProdTable& table,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double t1, t2; //interpolation variables, so that t1 = (1-t) and t2 = t.
|
Scalar t1, t2; //interpolation variables, so that t1 = (1-t) and t2 = t.
|
||||||
|
|
||||||
// Remove dimensions one by one
|
// Remove dimensions one by one
|
||||||
// Example: going from 3D to 2D to 1D, we start by interpolating along
|
// Example: going from 3D to 2D to 1D, we start by interpolating along
|
||||||
@@ -280,13 +249,14 @@ VFPEvaluation interpolate(const VFPProdTable& table,
|
|||||||
return nn[0][0][0][0][0];
|
return nn[0][0][0][0][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
VFPEvaluation interpolate(const VFPInjTable& table,
|
template<class Scalar>
|
||||||
const InterpData& flo_i,
|
detail::VFPEvaluation<Scalar> VFPHelpers<Scalar>::
|
||||||
const InterpData& thp_i)
|
interpolate(const VFPInjTable& table,
|
||||||
|
const detail::InterpData<Scalar>& flo_i,
|
||||||
|
const detail::InterpData<Scalar>& thp_i)
|
||||||
{
|
{
|
||||||
//Values and derivatives in a 2D plane
|
//Values and derivatives in a 2D plane
|
||||||
VFPEvaluation nn[2][2];
|
detail::VFPEvaluation<Scalar> nn[2][2];
|
||||||
|
|
||||||
|
|
||||||
//Pick out nearest neighbors (nn) to our evaluation point
|
//Pick out nearest neighbors (nn) to our evaluation point
|
||||||
//The following ladder of for loops will presumably be unrolled by a reasonable compiler.
|
//The following ladder of for loops will presumably be unrolled by a reasonable compiler.
|
||||||
@@ -318,7 +288,7 @@ VFPEvaluation interpolate(const VFPInjTable& table,
|
|||||||
nn[i][1].dflo = nn[i][0].dflo;
|
nn[i][1].dflo = nn[i][0].dflo;
|
||||||
}
|
}
|
||||||
|
|
||||||
double t1, t2; //interpolation variables, so that t1 = (1-t) and t2 = t.
|
Scalar t1, t2; //interpolation variables, so that t1 = (1-t) and t2 = t.
|
||||||
|
|
||||||
// Go from 2D to 1D
|
// Go from 2D to 1D
|
||||||
t2 = flo_i.factor_;
|
t2 = flo_i.factor_;
|
||||||
@@ -334,20 +304,22 @@ VFPEvaluation interpolate(const VFPInjTable& table,
|
|||||||
return nn[0][0];
|
return nn[0][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
VFPEvaluation bhp(const VFPProdTable& table,
|
template<class Scalar>
|
||||||
const double aqua,
|
detail::VFPEvaluation<Scalar> VFPHelpers<Scalar>::
|
||||||
const double liquid,
|
bhp(const VFPProdTable& table,
|
||||||
const double vapour,
|
const Scalar aqua,
|
||||||
const double thp,
|
const Scalar liquid,
|
||||||
const double alq,
|
const Scalar vapour,
|
||||||
const double explicit_wfr,
|
const Scalar thp,
|
||||||
const double explicit_gfr,
|
const Scalar alq,
|
||||||
const bool use_vfpexplicit)
|
const Scalar explicit_wfr,
|
||||||
|
const Scalar explicit_gfr,
|
||||||
|
const bool use_vfpexplicit)
|
||||||
{
|
{
|
||||||
//Find interpolation variables
|
//Find interpolation variables
|
||||||
double flo = detail::getFlo(table, aqua, liquid, vapour);
|
Scalar flo = detail::getFlo(table, aqua, liquid, vapour);
|
||||||
double wfr = detail::getWFR(table, aqua, liquid, vapour);
|
Scalar wfr = detail::getWFR(table, aqua, liquid, vapour);
|
||||||
double gfr = detail::getGFR(table, aqua, liquid, vapour);
|
Scalar gfr = detail::getGFR(table, aqua, liquid, vapour);
|
||||||
if (use_vfpexplicit || -flo < table.getFloAxis().front()) {
|
if (use_vfpexplicit || -flo < table.getFloAxis().front()) {
|
||||||
wfr = explicit_wfr;
|
wfr = explicit_wfr;
|
||||||
gfr = explicit_gfr;
|
gfr = explicit_gfr;
|
||||||
@@ -355,43 +327,47 @@ VFPEvaluation bhp(const VFPProdTable& table,
|
|||||||
|
|
||||||
//First, find the values to interpolate between
|
//First, find the values to interpolate between
|
||||||
//Recall that flo is negative in Opm, so switch sign.
|
//Recall that flo is negative in Opm, so switch sign.
|
||||||
auto flo_i = detail::findInterpData(-flo, table.getFloAxis());
|
auto flo_i = findInterpData(-flo, table.getFloAxis());
|
||||||
auto thp_i = detail::findInterpData( thp, table.getTHPAxis());
|
auto thp_i = findInterpData( thp, table.getTHPAxis());
|
||||||
auto wfr_i = detail::findInterpData( wfr, table.getWFRAxis());
|
auto wfr_i = findInterpData( wfr, table.getWFRAxis());
|
||||||
auto gfr_i = detail::findInterpData( gfr, table.getGFRAxis());
|
auto gfr_i = findInterpData( gfr, table.getGFRAxis());
|
||||||
auto alq_i = detail::findInterpData( alq, table.getALQAxis());
|
auto alq_i = findInterpData( alq, table.getALQAxis());
|
||||||
|
|
||||||
detail::VFPEvaluation retval = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
detail::VFPEvaluation retval = interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFPEvaluation bhp(const VFPInjTable& table,
|
template<class Scalar>
|
||||||
const double aqua,
|
detail::VFPEvaluation<Scalar> VFPHelpers<Scalar>::
|
||||||
const double liquid,
|
bhp(const VFPInjTable& table,
|
||||||
const double vapour,
|
const Scalar aqua,
|
||||||
const double thp)
|
const Scalar liquid,
|
||||||
|
const Scalar vapour,
|
||||||
|
const Scalar thp)
|
||||||
{
|
{
|
||||||
//Find interpolation variables
|
//Find interpolation variables
|
||||||
double flo = detail::getFlo(table, aqua, liquid, vapour);
|
Scalar flo = detail::getFlo(table, aqua, liquid, vapour);
|
||||||
|
|
||||||
//First, find the values to interpolate between
|
//First, find the values to interpolate between
|
||||||
auto flo_i = detail::findInterpData(flo, table.getFloAxis());
|
auto flo_i = findInterpData(flo, table.getFloAxis());
|
||||||
auto thp_i = detail::findInterpData(thp, table.getTHPAxis());
|
auto thp_i = findInterpData(thp, table.getTHPAxis());
|
||||||
|
|
||||||
//Then perform the interpolation itself
|
//Then perform the interpolation itself
|
||||||
detail::VFPEvaluation retval = detail::interpolate(table, flo_i, thp_i);
|
detail::VFPEvaluation retval = interpolate(table, flo_i, thp_i);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
double findTHP(const std::vector<double>& bhp_array,
|
template<class Scalar>
|
||||||
const std::vector<double>& thp_array,
|
Scalar VFPHelpers<Scalar>::
|
||||||
double bhp)
|
findTHP(const std::vector<Scalar>& bhp_array,
|
||||||
|
const std::vector<double>& thp_array,
|
||||||
|
Scalar bhp)
|
||||||
{
|
{
|
||||||
int nthp = thp_array.size();
|
int nthp = thp_array.size();
|
||||||
|
|
||||||
double thp = -1e100;
|
Scalar thp = -1e100;
|
||||||
|
|
||||||
//Check that our thp axis is sorted
|
//Check that our thp axis is sorted
|
||||||
assert(std::is_sorted(thp_array.begin(), thp_array.end()));
|
assert(std::is_sorted(thp_array.begin(), thp_array.end()));
|
||||||
@@ -406,19 +382,19 @@ double findTHP(const std::vector<double>& bhp_array,
|
|||||||
//Target bhp less than all values in array, extrapolate
|
//Target bhp less than all values in array, extrapolate
|
||||||
if (bhp <= bhp_array[0]) {
|
if (bhp <= bhp_array[0]) {
|
||||||
//TODO: LOG extrapolation
|
//TODO: LOG extrapolation
|
||||||
const double& x0 = thp_array[0];
|
const Scalar& x0 = thp_array[0];
|
||||||
const double& x1 = thp_array[1];
|
const Scalar& x1 = thp_array[1];
|
||||||
const double& y0 = bhp_array[0];
|
const Scalar& y0 = bhp_array[0];
|
||||||
const double& y1 = bhp_array[1];
|
const Scalar& y1 = bhp_array[1];
|
||||||
thp = findX(x0, x1, y0, y1, bhp);
|
thp = findX(x0, x1, y0, y1, bhp);
|
||||||
}
|
}
|
||||||
//Target bhp greater than all values in array, extrapolate
|
//Target bhp greater than all values in array, extrapolate
|
||||||
else if (bhp > bhp_array[nthp-1]) {
|
else if (bhp > bhp_array[nthp-1]) {
|
||||||
//TODO: LOG extrapolation
|
//TODO: LOG extrapolation
|
||||||
const double& x0 = thp_array[nthp-2];
|
const Scalar& x0 = thp_array[nthp-2];
|
||||||
const double& x1 = thp_array[nthp-1];
|
const Scalar& x1 = thp_array[nthp-1];
|
||||||
const double& y0 = bhp_array[nthp-2];
|
const Scalar& y0 = bhp_array[nthp-2];
|
||||||
const double& y1 = bhp_array[nthp-1];
|
const Scalar& y1 = bhp_array[nthp-1];
|
||||||
thp = findX(x0, x1, y0, y1, bhp);
|
thp = findX(x0, x1, y0, y1, bhp);
|
||||||
}
|
}
|
||||||
//Target bhp within table ranges, interpolate
|
//Target bhp within table ranges, interpolate
|
||||||
@@ -432,8 +408,8 @@ double findTHP(const std::vector<double>& bhp_array,
|
|||||||
int i=0;
|
int i=0;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (; i<nthp-1; ++i) {
|
for (; i<nthp-1; ++i) {
|
||||||
const double& y0 = bhp_array[i ];
|
const Scalar& y0 = bhp_array[i ];
|
||||||
const double& y1 = bhp_array[i+1];
|
const Scalar& y1 = bhp_array[i+1];
|
||||||
|
|
||||||
if (y0 < bhp && bhp <= y1) {
|
if (y0 < bhp && bhp <= y1) {
|
||||||
found = true;
|
found = true;
|
||||||
@@ -444,10 +420,10 @@ double findTHP(const std::vector<double>& bhp_array,
|
|||||||
assert(found == true);
|
assert(found == true);
|
||||||
static_cast<void>(found); //Silence compiler warning
|
static_cast<void>(found); //Silence compiler warning
|
||||||
|
|
||||||
const double& x0 = thp_array[i ];
|
const Scalar& x0 = thp_array[i ];
|
||||||
const double& x1 = thp_array[i+1];
|
const Scalar& x1 = thp_array[i+1];
|
||||||
const double& y0 = bhp_array[i ];
|
const Scalar& y0 = bhp_array[i ];
|
||||||
const double& y1 = bhp_array[i+1];
|
const Scalar& y1 = bhp_array[i+1];
|
||||||
thp = findX(x0, x1, y0, y1, bhp);
|
thp = findX(x0, x1, y0, y1, bhp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,8 +435,8 @@ double findTHP(const std::vector<double>& bhp_array,
|
|||||||
int i=0;
|
int i=0;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (; i<nthp-1; ++i) {
|
for (; i<nthp-1; ++i) {
|
||||||
const double& y0 = bhp_array[i ];
|
const Scalar& y0 = bhp_array[i ];
|
||||||
const double& y1 = bhp_array[i+1];
|
const Scalar& y1 = bhp_array[i+1];
|
||||||
|
|
||||||
if (y0 < bhp && bhp <= y1) {
|
if (y0 < bhp && bhp <= y1) {
|
||||||
found = true;
|
found = true;
|
||||||
@@ -468,27 +444,27 @@ double findTHP(const std::vector<double>& bhp_array,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
const double& x0 = thp_array[i ];
|
const Scalar& x0 = thp_array[i ];
|
||||||
const double& x1 = thp_array[i+1];
|
const Scalar& x1 = thp_array[i+1];
|
||||||
const double& y0 = bhp_array[i ];
|
const Scalar& y0 = bhp_array[i ];
|
||||||
const double& y1 = bhp_array[i+1];
|
const Scalar& y1 = bhp_array[i+1];
|
||||||
thp = findX(x0, x1, y0, y1, bhp);
|
thp = findX(x0, x1, y0, y1, bhp);
|
||||||
}
|
}
|
||||||
else if (bhp <= bhp_array[0]) {
|
else if (bhp <= bhp_array[0]) {
|
||||||
//TODO: LOG extrapolation
|
//TODO: LOG extrapolation
|
||||||
const double& x0 = thp_array[0];
|
const Scalar& x0 = thp_array[0];
|
||||||
const double& x1 = thp_array[1];
|
const Scalar& x1 = thp_array[1];
|
||||||
const double& y0 = bhp_array[0];
|
const Scalar& y0 = bhp_array[0];
|
||||||
const double& y1 = bhp_array[1];
|
const Scalar& y1 = bhp_array[1];
|
||||||
thp = findX(x0, x1, y0, y1, bhp);
|
thp = findX(x0, x1, y0, y1, bhp);
|
||||||
}
|
}
|
||||||
//Target bhp greater than all values in array, extrapolate
|
//Target bhp greater than all values in array, extrapolate
|
||||||
else if (bhp > bhp_array[nthp-1]) {
|
else if (bhp > bhp_array[nthp-1]) {
|
||||||
//TODO: LOG extrapolation
|
//TODO: LOG extrapolation
|
||||||
const double& x0 = thp_array[nthp-2];
|
const Scalar& x0 = thp_array[nthp-2];
|
||||||
const double& x1 = thp_array[nthp-1];
|
const Scalar& x1 = thp_array[nthp-1];
|
||||||
const double& y0 = bhp_array[nthp-2];
|
const Scalar& y0 = bhp_array[nthp-2];
|
||||||
const double& y1 = bhp_array[nthp-1];
|
const Scalar& y1 = bhp_array[nthp-1];
|
||||||
thp = findX(x0, x1, y0, y1, bhp);
|
thp = findX(x0, x1, y0, y1, bhp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -499,86 +475,88 @@ double findTHP(const std::vector<double>& bhp_array,
|
|||||||
return thp;
|
return thp;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<double, double>
|
template<class Scalar>
|
||||||
|
std::pair<Scalar, Scalar> VFPHelpers<Scalar>::
|
||||||
getMinimumBHPCoordinate(const VFPProdTable& table,
|
getMinimumBHPCoordinate(const VFPProdTable& table,
|
||||||
const double thp,
|
const Scalar thp,
|
||||||
const double wfr,
|
const Scalar wfr,
|
||||||
const double gfr,
|
const Scalar gfr,
|
||||||
const double alq)
|
const Scalar alq)
|
||||||
{
|
{
|
||||||
// Given fixed thp, wfr, gfr and alq, this function finds the minimum bhp and returns
|
// Given fixed thp, wfr, gfr and alq, this function finds the minimum bhp and returns
|
||||||
// the corresponding pair (-flo_at_bhp_min, bhp_min). No assumption is taken on the
|
// the corresponding pair (-flo_at_bhp_min, bhp_min). No assumption is taken on the
|
||||||
// shape of the function bhp(flo), so all points in the flo-axis is checked.
|
// shape of the function bhp(flo), so all points in the flo-axis is checked.
|
||||||
double flo_at_bhp_min = 0.0; // start by checking flo=0
|
Scalar flo_at_bhp_min = 0.0; // start by checking flo=0
|
||||||
auto flo_i = detail::findInterpData(flo_at_bhp_min, table.getFloAxis());
|
auto flo_i = findInterpData(flo_at_bhp_min, table.getFloAxis());
|
||||||
auto thp_i = detail::findInterpData( thp, table.getTHPAxis());
|
auto thp_i = findInterpData( thp, table.getTHPAxis());
|
||||||
auto wfr_i = detail::findInterpData( wfr, table.getWFRAxis());
|
auto wfr_i = findInterpData( wfr, table.getWFRAxis());
|
||||||
auto gfr_i = detail::findInterpData( gfr, table.getGFRAxis());
|
auto gfr_i = findInterpData( gfr, table.getGFRAxis());
|
||||||
auto alq_i = detail::findInterpData( alq, table.getALQAxis());
|
auto alq_i = findInterpData( alq, table.getALQAxis());
|
||||||
|
|
||||||
detail::VFPEvaluation bhp_i = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
detail::VFPEvaluation bhp_i = interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
||||||
double bhp_min = bhp_i.value;
|
Scalar bhp_min = bhp_i.value;
|
||||||
const std::vector<double>& flos = table.getFloAxis();
|
const std::vector<double>& flos = table.getFloAxis();
|
||||||
for (size_t i = 0; i < flos.size(); ++i) {
|
for (size_t i = 0; i < flos.size(); ++i) {
|
||||||
flo_i = detail::findInterpData(flos[i], flos);
|
flo_i = findInterpData(flos[i], flos);
|
||||||
bhp_i = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
bhp_i = interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
||||||
if (bhp_i.value < bhp_min){
|
if (bhp_i.value < bhp_min){
|
||||||
bhp_min = bhp_i.value;
|
bhp_min = bhp_i.value;
|
||||||
flo_at_bhp_min = flos[i];
|
flo_at_bhp_min = flos[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return negative flo
|
// return negative flo
|
||||||
return std::make_pair(-flo_at_bhp_min, bhp_min);
|
return std::make_pair(-flo_at_bhp_min, bhp_min);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<double, double>>
|
template<class Scalar>
|
||||||
|
std::optional<std::pair<Scalar, Scalar>> VFPHelpers<Scalar>::
|
||||||
intersectWithIPR(const VFPProdTable& table,
|
intersectWithIPR(const VFPProdTable& table,
|
||||||
const double thp,
|
const Scalar thp,
|
||||||
const double wfr,
|
const Scalar wfr,
|
||||||
const double gfr,
|
const Scalar gfr,
|
||||||
const double alq,
|
const Scalar alq,
|
||||||
const double ipr_a,
|
const Scalar ipr_a,
|
||||||
const double ipr_b,
|
const Scalar ipr_b,
|
||||||
const std::function<double(const double)>& adjust_bhp)
|
const std::function<Scalar(const Scalar)>& adjust_bhp)
|
||||||
{
|
{
|
||||||
// Given fixed thp, wfr, gfr and alq, this function finds a stable (-flo, bhp)-intersection
|
// Given fixed thp, wfr, gfr and alq, this function finds a stable (-flo, bhp)-intersection
|
||||||
// between the ipr-line and bhp(flo) if such an intersection exists. For multiple stable
|
// between the ipr-line and bhp(flo) if such an intersection exists. For multiple stable
|
||||||
// intersections, the one corresponding the largest flo is returned.
|
// intersections, the one corresponding the largest flo is returned.
|
||||||
// The adjust_bhp-function is used to adjust the vfp-table bhp-values to actual bhp-values due
|
// The adjust_bhp-function is used to adjust the vfp-table bhp-values to actual bhp-values due
|
||||||
// vfp/well ref-depth differences and/or WVFPDP-related pressure adjustments.
|
// vfp/well ref-depth differences and/or WVFPDP-related pressure adjustments.
|
||||||
|
|
||||||
// NOTE: ipr-line is q=b*bhp - a!
|
// NOTE: ipr-line is q=b*bhp - a!
|
||||||
// ipr is given for negative flo, so
|
// ipr is given for negative flo, so
|
||||||
// flo = -b*bhp + a, i.e., bhp = -(flo-a)/b
|
// flo = -b*bhp + a, i.e., bhp = -(flo-a)/b
|
||||||
auto thp_i = detail::findInterpData( thp, table.getTHPAxis());
|
auto thp_i = findInterpData( thp, table.getTHPAxis());
|
||||||
auto wfr_i = detail::findInterpData( wfr, table.getWFRAxis());
|
auto wfr_i = findInterpData( wfr, table.getWFRAxis());
|
||||||
auto gfr_i = detail::findInterpData( gfr, table.getGFRAxis());
|
auto gfr_i = findInterpData( gfr, table.getGFRAxis());
|
||||||
auto alq_i = detail::findInterpData( alq, table.getALQAxis());
|
auto alq_i = findInterpData( alq, table.getALQAxis());
|
||||||
|
|
||||||
if (ipr_b == 0.0) {
|
if (ipr_b == 0.0) {
|
||||||
// this shouldn't happen, but deal with it to be safe
|
// this shouldn't happen, but deal with it to be safe
|
||||||
auto flo_i = detail::findInterpData(ipr_a, table.getFloAxis());
|
auto flo_i = findInterpData(ipr_a, table.getFloAxis());
|
||||||
detail::VFPEvaluation bhp_i = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
detail::VFPEvaluation bhp_i = interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
||||||
return std::make_pair(-ipr_a, adjust_bhp(bhp_i.value));
|
return std::make_pair(-ipr_a, adjust_bhp(bhp_i.value));
|
||||||
}
|
}
|
||||||
// find largest flo (flo_x) for which y = bhp(flo) + (flo-a)/b = 0 and dy/dflo > 0
|
// find largest flo (flo_x) for which y = bhp(flo) + (flo-a)/b = 0 and dy/dflo > 0
|
||||||
double flo_x = -1.0;
|
Scalar flo_x = -1.0;
|
||||||
double flo0, flo1;
|
Scalar flo0, flo1;
|
||||||
double y0, y1;
|
Scalar y0, y1;
|
||||||
flo0 = 0.0; // start by checking flo=0
|
flo0 = 0.0; // start by checking flo=0
|
||||||
auto flo_i = detail::findInterpData(flo0, table.getFloAxis());
|
auto flo_i = findInterpData(flo0, table.getFloAxis());
|
||||||
detail::VFPEvaluation bhp_i = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
detail::VFPEvaluation bhp_i = interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
||||||
y0 = adjust_bhp(bhp_i.value) - ipr_a/ipr_b; // +0.0/ipr_b
|
y0 = adjust_bhp(bhp_i.value) - ipr_a/ipr_b; // +0.0/ipr_b
|
||||||
|
|
||||||
std::vector<double> flos = table.getFloAxis();
|
const std::vector<double>& flos = table.getFloAxis();
|
||||||
for (size_t i = 0; i < flos.size(); ++i) {
|
for (size_t i = 0; i < flos.size(); ++i) {
|
||||||
flo1 = flos[i];
|
flo1 = flos[i];
|
||||||
flo_i = detail::findInterpData(flo1, table.getFloAxis());
|
flo_i = findInterpData(flo1, flos);
|
||||||
bhp_i = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
bhp_i = interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
||||||
y1 = adjust_bhp(bhp_i.value) + (flo1 - ipr_a)/ipr_b;
|
y1 = adjust_bhp(bhp_i.value) + (flo1 - ipr_a)/ipr_b;
|
||||||
if (y0 < 0 && y1 >= 0){
|
if (y0 < 0 && y1 >= 0){
|
||||||
// crossing with positive slope
|
// crossing with positive slope
|
||||||
double w = -y0/(y1-y0);
|
Scalar w = -y0/(y1-y0);
|
||||||
w = std::clamp(w, 0.0, 1.0); // just to be safe (if y0~y1~0)
|
w = std::clamp(w, 0.0, 1.0); // just to be safe (if y0~y1~0)
|
||||||
flo_x = flo0 + w*(flo1 - flo0);
|
flo_x = flo0 + w*(flo1 - flo0);
|
||||||
}
|
}
|
||||||
@@ -591,7 +569,46 @@ intersectWithIPR(const VFPProdTable& table,
|
|||||||
} else {
|
} else {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
|
VFPEvaluation<Scalar> operator+(VFPEvaluation<Scalar> lhs, const VFPEvaluation<Scalar>& rhs)
|
||||||
|
{
|
||||||
|
lhs.value += rhs.value;
|
||||||
|
lhs.dthp += rhs.dthp;
|
||||||
|
lhs.dwfr += rhs.dwfr;
|
||||||
|
lhs.dgfr += rhs.dgfr;
|
||||||
|
lhs.dalq += rhs.dalq;
|
||||||
|
lhs.dflo += rhs.dflo;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
|
VFPEvaluation<Scalar> operator-(VFPEvaluation<Scalar> lhs, const VFPEvaluation<Scalar>& rhs)
|
||||||
|
{
|
||||||
|
lhs.value -= rhs.value;
|
||||||
|
lhs.dthp -= rhs.dthp;
|
||||||
|
lhs.dwfr -= rhs.dwfr;
|
||||||
|
lhs.dgfr -= rhs.dgfr;
|
||||||
|
lhs.dalq -= rhs.dalq;
|
||||||
|
lhs.dflo -= rhs.dflo;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
|
VFPEvaluation<Scalar> operator*(Scalar lhs, const VFPEvaluation<Scalar>& rhs)
|
||||||
|
{
|
||||||
|
VFPEvaluation<Scalar> retval;
|
||||||
|
retval.value = rhs.value * lhs;
|
||||||
|
retval.dthp = rhs.dthp * lhs;
|
||||||
|
retval.dwfr = rhs.dwfr * lhs;
|
||||||
|
retval.dgfr = rhs.dgfr * lhs;
|
||||||
|
retval.dalq = rhs.dalq * lhs;
|
||||||
|
retval.dflo = rhs.dflo * lhs;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T getFlo(const VFPProdTable& table,
|
T getFlo(const VFPProdTable& table,
|
||||||
@@ -753,4 +770,7 @@ INSTANCE(DenseAd::Evaluation<double, 9, 0u>)
|
|||||||
INSTANCE(DenseAd::Evaluation<double, 10, 0u>)
|
INSTANCE(DenseAd::Evaluation<double, 10, 0u>)
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
template class VFPHelpers<double>;
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|||||||
+111
-107
@@ -21,7 +21,6 @@
|
|||||||
#ifndef OPM_AUTODIFF_VFPHELPERS_HPP_
|
#ifndef OPM_AUTODIFF_VFPHELPERS_HPP_
|
||||||
#define OPM_AUTODIFF_VFPHELPERS_HPP_
|
#define OPM_AUTODIFF_VFPHELPERS_HPP_
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -37,6 +36,40 @@ class VFPProdTable;
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An "ADB-like" structure with a single value and a set of derivatives
|
||||||
|
*/
|
||||||
|
template<class Scalar>
|
||||||
|
struct VFPEvaluation
|
||||||
|
{
|
||||||
|
VFPEvaluation() : value(0.0), dthp(0.0), dwfr(0.0), dgfr(0.0), dalq(0.0), dflo(0.0) {};
|
||||||
|
Scalar value;
|
||||||
|
Scalar dthp;
|
||||||
|
Scalar dwfr;
|
||||||
|
Scalar dgfr;
|
||||||
|
Scalar dalq;
|
||||||
|
Scalar dflo;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
|
VFPEvaluation<Scalar> operator+(VFPEvaluation<Scalar> lhs, const VFPEvaluation<Scalar>& rhs);
|
||||||
|
template<class Scalar>
|
||||||
|
VFPEvaluation<Scalar> operator-(VFPEvaluation<Scalar> lhs, const VFPEvaluation<Scalar>& rhs);
|
||||||
|
template<class Scalar>
|
||||||
|
VFPEvaluation<Scalar> operator*(Scalar lhs, const VFPEvaluation<Scalar>& rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper struct for linear interpolation
|
||||||
|
*/
|
||||||
|
template<class Scalar>
|
||||||
|
struct InterpData
|
||||||
|
{
|
||||||
|
InterpData() : ind_{0, 0}, inv_dist_(0.0), factor_(0.0) {}
|
||||||
|
int ind_[2]; //[First element greater than or equal to value, Last element smaller than or equal to value]
|
||||||
|
Scalar inv_dist_; // 1 / distance between the two end points of the segment. Used to calculate derivatives and uses 1.0 / 0.0 = 0.0 as a convention
|
||||||
|
Scalar factor_; // Interpolation factor
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the flo parameter according to the flo_type_
|
* Computes the flo parameter according to the flo_type_
|
||||||
* for production tables
|
* for production tables
|
||||||
@@ -79,76 +112,6 @@ T getGFR(const VFPProdTable& table,
|
|||||||
const T& liquid,
|
const T& liquid,
|
||||||
const T& vapour);
|
const T& vapour);
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper struct for linear interpolation
|
|
||||||
*/
|
|
||||||
struct InterpData {
|
|
||||||
InterpData() : ind_{0, 0}, inv_dist_(0.0), factor_(0.0) {}
|
|
||||||
int ind_[2]; //[First element greater than or equal to value, Last element smaller than or equal to value]
|
|
||||||
double inv_dist_; // 1 / distance between the two end points of the segment. Used to calculate derivatives and uses 1.0 / 0.0 = 0.0 as a convention
|
|
||||||
double factor_; // Interpolation factor
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to find indices etc. for linear interpolation and extrapolation
|
|
||||||
* @param value_in Value to find in values
|
|
||||||
* @param values Sorted list of values to search for value in.
|
|
||||||
* @return Data required to find the interpolated value
|
|
||||||
*/
|
|
||||||
InterpData findInterpData(const double value_in, const std::vector<double>& values);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An "ADB-like" structure with a single value and a set of derivatives
|
|
||||||
*/
|
|
||||||
struct VFPEvaluation {
|
|
||||||
VFPEvaluation() : value(0.0), dthp(0.0), dwfr(0.0), dgfr(0.0), dalq(0.0), dflo(0.0) {};
|
|
||||||
double value;
|
|
||||||
double dthp;
|
|
||||||
double dwfr;
|
|
||||||
double dgfr;
|
|
||||||
double dalq;
|
|
||||||
double dflo;
|
|
||||||
};
|
|
||||||
|
|
||||||
VFPEvaluation operator+(VFPEvaluation lhs, const VFPEvaluation& rhs);
|
|
||||||
VFPEvaluation operator-(VFPEvaluation lhs, const VFPEvaluation& rhs);
|
|
||||||
VFPEvaluation operator*(double lhs, const VFPEvaluation& rhs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function which interpolates data using the indices etc. given in the inputs.
|
|
||||||
*/
|
|
||||||
VFPEvaluation interpolate(const VFPProdTable& table,
|
|
||||||
const InterpData& flo_i,
|
|
||||||
const InterpData& thp_i,
|
|
||||||
const InterpData& wfr_i,
|
|
||||||
const InterpData& gfr_i,
|
|
||||||
const InterpData& alq_i);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This basically models interpolate(VFPProdTable::array_type, ...)
|
|
||||||
* which performs 5D interpolation, but here for the 2D case only
|
|
||||||
*/
|
|
||||||
VFPEvaluation interpolate(const VFPInjTable& table,
|
|
||||||
const InterpData& flo_i,
|
|
||||||
const InterpData& thp_i);
|
|
||||||
|
|
||||||
VFPEvaluation bhp(const VFPProdTable& table,
|
|
||||||
const double aqua,
|
|
||||||
const double liquid,
|
|
||||||
const double vapour,
|
|
||||||
const double thp,
|
|
||||||
const double alq,
|
|
||||||
const double explicit_wfr,
|
|
||||||
const double explicit_gfr,
|
|
||||||
const bool use_vfpexplicit);
|
|
||||||
|
|
||||||
VFPEvaluation bhp(const VFPInjTable& table,
|
|
||||||
const double aqua,
|
|
||||||
const double liquid,
|
|
||||||
const double vapour,
|
|
||||||
const double thp);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the table from the map if found, or throws an exception
|
* Returns the table from the map if found, or throws an exception
|
||||||
*/
|
*/
|
||||||
@@ -164,54 +127,95 @@ bool hasTable(const std::map<int, std::reference_wrapper<const T>>& tables, int
|
|||||||
return (entry != tables.end() );
|
return (entry != tables.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type variable for FLO/GFR/WFR for production tables
|
* Returns the type variable for FLO/GFR/WFR for production tables
|
||||||
*/
|
*/
|
||||||
template <typename TYPE, typename TABLE>
|
template <typename TYPE, typename TABLE>
|
||||||
TYPE getType(const TABLE& table);
|
TYPE getType(const TABLE& table);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
template<class Scalar>
|
||||||
* This function finds the value of THP given a specific BHP.
|
class VFPHelpers {
|
||||||
* Essentially:
|
public:
|
||||||
* Given the function f(thp_array(x)) = bhp_array(x), which is piecewise linear,
|
/**
|
||||||
* find thp so that f(thp) = bhp.
|
* Helper function to find indices etc. for linear interpolation and extrapolation
|
||||||
*/
|
* @param value_in Value to find in values
|
||||||
double findTHP(const std::vector<double>& bhp_array,
|
* @param values Sorted list of values to search for value in.
|
||||||
const std::vector<double>& thp_array,
|
* @return Data required to find the interpolated value
|
||||||
double bhp);
|
*/
|
||||||
|
static detail::InterpData<Scalar> findInterpData(const Scalar value_in,
|
||||||
|
const std::vector<double>& values);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get (flo, bhp) at minimum bhp for given thp,wfr,gfr,alq
|
* Helper function which interpolates data using the indices etc. given in the inputs.
|
||||||
*/
|
*/
|
||||||
std::pair<double, double>
|
static detail::VFPEvaluation<Scalar> interpolate(const VFPProdTable& table,
|
||||||
getMinimumBHPCoordinate(const VFPProdTable& table,
|
const detail::InterpData<Scalar>& flo_i,
|
||||||
const double thp,
|
const detail::InterpData<Scalar>& thp_i,
|
||||||
const double wfr,
|
const detail::InterpData<Scalar>& wfr_i,
|
||||||
const double gfr,
|
const detail::InterpData<Scalar>& gfr_i,
|
||||||
const double alq);
|
const detail::InterpData<Scalar>& alq_i);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get (flo, bhp) at largest occuring stable vfp/ipr-intersection
|
* This basically models interpolate(VFPProdTable::array_type, ...)
|
||||||
* if it exists
|
* which performs 5D interpolation, but here for the 2D case only
|
||||||
*/
|
*/
|
||||||
std::optional<std::pair<double, double>>
|
static detail::VFPEvaluation<Scalar> interpolate(const VFPInjTable& table,
|
||||||
intersectWithIPR(const VFPProdTable& table,
|
const detail::InterpData<Scalar>& flo_i,
|
||||||
const double thp,
|
const detail::InterpData<Scalar>& thp_i);
|
||||||
const double wfr,
|
|
||||||
const double gfr,
|
|
||||||
const double alq,
|
|
||||||
const double ipr_a,
|
|
||||||
const double ipr_b,
|
|
||||||
const std::function<double(const double)>& adjust_bhp);
|
|
||||||
|
|
||||||
} // namespace detail
|
static detail::VFPEvaluation<Scalar> bhp(const VFPProdTable& table,
|
||||||
|
const Scalar aqua,
|
||||||
|
const Scalar liquid,
|
||||||
|
const Scalar vapour,
|
||||||
|
const Scalar thp,
|
||||||
|
const Scalar alq,
|
||||||
|
const Scalar explicit_wfr,
|
||||||
|
const Scalar explicit_gfr,
|
||||||
|
const bool use_vfpexplicit);
|
||||||
|
|
||||||
|
static detail::VFPEvaluation<Scalar> bhp(const VFPInjTable& table,
|
||||||
|
const Scalar aqua,
|
||||||
|
const Scalar liquid,
|
||||||
|
const Scalar vapour,
|
||||||
|
const Scalar thp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function finds the value of THP given a specific BHP.
|
||||||
|
* Essentially:
|
||||||
|
* Given the function f(thp_array(x)) = bhp_array(x), which is piecewise linear,
|
||||||
|
* find thp so that f(thp) = bhp.
|
||||||
|
*/
|
||||||
|
static Scalar findTHP(const std::vector<Scalar>& bhp_array,
|
||||||
|
const std::vector<double>& thp_array,
|
||||||
|
Scalar bhp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get (flo, bhp) at minimum bhp for given thp,wfr,gfr,alq
|
||||||
|
*/
|
||||||
|
static std::pair<Scalar, Scalar>
|
||||||
|
getMinimumBHPCoordinate(const VFPProdTable& table,
|
||||||
|
const Scalar thp,
|
||||||
|
const Scalar wfr,
|
||||||
|
const Scalar gfr,
|
||||||
|
const Scalar alq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get (flo, bhp) at largest occuring stable vfp/ipr-intersection
|
||||||
|
* if it exists
|
||||||
|
*/
|
||||||
|
static std::optional<std::pair<Scalar, Scalar>>
|
||||||
|
intersectWithIPR(const VFPProdTable& table,
|
||||||
|
const Scalar thp,
|
||||||
|
const Scalar wfr,
|
||||||
|
const Scalar gfr,
|
||||||
|
const Scalar alq,
|
||||||
|
const Scalar ipr_a,
|
||||||
|
const Scalar ipr_b,
|
||||||
|
const std::function<Scalar(const Scalar)>& adjust_bhp);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* OPM_AUTODIFF_VFPHELPERS_HPP_ */
|
#endif /* OPM_AUTODIFF_VFPHELPERS_HPP_ */
|
||||||
|
|||||||
@@ -17,49 +17,51 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <opm/simulators/wells/VFPInjProperties.hpp>
|
#include <opm/simulators/wells/VFPInjProperties.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/VFPInjTable.hpp>
|
||||||
|
|
||||||
#include <opm/material/densead/Math.hpp>
|
#include <opm/material/densead/Math.hpp>
|
||||||
#include <opm/material/densead/Evaluation.hpp>
|
#include <opm/material/densead/Evaluation.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/VFPInjTable.hpp>
|
|
||||||
|
|
||||||
#include <opm/simulators/wells/VFPHelpers.hpp>
|
#include <opm/simulators/wells/VFPHelpers.hpp>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
double VFPInjProperties::bhp(int table_id,
|
template<class Scalar>
|
||||||
const double& aqua,
|
Scalar VFPInjProperties<Scalar>::
|
||||||
const double& liquid,
|
bhp(const int table_id,
|
||||||
const double& vapour,
|
const Scalar aqua,
|
||||||
const double& thp_arg) const {
|
const Scalar liquid,
|
||||||
|
const Scalar vapour,
|
||||||
|
const Scalar thp_arg) const
|
||||||
|
{
|
||||||
const VFPInjTable& table = detail::getTable(m_tables, table_id);
|
const VFPInjTable& table = detail::getTable(m_tables, table_id);
|
||||||
|
|
||||||
detail::VFPEvaluation retval = detail::bhp(table, aqua, liquid, vapour, thp_arg);
|
detail::VFPEvaluation retval = VFPHelpers<Scalar>::bhp(table, aqua, liquid, vapour, thp_arg);
|
||||||
return retval.value;
|
return retval.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double VFPInjProperties::thp(int table_id,
|
template<class Scalar>
|
||||||
const double& aqua,
|
Scalar VFPInjProperties<Scalar>::
|
||||||
const double& liquid,
|
thp(const int table_id,
|
||||||
const double& vapour,
|
const Scalar aqua,
|
||||||
const double& bhp_arg) const {
|
const Scalar liquid,
|
||||||
|
const Scalar vapour,
|
||||||
|
const Scalar bhp_arg) const
|
||||||
|
{
|
||||||
const VFPInjTable& table = detail::getTable(m_tables, table_id);
|
const VFPInjTable& table = detail::getTable(m_tables, table_id);
|
||||||
|
|
||||||
//Find interpolation variables
|
//Find interpolation variables
|
||||||
const double flo = detail::getFlo(table, aqua, liquid, vapour);
|
const Scalar flo = detail::getFlo(table, aqua, liquid, vapour);
|
||||||
if (std::abs(flo) < std::numeric_limits<double>::epsilon()) {
|
if (std::abs(flo) < std::numeric_limits<Scalar>::epsilon()) {
|
||||||
return 0.;
|
return 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<double> thp_array = table.getTHPAxis();
|
const auto thp_array = table.getTHPAxis();
|
||||||
int nthp = thp_array.size();
|
int nthp = thp_array.size();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,35 +69,42 @@ double VFPInjProperties::thp(int table_id,
|
|||||||
* by interpolating for every value of thp. This might be somewhat
|
* by interpolating for every value of thp. This might be somewhat
|
||||||
* expensive, but let us assome that nthp is small
|
* expensive, but let us assome that nthp is small
|
||||||
*/
|
*/
|
||||||
auto flo_i = detail::findInterpData(flo, table.getFloAxis());
|
const auto flo_i = VFPHelpers<Scalar>::findInterpData(flo, table.getFloAxis());
|
||||||
std::vector<double> bhp_array(nthp);
|
std::vector<Scalar> bhp_array(nthp);
|
||||||
for (int i=0; i<nthp; ++i) {
|
for (int i = 0; i < nthp; ++i) {
|
||||||
auto thp_i = detail::findInterpData(thp_array[i], thp_array);
|
auto thp_i = VFPHelpers<Scalar>::findInterpData(thp_array[i], thp_array);
|
||||||
bhp_array[i] = detail::interpolate(table, flo_i, thp_i).value;
|
bhp_array[i] = VFPHelpers<Scalar>::interpolate(table, flo_i, thp_i).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double retval = detail::findTHP(bhp_array, thp_array, bhp_arg);
|
return VFPHelpers<Scalar>::findTHP(bhp_array, thp_array, bhp_arg);
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const VFPInjTable& VFPInjProperties::getTable(const int table_id) const {
|
template<class Scalar>
|
||||||
|
const VFPInjTable&
|
||||||
|
VFPInjProperties<Scalar>::getTable(const int table_id) const
|
||||||
|
{
|
||||||
return detail::getTable(m_tables, table_id);
|
return detail::getTable(m_tables, table_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VFPInjProperties::hasTable(const int table_id) const {
|
template<class Scalar>
|
||||||
|
bool VFPInjProperties<Scalar>::hasTable(const int table_id) const
|
||||||
|
{
|
||||||
return detail::hasTable(m_tables, table_id);
|
return detail::hasTable(m_tables, table_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VFPInjProperties::addTable(const VFPInjTable& new_table) {
|
template<class Scalar>
|
||||||
|
void VFPInjProperties<Scalar>::addTable(const VFPInjTable& new_table)
|
||||||
|
{
|
||||||
this->m_tables.emplace( new_table.getTableNum(), new_table );
|
this->m_tables.emplace( new_table.getTableNum(), new_table );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
template <class EvalWell>
|
template <class EvalWell>
|
||||||
EvalWell VFPInjProperties::bhp(const int table_id,
|
EvalWell VFPInjProperties<Scalar>::bhp(const int table_id,
|
||||||
const EvalWell& aqua,
|
const EvalWell& aqua,
|
||||||
const EvalWell& liquid,
|
const EvalWell& liquid,
|
||||||
const EvalWell& vapour,
|
const EvalWell& vapour,
|
||||||
const double& thp) const
|
const Scalar thp) const
|
||||||
{
|
{
|
||||||
//Get the table
|
//Get the table
|
||||||
const VFPInjTable& table = detail::getTable(m_tables, table_id);
|
const VFPInjTable& table = detail::getTable(m_tables, table_id);
|
||||||
@@ -106,22 +115,24 @@ EvalWell VFPInjProperties::bhp(const int table_id,
|
|||||||
|
|
||||||
//First, find the values to interpolate between
|
//First, find the values to interpolate between
|
||||||
//Value of FLO is negative in OPM for producers, but positive in VFP table
|
//Value of FLO is negative in OPM for producers, but positive in VFP table
|
||||||
auto flo_i = detail::findInterpData(flo.value(), table.getFloAxis());
|
const auto flo_i = VFPHelpers<Scalar>::findInterpData(flo.value(), table.getFloAxis());
|
||||||
auto thp_i = detail::findInterpData( thp, table.getTHPAxis()); // assume constant
|
const auto thp_i = VFPHelpers<Scalar>::findInterpData(thp, table.getTHPAxis()); // assume constant
|
||||||
|
|
||||||
detail::VFPEvaluation bhp_val = detail::interpolate(table, flo_i, thp_i);
|
detail::VFPEvaluation bhp_val = VFPHelpers<Scalar>::interpolate(table, flo_i, thp_i);
|
||||||
|
|
||||||
bhp = bhp_val.dflo * flo;
|
bhp = bhp_val.dflo * flo;
|
||||||
bhp.setValue(bhp_val.value); // thp is assumed constant i.e.
|
bhp.setValue(bhp_val.value); // thp is assumed constant i.e.
|
||||||
return bhp;
|
return bhp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class VFPInjProperties<double>;
|
||||||
|
|
||||||
#define INSTANCE(...) \
|
#define INSTANCE(...) \
|
||||||
template __VA_ARGS__ VFPInjProperties::bhp<__VA_ARGS__>(const int, \
|
template __VA_ARGS__ VFPInjProperties<double>::bhp<__VA_ARGS__>(const int, \
|
||||||
const __VA_ARGS__&, \
|
const __VA_ARGS__&, \
|
||||||
const __VA_ARGS__&, \
|
const __VA_ARGS__&, \
|
||||||
const __VA_ARGS__&, \
|
const __VA_ARGS__&, \
|
||||||
const double&) const;
|
const double) const;
|
||||||
|
|
||||||
INSTANCE(DenseAd::Evaluation<double, -1, 4u>)
|
INSTANCE(DenseAd::Evaluation<double, -1, 4u>)
|
||||||
INSTANCE(DenseAd::Evaluation<double, -1, 5u>)
|
INSTANCE(DenseAd::Evaluation<double, -1, 5u>)
|
||||||
@@ -139,4 +150,5 @@ INSTANCE(DenseAd::Evaluation<double, 7, 0u>)
|
|||||||
INSTANCE(DenseAd::Evaluation<double, 8, 0u>)
|
INSTANCE(DenseAd::Evaluation<double, 8, 0u>)
|
||||||
INSTANCE(DenseAd::Evaluation<double, 9, 0u>)
|
INSTANCE(DenseAd::Evaluation<double, 9, 0u>)
|
||||||
INSTANCE(DenseAd::Evaluation<double, 10, 0u>)
|
INSTANCE(DenseAd::Evaluation<double, 10, 0u>)
|
||||||
|
|
||||||
} //Namespace Opm
|
} //Namespace Opm
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ namespace Opm {
|
|||||||
|
|
||||||
class VFPInjTable;
|
class VFPInjTable;
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
class VFPInjProperties {
|
class VFPInjProperties {
|
||||||
public:
|
public:
|
||||||
VFPInjProperties() = default;
|
|
||||||
/**
|
/**
|
||||||
* Takes *no* ownership of data.
|
* Takes *no* ownership of data.
|
||||||
*/
|
*/
|
||||||
@@ -55,11 +55,11 @@ public:
|
|||||||
* input ADB objects.
|
* input ADB objects.
|
||||||
*/
|
*/
|
||||||
template <class EvalWell>
|
template <class EvalWell>
|
||||||
EvalWell bhp(const int table_id,
|
EvalWell bhp(const int table_id,
|
||||||
const EvalWell& aqua,
|
const EvalWell& aqua,
|
||||||
const EvalWell& liquid,
|
const EvalWell& liquid,
|
||||||
const EvalWell& vapour,
|
const EvalWell& vapour,
|
||||||
const double& thp) const;
|
const Scalar thp) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the table associated with the ID, or throws an exception if
|
* Returns the table associated with the ID, or throws an exception if
|
||||||
@@ -75,7 +75,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Returns true if no vfp tables are in the current map
|
* Returns true if no vfp tables are in the current map
|
||||||
*/
|
*/
|
||||||
bool empty() const {
|
bool empty() const
|
||||||
|
{
|
||||||
return m_tables.empty();
|
return m_tables.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,11 +91,11 @@ public:
|
|||||||
* @return The bottom hole pressure, interpolated/extrapolated linearly using
|
* @return The bottom hole pressure, interpolated/extrapolated linearly using
|
||||||
* the above parameters from the values in the input table.
|
* the above parameters from the values in the input table.
|
||||||
*/
|
*/
|
||||||
double bhp(int table_id,
|
Scalar bhp(const int table_id,
|
||||||
const double& aqua,
|
const Scalar aqua,
|
||||||
const double& liquid,
|
const Scalar liquid,
|
||||||
const double& vapour,
|
const Scalar vapour,
|
||||||
const double& thp) const;
|
const Scalar thp) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linear interpolation of thp as a function of the input parameters
|
* Linear interpolation of thp as a function of the input parameters
|
||||||
@@ -107,19 +108,17 @@ public:
|
|||||||
* @return The tubing hole pressure, interpolated/extrapolated linearly using
|
* @return The tubing hole pressure, interpolated/extrapolated linearly using
|
||||||
* the above parameters from the values in the input table.
|
* the above parameters from the values in the input table.
|
||||||
*/
|
*/
|
||||||
double thp(int table_id,
|
Scalar thp(const int table_id,
|
||||||
const double& aqua,
|
const Scalar aqua,
|
||||||
const double& liquid,
|
const Scalar liquid,
|
||||||
const double& vapour,
|
const Scalar vapour,
|
||||||
const double& bhp) const;
|
const Scalar bhp) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Map which connects the table number with the table itself
|
// Map which connects the table number with the table itself
|
||||||
std::map<int, std::reference_wrapper<const VFPInjTable>> m_tables;
|
std::map<int, std::reference_wrapper<const VFPInjTable>> m_tables;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,21 +31,21 @@
|
|||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
|
Scalar VFPProdProperties<Scalar>::
|
||||||
|
thp(const int table_id,
|
||||||
double VFPProdProperties::thp(int table_id,
|
const Scalar aqua,
|
||||||
const double& aqua,
|
const Scalar liquid,
|
||||||
const double& liquid,
|
const Scalar vapour,
|
||||||
const double& vapour,
|
const Scalar bhp_arg,
|
||||||
const double& bhp_arg,
|
const Scalar alq) const
|
||||||
const double& alq) const {
|
{
|
||||||
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
||||||
|
|
||||||
// Find interpolation variables.
|
// Find interpolation variables.
|
||||||
double flo = 0.0;
|
Scalar flo = 0.0;
|
||||||
double wfr = 0.0;
|
Scalar wfr = 0.0;
|
||||||
double gfr = 0.0;
|
Scalar gfr = 0.0;
|
||||||
if (aqua == 0.0 && liquid == 0.0 && vapour == 0.0) {
|
if (aqua == 0.0 && liquid == 0.0 && vapour == 0.0) {
|
||||||
// All zero, likely at initial state.
|
// All zero, likely at initial state.
|
||||||
// Set FLO variable to minimum to avoid extrapolation.
|
// Set FLO variable to minimum to avoid extrapolation.
|
||||||
@@ -67,68 +67,75 @@ double VFPProdProperties::thp(int table_id,
|
|||||||
* by interpolating for every value of thp. This might be somewhat
|
* by interpolating for every value of thp. This might be somewhat
|
||||||
* expensive, but let us assome that nthp is small.
|
* expensive, but let us assome that nthp is small.
|
||||||
*/
|
*/
|
||||||
auto flo_i = detail::findInterpData( flo, table.getFloAxis());
|
auto flo_i = VFPHelpers<Scalar>::findInterpData( flo, table.getFloAxis());
|
||||||
auto wfr_i = detail::findInterpData( wfr, table.getWFRAxis());
|
auto wfr_i = VFPHelpers<Scalar>::findInterpData( wfr, table.getWFRAxis());
|
||||||
auto gfr_i = detail::findInterpData( gfr, table.getGFRAxis());
|
auto gfr_i = VFPHelpers<Scalar>::findInterpData( gfr, table.getGFRAxis());
|
||||||
auto alq_i = detail::findInterpData( alq, table.getALQAxis());
|
auto alq_i = VFPHelpers<Scalar>::findInterpData( alq, table.getALQAxis());
|
||||||
std::vector<double> bhp_array(nthp);
|
std::vector<Scalar> bhp_array(nthp);
|
||||||
for (int i=0; i<nthp; ++i) {
|
for (int i = 0; i < nthp; ++i) {
|
||||||
auto thp_i = detail::findInterpData(thp_array[i], thp_array);
|
auto thp_i = VFPHelpers<Scalar>::findInterpData(thp_array[i], thp_array);
|
||||||
bhp_array[i] = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i).value;
|
bhp_array[i] = VFPHelpers<Scalar>::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double retval = detail::findTHP(bhp_array, thp_array, bhp_arg);
|
return VFPHelpers<Scalar>::findTHP(bhp_array, thp_array, bhp_arg);
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
double VFPProdProperties::bhp(int table_id,
|
Scalar VFPProdProperties<Scalar>::
|
||||||
const double& aqua,
|
bhp(const int table_id,
|
||||||
const double& liquid,
|
const Scalar aqua,
|
||||||
const double& vapour,
|
const Scalar liquid,
|
||||||
const double& thp_arg,
|
const Scalar vapour,
|
||||||
const double& alq,
|
const Scalar thp_arg,
|
||||||
const double& explicit_wfr,
|
const Scalar alq,
|
||||||
const double& explicit_gfr,
|
const Scalar explicit_wfr,
|
||||||
const bool use_expvfp) const {
|
const Scalar explicit_gfr,
|
||||||
|
const bool use_expvfp) const
|
||||||
|
{
|
||||||
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
||||||
|
|
||||||
detail::VFPEvaluation retval = detail::bhp(table, aqua, liquid, vapour, thp_arg, alq, explicit_wfr,explicit_gfr, use_expvfp);
|
detail::VFPEvaluation retval = VFPHelpers<Scalar>::bhp(table, aqua, liquid, vapour,
|
||||||
|
thp_arg, alq, explicit_wfr,
|
||||||
|
explicit_gfr, use_expvfp);
|
||||||
return retval.value;
|
return retval.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
const VFPProdTable& VFPProdProperties::getTable(const int table_id) const {
|
const VFPProdTable&
|
||||||
|
VFPProdProperties<Scalar>::getTable(const int table_id) const
|
||||||
|
{
|
||||||
return detail::getTable(m_tables, table_id);
|
return detail::getTable(m_tables, table_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VFPProdProperties::hasTable(const int table_id) const {
|
template<class Scalar>
|
||||||
|
bool VFPProdProperties<Scalar>::hasTable(const int table_id) const
|
||||||
|
{
|
||||||
return detail::hasTable(m_tables, table_id);
|
return detail::hasTable(m_tables, table_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
std::vector<double>
|
std::vector<Scalar>
|
||||||
VFPProdProperties::
|
VFPProdProperties<Scalar>::
|
||||||
bhpwithflo(const std::vector<double>& flos,
|
bhpwithflo(const std::vector<Scalar>& flos,
|
||||||
const int table_id,
|
const int table_id,
|
||||||
const double wfr,
|
const Scalar wfr,
|
||||||
const double gfr,
|
const Scalar gfr,
|
||||||
const double thp,
|
const Scalar thp,
|
||||||
const double alq,
|
const Scalar alq,
|
||||||
const double dp) const
|
const Scalar dp) const
|
||||||
{
|
{
|
||||||
// Get the table
|
// Get the table
|
||||||
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
||||||
const auto thp_i = detail::findInterpData( thp, table.getTHPAxis()); // assume constant
|
const auto thp_i = VFPHelpers<Scalar>::findInterpData( thp, table.getTHPAxis()); // assume constant
|
||||||
const auto wfr_i = detail::findInterpData( wfr, table.getWFRAxis());
|
const auto wfr_i = VFPHelpers<Scalar>::findInterpData( wfr, table.getWFRAxis());
|
||||||
const auto gfr_i = detail::findInterpData( gfr, table.getGFRAxis());
|
const auto gfr_i = VFPHelpers<Scalar>::findInterpData( gfr, table.getGFRAxis());
|
||||||
const auto alq_i = detail::findInterpData( alq, table.getALQAxis()); //assume constant
|
const auto alq_i = VFPHelpers<Scalar>::findInterpData( alq, table.getALQAxis()); //assume constant
|
||||||
|
|
||||||
std::vector<double> bhps(flos.size(), 0.);
|
std::vector<Scalar> bhps(flos.size(), 0.);
|
||||||
for (std::size_t i = 0; i < flos.size(); ++i) {
|
for (std::size_t i = 0; i < flos.size(); ++i) {
|
||||||
// Value of FLO is negative in OPM for producers, but positive in VFP table
|
// Value of FLO is negative in OPM for producers, but positive in VFP table
|
||||||
const auto flo_i = detail::findInterpData(-flos[i], table.getFloAxis());
|
const auto flo_i = VFPHelpers<Scalar>::findInterpData(-flos[i], table.getFloAxis());
|
||||||
const detail::VFPEvaluation bhp_val = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
const detail::VFPEvaluation bhp_val = VFPHelpers<Scalar>::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
||||||
|
|
||||||
// TODO: this kind of breaks the conventions for the functions here by putting dp within the function
|
// TODO: this kind of breaks the conventions for the functions here by putting dp within the function
|
||||||
bhps[i] = bhp_val.value - dp;
|
bhps[i] = bhp_val.value - dp;
|
||||||
@@ -137,37 +144,39 @@ bhpwithflo(const std::vector<double>& flos,
|
|||||||
return bhps;
|
return bhps;
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
template<class Scalar>
|
||||||
VFPProdProperties::
|
Scalar VFPProdProperties<Scalar>::
|
||||||
minimumBHP(const int table_id,
|
minimumBHP(const int table_id,
|
||||||
const double thp,
|
const Scalar thp,
|
||||||
const double wfr,
|
const Scalar wfr,
|
||||||
const double gfr,
|
const Scalar gfr,
|
||||||
const double alq) const
|
const Scalar alq) const
|
||||||
{
|
{
|
||||||
// Get the table
|
// Get the table
|
||||||
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
||||||
const auto retval = detail::getMinimumBHPCoordinate(table, thp, wfr, gfr, alq);
|
const auto retval = VFPHelpers<Scalar>::getMinimumBHPCoordinate(table, thp, wfr, gfr, alq);
|
||||||
// returned pair is (flo, bhp)
|
// returned pair is (flo, bhp)
|
||||||
return retval.second;
|
return retval.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
|
void VFPProdProperties<Scalar>::addTable(const VFPProdTable& new_table)
|
||||||
void VFPProdProperties::addTable(const VFPProdTable& new_table) {
|
{
|
||||||
this->m_tables.emplace( new_table.getTableNum(), new_table );
|
this->m_tables.emplace( new_table.getTableNum(), new_table );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Scalar>
|
||||||
template <class EvalWell>
|
template <class EvalWell>
|
||||||
EvalWell VFPProdProperties::bhp(const int table_id,
|
EvalWell VFPProdProperties<Scalar>::
|
||||||
const EvalWell& aqua,
|
bhp(const int table_id,
|
||||||
const EvalWell& liquid,
|
const EvalWell& aqua,
|
||||||
const EvalWell& vapour,
|
const EvalWell& liquid,
|
||||||
const double& thp,
|
const EvalWell& vapour,
|
||||||
const double& alq,
|
const Scalar thp,
|
||||||
const double& explicit_wfr,
|
const Scalar alq,
|
||||||
const double& explicit_gfr,
|
const Scalar explicit_wfr,
|
||||||
const bool use_expvfp) const
|
const Scalar explicit_gfr,
|
||||||
|
const bool use_expvfp) const
|
||||||
{
|
{
|
||||||
//Get the table
|
//Get the table
|
||||||
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
const VFPProdTable& table = detail::getTable(m_tables, table_id);
|
||||||
@@ -184,23 +193,32 @@ EvalWell VFPProdProperties::bhp(const int table_id,
|
|||||||
|
|
||||||
//First, find the values to interpolate between
|
//First, find the values to interpolate between
|
||||||
//Value of FLO is negative in OPM for producers, but positive in VFP table
|
//Value of FLO is negative in OPM for producers, but positive in VFP table
|
||||||
auto flo_i = detail::findInterpData(-flo.value(), table.getFloAxis());
|
auto flo_i = VFPHelpers<Scalar>::findInterpData(-flo.value(), table.getFloAxis());
|
||||||
auto thp_i = detail::findInterpData( thp, table.getTHPAxis()); // assume constant
|
auto thp_i = VFPHelpers<Scalar>::findInterpData( thp, table.getTHPAxis()); // assume constant
|
||||||
auto wfr_i = detail::findInterpData( wfr.value(), table.getWFRAxis());
|
auto wfr_i = VFPHelpers<Scalar>::findInterpData( wfr.value(), table.getWFRAxis());
|
||||||
auto gfr_i = detail::findInterpData( gfr.value(), table.getGFRAxis());
|
auto gfr_i = VFPHelpers<Scalar>::findInterpData( gfr.value(), table.getGFRAxis());
|
||||||
auto alq_i = detail::findInterpData( alq, table.getALQAxis()); //assume constant
|
auto alq_i = VFPHelpers<Scalar>::findInterpData( alq, table.getALQAxis()); //assume constant
|
||||||
|
|
||||||
detail::VFPEvaluation bhp_val = detail::interpolate(table, flo_i, thp_i, wfr_i, gfr_i, alq_i);
|
detail::VFPEvaluation bhp_val = VFPHelpers<Scalar>::interpolate(table, flo_i, thp_i, wfr_i,
|
||||||
|
gfr_i, alq_i);
|
||||||
|
|
||||||
bhp = (bhp_val.dwfr * wfr) + (bhp_val.dgfr * gfr) - (std::max(0.0, bhp_val.dflo) * flo);
|
bhp = (bhp_val.dwfr * wfr) + (bhp_val.dgfr * gfr) - (std::max(0.0, bhp_val.dflo) * flo);
|
||||||
bhp.setValue(bhp_val.value);
|
bhp.setValue(bhp_val.value);
|
||||||
return bhp;
|
return bhp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class VFPProdProperties<double>;
|
||||||
|
|
||||||
#define INSTANCE(...) \
|
#define INSTANCE(...) \
|
||||||
template __VA_ARGS__ VFPProdProperties::bhp<__VA_ARGS__>(const int, \
|
template __VA_ARGS__ VFPProdProperties<double>::bhp<__VA_ARGS__>(const int, \
|
||||||
const __VA_ARGS__&, const __VA_ARGS__&, const __VA_ARGS__&, \
|
const __VA_ARGS__&, \
|
||||||
const double&, const double&, const double&, const double&, const bool) const;
|
const __VA_ARGS__&, \
|
||||||
|
const __VA_ARGS__&, \
|
||||||
|
const double, \
|
||||||
|
const double, \
|
||||||
|
const double, \
|
||||||
|
const double, \
|
||||||
|
const bool) const;
|
||||||
|
|
||||||
INSTANCE(DenseAd::Evaluation<double, -1, 4u>)
|
INSTANCE(DenseAd::Evaluation<double, -1, 4u>)
|
||||||
INSTANCE(DenseAd::Evaluation<double, -1, 5u>)
|
INSTANCE(DenseAd::Evaluation<double, -1, 5u>)
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ class VFPProdTable;
|
|||||||
* water fraction, gas fraction, and artificial lift for production VFP tables, and similarly
|
* water fraction, gas fraction, and artificial lift for production VFP tables, and similarly
|
||||||
* the BHP as a function of the rate and tubing head pressure.
|
* the BHP as a function of the rate and tubing head pressure.
|
||||||
*/
|
*/
|
||||||
|
template<class Scalar>
|
||||||
class VFPProdProperties {
|
class VFPProdProperties {
|
||||||
public:
|
public:
|
||||||
VFPProdProperties() = default;
|
|
||||||
/**
|
/**
|
||||||
* Takes *no* ownership of data.
|
* Takes *no* ownership of data.
|
||||||
*/
|
*/
|
||||||
@@ -60,15 +60,15 @@ public:
|
|||||||
* input ADB objects.
|
* input ADB objects.
|
||||||
*/
|
*/
|
||||||
template <class EvalWell>
|
template <class EvalWell>
|
||||||
EvalWell bhp(const int table_id,
|
EvalWell bhp(const int table_id,
|
||||||
const EvalWell& aqua,
|
const EvalWell& aqua,
|
||||||
const EvalWell& liquid,
|
const EvalWell& liquid,
|
||||||
const EvalWell& vapour,
|
const EvalWell& vapour,
|
||||||
const double& thp,
|
const Scalar thp,
|
||||||
const double& alq,
|
const Scalar alq,
|
||||||
const double& explicit_wfr,
|
const Scalar explicit_wfr,
|
||||||
const double& explicit_gfr,
|
const Scalar explicit_gfr,
|
||||||
const bool use_expvfp) const;
|
const bool use_expvfp) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linear interpolation of bhp as a function of the input parameters
|
* Linear interpolation of bhp as a function of the input parameters
|
||||||
@@ -82,15 +82,15 @@ public:
|
|||||||
* @return The bottom hole pressure, interpolated/extrapolated linearly using
|
* @return The bottom hole pressure, interpolated/extrapolated linearly using
|
||||||
* the above parameters from the values in the input table.
|
* the above parameters from the values in the input table.
|
||||||
*/
|
*/
|
||||||
double bhp(int table_id,
|
Scalar bhp(const int table_id,
|
||||||
const double& aqua,
|
const Scalar aqua,
|
||||||
const double& liquid,
|
const Scalar liquid,
|
||||||
const double& vapour,
|
const Scalar vapour,
|
||||||
const double& thp,
|
const Scalar thp,
|
||||||
const double& alq,
|
const Scalar alq,
|
||||||
const double& explicit_wfr,
|
const Scalar explicit_wfr,
|
||||||
const double& explicit_gfr,
|
const Scalar explicit_gfr,
|
||||||
const bool use_expvfp) const;
|
const bool use_expvfp) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linear interpolation of thp as a function of the input parameters
|
* Linear interpolation of thp as a function of the input parameters
|
||||||
@@ -104,12 +104,12 @@ public:
|
|||||||
* @return The tubing hole pressure, interpolated/extrapolated linearly using
|
* @return The tubing hole pressure, interpolated/extrapolated linearly using
|
||||||
* the above parameters from the values in the input table.
|
* the above parameters from the values in the input table.
|
||||||
*/
|
*/
|
||||||
double thp(int table_id,
|
Scalar thp(const int table_id,
|
||||||
const double& aqua,
|
const Scalar aqua,
|
||||||
const double& liquid,
|
const Scalar liquid,
|
||||||
const double& vapour,
|
const Scalar vapour,
|
||||||
const double& bhp,
|
const Scalar bhp,
|
||||||
const double& alq) const;
|
const Scalar alq) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the table associated with the ID, or throws an exception if
|
* Returns the table associated with the ID, or throws an exception if
|
||||||
@@ -125,33 +125,31 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Returns true if no vfp tables are in the current map
|
* Returns true if no vfp tables are in the current map
|
||||||
*/
|
*/
|
||||||
bool empty() const {
|
bool empty() const
|
||||||
|
{
|
||||||
return m_tables.empty();
|
return m_tables.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns minimum bhp for given thp, wfr, gfr and alq
|
* Returns minimum bhp for given thp, wfr, gfr and alq
|
||||||
*/
|
*/
|
||||||
double minimumBHP(const int table_id, const double thp,
|
Scalar minimumBHP(const int table_id, const Scalar thp,
|
||||||
const double wfr, const double gfr, const double alq) const;
|
const Scalar wfr, const Scalar gfr, const Scalar alq) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// calculate a group bhp values with a group of flo rate values
|
// calculate a group bhp values with a group of flo rate values
|
||||||
std::vector<double> bhpwithflo(const std::vector<double>& flos,
|
std::vector<Scalar> bhpwithflo(const std::vector<Scalar>& flos,
|
||||||
const int table_id,
|
const int table_id,
|
||||||
const double wfr,
|
const Scalar wfr,
|
||||||
const double gfr,
|
const Scalar gfr,
|
||||||
const double thp,
|
const Scalar thp,
|
||||||
const double alq,
|
const Scalar alq,
|
||||||
const double dp) const;
|
const Scalar dp) const;
|
||||||
|
|
||||||
// Map which connects the table number with the table itself
|
// Map which connects the table number with the table itself
|
||||||
std::map<int, std::reference_wrapper<const VFPProdTable>> m_tables;
|
std::map<int, std::reference_wrapper<const VFPProdTable>> m_tables;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace Opm
|
||||||
|
|
||||||
|
|
||||||
} //namespace
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* OPM_AUTODIFF_VFPPRODPROPERTIES_HPP_ */
|
#endif /* OPM_AUTODIFF_VFPPRODPROPERTIES_HPP_ */
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include <opm/simulators/wells/VFPHelpers.hpp>
|
#include <opm/simulators/wells/VFPHelpers.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
@@ -37,6 +36,7 @@ class VFPProdTable;
|
|||||||
* A thin wrapper class that holds one VFPProdProperties and one
|
* A thin wrapper class that holds one VFPProdProperties and one
|
||||||
* VFPInjProperties object.
|
* VFPInjProperties object.
|
||||||
*/
|
*/
|
||||||
|
template<class Scalar>
|
||||||
class VFPProperties {
|
class VFPProperties {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -48,8 +48,8 @@ public:
|
|||||||
|
|
||||||
VFPProperties(const std::vector<std::reference_wrapper<const VFPInjTable>>& inj_tables,
|
VFPProperties(const std::vector<std::reference_wrapper<const VFPInjTable>>& inj_tables,
|
||||||
const std::vector<std::reference_wrapper<const VFPProdTable>>& prod_tables,
|
const std::vector<std::reference_wrapper<const VFPProdTable>>& prod_tables,
|
||||||
const WellState<double>& well_state)
|
const WellState<Scalar>& well_state)
|
||||||
:well_state_(well_state)
|
: well_state_(well_state)
|
||||||
{
|
{
|
||||||
for (const auto& vfpinj : inj_tables)
|
for (const auto& vfpinj : inj_tables)
|
||||||
this->m_inj.addTable( vfpinj );
|
this->m_inj.addTable( vfpinj );
|
||||||
@@ -61,18 +61,21 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Returns the VFP properties for injection wells
|
* Returns the VFP properties for injection wells
|
||||||
*/
|
*/
|
||||||
const VFPInjProperties* getInj() const {
|
const VFPInjProperties<Scalar>* getInj() const
|
||||||
|
{
|
||||||
return &m_inj;
|
return &m_inj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the VFP properties for production wells
|
* Returns the VFP properties for production wells
|
||||||
*/
|
*/
|
||||||
const VFPProdProperties* getProd() const {
|
const VFPProdProperties<Scalar>* getProd() const
|
||||||
|
{
|
||||||
return &m_prod;
|
return &m_prod;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getExplicitWFR(const int table_id, const std::size_t well_index) const {
|
Scalar getExplicitWFR(const int table_id, const std::size_t well_index) const
|
||||||
|
{
|
||||||
const auto& rates = well_state_.well(well_index).prev_surface_rates;
|
const auto& rates = well_state_.well(well_index).prev_surface_rates;
|
||||||
const auto& pu = well_state_.phaseUsage();
|
const auto& pu = well_state_.phaseUsage();
|
||||||
const auto& aqua = pu.phase_used[BlackoilPhases::Aqua]? rates[pu.phase_pos[BlackoilPhases::Aqua]]:0.0;
|
const auto& aqua = pu.phase_used[BlackoilPhases::Aqua]? rates[pu.phase_pos[BlackoilPhases::Aqua]]:0.0;
|
||||||
@@ -82,7 +85,8 @@ public:
|
|||||||
return detail::getWFR(table, aqua, liquid, vapour);
|
return detail::getWFR(table, aqua, liquid, vapour);
|
||||||
}
|
}
|
||||||
|
|
||||||
double getExplicitGFR(const int table_id, const std::size_t well_index) const {
|
Scalar getExplicitGFR(const int table_id, const std::size_t well_index) const
|
||||||
|
{
|
||||||
const auto& rates = well_state_.well(well_index).prev_surface_rates;
|
const auto& rates = well_state_.well(well_index).prev_surface_rates;
|
||||||
const auto& pu = well_state_.phaseUsage();
|
const auto& pu = well_state_.phaseUsage();
|
||||||
const auto& aqua = pu.phase_used[BlackoilPhases::Aqua]? rates[pu.phase_pos[BlackoilPhases::Aqua]]:0.0;
|
const auto& aqua = pu.phase_used[BlackoilPhases::Aqua]? rates[pu.phase_pos[BlackoilPhases::Aqua]]:0.0;
|
||||||
@@ -93,13 +97,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VFPInjProperties m_inj;
|
VFPInjProperties<Scalar> m_inj;
|
||||||
VFPProdProperties m_prod;
|
VFPProdProperties<Scalar> m_prod;
|
||||||
const WellState<double>& well_state_;
|
const WellState<Scalar>& well_state_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace Opm
|
||||||
} //Namespace
|
|
||||||
|
|
||||||
#endif /* OPM_AUTODIFF_VFPPROPERTIES_HPP_ */
|
#endif /* OPM_AUTODIFF_VFPPROPERTIES_HPP_ */
|
||||||
|
|||||||
@@ -919,7 +919,9 @@ isStableSolution(const WellState<Scalar>& well_state,
|
|||||||
const auto& table = well_.vfpProperties()->getProd()->getTable(controls.vfp_table_number);
|
const auto& table = well_.vfpProperties()->getProd()->getTable(controls.vfp_table_number);
|
||||||
const bool use_vfpexplicit = well_.useVfpExplicit();
|
const bool use_vfpexplicit = well_.useVfpExplicit();
|
||||||
|
|
||||||
detail::VFPEvaluation bhp = detail::bhp(table, aqua, liquid, vapour, thp, well_.getALQ(well_state), wfr, gfr, use_vfpexplicit);
|
auto bhp = VFPHelpers<double>::bhp(table, aqua, liquid, vapour, thp,
|
||||||
|
well_.getALQ(well_state), wfr, gfr,
|
||||||
|
use_vfpexplicit);
|
||||||
|
|
||||||
if (bhp.dflo >= 0) {
|
if (bhp.dflo >= 0) {
|
||||||
return true;
|
return true;
|
||||||
@@ -964,7 +966,10 @@ estimateStableBhp(const WellState<Scalar>& well_state,
|
|||||||
auto bhp_adjusted = [this, &thp, &dp_hydro](const Scalar bhp) {
|
auto bhp_adjusted = [this, &thp, &dp_hydro](const Scalar bhp) {
|
||||||
return bhp - dp_hydro + getVfpBhpAdjustment(bhp, thp);
|
return bhp - dp_hydro + getVfpBhpAdjustment(bhp, thp);
|
||||||
};
|
};
|
||||||
const auto retval = detail::intersectWithIPR(table, thp, wfr, gfr, well_.getALQ(well_state), ipr.first, ipr.second, bhp_adjusted);
|
const auto retval = VFPHelpers<double>::intersectWithIPR(table, thp, wfr, gfr,
|
||||||
|
well_.getALQ(well_state),
|
||||||
|
ipr.first, ipr.second,
|
||||||
|
bhp_adjusted);
|
||||||
if (retval.has_value()) {
|
if (retval.has_value()) {
|
||||||
// returned pair is (flo, bhp)
|
// returned pair is (flo, bhp)
|
||||||
return retval.value().second;
|
return retval.value().second;
|
||||||
|
|||||||
@@ -811,7 +811,7 @@ WellGroupHelpers<Scalar>::
|
|||||||
computeNetworkPressures(const Network::ExtNetwork& network,
|
computeNetworkPressures(const Network::ExtNetwork& network,
|
||||||
const WellState<Scalar>& well_state,
|
const WellState<Scalar>& well_state,
|
||||||
const GroupState<Scalar>& group_state,
|
const GroupState<Scalar>& group_state,
|
||||||
const VFPProdProperties& vfp_prod_props,
|
const VFPProdProperties<Scalar>& vfp_prod_props,
|
||||||
const Schedule& schedule,
|
const Schedule& schedule,
|
||||||
const int report_time_step)
|
const int report_time_step)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ template<class Scalar> class GroupState;
|
|||||||
namespace Network { class ExtNetwork; }
|
namespace Network { class ExtNetwork; }
|
||||||
struct PhaseUsage;
|
struct PhaseUsage;
|
||||||
class Schedule;
|
class Schedule;
|
||||||
class VFPProdProperties;
|
template<class Scalar> class VFPProdProperties;
|
||||||
template<class Scalar> class WellState;
|
template<class Scalar> class WellState;
|
||||||
class FieldPropsManager;
|
class FieldPropsManager;
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ public:
|
|||||||
computeNetworkPressures(const Network::ExtNetwork& network,
|
computeNetworkPressures(const Network::ExtNetwork& network,
|
||||||
const WellState<Scalar>& well_state,
|
const WellState<Scalar>& well_state,
|
||||||
const GroupState<Scalar>& group_state,
|
const GroupState<Scalar>& group_state,
|
||||||
const VFPProdProperties& vfp_prod_props,
|
const VFPProdProperties<Scalar>& vfp_prod_props,
|
||||||
const Schedule& schedule,
|
const Schedule& schedule,
|
||||||
const int report_time_step);
|
const int report_time_step);
|
||||||
|
|
||||||
|
|||||||
@@ -374,7 +374,7 @@ closeCompletions(const WellTestState& wellTestState)
|
|||||||
|
|
||||||
template<class Scalar>
|
template<class Scalar>
|
||||||
void WellInterfaceGeneric<Scalar>::
|
void WellInterfaceGeneric<Scalar>::
|
||||||
setVFPProperties(const VFPProperties* vfp_properties_arg)
|
setVFPProperties(const VFPProperties<Scalar>* vfp_properties_arg)
|
||||||
{
|
{
|
||||||
vfp_properties_ = vfp_properties_arg;
|
vfp_properties_ = vfp_properties_arg;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class ParallelWellInfo;
|
|||||||
struct PerforationData;
|
struct PerforationData;
|
||||||
struct PhaseUsage;
|
struct PhaseUsage;
|
||||||
class SummaryState;
|
class SummaryState;
|
||||||
class VFPProperties;
|
template<class Scalar> class VFPProperties;
|
||||||
class WellTestState;
|
class WellTestState;
|
||||||
template<class Scalar> class WellState;
|
template<class Scalar> class WellState;
|
||||||
template<class Scalar> class SingleWellState;
|
template<class Scalar> class SingleWellState;
|
||||||
@@ -94,7 +94,7 @@ public:
|
|||||||
void initCompletions();
|
void initCompletions();
|
||||||
void closeCompletions(const WellTestState& wellTestState);
|
void closeCompletions(const WellTestState& wellTestState);
|
||||||
|
|
||||||
void setVFPProperties(const VFPProperties* vfp_properties_arg);
|
void setVFPProperties(const VFPProperties<Scalar>* vfp_properties_arg);
|
||||||
void setPrevSurfaceRates(WellState<Scalar>& well_state,
|
void setPrevSurfaceRates(WellState<Scalar>& well_state,
|
||||||
const WellState<Scalar>& prev_well_state) const;
|
const WellState<Scalar>& prev_well_state) const;
|
||||||
void setGuideRate(const GuideRate* guide_rate_arg);
|
void setGuideRate(const GuideRate* guide_rate_arg);
|
||||||
@@ -129,7 +129,7 @@ public:
|
|||||||
|
|
||||||
Scalar gravity() const { return gravity_; }
|
Scalar gravity() const { return gravity_; }
|
||||||
|
|
||||||
const VFPProperties* vfpProperties() const { return vfp_properties_; }
|
const VFPProperties<Scalar>* vfpProperties() const { return vfp_properties_; }
|
||||||
|
|
||||||
const ParallelWellInfo& parallelWellInfo() const { return parallel_well_info_; }
|
const ParallelWellInfo& parallelWellInfo() const { return parallel_well_info_; }
|
||||||
|
|
||||||
@@ -358,7 +358,7 @@ protected:
|
|||||||
std::vector<Scalar> inj_fc_multiplier_;
|
std::vector<Scalar> inj_fc_multiplier_;
|
||||||
|
|
||||||
Scalar well_efficiency_factor_;
|
Scalar well_efficiency_factor_;
|
||||||
const VFPProperties* vfp_properties_;
|
const VFPProperties<Scalar>* vfp_properties_;
|
||||||
const GuideRate* guide_rate_;
|
const GuideRate* guide_rate_;
|
||||||
|
|
||||||
std::vector<std::string> well_control_log_;
|
std::vector<std::string> well_control_log_;
|
||||||
|
|||||||
@@ -68,12 +68,12 @@ BOOST_AUTO_TEST_CASE(findInterpData)
|
|||||||
double first = 1;
|
double first = 1;
|
||||||
double last = 15;
|
double last = 15;
|
||||||
|
|
||||||
Opm::detail::InterpData eval0 = Opm::detail::findInterpData(exact, values);
|
auto eval0 = Opm::VFPHelpers<double>::findInterpData(exact, values);
|
||||||
Opm::detail::InterpData eval1 = Opm::detail::findInterpData(interpolate, values);
|
auto eval1 = Opm::VFPHelpers<double>::findInterpData(interpolate, values);
|
||||||
Opm::detail::InterpData eval2 = Opm::detail::findInterpData(extrapolate_left, values);
|
auto eval2 = Opm::VFPHelpers<double>::findInterpData(extrapolate_left, values);
|
||||||
Opm::detail::InterpData eval3 = Opm::detail::findInterpData(extrapolate_right, values);
|
auto eval3 = Opm::VFPHelpers<double>::findInterpData(extrapolate_right, values);
|
||||||
Opm::detail::InterpData eval4 = Opm::detail::findInterpData(first, values);
|
auto eval4 = Opm::VFPHelpers<double>::findInterpData(first, values);
|
||||||
Opm::detail::InterpData eval5 = Opm::detail::findInterpData(last, values);
|
auto eval5 = Opm::VFPHelpers<double>::findInterpData(last, values);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(eval0.ind_[0], 2);
|
BOOST_CHECK_EQUAL(eval0.ind_[0], 2);
|
||||||
BOOST_CHECK_EQUAL(eval0.ind_[1], 3);
|
BOOST_CHECK_EQUAL(eval0.ind_[1], 3);
|
||||||
@@ -109,7 +109,7 @@ BOOST_AUTO_TEST_SUITE_END() // HelperTests
|
|||||||
* values data is given at
|
* values data is given at
|
||||||
*/
|
*/
|
||||||
struct TrivialFixture {
|
struct TrivialFixture {
|
||||||
typedef Opm::detail::VFPEvaluation VFPEvaluation;
|
typedef Opm::detail::VFPEvaluation<double> VFPEvaluation;
|
||||||
|
|
||||||
TrivialFixture() : table_ids(1, 1),
|
TrivialFixture() : table_ids(1, 1),
|
||||||
thp_axis{0.0, 1.0},
|
thp_axis{0.0, 1.0},
|
||||||
@@ -208,7 +208,7 @@ struct TrivialFixture {
|
|||||||
alq_axis,
|
alq_axis,
|
||||||
data));
|
data));
|
||||||
|
|
||||||
properties = std::make_shared<Opm::VFPProdProperties>();
|
properties = std::make_shared<Opm::VFPProdProperties<double>>();
|
||||||
properties->addTable( *table );
|
properties->addTable( *table );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ struct TrivialFixture {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<Opm::VFPProdProperties> properties;
|
std::shared_ptr<Opm::VFPProdProperties<double>> properties;
|
||||||
std::shared_ptr<Opm::VFPProdTable> table;
|
std::shared_ptr<Opm::VFPProdTable> table;
|
||||||
std::vector<int> table_ids;
|
std::vector<int> table_ids;
|
||||||
|
|
||||||
@@ -612,7 +612,7 @@ VFPPROD \n\
|
|||||||
auto deck = parser.parseString(table_str);
|
auto deck = parser.parseString(table_str);
|
||||||
bool gaslift_active = false;
|
bool gaslift_active = false;
|
||||||
Opm::VFPProdTable table(deck["VFPPROD"].front(), gaslift_active, units);
|
Opm::VFPProdTable table(deck["VFPPROD"].front(), gaslift_active, units);
|
||||||
Opm::VFPProdProperties properties;
|
Opm::VFPProdProperties<double> properties;
|
||||||
properties.addTable( table );
|
properties.addTable( table );
|
||||||
|
|
||||||
const int n = 5; //Number of points to check per axis
|
const int n = 5; //Number of points to check per axis
|
||||||
@@ -673,7 +673,7 @@ BOOST_AUTO_TEST_CASE(ParseInterpolateRealisticVFPPROD)
|
|||||||
|
|
||||||
bool gaslift_active = false;
|
bool gaslift_active = false;
|
||||||
Opm::VFPProdTable table(deck["VFPPROD"].front(), gaslift_active, units);
|
Opm::VFPProdTable table(deck["VFPPROD"].front(), gaslift_active, units);
|
||||||
Opm::VFPProdProperties properties;
|
Opm::VFPProdProperties<double> properties;
|
||||||
properties.addTable(table);
|
properties.addTable(table);
|
||||||
|
|
||||||
//Do some rudimentary testing
|
//Do some rudimentary testing
|
||||||
|
|||||||
Reference in New Issue
Block a user