mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #5232 from steink/check_zero_target_from_group
When checking for zero target rates, also check wells under group control where required
This commit is contained in:
commit
8199342ce9
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
@ -849,11 +855,11 @@ namespace Opm
|
||||
updateIPRImplicit(const Simulator& simulator,
|
||||
WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
{
|
||||
// Compute IPR based on *converged* well-equation:
|
||||
// For a component rate r the derivative dr/dbhp is obtained by
|
||||
// For a component rate r the derivative dr/dbhp is obtained by
|
||||
// dr/dbhp = - (partial r/partial x) * inv(partial Eq/partial x) * (partial Eq/partial bhp_target)
|
||||
// where Eq(x)=0 is the well equation setup with bhp control and primary variables x
|
||||
// where Eq(x)=0 is the well equation setup with bhp control and primary variables x
|
||||
|
||||
// We shouldn't have zero rates at this stage, but check
|
||||
bool zero_rates;
|
||||
@ -867,7 +873,7 @@ namespace Opm
|
||||
const auto msg = fmt::format("updateIPRImplicit: Well {} has zero rate, IPRs might be problematic", this->name());
|
||||
deferred_logger.debug(msg);
|
||||
/*
|
||||
// could revert to standard approach here:
|
||||
// could revert to standard approach here:
|
||||
updateIPR(simulator, deferred_logger);
|
||||
for (int comp_idx = 0; comp_idx < this->num_components_; ++comp_idx){
|
||||
const int idx = this->modelCompIdxToFlowCompIdx(comp_idx);
|
||||
@ -876,12 +882,12 @@ namespace Opm
|
||||
}
|
||||
return;
|
||||
*/
|
||||
}
|
||||
}
|
||||
const auto& group_state = simulator.problem().wellModel().groupState();
|
||||
|
||||
std::fill(ws.implicit_ipr_a.begin(), ws.implicit_ipr_a.end(), 0.);
|
||||
std::fill(ws.implicit_ipr_b.begin(), ws.implicit_ipr_b.end(), 0.);
|
||||
|
||||
|
||||
auto inj_controls = Well::InjectionControls(0);
|
||||
auto prod_controls = Well::ProductionControls(0);
|
||||
prod_controls.addControl(Well::ProducerCMode::BHP);
|
||||
@ -898,7 +904,7 @@ namespace Opm
|
||||
rhs[0].resize(nEq);
|
||||
// rhs = 0 except -1 for control eq
|
||||
for (size_t i=0; i < nEq; ++i){
|
||||
rhs[0][i] = 0.0;
|
||||
rhs[0][i] = 0.0;
|
||||
}
|
||||
rhs[0][Bhp] = -1.0;
|
||||
|
||||
@ -910,7 +916,7 @@ namespace Opm
|
||||
EvalWell comp_rate = this->primary_variables_.getQs(comp_idx);
|
||||
const int idx = this->modelCompIdxToFlowCompIdx(comp_idx);
|
||||
for (size_t pvIdx = 0; pvIdx < nEq; ++pvIdx) {
|
||||
// well primary variable derivatives in EvalWell start at position Indices::numEq
|
||||
// well primary variable derivatives in EvalWell start at position Indices::numEq
|
||||
ws.implicit_ipr_b[idx] -= x_well[0][pvIdx]*comp_rate.derivative(pvIdx+Indices::numEq);
|
||||
}
|
||||
ws.implicit_ipr_a[idx] = ws.implicit_ipr_b[idx]*ws.bhp - comp_rate.value();
|
||||
@ -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);
|
||||
@ -1598,7 +1603,7 @@ namespace Opm
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// Create a copy of the well.
|
||||
// TODO: check if we can avoid taking multiple copies. Call from updateWellPotentials
|
||||
// TODO: check if we can avoid taking multiple copies. Call from updateWellPotentials
|
||||
// is allready a copy, but not from other calls.
|
||||
StandardWell<TypeTag> well_copy(*this);
|
||||
|
||||
@ -1618,7 +1623,7 @@ namespace Opm
|
||||
|
||||
// prepare/modify well state and control
|
||||
well_copy.prepareForPotentialCalculations(summary_state, well_state_copy, inj_controls, prod_controls);
|
||||
|
||||
|
||||
// initialize rates from previous potentials
|
||||
const int np = this->number_of_phases_;
|
||||
bool trivial = true;
|
||||
@ -1718,7 +1723,7 @@ namespace Opm
|
||||
if (this->param_.local_well_solver_control_switching_) {
|
||||
converged_implicit = computeWellPotentialsImplicit(simulator, well_potentials, deferred_logger);
|
||||
}
|
||||
if (!converged_implicit) {
|
||||
if (!converged_implicit) {
|
||||
// does the well have a THP related constraint?
|
||||
const auto& summaryState = simulator.vanguard().summaryState();
|
||||
if (!Base::wellHasTHPConstraints(summaryState) || bhp_controlled_well) {
|
||||
@ -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
|
||||
@ -1841,7 +1846,7 @@ namespace Opm
|
||||
PerforationRates<Scalar> perf_rates;
|
||||
Scalar trans_mult = simulator.problem().template wellTransMultiplier<Scalar>(int_quant, cell_idx);
|
||||
const auto& wellstate_nupcol = simulator.problem().wellModel().nupcolWellState().well(this->index_of_well_);
|
||||
const std::vector<Scalar> Tw = this->wellIndex(perf, int_quant, trans_mult, wellstate_nupcol);
|
||||
const std::vector<Scalar> Tw = this->wellIndex(perf, int_quant, trans_mult, wellstate_nupcol);
|
||||
computePerfRate(int_quant, mob, bhp, Tw, perf, allow_cf, cq_s,
|
||||
perf_rates, deferred_logger);
|
||||
// TODO: make area a member
|
||||
@ -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
|
||||
@ -2340,8 +2344,8 @@ namespace Opm
|
||||
const Well::ProductionControls& prod_controls,
|
||||
WellState<Scalar>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control /*false*/,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control /*false*/,
|
||||
const bool fixed_status /*false*/)
|
||||
{
|
||||
const int max_iter = this->param_.max_inner_iter_wells_;
|
||||
@ -2352,8 +2356,8 @@ namespace Opm
|
||||
const auto& summary_state = simulator.vanguard().summaryState();
|
||||
|
||||
// Always take a few (more than one) iterations after a switch before allowing a new switch
|
||||
// The optimal number here is subject to further investigation, but it has been observerved
|
||||
// that unless this number is >1, we may get stuck in a cycle
|
||||
// The optimal number here is subject to further investigation, but it has been observerved
|
||||
// that unless this number is >1, we may get stuck in a cycle
|
||||
constexpr int min_its_after_switch = 4;
|
||||
int its_since_last_switch = min_its_after_switch;
|
||||
int switch_count= 0;
|
||||
@ -2366,8 +2370,10 @@ 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->wellUnderZeroRateTarget(simulator, well_state, deferred_logger) &&
|
||||
(!fixed_control || !fixed_status) && allow_open;
|
||||
|
||||
bool changed = false;
|
||||
bool final_check = false;
|
||||
// well needs to be set operable or else solving/updating of re-opened wells is skipped
|
||||
@ -2402,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) {
|
||||
@ -2417,11 +2423,11 @@ namespace Opm
|
||||
}
|
||||
|
||||
++it;
|
||||
solveEqAndUpdateWellState(summary_state, well_state, deferred_logger);
|
||||
solveEqAndUpdateWellState(simulator, well_state, deferred_logger);
|
||||
initPrimaryVariablesEvaluation();
|
||||
|
||||
} while (it < max_iter);
|
||||
|
||||
|
||||
if (converged) {
|
||||
if (allow_switching){
|
||||
// update operability if status change
|
||||
|
@ -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,6 +225,14 @@ public:
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const = 0;
|
||||
|
||||
bool wellUnderZeroRateTarget(const Simulator& simulator,
|
||||
const WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool stoppedOrZeroRateTarget(const Simulator& simulator,
|
||||
const WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool updateWellStateWithTHPTargetProd(const Simulator& simulator,
|
||||
WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
@ -246,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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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,8 +606,8 @@ isPressureControlled(const WellState<Scalar>& well_state) const
|
||||
|
||||
template<class Scalar>
|
||||
bool WellInterfaceGeneric<Scalar>::
|
||||
wellUnderZeroRateTarget(const SummaryState& summary_state,
|
||||
const WellState<Scalar>& well_state) const
|
||||
wellUnderZeroRateTargetIndividual(const SummaryState& summary_state,
|
||||
const WellState<Scalar>& well_state) const
|
||||
{
|
||||
if (this->isProducer()) { // producers
|
||||
const auto prod_controls = this->well_ecl_.productionControls(summary_state);
|
||||
@ -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()
|
||||
{
|
||||
|
@ -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,8 +197,8 @@ protected:
|
||||
int polymerInjTable_() const;
|
||||
int polymerWaterTable_() const;
|
||||
|
||||
bool wellUnderZeroRateTarget(const SummaryState& summary_state,
|
||||
const WellState<Scalar>& well_state) const;
|
||||
bool wellUnderZeroRateTargetIndividual(const SummaryState& summary_state,
|
||||
const WellState<Scalar>& well_state) const;
|
||||
|
||||
std::pair<bool,bool>
|
||||
computeWellPotentials(std::vector<Scalar>& well_potentials,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -311,8 +310,8 @@ namespace Opm
|
||||
updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger);
|
||||
} 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,13 +537,13 @@ 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);
|
||||
bool is_stable = WellBhpThpCalculator(*this).isStableSolution(well_state, this->well_ecl_, rates, summary_state);
|
||||
if (!is_stable) {
|
||||
// solution converged to an unstable point!
|
||||
// solution converged to an unstable point!
|
||||
this->operability_status_.use_vfpexplicit = true;
|
||||
auto bhp_stable = WellBhpThpCalculator(*this).estimateStableBhp(well_state, this->well_ecl_, rates, this->getRefDensity(), summary_state);
|
||||
// if we find an intersection with a sufficiently lower bhp, re-solve equations
|
||||
@ -570,10 +568,10 @@ namespace Opm
|
||||
if (!bhp_target.has_value()) {
|
||||
// well can't operate using explicit fractions
|
||||
is_operable = false;
|
||||
// solve with zero rate
|
||||
// solve with zero rate
|
||||
converged = solveWellWithZeroRate(simulator, dt, well_state, deferred_logger);
|
||||
this->stopWell();
|
||||
} else {
|
||||
} else {
|
||||
// solve well with the estimated target bhp (or limit)
|
||||
const Scalar bhp = std::max(bhp_target.value(),
|
||||
static_cast<Scalar>(prod_controls.bhp_limit));
|
||||
@ -602,8 +600,8 @@ namespace Opm
|
||||
WellState<Scalar>& well_state,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
// Given an unconverged well or closed well, estimate an operable bhp (if any)
|
||||
{
|
||||
// Given an unconverged well or closed well, estimate an operable bhp (if any)
|
||||
// Get minimal bhp from vfp-curve
|
||||
Scalar bhp_min = WellBhpThpCalculator(*this).calculateMinimumBhpFromThp(well_state, this->well_ecl_, summary_state, this->getRefDensity());
|
||||
// Solve
|
||||
@ -615,7 +613,7 @@ namespace Opm
|
||||
auto rates = well_state.well(this->index_of_well_).surface_rates;
|
||||
this->adaptRatesForVFP(rates);
|
||||
return WellBhpThpCalculator(*this).estimateStableBhp(well_state, this->well_ecl_, rates, this->getRefDensity(), summary_state);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
@ -625,11 +623,11 @@ namespace Opm
|
||||
const Scalar bhp,
|
||||
WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
{
|
||||
// Solve a well using single bhp-constraint (but close if not operable under this)
|
||||
auto group_state = GroupState<Scalar>(); // empty group
|
||||
auto inj_controls = Well::InjectionControls(0);
|
||||
auto prod_controls = Well::ProductionControls(0);
|
||||
auto prod_controls = Well::ProductionControls(0);
|
||||
auto& ws = well_state.well(this->index_of_well_);
|
||||
auto cmode_inj = ws.injection_cmode;
|
||||
auto cmode_prod = ws.production_cmode;
|
||||
@ -637,21 +635,21 @@ namespace Opm
|
||||
inj_controls.addControl(Well::InjectorCMode::BHP);
|
||||
inj_controls.bhp_limit = bhp;
|
||||
inj_controls.cmode = Well::InjectorCMode::BHP;
|
||||
ws.injection_cmode = Well::InjectorCMode::BHP;
|
||||
ws.injection_cmode = Well::InjectorCMode::BHP;
|
||||
} else {
|
||||
prod_controls.addControl(Well::ProducerCMode::BHP);
|
||||
prod_controls.bhp_limit = bhp;
|
||||
prod_controls.cmode = Well::ProducerCMode::BHP;
|
||||
ws.production_cmode = Well::ProducerCMode::BHP;
|
||||
ws.production_cmode = Well::ProducerCMode::BHP;
|
||||
}
|
||||
// update well-state
|
||||
ws.bhp = bhp;
|
||||
// solve
|
||||
// solve
|
||||
const bool converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger, /*fixed_control*/true);
|
||||
ws.injection_cmode = cmode_inj;
|
||||
ws.production_cmode = cmode_prod;
|
||||
return converged;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
@ -660,18 +658,18 @@ namespace Opm
|
||||
const double dt,
|
||||
WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
{
|
||||
// Solve a well as stopped
|
||||
const auto well_status_orig = this->wellStatus_;
|
||||
this->stopWell();
|
||||
|
||||
|
||||
auto group_state = GroupState<Scalar>(); // empty group
|
||||
auto inj_controls = Well::InjectionControls(0);
|
||||
auto prod_controls = Well::ProductionControls(0);
|
||||
auto prod_controls = Well::ProductionControls(0);
|
||||
const bool converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger, /*fixed_control*/true, /*fixed_status*/ true);
|
||||
this->wellStatus_ = well_status_orig;
|
||||
return converged;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
@ -1427,6 +1425,42 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
wellUnderZeroRateTarget(const Simulator& simulator,
|
||||
const WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// Check if well is under zero rate control, either directly or from group
|
||||
const auto& ws = well_state.well(this->index_of_well_);
|
||||
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 "individual" version
|
||||
const auto& summaryState = simulator.vanguard().summaryState();
|
||||
return this->wellUnderZeroRateTargetIndividual(summaryState, well_state);
|
||||
} else {
|
||||
const auto& summaryState = simulator.vanguard().summaryState();
|
||||
const auto& group_state = simulator.problem().wellModel().groupState();
|
||||
const auto& schedule = simulator.vanguard().schedule();
|
||||
return this->wellUnderZeroRateTargetGroup(summaryState, schedule, well_state, group_state, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
stoppedOrZeroRateTarget(const Simulator& simulator,
|
||||
const WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// Check if well is stopped or under zero rate control, either directly or from group
|
||||
return (this->wellIsStopped() || wellUnderZeroRateTarget(simulator,
|
||||
well_state,
|
||||
deferred_logger));
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
std::vector<typename WellInterface<TypeTag>::Scalar>
|
||||
WellInterface<TypeTag>::
|
||||
|
Loading…
Reference in New Issue
Block a user