mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Add option for explicit vfp lookup for problmatic wells
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user