mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
shut/stop unsolvable wells
This commit is contained in:
parent
2dae87fb74
commit
b5e29684f2
@ -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");
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user