shut/stop unsolvable wells

This commit is contained in:
Tor Harald Sandve 2021-04-16 14:44:14 +02:00
parent 2dae87fb74
commit b5e29684f2
5 changed files with 75 additions and 25 deletions

View File

@ -142,6 +142,10 @@ struct MaxNewtonIterationsWithInnerWellIterations {
using type = UndefinedProperty; using type = UndefinedProperty;
}; };
template<class TypeTag, class MyTypeTag> template<class TypeTag, class MyTypeTag>
struct ShutUnsolvableWells {
using type = UndefinedProperty;
};
template<class TypeTag, class MyTypeTag>
struct MaxInnerIterWells { struct MaxInnerIterWells {
using type = UndefinedProperty; using type = UndefinedProperty;
}; };
@ -251,6 +255,10 @@ struct MaxInnerIterWells<TypeTag, TTag::FlowModelParameters> {
static constexpr int value = 50; static constexpr int value = 50;
}; };
template<class TypeTag> template<class TypeTag>
struct ShutUnsolvableWells<TypeTag, TTag::FlowModelParameters> {
static constexpr bool value = false;
};
template<class TypeTag>
struct AlternativeWellRateInit<TypeTag, TTag::FlowModelParameters> { struct AlternativeWellRateInit<TypeTag, TTag::FlowModelParameters> {
static constexpr bool value = true; static constexpr bool value = true;
}; };
@ -341,6 +349,9 @@ namespace Opm
/// Maximum newton iterations with inner well iterations /// Maximum newton iterations with inner well iterations
int max_niter_inner_well_iter_; int max_niter_inner_well_iter_;
/// Whether to shut unsolvable well
bool shut_unsolvable_wells_;
/// Maximum inner iteration number for standard wells /// Maximum inner iteration number for standard wells
int max_inner_iter_wells_; int max_inner_iter_wells_;
@ -398,6 +409,7 @@ namespace Opm
strict_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, StrictInnerIterMsWells); strict_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, StrictInnerIterMsWells);
regularization_factor_ms_wells_ = EWOMS_GET_PARAM(TypeTag, Scalar, RegularizationFactorMsw); regularization_factor_ms_wells_ = EWOMS_GET_PARAM(TypeTag, Scalar, RegularizationFactorMsw);
max_niter_inner_well_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxNewtonIterationsWithInnerWellIterations); max_niter_inner_well_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxNewtonIterationsWithInnerWellIterations);
shut_unsolvable_wells_ = EWOMS_GET_PARAM(TypeTag, bool, ShutUnsolvableWells);
max_inner_iter_wells_ = EWOMS_GET_PARAM(TypeTag, int, MaxInnerIterWells); max_inner_iter_wells_ = EWOMS_GET_PARAM(TypeTag, int, MaxInnerIterWells);
maxSinglePrecisionTimeStep_ = EWOMS_GET_PARAM(TypeTag, Scalar, MaxSinglePrecisionDays) *24*60*60; maxSinglePrecisionTimeStep_ = EWOMS_GET_PARAM(TypeTag, Scalar, MaxSinglePrecisionDays) *24*60*60;
max_strict_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxStrictIter); max_strict_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxStrictIter);
@ -430,6 +442,7 @@ namespace Opm
EWOMS_REGISTER_PARAM(TypeTag, int, MaxInnerIterMsWells, "Maximum number of inner iterations for multi-segment wells"); EWOMS_REGISTER_PARAM(TypeTag, int, MaxInnerIterMsWells, "Maximum number of inner iterations for multi-segment wells");
EWOMS_REGISTER_PARAM(TypeTag, int, StrictInnerIterMsWells, "Number of inner iterations for multi-segment wells with strict tolerance"); EWOMS_REGISTER_PARAM(TypeTag, int, StrictInnerIterMsWells, "Number of inner iterations for multi-segment wells with strict tolerance");
EWOMS_REGISTER_PARAM(TypeTag, int, MaxNewtonIterationsWithInnerWellIterations, "Maximum newton iterations with inner well iterations"); EWOMS_REGISTER_PARAM(TypeTag, int, MaxNewtonIterationsWithInnerWellIterations, "Maximum newton iterations with inner well iterations");
EWOMS_REGISTER_PARAM(TypeTag, bool, ShutUnsolvableWells, "Shut unsolvable wells");
EWOMS_REGISTER_PARAM(TypeTag, int, MaxInnerIterWells, "Maximum number of inner iterations for standard wells"); EWOMS_REGISTER_PARAM(TypeTag, int, MaxInnerIterWells, "Maximum number of inner iterations for standard wells");
EWOMS_REGISTER_PARAM(TypeTag, bool, AlternativeWellRateInit, "Use alternative well rate initialization procedure"); EWOMS_REGISTER_PARAM(TypeTag, bool, AlternativeWellRateInit, "Use alternative well rate initialization procedure");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, RegularizationFactorMsw, "Regularization factor for ms wells"); EWOMS_REGISTER_PARAM(TypeTag, Scalar, RegularizationFactorMsw, "Regularization factor for ms wells");

View File

@ -1262,6 +1262,7 @@ namespace Opm {
std::string exc_msg; std::string exc_msg;
try { try {
for (const auto& well : well_container_) { for (const auto& well : well_container_) {
const bool old_well_operable = well->isOperable();
well->checkWellOperability(ebosSimulator_, this->wellState(), deferred_logger); well->checkWellOperability(ebosSimulator_, this->wellState(), deferred_logger);
if (!well->isOperable() ) continue; if (!well->isOperable() ) continue;
@ -1279,6 +1280,22 @@ namespace Opm {
well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), deferred_logger); well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), deferred_logger);
} }
const bool well_operable = well->isOperable();
if (!well_operable && old_well_operable) {
const Well& well_ecl = getWellEcl(well->name());
if (well_ecl.getAutomaticShutIn()) {
deferred_logger.info(" well " + well->name() + " gets SHUT at the beginning of the time step ");
} else {
if (!well->wellIsStopped()) {
deferred_logger.info(" well " + well->name() + " gets STOPPED at the beginning of the time step ");
well->stopWell();
}
}
} else if (well_operable && !old_well_operable) {
deferred_logger.info(" well " + well->name() + " gets REVIVED at the beginning of the time step ");
well->openWell();
}
} // end of for (const auto& well : well_container_) } // end of for (const auto& well : well_container_)
updatePrimaryVariables(deferred_logger); updatePrimaryVariables(deferred_logger);
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {

View File

@ -340,6 +340,8 @@ protected:
void solveWellForTesting(const Simulator& ebosSimulator, WellState& well_state, const GroupState& group_state, void solveWellForTesting(const Simulator& ebosSimulator, WellState& well_state, const GroupState& group_state,
DeferredLogger& deferred_logger); DeferredLogger& deferred_logger);
bool shutUnsolvableWells() const;
}; };
} }

View File

@ -177,7 +177,7 @@ protected:
// definition of the struct OperabilityStatus // definition of the struct OperabilityStatus
struct OperabilityStatus { struct OperabilityStatus {
bool isOperable() const { bool isOperable() const {
if (!operable_under_only_bhp_limit) { if (!operable_under_only_bhp_limit || !solvable) {
return false; return false;
} else { } else {
return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) ); return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) );
@ -197,6 +197,7 @@ protected:
obey_thp_limit_under_bhp_limit = true; obey_thp_limit_under_bhp_limit = true;
can_obtain_bhp_with_thp_limit = true; can_obtain_bhp_with_thp_limit = true;
obey_bhp_limit_with_thp_limit = true; obey_bhp_limit_with_thp_limit = true;
solvable = true;
} }
// whether the well can be operated under bhp limit // whether the well can be operated under bhp limit
@ -210,6 +211,8 @@ protected:
bool can_obtain_bhp_with_thp_limit = true; bool can_obtain_bhp_with_thp_limit = true;
// whether the well obey bhp limit when operated under thp limit // whether the well obey bhp limit when operated under thp limit
bool obey_bhp_limit_with_thp_limit = true; bool obey_bhp_limit_with_thp_limit = true;
// the well is solveable
bool solvable = true;
}; };
OperabilityStatus operability_status_; OperabilityStatus operability_status_;

View File

@ -342,12 +342,14 @@ namespace Opm
const WellState well_state0 = well_state; const WellState well_state0 = well_state;
const double dt = ebosSimulator.timeStepSize(); const double dt = ebosSimulator.timeStepSize();
const bool converged = iterateWellEquations(ebosSimulator, dt, well_state, group_state, deferred_logger); const bool converged = iterateWellEquations(ebosSimulator, dt, well_state, group_state, deferred_logger);
if (converged) { if (!converged) {
deferred_logger.debug("Compute initial well solution for well " + this->name() + ". Converged");
} else {
const int max_iter = param_.max_welleq_iter_; const int max_iter = param_.max_welleq_iter_;
deferred_logger.debug("Compute initial well solution for well " + this->name() + ". Failed to converge in " deferred_logger.debug("Compute initial well solution for well " + this->name() + ". Failed to converge in "
+ std::to_string(max_iter) + " iterations"); + std::to_string(max_iter) + " iterations");
// the well operability system currently works only for producers in prediction mode
if (this->shutUnsolvableWells())
this->operability_status_.solvable = false;
well_state = well_state0; well_state = well_state0;
} }
} }
@ -363,13 +365,35 @@ namespace Opm
const GroupState& group_state, const GroupState& group_state,
DeferredLogger& deferred_logger) DeferredLogger& deferred_logger)
{ {
const bool old_well_operable = this->operability_status_.isOperable();
checkWellOperability(ebosSimulator, well_state, deferred_logger); checkWellOperability(ebosSimulator, well_state, deferred_logger);
// only use inner well iterations for the first newton iterations. // only use inner well iterations for the first newton iterations.
const int iteration_idx = ebosSimulator.model().newtonMethod().numIterations(); const int iteration_idx = ebosSimulator.model().newtonMethod().numIterations();
if (iteration_idx < param_.max_niter_inner_well_iter_) { bool converged = true;
this->iterateWellEquations(ebosSimulator, dt, well_state, group_state, deferred_logger); if (iteration_idx < param_.max_niter_inner_well_iter_)
converged = this->iterateWellEquations(ebosSimulator, dt, well_state, group_state, deferred_logger);
// unsolvable wells are treated as not operable and will not be solved for in this iteration.
if (!converged) {
if (this->shutUnsolvableWells())
this->operability_status_.solvable = false;
}
const bool well_operable = this->operability_status_.isOperable();
if (!well_operable && old_well_operable) {
if (this->well_ecl_.getAutomaticShutIn()) {
deferred_logger.info(" well " + this->name() + " gets SHUT during iteration ");
} else {
if (!this->wellIsStopped()) {
deferred_logger.info(" well " + this->name() + " gets STOPPED during iteration ");
this->stopWell();
changed_to_stopped_this_step_ = true;
}
}
} else if (well_operable && !old_well_operable) {
deferred_logger.info(" well " + this->name() + " gets REVIVED during iteration ");
this->openWell();
changed_to_stopped_this_step_ = false;
} }
const auto& summary_state = ebosSimulator.vanguard().summaryState(); const auto& summary_state = ebosSimulator.vanguard().summaryState();
@ -498,27 +522,18 @@ namespace Opm
return; return;
} }
const bool old_well_operable = this->operability_status_.isOperable();
updateWellOperability(ebos_simulator, well_state, deferred_logger); updateWellOperability(ebos_simulator, well_state, deferred_logger);
}
const bool well_operable = this->operability_status_.isOperable();
if (!well_operable && old_well_operable) { template<typename TypeTag>
if (this->well_ecl_.getAutomaticShutIn()) { bool
deferred_logger.info(" well " + this->name() + " gets SHUT during iteration "); WellInterface<TypeTag>::
} else { shutUnsolvableWells() const
if (!this->wellIsStopped()) { {
deferred_logger.info(" well " + this->name() + " gets STOPPED during iteration "); bool shut_unsolvable_wells = param_.shut_unsolvable_wells_;
this->stopWell(); // the well operability system currently works only for producers in prediction mode
changed_to_stopped_this_step_ = true; return shut_unsolvable_wells && !this->isInjector() && this->underPredictionMode();
}
}
} else if (well_operable && !old_well_operable) {
deferred_logger.info(" well " + this->name() + " gets REVIVED during iteration ");
this->openWell();
changed_to_stopped_this_step_ = false;
}
} }