Merge pull request #3569 from totto82/operInj

check operability injectors
This commit is contained in:
Tor Harald Sandve 2021-10-18 08:50:50 +02:00 committed by GitHub
commit d925e74b76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 62 deletions

View File

@ -316,10 +316,10 @@ namespace Opm
double maxPerfPress(const Simulator& ebos_simulator) const;
// check whether the well is operable under BHP limit with current reservoir condition
virtual void checkOperabilityUnderBHPLimitProducer(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger) override;
virtual void checkOperabilityUnderBHPLimit(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger) override;
// check whether the well is operable under THP limit with current reservoir condition
virtual void checkOperabilityUnderTHPLimitProducer(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger) override;
virtual void checkOperabilityUnderTHPLimit(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger) override;
// updating the inflow based on the current reservoir condition
virtual void updateIPR(const Simulator& ebos_simulator, DeferredLogger& deferred_logger) const override;

View File

@ -1128,7 +1128,7 @@ namespace Opm
template<typename TypeTag>
void
MultisegmentWell<TypeTag>::
checkOperabilityUnderBHPLimitProducer(const WellState& /*well_state*/, const Simulator& ebos_simulator, DeferredLogger& deferred_logger)
checkOperabilityUnderBHPLimit(const WellState& /*well_state*/, const Simulator& ebos_simulator, DeferredLogger& deferred_logger)
{
const auto& summaryState = ebos_simulator.vanguard().summaryState();
const double bhp_limit = Base::mostStrictBhpFromBhpLimits(summaryState);
@ -1139,11 +1139,11 @@ namespace Opm
// if the BHP limit is not defaulted or the well does not have a THP limit
// we need to check the BHP limit
double temp = 0;
double ipr_rate = 0;
for (int p = 0; p < this->number_of_phases_; ++p) {
temp += this->ipr_a_[p] - this->ipr_b_[p] * bhp_limit;
ipr_rate += this->ipr_a_[p] - this->ipr_b_[p] * bhp_limit;
}
if (temp < 0.) {
if ( (this->isProducer() && ipr_rate < 0.) || (this->isInjector() && ipr_rate > 0.) ) {
this->operability_status_.operable_under_only_bhp_limit = false;
}
@ -1156,10 +1156,8 @@ namespace Opm
computeWellRatesWithBhp(ebos_simulator, bhp_limit, well_rates_bhp_limit, deferred_logger);
const double thp = this->calculateThpFromBhp(well_rates_bhp_limit, bhp_limit, getRefDensity(), deferred_logger);
const double thp_limit = this->getTHPConstraint(summaryState);
if (thp < thp_limit) {
if ( (this->isProducer() && thp < thp_limit) || (this->isInjector() && thp > thp_limit) ) {
this->operability_status_.obey_thp_limit_under_bhp_limit = false;
}
}
@ -1185,12 +1183,6 @@ namespace Opm
{
// TODO: not handling solvent related here for now
// TODO: it only handles the producers for now
// the formular for the injectors are not formulated yet
if (this->isInjector()) {
return;
}
// initialize all the values to be zero to begin with
std::fill(this->ipr_a_.begin(), this->ipr_a_.end(), 0.);
std::fill(this->ipr_b_.begin(), this->ipr_b_.end(), 0.);
@ -1234,12 +1226,10 @@ namespace Opm
const double h_perf = cell_perf_press_diff + perf_seg_press_diff + seg_bhp_press_diff;
const double pressure_diff = pressure_cell - h_perf;
// Let us add a check, since the pressure is calculated based on zero value BHP
// it should not be negative anyway. If it is negative, we might need to re-formulate
// to taking into consideration the crossflow here.
if (pressure_diff <= 0.) {
deferred_logger.warning("NON_POSITIVE_DRAWDOWN_IPR",
"non-positive drawdown found when updateIPR for well " + this->name());
// do not take into consideration the crossflow here.
if ( (this->isProducer() && pressure_diff < 0.) || (this->isInjector() && pressure_diff > 0.) ) {
deferred_logger.debug("CROSSFLOW_IPR",
"cross flow found when updateIPR for well " + this->name());
}
// the well index associated with the connection
@ -1288,10 +1278,11 @@ namespace Opm
template<typename TypeTag>
void
MultisegmentWell<TypeTag>::
checkOperabilityUnderTHPLimitProducer(const Simulator& ebos_simulator, const WellState& /*well_state*/, DeferredLogger& deferred_logger)
checkOperabilityUnderTHPLimit(const Simulator& ebos_simulator, const WellState& /*well_state*/, DeferredLogger& deferred_logger)
{
const auto& summaryState = ebos_simulator.vanguard().summaryState();
const auto obtain_bhp = computeBhpAtThpLimitProd(ebos_simulator, summaryState, deferred_logger);
const auto obtain_bhp = this->isProducer() ? computeBhpAtThpLimitProd(ebos_simulator, summaryState, deferred_logger)
: computeBhpAtThpLimitInj(ebos_simulator, summaryState, deferred_logger);
if (obtain_bhp) {
this->operability_status_.can_obtain_bhp_with_thp_limit = true;
@ -1300,13 +1291,20 @@ namespace Opm
this->operability_status_.obey_bhp_limit_with_thp_limit = (*obtain_bhp >= bhp_limit);
const double thp_limit = this->getTHPConstraint(summaryState);
if (*obtain_bhp < thp_limit) {
if (this->isProducer() && *obtain_bhp < thp_limit) {
const std::string msg = " obtained bhp " + std::to_string(unit::convert::to(*obtain_bhp, unit::barsa))
+ " bars is SMALLER than thp limit "
+ std::to_string(unit::convert::to(thp_limit, unit::barsa))
+ " bars as a producer for well " + this->name();
deferred_logger.debug(msg);
}
else if (this->isInjector() && *obtain_bhp > thp_limit) {
const std::string msg = " obtained bhp " + std::to_string(unit::convert::to(*obtain_bhp, unit::barsa))
+ " bars is LARGER than thp limit "
+ std::to_string(unit::convert::to(thp_limit, unit::barsa))
+ " bars as a injector for well " + this->name();
deferred_logger.debug(msg);
}
} else {
// Shutting wells that can not find bhp value from thp
// when under THP control

View File

@ -394,10 +394,10 @@ namespace Opm
DeferredLogger& deferred_logger) const;
// check whether the well is operable under BHP limit with current reservoir condition
virtual void checkOperabilityUnderBHPLimitProducer(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger) override;
virtual void checkOperabilityUnderBHPLimit(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger) override;
// check whether the well is operable under THP limit with current reservoir condition
virtual void checkOperabilityUnderTHPLimitProducer(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger) override;
virtual void checkOperabilityUnderTHPLimit(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger) override;
// updating the inflow based on the current reservoir condition
virtual void updateIPR(const Simulator& ebos_simulator, DeferredLogger& deferred_logger) const override;

View File

@ -952,12 +952,6 @@ namespace Opm
{
// TODO: not handling solvent related here for now
// TODO: it only handles the producers for now
// the formular for the injectors are not formulated yet
if (this->isInjector()) {
return;
}
// initialize all the values to be zero to begin with
std::fill(this->ipr_a_.begin(), this->ipr_a_.end(), 0.);
std::fill(this->ipr_b_.begin(), this->ipr_b_.end(), 0.);
@ -990,9 +984,9 @@ namespace Opm
// Let us add a check, since the pressure is calculated based on zero value BHP
// it should not be negative anyway. If it is negative, we might need to re-formulate
// to taking into consideration the crossflow here.
if (pressure_diff <= 0.) {
deferred_logger.warning("NON_POSITIVE_DRAWDOWN_IPR",
"non-positive drawdown found when updateIPR for well " + name());
if ( (this->isProducer() && pressure_diff < 0.) || (this->isInjector() && pressure_diff > 0.) ) {
deferred_logger.debug("CROSSFLOW_IPR",
"cross flow found when updateIPR for well " + name());
}
// the well index associated with the connection
@ -1043,7 +1037,7 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
checkOperabilityUnderBHPLimitProducer(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger)
checkOperabilityUnderBHPLimit(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger)
{
const auto& summaryState = ebos_simulator.vanguard().summaryState();
const double bhp_limit = this->mostStrictBhpFromBhpLimits(summaryState);
@ -1055,8 +1049,8 @@ namespace Opm
// we need to check the BHP limit
for (int p = 0; p < this->number_of_phases_; ++p) {
const double temp = this->ipr_a_[p] - this->ipr_b_[p] * bhp_limit;
if (temp < 0.) {
const double ipr_rate = this->ipr_a_[p] - this->ipr_b_[p] * bhp_limit;
if ( (this->isProducer() && ipr_rate < 0.) || (this->isInjector() && ipr_rate > 0.) ) {
this->operability_status_.operable_under_only_bhp_limit = false;
break;
}
@ -1072,8 +1066,7 @@ namespace Opm
const double thp = this->calculateThpFromBhp(well_state, well_rates_bhp_limit, bhp_limit, deferred_logger);
const double thp_limit = this->getTHPConstraint(summaryState);
if (thp < thp_limit) {
if ( (this->isProducer() && thp < thp_limit) || (this->isInjector() && thp > thp_limit) ) {
this->operability_status_.obey_thp_limit_under_bhp_limit = false;
}
}
@ -1097,10 +1090,11 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
checkOperabilityUnderTHPLimitProducer(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger)
checkOperabilityUnderTHPLimit(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger)
{
const auto& summaryState = ebos_simulator.vanguard().summaryState();
const auto obtain_bhp = computeBhpAtThpLimitProd(well_state, ebos_simulator, summaryState, deferred_logger);
const auto obtain_bhp = this->isProducer() ? computeBhpAtThpLimitProd(well_state, ebos_simulator, summaryState, deferred_logger)
: computeBhpAtThpLimitInj(ebos_simulator, summaryState, deferred_logger);
if (obtain_bhp) {
this->operability_status_.can_obtain_bhp_with_thp_limit = true;
@ -1109,13 +1103,20 @@ namespace Opm
this->operability_status_.obey_bhp_limit_with_thp_limit = (*obtain_bhp >= bhp_limit);
const double thp_limit = this->getTHPConstraint(summaryState);
if (*obtain_bhp < thp_limit) {
if (this->isProducer() && *obtain_bhp < thp_limit) {
const std::string msg = " obtained bhp " + std::to_string(unit::convert::to(*obtain_bhp, unit::barsa))
+ " bars is SMALLER than thp limit "
+ std::to_string(unit::convert::to(thp_limit, unit::barsa))
+ " bars as a producer for well " + name();
deferred_logger.debug(msg);
}
else if (this->isInjector() && *obtain_bhp > thp_limit) {
const std::string msg = " obtained bhp " + std::to_string(unit::convert::to(*obtain_bhp, unit::barsa))
+ " bars is LARGER than thp limit "
+ std::to_string(unit::convert::to(thp_limit, unit::barsa))
+ " bars as a injector for well " + name();
deferred_logger.debug(msg);
}
} else {
this->operability_status_.can_obtain_bhp_with_thp_limit = false;
this->operability_status_.obey_bhp_limit_with_thp_limit = false;

View File

@ -299,10 +299,10 @@ protected:
std::vector<double> initialWellRateFractions(const Simulator& ebosSimulator, const WellState& well_state) const;
// check whether the well is operable under BHP limit with current reservoir condition
virtual void checkOperabilityUnderBHPLimitProducer(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger) =0;
virtual void checkOperabilityUnderBHPLimit(const WellState& well_state, const Simulator& ebos_simulator, DeferredLogger& deferred_logger) =0;
// check whether the well is operable under THP limit with current reservoir condition
virtual void checkOperabilityUnderTHPLimitProducer(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger) =0;
virtual void checkOperabilityUnderTHPLimit(const Simulator& ebos_simulator, const WellState& well_state, DeferredLogger& deferred_logger) =0;
virtual void updateIPR(const Simulator& ebos_simulator, DeferredLogger& deferred_logger) const=0;

View File

@ -812,11 +812,6 @@ updateWellTestState(const SingleWellState& ws,
DeferredLogger& deferred_logger) const
{
// currently, we only updateWellTestState for producers
if (this->isInjector()) {
return;
}
// Based on current understanding, only under prediction mode, we need to shut well due to various
// reasons or limits. With more knowlage or testing cases later, this might need to be corrected.
if (!underPredictionMode() ) {
@ -897,7 +892,6 @@ checkMaxRatioLimitWell(const SingleWellState& ws,
}
const double well_ratio = ratioFunc(well_rates, phaseUsage());
return (well_ratio > max_ratio_limit);
}

View File

@ -551,11 +551,6 @@ namespace Opm
return;
}
// focusing on PRODUCER for now
if (this->isInjector()) {
return;
}
if (!this->underPredictionMode() ) {
return;
}
@ -575,7 +570,7 @@ namespace Opm
{
bool shut_unsolvable_wells = param_.shut_unsolvable_wells_;
// the well operability system currently works only for producers in prediction mode
return shut_unsolvable_wells && !this->isInjector() && this->underPredictionMode();
return shut_unsolvable_wells && this->underPredictionMode();
}
@ -591,16 +586,20 @@ namespace Opm
{
this->operability_status_.resetOperability();
auto current_control = well_state.well(this->index_of_well_).production_cmode;
bool thp_controled = this->isInjector() ? well_state.well(this->index_of_well_).injection_cmode == Well::InjectorCMode::THP:
well_state.well(this->index_of_well_).production_cmode == Well::ProducerCMode::THP;
bool bhp_controled = this->isInjector() ? well_state.well(this->index_of_well_).injection_cmode == Well::InjectorCMode::BHP:
well_state.well(this->index_of_well_).production_cmode == Well::ProducerCMode::BHP;
// Operability checking is not free
// Only check wells under BHP and THP control
if(current_control == Well::ProducerCMode::BHP || current_control == Well::ProducerCMode::THP) {
if(bhp_controled || thp_controled) {
updateIPR(ebos_simulator, deferred_logger);
checkOperabilityUnderBHPLimitProducer(well_state, ebos_simulator, deferred_logger);
checkOperabilityUnderBHPLimit(well_state, ebos_simulator, deferred_logger);
}
// we do some extra checking for wells under THP control.
if (current_control == Well::ProducerCMode::THP) {
checkOperabilityUnderTHPLimitProducer(ebos_simulator, well_state, deferred_logger);
if (thp_controled) {
checkOperabilityUnderTHPLimit(ebos_simulator, well_state, deferred_logger);
}
}