mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-11-22 01:07:24 -06:00
Added tests for computing the flo/wfr/gfr values based on the aqua/liquid/vapour flow rates
This commit is contained in:
parent
2f6e44500b
commit
ccf06c2c1c
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <opm/autodiff/AutoDiffHelpers.hpp>
|
#include <opm/autodiff/AutoDiffHelpers.hpp>
|
||||||
#include <opm/core/props/BlackoilPhases.hpp>
|
#include <opm/core/props/BlackoilPhases.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
@ -127,7 +128,9 @@ VFPProperties::VFPProperties(DeckKeywordConstPtr table) {
|
|||||||
}
|
}
|
||||||
catch (std::invalid_argument& e) {
|
catch (std::invalid_argument& e) {
|
||||||
//TODO: log here
|
//TODO: log here
|
||||||
alq_type_ = ALQ_INVALID;
|
//FIXME: header->getItem("ALQ")->getString(0); appears to fail, ignoring in current implementation
|
||||||
|
//alq_type_ = ALQ_INVALID;
|
||||||
|
alq_type_ = ALQ_UNDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get actual rate / flow values
|
//Get actual rate / flow values
|
||||||
@ -169,14 +172,87 @@ VFPProperties::VFPProperties(DeckKeywordConstPtr table) {
|
|||||||
//Rest of values (bottom hole pressure or tubing head temperature) have index of flo value
|
//Rest of values (bottom hole pressure or tubing head temperature) have index of flo value
|
||||||
const std::vector<double>& bhp_tht = (*iter)->getItem("VALUES")->getRawDoubleData();
|
const std::vector<double>& bhp_tht = (*iter)->getItem("VALUES")->getRawDoubleData();
|
||||||
std::copy(bhp_tht.begin(), bhp_tht.end(), &data_[t][w][g][a][0]);
|
std::copy(bhp_tht.begin(), bhp_tht.end(), &data_[t][w][g][a][0]);
|
||||||
|
}
|
||||||
|
|
||||||
//Check for large values
|
check();
|
||||||
for (size_t i = 0; i<bhp_tht.size(); ++i) {
|
}
|
||||||
if (bhp_tht[i] > 1.0e10) {
|
|
||||||
//TODO: Replace with proper log message
|
|
||||||
std::cerr << "Too large value encountered in VFPPROD in ["
|
VFPProperties::VFPProperties(int table_num,
|
||||||
<< t << "," << w << "," << g << "," << a << "]="
|
double datum_depth,
|
||||||
<< bhp_tht[i] << std::endl;
|
FLO_TYPE flo_type,
|
||||||
|
WFR_TYPE wfr_type,
|
||||||
|
GFR_TYPE gfr_type,
|
||||||
|
ALQ_TYPE alq_type,
|
||||||
|
const std::vector<double>& flo_data,
|
||||||
|
const std::vector<double>& thp_data,
|
||||||
|
const std::vector<double>& wfr_data,
|
||||||
|
const std::vector<double>& gfr_data,
|
||||||
|
const std::vector<double>& alq_data,
|
||||||
|
array_type data
|
||||||
|
) :
|
||||||
|
table_num_(table_num),
|
||||||
|
datum_depth_(datum_depth),
|
||||||
|
flo_type_(flo_type),
|
||||||
|
wfr_type_(wfr_type),
|
||||||
|
gfr_type_(gfr_type),
|
||||||
|
alq_type_(alq_type),
|
||||||
|
flo_data_(flo_data),
|
||||||
|
thp_data_(thp_data),
|
||||||
|
wfr_data_(wfr_data),
|
||||||
|
gfr_data_(gfr_data),
|
||||||
|
alq_data_(alq_data),
|
||||||
|
data_(data) {
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VFPProperties::check() {
|
||||||
|
//Table number
|
||||||
|
assert(table_num_ > 0);
|
||||||
|
|
||||||
|
//Misc types
|
||||||
|
assert(flo_type_ >= FLO_OIL && flo_type_ < FLO_INVALID);
|
||||||
|
assert(wfr_type_ >= WFR_WOR && flo_type_ < WFR_INVALID);
|
||||||
|
assert(gfr_type_ >= GFR_GOR && flo_type_ < GFR_INVALID);
|
||||||
|
assert(alq_type_ >= ALQ_GRAT && flo_type_ < ALQ_INVALID);
|
||||||
|
|
||||||
|
//Data axis size
|
||||||
|
assert(flo_data_.size() > 0);
|
||||||
|
assert(thp_data_.size() > 0);
|
||||||
|
assert(wfr_data_.size() > 0);
|
||||||
|
assert(gfr_data_.size() > 0);
|
||||||
|
assert(alq_data_.size() > 0);
|
||||||
|
|
||||||
|
//Data axis sorted?
|
||||||
|
assert(is_sorted(flo_data_.begin(), flo_data_.end()));
|
||||||
|
assert(is_sorted(thp_data_.begin(), thp_data_.end()));
|
||||||
|
assert(is_sorted(wfr_data_.begin(), wfr_data_.end()));
|
||||||
|
assert(is_sorted(gfr_data_.begin(), gfr_data_.end()));
|
||||||
|
assert(is_sorted(alq_data_.begin(), alq_data_.end()));
|
||||||
|
|
||||||
|
//Check data size matches axes
|
||||||
|
assert(data_.num_dimensions() == 5);
|
||||||
|
assert(data_.shape()[0] == thp_data_.size());
|
||||||
|
assert(data_.shape()[1] == wfr_data_.size());
|
||||||
|
assert(data_.shape()[2] == gfr_data_.size());
|
||||||
|
assert(data_.shape()[3] == alq_data_.size());
|
||||||
|
assert(data_.shape()[4] == flo_data_.size());
|
||||||
|
|
||||||
|
//Finally, check that all data is within reasonable ranges, defined to be up-to 1.0e10...
|
||||||
|
for (int t=0; t<data_.shape()[0]; ++t) {
|
||||||
|
for (int w=0; w<data_.shape()[1]; ++w) {
|
||||||
|
for (int g=0; g<data_.shape()[2]; ++g) {
|
||||||
|
for (int a=0; a<data_.shape()[3]; ++a) {
|
||||||
|
for (int f=0; f<data_.shape()[4]; ++f) {
|
||||||
|
if (data_[t][w][g][a][f] > 1.0e10) {
|
||||||
|
//TODO: Replace with proper log message
|
||||||
|
std::cerr << "Too large value encountered in VFPPROD in ["
|
||||||
|
<< t << "," << w << "," << g << "," << a << "," << f << "]="
|
||||||
|
<< data_[t][w][g][a][f] << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,10 +294,6 @@ VFPProperties::ADB VFPProperties::bhp(const ADB& flo, const ADB& thp, const ADB&
|
|||||||
|
|
||||||
|
|
||||||
VFPProperties::ADB VFPProperties::bhp(const Wells& wells, const ADB& qs, const ADB& thp, const ADB& alq) {
|
VFPProperties::ADB VFPProperties::bhp(const Wells& wells, const ADB& qs, const ADB& thp, const ADB& alq) {
|
||||||
ADB flo = ADB::null();
|
|
||||||
ADB wfr = ADB::null();
|
|
||||||
ADB gfr = ADB::null();
|
|
||||||
|
|
||||||
const int np = wells.number_of_phases;
|
const int np = wells.number_of_phases;
|
||||||
const int nw = wells.number_of_wells;
|
const int nw = wells.number_of_wells;
|
||||||
|
|
||||||
@ -230,74 +302,29 @@ VFPProperties::ADB VFPProperties::bhp(const Wells& wells, const ADB& qs, const A
|
|||||||
const ADB& o = subset(qs, Span(nw, 1, BlackoilPhases::Liquid*nw));
|
const ADB& o = subset(qs, Span(nw, 1, BlackoilPhases::Liquid*nw));
|
||||||
const ADB& g = subset(qs, Span(nw, 1, BlackoilPhases::Vapour*nw));
|
const ADB& g = subset(qs, Span(nw, 1, BlackoilPhases::Vapour*nw));
|
||||||
|
|
||||||
switch (flo_type_) {
|
ADB flo = getFlo(w, o, g);
|
||||||
case FLO_OIL: //Oil = oil phase
|
ADB wfr = getWFR(w, o, g);
|
||||||
//TODO assert("has oil phase")
|
ADB gfr = getGFR(w, o, g);
|
||||||
flo = o;
|
|
||||||
break;
|
|
||||||
case FLO_LIQ: //Liquid = water + oil phases
|
|
||||||
flo = w + o;
|
|
||||||
break;
|
|
||||||
case FLO_GAS: //Gas = gas phase
|
|
||||||
flo = g;
|
|
||||||
break;
|
|
||||||
case FLO_INVALID: //Intentional fall-through
|
|
||||||
default:
|
|
||||||
//TODO: Log
|
|
||||||
std::cerr << "ERROR, FLO_INVALID" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(wfr_type_) {
|
//TODO: What is this actually supposed to be used for?
|
||||||
case WFR_WOR: //Water-oil ratio = water / oil
|
|
||||||
wfr = w / o;
|
|
||||||
break;
|
|
||||||
case WFR_WCT: //Water cut = water / (oil + gas)
|
|
||||||
wfr = w / (o + g);
|
|
||||||
break;
|
|
||||||
case WFR_WGR: //Water-gas ratio = water / gas
|
|
||||||
wfr = w / g;
|
|
||||||
break;
|
|
||||||
case WFR_INVALID: //Intentional fall-through
|
|
||||||
default:
|
|
||||||
//TODO: Log
|
|
||||||
std::cerr << "ERROR, WFR_INVALID" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(gfr_type_) {
|
|
||||||
case GFR_GOR: // Gas-oil ratio = gas / oil
|
|
||||||
gfr = g / o;
|
|
||||||
break;
|
|
||||||
case GFR_GLR: // Gas-liquid ratio = gas / (oil + water)
|
|
||||||
gfr = g / (o + w);
|
|
||||||
break;
|
|
||||||
case GFR_OGR: // Oil-gas ratio = oil / gas
|
|
||||||
gfr = o / g;
|
|
||||||
break;
|
|
||||||
case GFR_INVALID: //Intentional fall-through
|
|
||||||
default:
|
|
||||||
//TODO: Log
|
|
||||||
std::cerr << "ERROR, GFR_INVALID" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: What is this actually used for, and how to check?
|
|
||||||
switch(alq_type_) {
|
switch(alq_type_) {
|
||||||
case ALQ_GRAT: //< Lift as injection rate
|
case ALQ_GRAT: // Lift as injection rate
|
||||||
break;
|
break;
|
||||||
case ALQ_IGLR: //< Injection gas-liquid ratio
|
case ALQ_IGLR: // Injection gas-liquid ratio
|
||||||
break;
|
break;
|
||||||
case ALQ_TGLR: //< Total gas-liquid ratio
|
case ALQ_TGLR: // Total gas-liquid ratio
|
||||||
break;
|
break;
|
||||||
case ALQ_PUMP: //< Pump rating
|
case ALQ_PUMP: // Pump rating
|
||||||
break;
|
break;
|
||||||
case ALQ_COMP: //< Compressor power
|
case ALQ_COMP: // Compressor power
|
||||||
break;
|
break;
|
||||||
case ALQ_BEAN: //< Choke diameter
|
case ALQ_BEAN: // Choke diameter
|
||||||
break;
|
break;
|
||||||
case ALQ_UNDEF: //< Undefined
|
case ALQ_UNDEF: // Undefined
|
||||||
break;
|
break;
|
||||||
case ALQ_INVALID: //Intentional fall-through
|
case ALQ_INVALID: //Intentional fall-through
|
||||||
default:
|
default:
|
||||||
//TODO: Log
|
//TODO: Log/throw
|
||||||
std::cerr << "ERROR, ALQ_INVALID" << std::endl;
|
std::cerr << "ERROR, ALQ_INVALID" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,6 +332,65 @@ VFPProperties::ADB VFPProperties::bhp(const Wells& wells, const ADB& qs, const A
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VFPProperties::ADB VFPProperties::getFlo(const ADB& aqua, const ADB& liquid, const ADB& vapour) {
|
||||||
|
switch (flo_type_) {
|
||||||
|
case FLO_OIL:
|
||||||
|
//Oil = liquid phase
|
||||||
|
//TODO assert("qs has oil phase")
|
||||||
|
return liquid;
|
||||||
|
case FLO_LIQ:
|
||||||
|
//Liquid = aqua + liquid phases
|
||||||
|
return aqua + liquid;
|
||||||
|
case FLO_GAS:
|
||||||
|
//Gas = vapor phase
|
||||||
|
return vapour;
|
||||||
|
case FLO_INVALID: //Intentional fall-through
|
||||||
|
default:
|
||||||
|
//TODO: Log/throw
|
||||||
|
std::cerr << "ERROR, FLO_INVALID" << std::endl;
|
||||||
|
return ADB::null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VFPProperties::ADB VFPProperties::getWFR(const ADB& aqua, const ADB& liquid, const ADB& vapour) {
|
||||||
|
switch(wfr_type_) {
|
||||||
|
case WFR_WOR:
|
||||||
|
//Water-oil ratio = water / oil
|
||||||
|
return aqua / liquid;
|
||||||
|
case WFR_WCT:
|
||||||
|
//Water cut = water / (water + oil + gas)
|
||||||
|
return aqua / (aqua + liquid + vapour);
|
||||||
|
case WFR_WGR:
|
||||||
|
//Water-gas ratio = water / gas
|
||||||
|
return aqua / vapour;
|
||||||
|
case WFR_INVALID: //Intentional fall-through
|
||||||
|
default:
|
||||||
|
//TODO: Log/throw
|
||||||
|
std::cerr << "ERROR, WFR_INVALID" << std::endl;
|
||||||
|
return ADB::null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VFPProperties::ADB VFPProperties::getGFR(const ADB& aqua, const ADB& liquid, const ADB& vapour) {
|
||||||
|
switch(gfr_type_) {
|
||||||
|
case GFR_GOR:
|
||||||
|
// Gas-oil ratio = gas / oil
|
||||||
|
return vapour / liquid;
|
||||||
|
case GFR_GLR:
|
||||||
|
// Gas-liquid ratio = gas / (oil + water)
|
||||||
|
return vapour / (liquid + aqua);
|
||||||
|
case GFR_OGR:
|
||||||
|
// Oil-gas ratio = oil / gas
|
||||||
|
return liquid / vapour;
|
||||||
|
case GFR_INVALID: //Intentional fall-through
|
||||||
|
default:
|
||||||
|
//TODO: Log/throw
|
||||||
|
std::cerr << "ERROR, GFR_INVALID" << std::endl;
|
||||||
|
return ADB::null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VFPProperties::InterpData VFPProperties::find_interp_data(const double& value, const std::vector<double>& values) {
|
VFPProperties::InterpData VFPProperties::find_interp_data(const double& value, const std::vector<double>& values) {
|
||||||
InterpData retval;
|
InterpData retval;
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
|
|
||||||
///Rate type
|
///Rate type
|
||||||
enum FLO_TYPE {
|
enum FLO_TYPE {
|
||||||
FLO_OIL, //< Oil rate
|
FLO_OIL=1, //< Oil rate
|
||||||
FLO_LIQ, //< Liquid rate
|
FLO_LIQ, //< Liquid rate
|
||||||
FLO_GAS, //< Gas rate
|
FLO_GAS, //< Gas rate
|
||||||
//FLO_WG
|
//FLO_WG
|
||||||
@ -49,7 +49,7 @@ public:
|
|||||||
|
|
||||||
///Water fraction variable
|
///Water fraction variable
|
||||||
enum WFR_TYPE {
|
enum WFR_TYPE {
|
||||||
WFR_WOR, //< Water-oil ratio
|
WFR_WOR=11, //< Water-oil ratio
|
||||||
WFR_WCT, //< Water cut
|
WFR_WCT, //< Water cut
|
||||||
WFR_WGR, //< Water-gas ratio
|
WFR_WGR, //< Water-gas ratio
|
||||||
WFR_INVALID
|
WFR_INVALID
|
||||||
@ -57,7 +57,7 @@ public:
|
|||||||
|
|
||||||
///Gas fraction variable
|
///Gas fraction variable
|
||||||
enum GFR_TYPE {
|
enum GFR_TYPE {
|
||||||
GFR_GOR, //< Gas-oil ratio
|
GFR_GOR=21, //< Gas-oil ratio
|
||||||
GFR_GLR, //< Gas-liquid ratio
|
GFR_GLR, //< Gas-liquid ratio
|
||||||
GFR_OGR, //< Oil-gas ratio
|
GFR_OGR, //< Oil-gas ratio
|
||||||
GFR_INVALID
|
GFR_INVALID
|
||||||
@ -65,7 +65,7 @@ public:
|
|||||||
|
|
||||||
///Artificial lift quantity
|
///Artificial lift quantity
|
||||||
enum ALQ_TYPE {
|
enum ALQ_TYPE {
|
||||||
ALQ_GRAT, //< Lift as injection rate
|
ALQ_GRAT=31, //< Lift as injection rate
|
||||||
ALQ_IGLR, //< Injection gas-liquid ratio
|
ALQ_IGLR, //< Injection gas-liquid ratio
|
||||||
ALQ_TGLR, //< Total gas-liquid ratio
|
ALQ_TGLR, //< Total gas-liquid ratio
|
||||||
ALQ_PUMP, //< Pump rating
|
ALQ_PUMP, //< Pump rating
|
||||||
@ -102,22 +102,7 @@ public:
|
|||||||
const std::vector<double>& wfr_data,
|
const std::vector<double>& wfr_data,
|
||||||
const std::vector<double>& gfr_data,
|
const std::vector<double>& gfr_data,
|
||||||
const std::vector<double>& alq_data,
|
const std::vector<double>& alq_data,
|
||||||
array_type data
|
array_type data);
|
||||||
) :
|
|
||||||
table_num_(table_num),
|
|
||||||
datum_depth_(datum_depth),
|
|
||||||
flo_type_(flo_type),
|
|
||||||
wfr_type_(wfr_type),
|
|
||||||
gfr_type_(gfr_type),
|
|
||||||
alq_type_(alq_type),
|
|
||||||
flo_data_(flo_data),
|
|
||||||
thp_data_(thp_data),
|
|
||||||
wfr_data_(wfr_data),
|
|
||||||
gfr_data_(gfr_data),
|
|
||||||
alq_data_(alq_data),
|
|
||||||
data_(data) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor which parses a deck keyword and retrieves the relevant parts for a
|
* Constructor which parses a deck keyword and retrieves the relevant parts for a
|
||||||
@ -150,9 +135,45 @@ public:
|
|||||||
*/
|
*/
|
||||||
double bhp(const double& flo, const double& thp, const double& wfr, const double& gfr, const double& alq);
|
double bhp(const double& flo, const double& thp, const double& wfr, const double& gfr, const double& alq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Linear interpolation of bhp as a function of the input parameters given as ADBs
|
||||||
|
* @param flo Production rate of oil, gas or liquid
|
||||||
|
* @param thp Tubing head pressure
|
||||||
|
* @param wfr Water-oil ratio, water cut, or water-gas ratio
|
||||||
|
* @param gfr Gas-oil ratio, gas-liquid ratio, or oil-gas ratio
|
||||||
|
* @param alq Artificial lift or other parameter
|
||||||
|
*
|
||||||
|
* @return The bottom hole pressure, interpolated/extrapolated linearly using
|
||||||
|
* the above parameters from the values in the input table, for each entry in the
|
||||||
|
* input ADB objects.
|
||||||
|
*/
|
||||||
ADB bhp(const ADB& flo, const ADB& thp, const ADB& wfr, const ADB& gfr, const ADB& alq);
|
ADB bhp(const ADB& flo, const ADB& thp, const ADB& wfr, const ADB& gfr, const ADB& alq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the flo parameter according to the flo_type_
|
||||||
|
* @return Production rate of oil, gas or liquid.
|
||||||
|
*/
|
||||||
|
ADB getFlo(const ADB& aqua, const ADB& liquid, const ADB& vapour);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the wfr parameter according to the wfr_type_
|
||||||
|
* @return Production rate of oil, gas or liquid.
|
||||||
|
*/
|
||||||
|
ADB getWFR(const ADB& aqua, const ADB& liquid, const ADB& vapour);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the gfr parameter according to the gfr_type_
|
||||||
|
* @return Production rate of oil, gas or liquid.
|
||||||
|
*/
|
||||||
|
ADB getGFR(const ADB& aqua, const ADB& liquid, const ADB& vapour);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Debug function that runs a series of asserts to check for sanity of inputs.
|
||||||
|
* Called after constructor to check that everything looks ok.
|
||||||
|
*/
|
||||||
|
void check();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper struct for linear interpolation
|
* Helper struct for linear interpolation
|
||||||
*/
|
*/
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user