Add option for explicit vfp lookup for problmatic wells

This commit is contained in:
Tor Harald Sandve
2022-02-22 15:25:10 +01:00
parent b3a9253de1
commit b1b23a57de
11 changed files with 86 additions and 12 deletions

View File

@@ -227,7 +227,7 @@ namespace Opm {
{
const auto& sched_state = this->schedule()[timeStepIdx];
// update VFP properties
vfp_properties_.reset(new VFPProperties( sched_state.vfpinj(), sched_state.vfpprod()) );
vfp_properties_.reset(new VFPProperties( sched_state.vfpinj(), sched_state.vfpprod(), this->prevWellState()));
this->initializeWellProdIndCalculators();
if (sched_state.events().hasEvent(ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX)) {
this->runWellPIScaling(timeStepIdx, local_deferredLogger);

View File

@@ -345,12 +345,19 @@ VFPEvaluation bhp(const VFPProdTable& table,
const double liquid,
const double vapour,
const double thp,
const double alq)
const double alq,
const double explicit_wfr,
const double explicit_gfr,
const bool vfpexplicit)
{
//Find interpolation variables
double flo = detail::getFlo(table, aqua, liquid, vapour);
double wfr = detail::getWFR(table, aqua, liquid, vapour);
double gfr = detail::getGFR(table, aqua, liquid, vapour);
if (vfpexplicit) {
wfr = explicit_wfr;
gfr = explicit_gfr;
}
//First, find the values to interpolate between
//Recall that flo is negative in Opm, so switch sign.

View File

@@ -136,7 +136,10 @@ VFPEvaluation bhp(const VFPProdTable& table,
const double liquid,
const double vapour,
const double thp,
const double alq);
const double alq,
const double explicit_wfr,
const double explicit_gfr,
const bool vfpexplicit);
VFPEvaluation bhp(const VFPInjTable& table,
const double aqua,

View File

@@ -87,10 +87,13 @@ double VFPProdProperties::bhp(int table_id,
const double& liquid,
const double& vapour,
const double& thp_arg,
const double& alq) const {
const double& alq,
const double& explicit_wfr,
const double& explicit_gfr,
const bool expvfp) const {
const VFPProdTable& table = detail::getTable(m_tables, table_id);
detail::VFPEvaluation retval = detail::bhp(table, aqua, liquid, vapour, thp_arg, alq);
detail::VFPEvaluation retval = detail::bhp(table, aqua, liquid, vapour, thp_arg, alq, explicit_wfr,explicit_gfr, expvfp);
return retval.value;
}
@@ -145,7 +148,10 @@ EvalWell VFPProdProperties::bhp(const int table_id,
const EvalWell& liquid,
const EvalWell& vapour,
const double& thp,
const double& alq) const
const double& alq,
const double& explicit_wfr,
const double& explicit_gfr,
const bool expvfp) const
{
//Get the table
const VFPProdTable& table = detail::getTable(m_tables, table_id);
@@ -155,6 +161,10 @@ EvalWell VFPProdProperties::bhp(const int table_id,
EvalWell flo = detail::getFlo(table, aqua, liquid, vapour);
EvalWell wfr = detail::getWFR(table, aqua, liquid, vapour);
EvalWell gfr = detail::getGFR(table, aqua, liquid, vapour);
if(expvfp) {
wfr = explicit_wfr;
gfr = explicit_gfr;
}
//First, find the values to interpolate between
//Value of FLO is negative in OPM for producers, but positive in VFP table
@@ -175,7 +185,7 @@ EvalWell VFPProdProperties::bhp(const int table_id,
#define INSTANCE(...) \
template __VA_ARGS__ VFPProdProperties::bhp<__VA_ARGS__>(const int, \
const __VA_ARGS__&, const __VA_ARGS__&, const __VA_ARGS__&, \
const double&, const double&) const;
const double&, const double&, const double&, const double&, const bool) const;
INSTANCE(DenseAd::Evaluation<double, -1, 4u>)
INSTANCE(DenseAd::Evaluation<double, -1, 5u>)

View File

@@ -65,7 +65,10 @@ public:
const EvalWell& liquid,
const EvalWell& vapour,
const double& thp,
const double& alq) const;
const double& alq,
const double& wfr,
const double& gfr,
const bool expvfp) const;
/**
* Linear interpolation of bhp as a function of the input parameters
@@ -84,7 +87,10 @@ public:
const double& liquid,
const double& vapour,
const double& thp,
const double& alq) const;
const double& alq,
const double& explicit_wfr,
const double& explicit_gfr,
const bool expvfp) const;
/**
* Linear interpolation of thp as a function of the input parameters

View File

@@ -22,6 +22,8 @@
#include <opm/simulators/wells/VFPInjProperties.hpp>
#include <opm/simulators/wells/VFPProdProperties.hpp>
#include <opm/simulators/wells/WellState.hpp>
#include <opm/simulators/wells/VFPHelpers.hpp>
#include <map>
@@ -47,7 +49,9 @@ public:
*/
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& well_state)
:well_state_(well_state)
{
for (const auto& vfpinj : inj_tables)
this->m_inj.addTable( vfpinj );
@@ -70,9 +74,33 @@ public:
return &m_prod;
}
double getExplicitWFR(const int table_id, const size_t well_index) const {
const auto& rates = well_state_.well(well_index).surface_rates;
assert(rates.size() == 3);
const auto& pu = well_state_.phaseUsage();
const auto& aqua = rates[pu.phase_pos[BlackoilPhases::Aqua]];
const auto& liquid = rates[pu.phase_pos[BlackoilPhases::Liquid]];
const auto& vapour = rates[pu.phase_pos[BlackoilPhases::Vapour]];
const VFPProdTable& table = this->m_prod.getTable(table_id);
return detail::getWFR(table, aqua, liquid, vapour);
}
double getExplicitGFR(const int table_id, const size_t well_index) const {
const auto& rates = well_state_.well(well_index).surface_rates;
assert(rates.size() == 3);
const auto& pu = well_state_.phaseUsage();
const auto& aqua = rates[pu.phase_pos[BlackoilPhases::Aqua]];
const auto& liquid = rates[pu.phase_pos[BlackoilPhases::Liquid]];
const auto& vapour = rates[pu.phase_pos[BlackoilPhases::Vapour]];
const VFPProdTable& table = this->m_prod.getTable(table_id);
return detail::getGFR(table, aqua, liquid, vapour);
}
private:
VFPInjProperties m_inj;
VFPProdProperties m_prod;
const WellState& well_state_;
};

View File

@@ -766,7 +766,10 @@ namespace WellGroupHelpers
rates[BlackoilPhases::Liquid],
rates[BlackoilPhases::Vapour],
up_press,
alq);
alq,
0.0, //explicit_wfr
0.0, //explicit_gfr
false); //expvfp we dont support explicit lookup
#define EXTRA_DEBUG_NETWORK 0
#if EXTRA_DEBUG_NETWORK
std::ostringstream oss;

View File

@@ -493,7 +493,10 @@ calculateBhpFromThp(const WellState& well_state,
const auto& controls = well.productionControls(summaryState);
const double vfp_ref_depth = baseif_.vfpProperties()->getProd()->getTable(controls.vfp_table_number).getDatumDepth();
const double dp = wellhelpers::computeHydrostaticCorrection(baseif_.refDepth(), vfp_ref_depth, rho, baseif_.gravity());
return baseif_.vfpProperties()->getProd()->bhp(controls.vfp_table_number, aqua, liquid, vapour, baseif_.getTHPConstraint(summaryState), baseif_.getALQ(well_state)) - dp;
const auto& wfr = baseif_.vfpProperties()->getExplicitWFR(controls.vfp_table_number, baseif_.indexOfWell());
const auto& gfr = baseif_.vfpProperties()->getExplicitGFR(controls.vfp_table_number, baseif_.indexOfWell());
const bool vfpexp = baseif_.vfpExplicit();
return baseif_.vfpProperties()->getProd()->bhp(controls.vfp_table_number, aqua, liquid, vapour, baseif_.getTHPConstraint(summaryState), baseif_.getALQ(well_state), wfr, gfr, vfpexp) - dp;
}
else {
OPM_DEFLOG_THROW(std::logic_error, "Expected INJECTOR or PRODUCER for well " + baseif_.name(), deferred_logger);

View File

@@ -414,6 +414,11 @@ bool WellInterfaceGeneric::isOperableAndSolvable() const
return operability_status_.isOperableAndSolvable();
}
bool WellInterfaceGeneric::vfpExplicit() const
{
return operability_status_.vfpexplicit;
}
double WellInterfaceGeneric::getALQ(const WellState& well_state) const
{
return well_state.getALQ(name());

View File

@@ -88,6 +88,7 @@ public:
// whether the well is operable
bool isOperableAndSolvable() const;
bool vfpExplicit () const;
void initCompletions();
void closeCompletions(const WellTestState& wellTestState);
@@ -265,6 +266,8 @@ protected:
bool has_negative_potentials = false;
//thp limit violated but not switched
mutable bool thp_limit_violated_but_not_switched = false;
bool vfpexplicit = false;
};
OperabilityStatus operability_status_;

View File

@@ -613,6 +613,12 @@ namespace Opm
}
updateWellOperability(ebos_simulator, well_state, deferred_logger);
if (!this->operability_status_.isOperableAndSolvable()) {
this->operability_status_.vfpexplicit = true;
deferred_logger.debug("EXPLICIT_LOOKUP_VFP",
"well not operable, trying with explicit vfp lookup: " + this->name());
updateWellOperability(ebos_simulator, well_state, deferred_logger);
}
}
template<typename TypeTag>