mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Mark wells with negative and trivial potentials as not operable
The simulator will try to compute potentials at every iterations to try to reopen the well.
This commit is contained in:
@@ -2374,4 +2374,20 @@ runWellPIScaling(const int timeStepIdx,
|
|||||||
this->last_run_wellpi_ = timeStepIdx;
|
this->last_run_wellpi_ = timeStepIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BlackoilWellModelGeneric::
|
||||||
|
guideRateUpdateIsNeeded() const {
|
||||||
|
int update = 0;
|
||||||
|
for (const auto& well : well_container_generic_) {
|
||||||
|
if (well->changedToOpenThisStep()) {
|
||||||
|
update = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update = comm_.max(update);
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -396,6 +396,8 @@ protected:
|
|||||||
const SummaryConfig& summaryConfig,
|
const SummaryConfig& summaryConfig,
|
||||||
DeferredLogger& deferred_logger);
|
DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
|
bool guideRateUpdateIsNeeded() const;
|
||||||
|
|
||||||
// create the well container
|
// create the well container
|
||||||
virtual void createWellContainer(const int time_step) = 0;
|
virtual void createWellContainer(const int time_step) = 0;
|
||||||
virtual void initWellContainer() = 0;
|
virtual void initWellContainer() = 0;
|
||||||
|
|||||||
@@ -840,6 +840,18 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "assemble() failed: ",
|
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "assemble() failed: ",
|
||||||
terminal_output_, grid().comm());
|
terminal_output_, grid().comm());
|
||||||
|
|
||||||
|
//update guide rates
|
||||||
|
if (guideRateUpdateIsNeeded()) {
|
||||||
|
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
||||||
|
const double simulationTime = ebosSimulator_.time();
|
||||||
|
const auto& comm = ebosSimulator_.vanguard().grid().comm();
|
||||||
|
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
|
||||||
|
std::vector<double> pot(numPhases(), 0.0);
|
||||||
|
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
|
||||||
|
WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime,
|
||||||
|
this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger);
|
||||||
|
}
|
||||||
last_report_.converged = true;
|
last_report_.converged = true;
|
||||||
last_report_.assemble_time_well += perfTimer.stop();
|
last_report_.assemble_time_well += perfTimer.stop();
|
||||||
}
|
}
|
||||||
@@ -1343,7 +1355,8 @@ namespace Opm {
|
|||||||
// and updated only if sucessfull. i.e. the potentials are zero for exceptions
|
// and updated only if sucessfull. i.e. the potentials are zero for exceptions
|
||||||
auto& ws = this->wellState().well(well->indexOfWell());
|
auto& ws = this->wellState().well(well->indexOfWell());
|
||||||
for (int p = 0; p < np; ++p) {
|
for (int p = 0; p < np; ++p) {
|
||||||
ws.well_potentials[p] = std::abs(potentials[p]);
|
// make sure the potentials are positive
|
||||||
|
ws.well_potentials[p] = std::max(0.0, potentials[p]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1424,8 +1437,13 @@ namespace Opm {
|
|||||||
events.clearEvent(WellState::event_mask);
|
events.clearEvent(WellState::event_mask);
|
||||||
}
|
}
|
||||||
// solve the well equation initially to improve the initial solution of the well model
|
// solve the well equation initially to improve the initial solution of the well model
|
||||||
if (param_.solve_welleq_initially_) {
|
if (param_.solve_welleq_initially_ && well->isOperableAndSolvable()) {
|
||||||
well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), deferred_logger);
|
try {
|
||||||
|
well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), deferred_logger);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
const std::string msg = "Compute initial well solution for " + well->name() + " initially failed. Continue with the privious rates";
|
||||||
|
deferred_logger.warning("WELL_INITIAL_SOLVE_FAILED", msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updatePrimaryVariables(deferred_logger);
|
updatePrimaryVariables(deferred_logger);
|
||||||
|
|||||||
@@ -112,6 +112,11 @@ computeWellRates_(
|
|||||||
-potentials[this->water_pos_]);
|
-potentials[this->water_pos_]);
|
||||||
displayDebugMessage_(msg);
|
displayDebugMessage_(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t phase = 0; phase < potentials.size(); ++phase){
|
||||||
|
// make sure the potentials are negative
|
||||||
|
potentials[phase] = std::min(0.0, potentials[phase]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ namespace Opm
|
|||||||
if (this->wellIsStopped()) {
|
if (this->wellIsStopped()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this->operability_status_.has_non_positive_potentials = false;
|
||||||
|
|
||||||
// If the well is pressure controlled the potential equals the rate.
|
// If the well is pressure controlled the potential equals the rate.
|
||||||
bool thp_controlled_well = false;
|
bool thp_controlled_well = false;
|
||||||
@@ -285,9 +286,20 @@ namespace Opm
|
|||||||
// if the rates are trivial we are most probably looking at the newly
|
// if the rates are trivial we are most probably looking at the newly
|
||||||
// opened well and we therefore make the affort of computing the potentials anyway.
|
// opened well and we therefore make the affort of computing the potentials anyway.
|
||||||
if (std::abs(total_rate) > 0) {
|
if (std::abs(total_rate) > 0) {
|
||||||
|
const double sign = this->isInjector() ? 1.0:-1.0;
|
||||||
|
double total_potential = 0.0;
|
||||||
for (int phase = 0; phase < np; ++phase){
|
for (int phase = 0; phase < np; ++phase){
|
||||||
well_potentials[phase] = ws.surface_rates[phase];
|
well_potentials[phase] = sign * ws.surface_rates[phase];
|
||||||
|
total_potential += well_potentials[phase];
|
||||||
}
|
}
|
||||||
|
if (total_potential <= 0.0) {
|
||||||
|
// wells with trivial or non-positive potentials
|
||||||
|
// are not operable
|
||||||
|
this->operability_status_.has_non_positive_potentials = true;
|
||||||
|
const std::string msg = std::string("well ") + this->name() + std::string(": has non positive potentials and is not operable");
|
||||||
|
deferred_logger.info(msg);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,6 +314,20 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
deferred_logger.debug("Cost in iterations of finding well potential for well "
|
deferred_logger.debug("Cost in iterations of finding well potential for well "
|
||||||
+ this->name() + ": " + std::to_string(debug_cost_counter_));
|
+ this->name() + ": " + std::to_string(debug_cost_counter_));
|
||||||
|
|
||||||
|
const double sign = this->isInjector() ? 1.0:-1.0;
|
||||||
|
double total_potential = 0.0;
|
||||||
|
for (int phase = 0; phase < np; ++phase){
|
||||||
|
well_potentials[phase] *= sign;
|
||||||
|
total_potential += well_potentials[phase];
|
||||||
|
}
|
||||||
|
if (total_potential <= 0.0) {
|
||||||
|
// wells with trivial or non-positive potentials
|
||||||
|
// are not operable
|
||||||
|
this->operability_status_.has_non_positive_potentials = true;
|
||||||
|
const std::string msg = std::string("well ") + this->name() + std::string(": has non positive potentials is not operable");
|
||||||
|
deferred_logger.info(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1868,6 +1868,7 @@ namespace Opm
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->operability_status_.has_non_positive_potentials = false;
|
||||||
// If the well is pressure controlled the potential equals the rate.
|
// If the well is pressure controlled the potential equals the rate.
|
||||||
bool thp_controlled_well = false;
|
bool thp_controlled_well = false;
|
||||||
bool bhp_controlled_well = false;
|
bool bhp_controlled_well = false;
|
||||||
@@ -1899,8 +1900,18 @@ namespace Opm
|
|||||||
// if the rates are trivial we are most probably looking at the newly
|
// if the rates are trivial we are most probably looking at the newly
|
||||||
// opened well and we therefore make the affort of computing the potentials anyway.
|
// opened well and we therefore make the affort of computing the potentials anyway.
|
||||||
if (std::abs(total_rate) > 0) {
|
if (std::abs(total_rate) > 0) {
|
||||||
|
const double sign = this->isInjector() ? 1.0:-1.0;
|
||||||
|
double total_potential = 0.0;
|
||||||
for (int phase = 0; phase < np; ++phase){
|
for (int phase = 0; phase < np; ++phase){
|
||||||
well_potentials[phase] = ws.surface_rates[phase];
|
well_potentials[phase] = sign * ws.surface_rates[phase];
|
||||||
|
total_potential += well_potentials[phase];
|
||||||
|
}
|
||||||
|
if (total_potential <= 0.0) {
|
||||||
|
// wells with trivial or non-positive potentials
|
||||||
|
// are not operable
|
||||||
|
this->operability_status_.has_non_positive_potentials = true;
|
||||||
|
const std::string msg = std::string("well ") + this->name() + std::string(": has non positive potentials and is not operable");
|
||||||
|
deferred_logger.info(msg);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1917,6 +1928,20 @@ namespace Opm
|
|||||||
// the well has a THP related constraint
|
// the well has a THP related constraint
|
||||||
well_potentials = computeWellPotentialWithTHP(ebosSimulator, deferred_logger, well_state);
|
well_potentials = computeWellPotentialWithTHP(ebosSimulator, deferred_logger, well_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const double sign = this->isInjector() ? 1.0:-1.0;
|
||||||
|
double total_potential = 0.0;
|
||||||
|
for (int phase = 0; phase < np; ++phase){
|
||||||
|
well_potentials[phase] *= sign;
|
||||||
|
total_potential += well_potentials[phase];
|
||||||
|
}
|
||||||
|
if (total_potential <= 0.0) {
|
||||||
|
// wells with trivial or non-positive potentials
|
||||||
|
// are not operable
|
||||||
|
this->operability_status_.has_non_positive_potentials = true;
|
||||||
|
const std::string msg = std::string("well ") + this->name() + std::string(": has non positive potentials and is not operable");
|
||||||
|
deferred_logger.info(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -174,6 +174,9 @@ public:
|
|||||||
|
|
||||||
void reportWellSwitching(const SingleWellState& ws, DeferredLogger& deferred_logger) const;
|
void reportWellSwitching(const SingleWellState& ws, DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
|
bool changedToOpenThisStep() const {
|
||||||
|
return this->changed_to_open_this_step_;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
bool getAllowCrossFlow() const;
|
bool getAllowCrossFlow() const;
|
||||||
double mostStrictBhpFromBhpLimits(const SummaryState& summaryState) const;
|
double mostStrictBhpFromBhpLimits(const SummaryState& summaryState) const;
|
||||||
@@ -186,7 +189,7 @@ protected:
|
|||||||
// definition of the struct OperabilityStatus
|
// definition of the struct OperabilityStatus
|
||||||
struct OperabilityStatus {
|
struct OperabilityStatus {
|
||||||
bool isOperableAndSolvable() const {
|
bool isOperableAndSolvable() const {
|
||||||
if (!operable_under_only_bhp_limit || !solvable) {
|
if (!operable_under_only_bhp_limit || !solvable || has_non_positive_potentials) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) );
|
return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) );
|
||||||
@@ -221,6 +224,8 @@ protected:
|
|||||||
bool obey_bhp_limit_with_thp_limit = true;
|
bool obey_bhp_limit_with_thp_limit = true;
|
||||||
// the well is solveable
|
// the well is solveable
|
||||||
bool solvable = true;
|
bool solvable = true;
|
||||||
|
// the well have non positive potentials
|
||||||
|
bool has_non_positive_potentials = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
OperabilityStatus operability_status_;
|
OperabilityStatus operability_status_;
|
||||||
@@ -308,6 +313,8 @@ protected:
|
|||||||
const GuideRate* guide_rate_;
|
const GuideRate* guide_rate_;
|
||||||
|
|
||||||
std::vector< std::string> well_control_log_;
|
std::vector< std::string> well_control_log_;
|
||||||
|
|
||||||
|
bool changed_to_open_this_step_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
const int np = well_state_copy.numPhases();
|
const int np = well_state_copy.numPhases();
|
||||||
for (int p = 0; p < np; ++p) {
|
for (int p = 0; p < np; ++p) {
|
||||||
ws.well_potentials[p] = std::abs(potentials[p]);
|
ws.well_potentials[p] = std::max(0.0, potentials[p]);
|
||||||
}
|
}
|
||||||
this->updateWellTestState(well_state_copy.well(this->indexOfWell()), simulation_time, /*writeMessageToOPMLog=*/ false, welltest_state_temp, deferred_logger);
|
this->updateWellTestState(well_state_copy.well(this->indexOfWell()), simulation_time, /*writeMessageToOPMLog=*/ false, welltest_state_temp, deferred_logger);
|
||||||
this->closeCompletions(welltest_state_temp);
|
this->closeCompletions(welltest_state_temp);
|
||||||
@@ -482,7 +482,23 @@ namespace Opm
|
|||||||
this->operability_status_.solvable = false;
|
this->operability_status_.solvable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this->operability_status_.has_non_positive_potentials) {
|
||||||
|
auto well_state_copy = well_state;
|
||||||
|
std::vector<double> potentials;
|
||||||
|
try {
|
||||||
|
computeWellPotentials(ebosSimulator, well_state_copy, potentials, deferred_logger);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
const std::string msg = std::string("well ") + this->name() + std::string(": computeWellPotentials() failed during for re-computing: ") + e.what();
|
||||||
|
deferred_logger.info(msg);
|
||||||
|
this->operability_status_.has_non_positive_potentials = true;
|
||||||
|
}
|
||||||
|
auto& ws = well_state.well(this->indexOfWell());
|
||||||
|
const int np = well_state.numPhases();
|
||||||
|
for (int p = 0; p < np; ++p) {
|
||||||
|
ws.well_potentials[p] = std::max(0.0, potentials[p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->changed_to_open_this_step_ = false;
|
||||||
const bool well_operable = this->operability_status_.isOperableAndSolvable();
|
const bool well_operable = this->operability_status_.isOperableAndSolvable();
|
||||||
if (!well_operable && old_well_operable) {
|
if (!well_operable && old_well_operable) {
|
||||||
if (this->well_ecl_.getAutomaticShutIn()) {
|
if (this->well_ecl_.getAutomaticShutIn()) {
|
||||||
@@ -498,6 +514,7 @@ namespace Opm
|
|||||||
deferred_logger.info(" well " + this->name() + " gets REVIVED during iteration ");
|
deferred_logger.info(" well " + this->name() + " gets REVIVED during iteration ");
|
||||||
this->openWell();
|
this->openWell();
|
||||||
changed_to_stopped_this_step_ = false;
|
changed_to_stopped_this_step_ = false;
|
||||||
|
this->changed_to_open_this_step_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||||
|
|||||||
Reference in New Issue
Block a user