Include checking for zero targets from groups where required

This commit is contained in:
Stein Krogstad 2024-03-19 12:50:34 +01:00 committed by Arne Morten Kvarving
parent 2db90a92e7
commit 427351cc12
15 changed files with 195 additions and 189 deletions

View File

@ -490,7 +490,7 @@ namespace Opm {
// This is done only for producers, as injectors will only have a single
// nonzero phase anyway.
for (auto& well : well_container_) {
const bool zero_target = well->stopppedOrZeroRateTarget(summaryState, this->wellState());
const bool zero_target = well->stoppedOrZeroRateTarget(simulator_, this->wellState(), local_deferredLogger);
if (well->isProducer() && !zero_target) {
well->updateWellStateRates(simulator_, this->wellState(), local_deferredLogger);
}
@ -1076,8 +1076,7 @@ namespace Opm {
}
++iter;
for (auto& well : this->well_container_) {
const auto& summary_state = this->simulator_.vanguard().summaryState();
well->solveEqAndUpdateWellState(summary_state, well_state, deferred_logger);
well->solveEqAndUpdateWellState(simulator_, well_state, deferred_logger);
}
this->initPrimaryVariablesEvaluation();
} while (iter < max_iter);
@ -1711,9 +1710,8 @@ namespace Opm {
DeferredLogger local_deferredLogger;
OPM_BEGIN_PARALLEL_TRY_CATCH();
{
const auto& summary_state = simulator_.vanguard().summaryState();
for (auto& well : well_container_) {
well->recoverWellSolutionAndUpdateWellState(summary_state, x, this->wellState(), local_deferredLogger);
well->recoverWellSolutionAndUpdateWellState(simulator_, x, this->wellState(), local_deferredLogger);
}
}
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
@ -1731,10 +1729,9 @@ namespace Opm {
// try/catch here, as this function is not called in
// parallel but for each individual domain of each rank.
DeferredLogger local_deferredLogger;
const auto& summary_state = this->simulator_.vanguard().summaryState();
for (auto& well : well_container_) {
if (well_domain_.at(well->name()) == domain.index) {
well->recoverWellSolutionAndUpdateWellState(summary_state, x,
well->recoverWellSolutionAndUpdateWellState(simulator_, x,
this->wellState(),
local_deferredLogger);
}
@ -1782,7 +1779,6 @@ namespace Opm {
const std::vector<Scalar>& B_avg,
DeferredLogger& local_deferredLogger) const
{
const auto& summary_state = simulator_.vanguard().summaryState();
const int iterationIdx = simulator_.model().newtonMethod().numIterations();
const bool relax_tolerance = iterationIdx > param_.strict_outer_iter_wells_;
@ -1790,7 +1786,7 @@ namespace Opm {
for (const auto& well : well_container_) {
if ((well_domain_.at(well->name()) == domain.index)) {
if (well->isOperableAndSolvable() || well->wellIsStopped()) {
report += well->getWellConvergence(summary_state,
report += well->getWellConvergence(simulator_,
this->wellState(),
B_avg,
local_deferredLogger,
@ -1833,9 +1829,8 @@ namespace Opm {
const int iterationIdx = simulator_.model().newtonMethod().numIterations();
for (const auto& well : well_container_) {
if (well->isOperableAndSolvable() || well->wellIsStopped()) {
const auto& summary_state = simulator_.vanguard().summaryState();
local_report += well->getWellConvergence(
summary_state, this->wellState(), B_avg, local_deferredLogger,
simulator_, this->wellState(), B_avg, local_deferredLogger,
iterationIdx > param_.strict_outer_iter_wells_);
} else {
ConvergenceReport report;
@ -2356,8 +2351,7 @@ namespace Opm {
auto& events = this->wellState().well(well->indexOfWell()).events;
if (events.hasEvent(WellState<Scalar>::event_mask)) {
well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), deferred_logger);
const auto& summary_state = simulator_.vanguard().summaryState();
well->updatePrimaryVariables(summary_state, this->wellState(), deferred_logger);
well->updatePrimaryVariables(simulator_, this->wellState(), deferred_logger);
well->initPrimaryVariablesEvaluation();
// There is no new well control change input within a report step,
// so next time step, the well does not consider to have effective events anymore.
@ -2441,8 +2435,7 @@ namespace Opm {
updatePrimaryVariables(DeferredLogger& deferred_logger)
{
for (const auto& well : well_container_) {
const auto& summary_state = simulator_.vanguard().summaryState();
well->updatePrimaryVariables(summary_state, this->wellState(), deferred_logger);
well->updatePrimaryVariables(simulator_, this->wellState(), deferred_logger);
}
}

View File

@ -94,7 +94,7 @@ namespace Opm {
DeferredLogger& deferred_logger) const override;
/// check whether the well equations get converged for this well
ConvergenceReport getWellConvergence(const SummaryState& summary_state,
ConvergenceReport getWellConvergence(const Simulator& simulator,
const WellState<Scalar>& well_state,
const std::vector<Scalar>& B_avg,
DeferredLogger& deferred_logger,
@ -107,7 +107,7 @@ namespace Opm {
/// using the solution x to recover the solution xw for wells and applying
/// xw to update Well State
void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
void recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
const BVector& x,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) override;
@ -118,11 +118,11 @@ namespace Opm {
std::vector<Scalar>& well_potentials,
DeferredLogger& deferred_logger) override;
void updatePrimaryVariables(const SummaryState& summary_state,
void updatePrimaryVariables(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) override;
void solveEqAndUpdateWellState(const SummaryState& summary_state,
void solveEqAndUpdateWellState(const Simulator& simulator,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) override; // const?
@ -174,7 +174,7 @@ namespace Opm {
mutable int debug_cost_counter_ = 0;
// updating the well_state based on well solution dwells
void updateWellState(const SummaryState& summary_state,
void updateWellState(const Simulator& simulator,
const BVectorWell& dwells,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger,

View File

@ -92,6 +92,7 @@ assembleControlEq(const WellState<Scalar>& well_state,
const Scalar rho,
const PrimaryVariables& primary_variables,
Equations& eqns1,
const bool stopped_or_zero_target,
DeferredLogger& deferred_logger) const
{
static constexpr int Gas = BlackoilPhases::Vapour;
@ -116,7 +117,7 @@ assembleControlEq(const WellState<Scalar>& well_state,
return rates;
};
if (well_.stopppedOrZeroRateTarget(summaryState, well_state)) {
if (stopped_or_zero_target) {
control_eq = primary_variables.getWQTotal();
} else if (well_.isInjector() ) {
// Find scaling factor to get injection rate,

View File

@ -79,6 +79,7 @@ public:
const Scalar rho,
const PrimaryVariables& primary_variables,
Equations& eqns,
const bool stopped_or_zero_target,
DeferredLogger& deferred_logger) const;
//! \brief Assemble piece of the acceleration term

View File

@ -162,11 +162,11 @@ namespace Opm
template <typename TypeTag>
void
MultisegmentWell<TypeTag>::
updatePrimaryVariables(const SummaryState& summary_state,
updatePrimaryVariables(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& /* deferred_logger */)
DeferredLogger& deferred_logger)
{
const bool stop_or_zero_rate_target = this->stopppedOrZeroRateTarget(summary_state, well_state);
const bool stop_or_zero_rate_target = this->stoppedOrZeroRateTarget(simulator, well_state, deferred_logger);
this->primary_variables_.update(well_state, stop_or_zero_rate_target);
}
@ -199,7 +199,7 @@ namespace Opm
template <typename TypeTag>
ConvergenceReport
MultisegmentWell<TypeTag>::
getWellConvergence(const SummaryState& /* summary_state */,
getWellConvergence(const Simulator& /* simulator */,
const WellState<Scalar>& well_state,
const std::vector<Scalar>& B_avg,
DeferredLogger& deferred_logger,
@ -260,7 +260,7 @@ namespace Opm
template <typename TypeTag>
void
MultisegmentWell<TypeTag>::
recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
const BVector& x,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
@ -271,7 +271,7 @@ namespace Opm
BVectorWell xw(1);
this->linSys_.recoverSolutionWell(x, xw);
updateWellState(summary_state, xw, well_state, deferred_logger);
updateWellState(simulator, xw, well_state, deferred_logger);
}
@ -578,7 +578,7 @@ namespace Opm
template <typename TypeTag>
void
MultisegmentWell<TypeTag>::
solveEqAndUpdateWellState(const SummaryState& summary_state,
solveEqAndUpdateWellState(const Simulator& simulator,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
{
@ -589,7 +589,7 @@ namespace Opm
try{
const BVectorWell dx_well = this->linSys_.solve();
updateWellState(summary_state, dx_well, well_state, deferred_logger);
updateWellState(simulator, dx_well, well_state, deferred_logger);
}
catch(const NumericalProblem& exp) {
// Add information about the well and log to deferred logger
@ -681,7 +681,7 @@ namespace Opm
template <typename TypeTag>
void
MultisegmentWell<TypeTag>::
updateWellState(const SummaryState& summary_state,
updateWellState(const Simulator& simulator,
const BVectorWell& dwells,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger,
@ -691,15 +691,20 @@ namespace Opm
const Scalar dFLimit = this->param_.dwell_fraction_max_;
const Scalar max_pressure_change = this->param_.max_pressure_change_ms_wells_;
const bool stop_or_zero_rate_target = this->stopppedOrZeroRateTarget(summary_state, well_state);
const bool stop_or_zero_rate_target =
this->stoppedOrZeroRateTarget(simulator, well_state, deferred_logger);
this->primary_variables_.updateNewton(dwells,
relaxation_factor,
dFLimit,
stop_or_zero_rate_target,
max_pressure_change);
this->primary_variables_.copyToWellState(*this, getRefDensity(), stop_or_zero_rate_target,
well_state, summary_state, deferred_logger);
const auto& summary_state = simulator.vanguard().summaryState();
this->primary_variables_.copyToWellState(*this, getRefDensity(),
stop_or_zero_rate_target,
well_state,
summary_state,
deferred_logger);
{
auto& ws = well_state.well(this->index_of_well_);
@ -720,8 +725,7 @@ namespace Opm
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
{
const auto& summary_state = simulator.vanguard().summaryState();
updatePrimaryVariables(summary_state, well_state, deferred_logger);
updatePrimaryVariables(simulator, well_state, deferred_logger);
initPrimaryVariablesEvaluation();
computePerfCellPressDiffs(simulator);
computeInitialSegmentFluids(simulator);
@ -1489,8 +1493,7 @@ namespace Opm
this->regularize_ = true;
}
const auto& summary_state = simulator.vanguard().summaryState();
const auto report = getWellConvergence(summary_state, well_state, Base::B_avg_, deferred_logger, relax_convergence);
const auto report = getWellConvergence(simulator, well_state, Base::B_avg_, deferred_logger, relax_convergence);
if (report.converged()) {
converged = true;
break;
@ -1526,7 +1529,7 @@ namespace Opm
++stagnate_count;
if (stagnate_count == 6) {
sstr << " well " << this->name() << " observes severe stagnation and/or oscillation. We relax the tolerance and check for convergence. \n";
const auto reportStag = getWellConvergence(summary_state, well_state, Base::B_avg_, deferred_logger, true);
const auto reportStag = getWellConvergence(simulator, well_state, Base::B_avg_, deferred_logger, true);
if (reportStag.converged()) {
converged = true;
sstr << " well " << this->name() << " manages to get converged with relaxed tolerances in " << it << " inner iterations";
@ -1553,7 +1556,7 @@ namespace Opm
this->regularize_ = true;
deferred_logger.debug(sstr.str());
}
updateWellState(summary_state, dx_well, well_state, deferred_logger, relaxation_factor);
updateWellState(simulator, dx_well, well_state, deferred_logger, relaxation_factor);
initPrimaryVariablesEvaluation();
}
@ -1635,7 +1638,7 @@ namespace Opm
const bool allow_open = this->well_ecl_.getStatus() == WellStatus::OPEN &&
well_state.well(this->index_of_well_).status == WellStatus::OPEN;
// don't allow switcing for wells under zero rate target or requested fixed status and control
const bool allow_switching = !this->wellUnderZeroRateTarget(summary_state, well_state) &&
const bool allow_switching = !this->wellUnderZeroRateTarget(simulator, well_state, deferred_logger) &&
(!fixed_control || !fixed_status) && allow_open;
bool changed = false;
bool final_check = false;
@ -1673,7 +1676,7 @@ namespace Opm
this->regularize_ = true;
}
const auto report = getWellConvergence(summary_state, well_state, Base::B_avg_, deferred_logger, relax_convergence);
const auto report = getWellConvergence(simulator, well_state, Base::B_avg_, deferred_logger, relax_convergence);
converged = report.converged();
if (converged) {
// if equations are sufficiently linear they might converge in less than min_its_after_switch
@ -1717,7 +1720,7 @@ namespace Opm
if (false) { // this disables the usage of the relaxed tolerance
fmt::format_to(std::back_inserter(message), " Well {} observes severe stagnation and/or oscillation."
" We relax the tolerance and check for convergence. \n", this->name());
const auto reportStag = getWellConvergence(summary_state, well_state, Base::B_avg_,
const auto reportStag = getWellConvergence(simulator, well_state, Base::B_avg_,
deferred_logger, true);
if (reportStag.converged()) {
converged = true;
@ -1745,7 +1748,7 @@ namespace Opm
deferred_logger.debug(message);
}
}
updateWellState(summary_state, dx_well, well_state, deferred_logger, relaxation_factor);
updateWellState(simulator, dx_well, well_state, deferred_logger, relaxation_factor);
initPrimaryVariablesEvaluation();
}
@ -1906,10 +1909,11 @@ namespace Opm
}
}
// the fourth dequation, the pressure drop equation
// the fourth equation, the pressure drop equation
if (seg == 0) { // top segment, pressure equation is the control equation
const auto& summaryState = simulator.vanguard().summaryState();
const Schedule& schedule = simulator.vanguard().schedule();
const bool stopped_or_zero_target = this->stoppedOrZeroRateTarget(simulator, well_state, deferred_logger);
MultisegmentWellAssemble(*this).
assembleControlEq(well_state,
group_state,
@ -1920,6 +1924,7 @@ namespace Opm
getRefDensity(),
this->primary_variables_,
this->linSys_,
stopped_or_zero_target,
deferred_logger);
} else {
const UnitSystem& unit_system = simulator.vanguard().eclState().getDeckUnitSystem();

View File

@ -140,7 +140,7 @@ namespace Opm
void initPrimaryVariablesEvaluation() override;
/// check whether the well equations get converged for this well
virtual ConvergenceReport getWellConvergence(const SummaryState& summary_state,
virtual ConvergenceReport getWellConvergence(const Simulator& simulator,
const WellState<Scalar>& well_state,
const std::vector<Scalar>& B_avg,
DeferredLogger& deferred_logger,
@ -153,7 +153,7 @@ namespace Opm
/// using the solution x to recover the solution xw for wells and applying
/// xw to update Well State
void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
void recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
const BVector& x,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) override;
@ -164,11 +164,11 @@ namespace Opm
std::vector<Scalar>& well_potentials,
DeferredLogger& deferred_logger) /* const */ override;
void updatePrimaryVariables(const SummaryState& summary_state,
void updatePrimaryVariables(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) override;
void solveEqAndUpdateWellState(const SummaryState& summary_state,
void solveEqAndUpdateWellState(const Simulator& simulator,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) override;
@ -262,7 +262,7 @@ namespace Opm
bool regularize_;
// updating the well_state based on well solution dwells
void updateWellState(const SummaryState& summary_state,
void updateWellState(const Simulator& simulator,
const BVectorWell& dwells,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger);

View File

@ -93,6 +93,7 @@ assembleControlEq(const WellState<Scalar>& well_state,
const PrimaryVariables& primary_variables,
const Scalar rho,
StandardWellEquations<Scalar,Indices::numEq>& eqns1,
const bool stopped_or_zero_target,
DeferredLogger& deferred_logger) const
{
static constexpr int Water = BlackoilPhases::Aqua;
@ -119,7 +120,7 @@ assembleControlEq(const WellState<Scalar>& well_state,
return rates;
};
if (well_.stopppedOrZeroRateTarget(summaryState, well_state)) {
if (stopped_or_zero_target) {
control_eq = primary_variables.eval(PrimaryVariables::WQTotal);
} else if (well_.isInjector()) {
// Find injection rate.

View File

@ -61,6 +61,7 @@ public:
const PrimaryVariables& primary_variables,
const Scalar rho,
StandardWellEquations<Scalar,Indices::numEq>& eqns,
const bool stopped_or_zero_target,
DeferredLogger& deferred_logger) const;
//! \brief Assemble injectivity equation.

View File

@ -462,6 +462,7 @@ namespace Opm
const auto& summaryState = simulator.vanguard().summaryState();
const Schedule& schedule = simulator.vanguard().schedule();
const bool stopped_or_zero_target = this->stoppedOrZeroRateTarget(simulator, well_state, deferred_logger);
StandardWellAssemble<FluidSystem,Indices>(*this).
assembleControlEq(well_state, group_state,
schedule, summaryState,
@ -469,6 +470,7 @@ namespace Opm
this->primary_variables_,
this->connections_.rho(),
this->linSys_,
stopped_or_zero_target,
deferred_logger);
@ -692,16 +694,17 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
updateWellState(const SummaryState& summary_state,
updateWellState(const Simulator& simulator,
const BVectorWell& dwells,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
{
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
const bool stop_or_zero_rate_target = this->stopppedOrZeroRateTarget(summary_state, well_state);
const bool stop_or_zero_rate_target = this->stoppedOrZeroRateTarget(simulator, well_state, deferred_logger);
updatePrimaryVariablesNewton(dwells, stop_or_zero_rate_target, deferred_logger);
const auto& summary_state = simulator.vanguard().summaryState();
updateWellStateFromPrimaryVariables(stop_or_zero_rate_target, well_state, summary_state, deferred_logger);
Base::calculateReservoirRates(well_state.well(this->index_of_well_));
}
@ -805,7 +808,10 @@ namespace Opm
// the well index associated with the connection
Scalar trans_mult = simulator.problem().template wellTransMultiplier<Scalar>(int_quantities, cell_idx);
const auto& wellstate_nupcol = simulator.problem().wellModel().nupcolWellState().well(this->index_of_well_);
const std::vector<Scalar> tw_perf = this->wellIndex(perf, int_quantities, trans_mult, wellstate_nupcol);
const std::vector<Scalar> tw_perf = this->wellIndex(perf,
int_quantities,
trans_mult,
wellstate_nupcol);
std::vector<Scalar> ipr_a_perf(this->ipr_a_.size());
std::vector<Scalar> ipr_b_perf(this->ipr_b_.size());
for (int comp_idx = 0; comp_idx < this->num_components_; ++comp_idx) {
@ -1175,7 +1181,7 @@ namespace Opm
template<typename TypeTag>
ConvergenceReport
StandardWell<TypeTag>::
getWellConvergence(const SummaryState& summary_state,
getWellConvergence(const Simulator& simulator,
const WellState<Scalar>& well_state,
const std::vector<Scalar>& B_avg,
DeferredLogger& deferred_logger,
@ -1190,7 +1196,7 @@ namespace Opm
constexpr Scalar stopped_factor = 1.e-4;
// use stricter tolerance for dynamic thp to ameliorate network convergence
constexpr Scalar dynamic_thp_factor = 1.e-1;
if (this->stopppedOrZeroRateTarget(summary_state, well_state)) {
if (this->stoppedOrZeroRateTarget(simulator, well_state, deferred_logger)) {
tol_wells = tol_wells*stopped_factor;
} else if (this->getDynamicThpLimit()) {
tol_wells = tol_wells*dynamic_thp_factor;
@ -1357,7 +1363,7 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
solveEqAndUpdateWellState(const SummaryState& summary_state,
solveEqAndUpdateWellState(const Simulator& simulator,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
{
@ -1369,7 +1375,7 @@ namespace Opm
dx_well[0].resize(this->primary_variables_.numWellEq());
this->linSys_.solve( dx_well);
updateWellState(summary_state, dx_well, well_state, deferred_logger);
updateWellState(simulator, dx_well, well_state, deferred_logger);
}
@ -1383,8 +1389,7 @@ namespace Opm
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
{
const auto& summary_state = simulator.vanguard().summaryState();
updatePrimaryVariables(summary_state, well_state, deferred_logger);
updatePrimaryVariables(simulator, well_state, deferred_logger);
initPrimaryVariablesEvaluation();
computeWellConnectionPressures(simulator, well_state, deferred_logger);
this->computeAccumWell();
@ -1427,7 +1432,7 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
const BVector& x,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
@ -1438,7 +1443,7 @@ namespace Opm
xw[0].resize(this->primary_variables_.numWellEq());
this->linSys_.recoverSolutionWell(x, xw);
updateWellState(summary_state, xw, well_state, deferred_logger);
updateWellState(simulator, xw, well_state, deferred_logger);
}
@ -1535,7 +1540,7 @@ namespace Opm
well_state_copy.wellRates(this->index_of_well_)[phase]
= sign * ws.well_potentials[phase];
}
well_copy.updatePrimaryVariables(summary_state, well_state_copy, deferred_logger);
well_copy.updatePrimaryVariables(simulator, well_state_copy, deferred_logger);
well_copy.initPrimaryVariablesEvaluation();
well_copy.computeAccumWell();
@ -1546,7 +1551,7 @@ namespace Opm
" potentials are computed based on unconverged solution";
deferred_logger.debug(msg);
}
well_copy.updatePrimaryVariables(summary_state, well_state_copy, deferred_logger);
well_copy.updatePrimaryVariables(simulator, well_state_copy, deferred_logger);
well_copy.computeWellConnectionPressures(simulator, well_state_copy, deferred_logger);
well_copy.initPrimaryVariablesEvaluation();
well_copy.computeWellRatesWithBhp(simulator, bhp, well_flux, deferred_logger);
@ -1774,13 +1779,13 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
updatePrimaryVariables(const SummaryState& summary_state,
updatePrimaryVariables(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger)
{
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
const bool stop_or_zero_rate_target = this->stopppedOrZeroRateTarget(summary_state, well_state);
const bool stop_or_zero_rate_target = this->stoppedOrZeroRateTarget(simulator, well_state, deferred_logger);
this->primary_variables_.update(well_state, stop_or_zero_rate_target, deferred_logger);
// other primary variables related to polymer injection
@ -2300,7 +2305,6 @@ namespace Opm
bool converged;
bool relax_convergence = false;
this->regularize_ = false;
const auto& summary_state = simulator.vanguard().summaryState();
do {
assembleWellEqWithoutIteration(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
@ -2309,7 +2313,7 @@ namespace Opm
this->regularize_ = true;
}
auto report = getWellConvergence(summary_state, well_state, Base::B_avg_, deferred_logger, relax_convergence);
auto report = getWellConvergence(simulator, well_state, Base::B_avg_, deferred_logger, relax_convergence);
converged = report.converged();
if (converged) {
@ -2317,7 +2321,7 @@ namespace Opm
}
++it;
solveEqAndUpdateWellState(summary_state, well_state, deferred_logger);
solveEqAndUpdateWellState(simulator, well_state, deferred_logger);
// TODO: when this function is used for well testing purposes, will need to check the controls, so that we will obtain convergence
// under the most restrictive control. Based on this converged results, we can check whether to re-open the well. Either we refactor
@ -2366,9 +2370,8 @@ namespace Opm
const bool allow_open = this->well_ecl_.getStatus() == WellStatus::OPEN &&
well_state.well(this->index_of_well_).status == WellStatus::OPEN;
// don't allow switcing for wells under zero rate target or requested fixed status and control
//const bool allow_switching = !this->wellUnderZeroRateTarget(summary_state, well_state) &&
// (!fixed_control || !fixed_status) && allow_open;
const bool allow_switching = !this->wellUnderZeroRateTargetVersion(simulator, well_state, deferred_logger) &&
const bool allow_switching =
!this->wellUnderZeroRateTarget(simulator, well_state, deferred_logger) &&
(!fixed_control || !fixed_status) && allow_open;
bool changed = false;
@ -2405,7 +2408,7 @@ namespace Opm
this->regularize_ = true;
}
auto report = getWellConvergence(summary_state, well_state, Base::B_avg_, deferred_logger, relax_convergence);
auto report = getWellConvergence(simulator, well_state, Base::B_avg_, deferred_logger, relax_convergence);
converged = report.converged();
if (converged) {
@ -2420,7 +2423,7 @@ namespace Opm
}
++it;
solveEqAndUpdateWellState(summary_state, well_state, deferred_logger);
solveEqAndUpdateWellState(simulator, well_state, deferred_logger);
initPrimaryVariablesEvaluation();
} while (it < max_iter);

View File

@ -155,13 +155,13 @@ public:
virtual void initPrimaryVariablesEvaluation() = 0;
virtual ConvergenceReport getWellConvergence(const SummaryState& summary_state,
virtual ConvergenceReport getWellConvergence(const Simulator& simulator,
const WellState<Scalar>& well_state,
const std::vector<Scalar>& B_avg,
DeferredLogger& deferred_logger,
const bool relax_tolerance) const = 0;
virtual void solveEqAndUpdateWellState(const SummaryState& summary_state,
virtual void solveEqAndUpdateWellState(const Simulator& simulator,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) = 0;
@ -198,7 +198,7 @@ public:
/// using the solution x to recover the solution xw for wells and applying
/// xw to update Well State
virtual void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
virtual void recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
const BVector& x,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) = 0;
@ -225,11 +225,11 @@ public:
std::vector<Scalar>& well_flux,
DeferredLogger& deferred_logger) const = 0;
bool wellUnderZeroRateTargetVersion(const Simulator& simulator,
bool wellUnderZeroRateTarget(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const;
bool stoppedOrZeroRateTargetVersion(const Simulator& simulator,
bool stoppedOrZeroRateTarget(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const;
@ -254,7 +254,7 @@ public:
const bool fixed_control = false,
const bool fixed_status = false);
virtual void updatePrimaryVariables(const SummaryState& summary_state,
virtual void updatePrimaryVariables(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) = 0;

View File

@ -305,6 +305,42 @@ getGroupProductionTargetRate(const Group& group,
deferred_logger);
}
template<typename FluidSystem>
bool
WellInterfaceFluidSystem<FluidSystem>::
wellUnderZeroRateTargetGroup(const SummaryState& summary_state,
const Schedule& schedule,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger) const
{
const auto& well = this->well_ecl_;
const auto& group = schedule.getGroup(well.groupName(), this->currentStep());
const Scalar efficiencyFactor = well.getEfficiencyFactor();
if (this->isInjector()) {
// Check injector under group control
const auto& controls = well.injectionControls(summary_state);
const std::optional<Scalar> target =
this->getGroupInjectionTargetRate(group, well_state,
group_state, schedule,
summary_state, controls.injector_type,
efficiencyFactor, deferred_logger);
if (target.has_value()) {
return target.value() == 0.0;
} else {
return false;
}
} else {
// Check producer under group control
const Scalar scale =
this->getGroupProductionTargetRate(group, well_state,
group_state, schedule,
summary_state, efficiencyFactor,
deferred_logger);
return scale == 0.0;
}
}
template class WellInterfaceFluidSystem<BlackOilFluidSystem<double,BlackOilDefaultIndexTraits>>;
} // namespace Opm

View File

@ -117,6 +117,12 @@ protected:
Scalar efficiencyFactor,
DeferredLogger& deferred_logger) const;
bool wellUnderZeroRateTargetGroup(const SummaryState& summary_state,
const Schedule& schedule,
const WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferredLogger) const;
// For the conversion between the surface volume rate and reservoir voidage rate
const RateConverterType& rateConverter_;
};

View File

@ -24,6 +24,7 @@
#include <opm/common/ErrorMacros.hpp>
#include <opm/input/eclipse/Schedule/Schedule.hpp>
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
#include <opm/input/eclipse/Schedule/Well/WellBrineProperties.hpp>
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
@ -605,7 +606,7 @@ isPressureControlled(const WellState<Scalar>& well_state) const
template<class Scalar>
bool WellInterfaceGeneric<Scalar>::
wellUnderZeroRateTarget(const SummaryState& summary_state,
wellUnderZeroRateTargetIndividual(const SummaryState& summary_state,
const WellState<Scalar>& well_state) const
{
if (this->isProducer()) { // producers
@ -619,15 +620,6 @@ wellUnderZeroRateTarget(const SummaryState& summary_state,
}
}
template<class Scalar>
bool WellInterfaceGeneric<Scalar>::
stopppedOrZeroRateTarget(const SummaryState& summary_state,
const WellState<Scalar>& well_state) const
{
return (this->wellIsStopped() || this->wellUnderZeroRateTarget(summary_state, well_state));
}
template<class Scalar>
void WellInterfaceGeneric<Scalar>::resetWellOperability()
{

View File

@ -173,9 +173,6 @@ public:
bool isPressureControlled(const WellState<Scalar>& well_state) const;
bool stopppedOrZeroRateTarget(const SummaryState& summary_state,
const WellState<Scalar>& well_state) const;
Scalar wellEfficiencyFactor() const { return well_efficiency_factor_; }
//! \brief Update filter cake multipliers.
@ -200,7 +197,7 @@ protected:
int polymerInjTable_() const;
int polymerWaterTable_() const;
bool wellUnderZeroRateTarget(const SummaryState& summary_state,
bool wellUnderZeroRateTargetIndividual(const SummaryState& summary_state,
const WellState<Scalar>& well_state) const;
std::pair<bool,bool>

View File

@ -198,8 +198,7 @@ namespace Opm
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger) /* const */
{
const auto& summary_state = simulator.vanguard().summaryState();
if (this->stopppedOrZeroRateTarget(summary_state, well_state)) {
if (stoppedOrZeroRateTarget(simulator, well_state, deferred_logger)) {
return false;
}
@ -260,7 +259,7 @@ namespace Opm
this->well_control_log_.push_back(from);
updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger);
updatePrimaryVariables(summaryState, well_state, deferred_logger);
updatePrimaryVariables(simulator, well_state, deferred_logger);
}
return changed;
@ -282,7 +281,7 @@ namespace Opm
const auto& summary_state = simulator.vanguard().summaryState();
const auto& schedule = simulator.vanguard().schedule();
if (this->wellUnderZeroRateTarget(summary_state, well_state) || !(this->well_ecl_.getStatus() == WellStatus::OPEN)) {
if (this->wellUnderZeroRateTarget(simulator, well_state, deferred_logger) || !(this->well_ecl_.getStatus() == WellStatus::OPEN)) {
return false;
}
@ -312,7 +311,7 @@ namespace Opm
} else {
ws.thp = this->getTHPConstraint(summary_state);
}
updatePrimaryVariables(summary_state, well_state, deferred_logger);
updatePrimaryVariables(simulator, well_state, deferred_logger);
}
}
return changed;
@ -377,8 +376,7 @@ namespace Opm
updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger);
calculateExplicitQuantities(simulator, well_state_copy, deferred_logger);
const auto& summary_state = simulator.vanguard().summaryState();
updatePrimaryVariables(summary_state, well_state_copy, deferred_logger);
updatePrimaryVariables(simulator, well_state_copy, deferred_logger);
initPrimaryVariablesEvaluation();
if (this->isProducer()) {
@ -539,7 +537,7 @@ namespace Opm
const bool isThp = ws.production_cmode == Well::ProducerCMode::THP;
// check stability of solution under thp-control
if (converged && !this->stopppedOrZeroRateTarget(summary_state, well_state) && isThp) {
if (converged && !stoppedOrZeroRateTarget(simulator, well_state, deferred_logger) && isThp) {
auto rates = well_state.well(this->index_of_well_).surface_rates;
this->adaptRatesForVFP(rates);
this->updateIPRImplicit(simulator, well_state, deferred_logger);
@ -1430,63 +1428,35 @@ namespace Opm
template<typename TypeTag>
bool
WellInterface<TypeTag>::
wellUnderZeroRateTargetVersion(const Simulator& simulator,
wellUnderZeroRateTarget(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const
{
// Extended version of WellInterfaceGeneric::wellUnderZeroRateTarget that also checks group controls
// Check if well is under zero rate control, either directly or from group
const auto& ws = well_state.well(this->index_of_well_);
const auto& summaryState = simulator.vanguard().summaryState();
const bool isGroupControlled = (this->isInjector() && ws.injection_cmode == Well::InjectorCMode::GRUP) ||
(this->isProducer() && ws.production_cmode == Well::ProducerCMode::GRUP);
if (!isGroupControlled) {
// well is not under group control, check "light-weight" version
return this->wellUnderZeroRateTarget(summaryState, well_state);
// well is not under group control, check "individual" version
const auto& summaryState = simulator.vanguard().summaryState();
return this->wellUnderZeroRateTargetIndividual(summaryState, well_state);
} else {
const auto& well = this->well_ecl_;
const auto& schedule = simulator.vanguard().schedule();
const auto& summaryState = simulator.vanguard().summaryState();
const auto& group_state = simulator.problem().wellModel().groupState();
const auto& group = schedule.getGroup(well.groupName(), this->currentStep());
const Scalar efficiencyFactor = well.getEfficiencyFactor();
if (this->isInjector()) {
// Check injector under group control
const auto& controls = well.injectionControls(summaryState);
std::optional<Scalar> target = this->getGroupInjectionTargetRate(group,
well_state,
group_state,
schedule,
summaryState,
controls.injector_type,
efficiencyFactor,
deferred_logger);
if (target.has_value()) {
return target.value() == 0.0;
} else {
return false;
}
} else {
// Check producer under group control
Scalar scale = this->getGroupProductionTargetRate(group,
well_state,
group_state,
schedule,
summaryState,
efficiencyFactor,
deferred_logger);
return scale == 0.0;
}
const auto& schedule = simulator.vanguard().schedule();
return this->wellUnderZeroRateTargetGroup(summaryState, schedule, well_state, group_state, deferred_logger);
}
}
template<typename TypeTag>
bool
WellInterface<TypeTag>::
stoppedOrZeroRateTargetVersion(const Simulator& simulator,
stoppedOrZeroRateTarget(const Simulator& simulator,
const WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const
{
// Extended version of WellInterfaceGeneric::stopppedOrZeroRateTarget that also checks group controls
return (this->wellIsStopped() || wellUnderZeroRateTargetVersion(simulator,
// Check if well is stopped or under zero rate control, either directly or from group
return (this->wellIsStopped() || wellUnderZeroRateTarget(simulator,
well_state,
deferred_logger));
}