mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-26 01:01:00 -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:
parent
d163bebcdc
commit
b5cdb1048a
@ -2374,4 +2374,20 @@ runWellPIScaling(const int 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,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
bool guideRateUpdateIsNeeded() const;
|
||||
|
||||
// create the well container
|
||||
virtual void createWellContainer(const int time_step) = 0;
|
||||
virtual void initWellContainer() = 0;
|
||||
|
@ -840,6 +840,18 @@ namespace Opm {
|
||||
}
|
||||
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "assemble() failed: ",
|
||||
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_.assemble_time_well += perfTimer.stop();
|
||||
}
|
||||
@ -1343,7 +1355,8 @@ namespace Opm {
|
||||
// and updated only if sucessfull. i.e. the potentials are zero for exceptions
|
||||
auto& ws = this->wellState().well(well->indexOfWell());
|
||||
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);
|
||||
}
|
||||
// solve the well equation initially to improve the initial solution of the well model
|
||||
if (param_.solve_welleq_initially_) {
|
||||
well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), deferred_logger);
|
||||
if (param_.solve_welleq_initially_ && well->isOperableAndSolvable()) {
|
||||
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);
|
||||
|
@ -112,6 +112,11 @@ computeWellRates_(
|
||||
-potentials[this->water_pos_]);
|
||||
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>
|
||||
|
@ -253,6 +253,7 @@ namespace Opm
|
||||
if (this->wellIsStopped()) {
|
||||
return;
|
||||
}
|
||||
this->operability_status_.has_non_positive_potentials = false;
|
||||
|
||||
// If the well is pressure controlled the potential equals the rate.
|
||||
bool thp_controlled_well = false;
|
||||
@ -285,9 +286,20 @@ namespace Opm
|
||||
// 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.
|
||||
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){
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -302,6 +314,20 @@ namespace Opm
|
||||
}
|
||||
deferred_logger.debug("Cost in iterations of finding well potential for well "
|
||||
+ 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;
|
||||
}
|
||||
|
||||
this->operability_status_.has_non_positive_potentials = false;
|
||||
// If the well is pressure controlled the potential equals the rate.
|
||||
bool thp_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
|
||||
// opened well and we therefore make the affort of computing the potentials anyway.
|
||||
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){
|
||||
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;
|
||||
}
|
||||
@ -1917,6 +1928,20 @@ namespace Opm
|
||||
// the well has a THP related constraint
|
||||
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;
|
||||
|
||||
bool changedToOpenThisStep() const {
|
||||
return this->changed_to_open_this_step_;
|
||||
}
|
||||
protected:
|
||||
bool getAllowCrossFlow() const;
|
||||
double mostStrictBhpFromBhpLimits(const SummaryState& summaryState) const;
|
||||
@ -186,7 +189,7 @@ protected:
|
||||
// definition of the struct OperabilityStatus
|
||||
struct OperabilityStatus {
|
||||
bool isOperableAndSolvable() const {
|
||||
if (!operable_under_only_bhp_limit || !solvable) {
|
||||
if (!operable_under_only_bhp_limit || !solvable || has_non_positive_potentials) {
|
||||
return false;
|
||||
} else {
|
||||
return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) );
|
||||
@ -221,6 +224,8 @@ protected:
|
||||
bool obey_bhp_limit_with_thp_limit = true;
|
||||
// the well is solveable
|
||||
bool solvable = true;
|
||||
// the well have non positive potentials
|
||||
bool has_non_positive_potentials = false;
|
||||
};
|
||||
|
||||
OperabilityStatus operability_status_;
|
||||
@ -308,6 +313,8 @@ protected:
|
||||
const GuideRate* guide_rate_;
|
||||
|
||||
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();
|
||||
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->closeCompletions(welltest_state_temp);
|
||||
@ -482,7 +482,23 @@ namespace Opm
|
||||
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();
|
||||
if (!well_operable && old_well_operable) {
|
||||
if (this->well_ecl_.getAutomaticShutIn()) {
|
||||
@ -498,6 +514,7 @@ namespace Opm
|
||||
deferred_logger.info(" well " + this->name() + " gets REVIVED during iteration ");
|
||||
this->openWell();
|
||||
changed_to_stopped_this_step_ = false;
|
||||
this->changed_to_open_this_step_ = true;
|
||||
}
|
||||
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
|
Loading…
Reference in New Issue
Block a user