Added tests for computing the flo/wfr/gfr values based on the aqua/liquid/vapour flow rates

This commit is contained in:
André R. Brodtkorb 2015-06-22 14:54:23 +02:00 committed by babrodtk
parent 2f6e44500b
commit ccf06c2c1c
3 changed files with 458 additions and 122 deletions

View File

@ -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) {
VFPProperties::VFPProperties(int table_num,
double datum_depth,
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 //TODO: Replace with proper log message
std::cerr << "Too large value encountered in VFPPROD in [" std::cerr << "Too large value encountered in VFPPROD in ["
<< t << "," << w << "," << g << "," << a << "]=" << t << "," << w << "," << g << "," << a << "," << f << "]="
<< bhp_tht[i] << std::endl; << 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;

View File

@ -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