mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
make sure zero production rates are obtained for the following wells
1. stopped production wells 2. production wells under zero rate control We guarantee the objective through enforce zero values for the WQTotal primary variable during the initialization and update process during the Newton solution.
This commit is contained in:
parent
8858d725a8
commit
2c5a4398c9
@ -1324,7 +1324,8 @@ namespace Opm {
|
||||
OPM_BEGIN_PARALLEL_TRY_CATCH();
|
||||
{
|
||||
for (auto& well : well_container_) {
|
||||
well->recoverWellSolutionAndUpdateWellState(x, this->wellState(), local_deferredLogger);
|
||||
const auto& summary_state = ebosSimulator_.vanguard().summaryState();
|
||||
well->recoverWellSolutionAndUpdateWellState(summary_state, x, this->wellState(), local_deferredLogger);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1659,7 +1660,8 @@ namespace Opm {
|
||||
auto& events = this->wellState().well(well->indexOfWell()).events;
|
||||
if (events.hasEvent(WellState::event_mask)) {
|
||||
well->updateWellStateWithTarget(ebosSimulator_, this->groupState(), this->wellState(), deferred_logger);
|
||||
well->updatePrimaryVariables(this->wellState(), deferred_logger);
|
||||
const auto& summary_state = ebosSimulator_.vanguard().summaryState();
|
||||
well->updatePrimaryVariables(summary_state, 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.
|
||||
@ -1733,7 +1735,8 @@ namespace Opm {
|
||||
updatePrimaryVariables(DeferredLogger& deferred_logger)
|
||||
{
|
||||
for (const auto& well : well_container_) {
|
||||
well->updatePrimaryVariables(this->wellState(), deferred_logger);
|
||||
const auto& summary_state = ebosSimulator_.vanguard().summaryState();
|
||||
well->updatePrimaryVariables(summary_state, this->wellState(), deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,8 @@ namespace Opm
|
||||
|
||||
/// using the solution x to recover the solution xw for wells and applying
|
||||
/// xw to update Well State
|
||||
void recoverWellSolutionAndUpdateWellState(const BVector& x,
|
||||
void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||
const BVector& x,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
@ -118,9 +119,13 @@ namespace Opm
|
||||
std::vector<double>& well_potentials,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
void updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_logger) override;
|
||||
void updatePrimaryVariables(const SummaryState& summary_state,
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
virtual void solveEqAndUpdateWellState(WellState& well_state, DeferredLogger& deferred_logger) override; // const?
|
||||
virtual void solveEqAndUpdateWellState(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger) override; // const?
|
||||
|
||||
virtual void calculateExplicitQuantities(const Simulator& ebosSimulator,
|
||||
const WellState& well_state,
|
||||
@ -171,7 +176,8 @@ namespace Opm
|
||||
mutable int debug_cost_counter_ = 0;
|
||||
|
||||
// updating the well_state based on well solution dwells
|
||||
void updateWellState(const BVectorWell& dwells,
|
||||
void updateWellState(const SummaryState& summary_state,
|
||||
const BVectorWell& dwells,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const double relaxation_factor = 1.0);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <opm/simulators/wells/MultisegmentWellPrimaryVariables.hpp>
|
||||
#include <opm/simulators/wells/WellAssemble.hpp>
|
||||
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
|
||||
#include <opm/simulators/wells/WellHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellInterfaceIndices.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
@ -163,7 +164,7 @@ assembleControlEq(const WellState& well_state,
|
||||
bhp_from_thp,
|
||||
control_eq,
|
||||
deferred_logger);
|
||||
} else if (rateControlWithZeroTarget(well_state.well(well_.indexOfWell()).production_cmode, prod_controls)) {
|
||||
} else if (wellhelpers::rateControlWithZeroTarget(well_state.well(well_.indexOfWell()).production_cmode, prod_controls)) {
|
||||
// Production mode, zero target. Treat as STOP.
|
||||
control_eq = primary_variables.getWQTotal();
|
||||
} else {
|
||||
|
@ -64,7 +64,7 @@ init()
|
||||
|
||||
template<class FluidSystem, class Indices, class Scalar>
|
||||
void MultisegmentWellPrimaryVariables<FluidSystem,Indices,Scalar>::
|
||||
update(const WellState& well_state)
|
||||
update(const WellState& well_state, const bool zero_rate_target)
|
||||
{
|
||||
static constexpr int Water = BlackoilPhases::Aqua;
|
||||
static constexpr int Gas = BlackoilPhases::Vapour;
|
||||
@ -104,6 +104,9 @@ update(const WellState& well_state)
|
||||
}
|
||||
}
|
||||
value_[seg][WQTotal] = total_seg_rate;
|
||||
if (zero_rate_target && seg == 0) {
|
||||
value_[seg][WQTotal] = 0;
|
||||
}
|
||||
if (std::abs(total_seg_rate) > 0.) {
|
||||
if (has_wfrac_variable) {
|
||||
const int water_pos = pu.phase_pos[Water];
|
||||
@ -152,6 +155,7 @@ void MultisegmentWellPrimaryVariables<FluidSystem,Indices,Scalar>::
|
||||
updateNewton(const BVectorWell& dwells,
|
||||
const double relaxation_factor,
|
||||
const double dFLimit,
|
||||
const bool zero_rate_target,
|
||||
const double max_pressure_change)
|
||||
{
|
||||
const std::vector<std::array<double, numWellEq>> old_primary_variables = value_;
|
||||
@ -193,6 +197,10 @@ updateNewton(const BVectorWell& dwells,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (zero_rate_target) {
|
||||
value_[0][WQTotal] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
template<class FluidSystem, class Indices, class Scalar>
|
||||
|
@ -88,12 +88,13 @@ public:
|
||||
void init();
|
||||
|
||||
//! \brief Copy values from well state.
|
||||
void update(const WellState& well_state);
|
||||
void update(const WellState& well_state, const bool zero_rate_target);
|
||||
|
||||
//! \brief Update values from newton update vector.
|
||||
void updateNewton(const BVectorWell& dwells,
|
||||
const double relaxation_factor,
|
||||
const double DFLimit,
|
||||
const bool zero_rate_target,
|
||||
const double max_pressure_change);
|
||||
|
||||
//! \brief Copy values to well state.
|
||||
|
@ -148,9 +148,12 @@ namespace Opm
|
||||
template <typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
updatePrimaryVariables(const WellState& well_state, DeferredLogger& /* deferred_logger */)
|
||||
updatePrimaryVariables(const SummaryState& summary_state,
|
||||
const WellState& well_state,
|
||||
DeferredLogger& /* deferred_logger */)
|
||||
{
|
||||
this->primary_variables_.update(well_state);
|
||||
const bool zero_rate_target = this->wellUnderZeroProductionRateControl(summary_state, well_state);
|
||||
this->primary_variables_.update(well_state, zero_rate_target);
|
||||
}
|
||||
|
||||
|
||||
@ -240,7 +243,8 @@ namespace Opm
|
||||
template <typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
recoverWellSolutionAndUpdateWellState(const BVector& x,
|
||||
recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||
const BVector& x,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
@ -250,7 +254,7 @@ namespace Opm
|
||||
|
||||
BVectorWell xw(1);
|
||||
this->linSys_.recoverSolutionWell(x, xw);
|
||||
updateWellState(xw, well_state, deferred_logger);
|
||||
updateWellState(summary_state, xw, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
@ -528,7 +532,9 @@ namespace Opm
|
||||
template <typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
solveEqAndUpdateWellState(WellState& well_state, DeferredLogger& deferred_logger)
|
||||
solveEqAndUpdateWellState(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
||||
|
||||
@ -536,7 +542,8 @@ namespace Opm
|
||||
// which is why we do not put the assembleWellEq here.
|
||||
const BVectorWell dx_well = this->linSys_.solve();
|
||||
|
||||
updateWellState(dx_well, well_state, deferred_logger);
|
||||
const auto& summary_state = ebos_simulator.vanguard().summaryState();
|
||||
updateWellState(summary_state, dx_well, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
@ -619,7 +626,8 @@ namespace Opm
|
||||
template <typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
updateWellState(const BVectorWell& dwells,
|
||||
updateWellState(const SummaryState& summary_state,
|
||||
const BVectorWell& dwells,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const double relaxation_factor)
|
||||
@ -628,9 +636,11 @@ namespace Opm
|
||||
|
||||
const double dFLimit = this->param_.dwell_fraction_max_;
|
||||
const double max_pressure_change = this->param_.max_pressure_change_ms_wells_;
|
||||
const bool zero_rate_target = this->wellUnderZeroProductionRateControl(summary_state, well_state);
|
||||
this->primary_variables_.updateNewton(dwells,
|
||||
relaxation_factor,
|
||||
dFLimit,
|
||||
zero_rate_target,
|
||||
max_pressure_change);
|
||||
|
||||
this->primary_variables_.copyToWellState(*this, getRefDensity(),
|
||||
@ -649,7 +659,8 @@ namespace Opm
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
updatePrimaryVariables(well_state, deferred_logger);
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
updatePrimaryVariables(summary_state, well_state, deferred_logger);
|
||||
initPrimaryVariablesEvaluation();
|
||||
computePerfCellPressDiffs(ebosSimulator);
|
||||
computeInitialSegmentFluids(ebosSimulator);
|
||||
@ -1492,7 +1503,8 @@ namespace Opm
|
||||
this->regularize_ = true;
|
||||
deferred_logger.debug(sstr.str());
|
||||
}
|
||||
updateWellState(dx_well, well_state, deferred_logger, relaxation_factor);
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
updateWellState(summary_state, dx_well, well_state, deferred_logger, relaxation_factor);
|
||||
initPrimaryVariablesEvaluation();
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,8 @@ namespace Opm
|
||||
|
||||
/// using the solution x to recover the solution xw for wells and applying
|
||||
/// xw to update Well State
|
||||
void recoverWellSolutionAndUpdateWellState(const BVector& x,
|
||||
void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||
const BVector& x,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
@ -166,9 +167,13 @@ namespace Opm
|
||||
std::vector<double>& well_potentials,
|
||||
DeferredLogger& deferred_logger) /* const */ override;
|
||||
|
||||
void updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_logger) override;
|
||||
void updatePrimaryVariables(const SummaryState& summary_state,
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
virtual void solveEqAndUpdateWellState(WellState& well_state, DeferredLogger& deferred_logger) override;
|
||||
void solveEqAndUpdateWellState(const SummaryState& summary_state,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
virtual void calculateExplicitQuantities(const Simulator& ebosSimulator,
|
||||
const WellState& well_state,
|
||||
@ -252,7 +257,8 @@ namespace Opm
|
||||
bool regularize_;
|
||||
|
||||
// updating the well_state based on well solution dwells
|
||||
void updateWellState(const BVectorWell& dwells,
|
||||
void updateWellState(const SummaryState& summary_state,
|
||||
const BVectorWell& dwells,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
@ -359,7 +365,7 @@ namespace Opm
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
void updatePrimaryVariablesNewton(const BVectorWell& dwells,
|
||||
const WellState& well_state,
|
||||
const bool zero_rate_target,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
void updateWellStateFromPrimaryVariables(WellState& well_state, DeferredLogger& deferred_logger) const;
|
||||
|
@ -143,7 +143,7 @@ assembleControlEq(const WellState& well_state,
|
||||
bhp_from_thp,
|
||||
control_eq,
|
||||
deferred_logger);
|
||||
} else if (rateControlWithZeroTarget(well_state.well(well_.indexOfWell()).production_cmode, prod_controls)) {
|
||||
} else if (wellhelpers::rateControlWithZeroTarget(well_state.well(well_.indexOfWell()).production_cmode, prod_controls)) {
|
||||
// Production mode, zero target. Treat as STOP.
|
||||
control_eq = primary_variables.eval(PrimaryVariables::WQTotal);
|
||||
} else {
|
||||
|
@ -81,7 +81,7 @@ Scalar relaxationFactorRate(const Scalar old_value,
|
||||
const Scalar original_total_rate = old_value;
|
||||
const Scalar possible_update_total_rate = old_value - newton_update;
|
||||
|
||||
// 0.8 here is a experimental value, which remains to be optimized
|
||||
// 0.8 here is an experimental value, which remains to be optimized
|
||||
// if the original rate is zero or possible_update_total_rate is zero, relaxation_factor will
|
||||
// always be 1.0, more thoughts might be needed.
|
||||
if (original_total_rate * possible_update_total_rate < 0.) { // sign changed
|
||||
@ -121,7 +121,9 @@ resize(const int numWellEq)
|
||||
|
||||
template<class FluidSystem, class Indices, class Scalar>
|
||||
void StandardWellPrimaryVariables<FluidSystem,Indices,Scalar>::
|
||||
update(const WellState& well_state, DeferredLogger& deferred_logger)
|
||||
update(const WellState& well_state,
|
||||
const bool zero_rate_target,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
static constexpr int Water = BlackoilPhases::Aqua;
|
||||
static constexpr int Oil = BlackoilPhases::Liquid;
|
||||
@ -158,6 +160,9 @@ update(const WellState& well_state, DeferredLogger& deferred_logger)
|
||||
}
|
||||
} else {
|
||||
value_[WQTotal] = total_well_rate;
|
||||
if (zero_rate_target) {
|
||||
value_[WQTotal] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::abs(total_well_rate) > 0.) {
|
||||
@ -240,6 +245,7 @@ updatePolyMW(const WellState& well_state)
|
||||
template<class FluidSystem, class Indices, class Scalar>
|
||||
void StandardWellPrimaryVariables<FluidSystem,Indices,Scalar>::
|
||||
updateNewton(const BVectorWell& dwells,
|
||||
const bool zero_rate_target,
|
||||
[[maybe_unused]] const double dFLimit,
|
||||
const double dBHPLimit)
|
||||
{
|
||||
@ -275,6 +281,10 @@ updateNewton(const BVectorWell& dwells,
|
||||
|
||||
// updating the total rates Q_t
|
||||
value_[WQTotal] = value_[WQTotal] - dwells[0][WQTotal] * relaxation_factor_rate;
|
||||
if (zero_rate_target) {
|
||||
value_[WQTotal] = 0.;
|
||||
}
|
||||
// TODO: here, we make sure it is zero for zero rated wells
|
||||
|
||||
// updating the bottom hole pressure
|
||||
const int sign1 = dwells[0][Bhp] > 0 ? 1: -1;
|
||||
|
@ -101,13 +101,16 @@ public:
|
||||
int numWellEq() const { return numWellEq_; }
|
||||
|
||||
//! \brief Copy values from well state.
|
||||
void update(const WellState& well_state, DeferredLogger& deferred_logger);
|
||||
void update(const WellState& well_state,
|
||||
const bool zero_rate_target,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
//! \brief Copy polymer molecular weigt values from well state.
|
||||
void updatePolyMW(const WellState& well_state);
|
||||
|
||||
//! \brief Update values from newton update vector.
|
||||
void updateNewton(const BVectorWell& dwells,
|
||||
const bool zero_rate_target,
|
||||
const double dFLimit,
|
||||
const double dBHPLimit);
|
||||
|
||||
|
@ -993,13 +993,15 @@ namespace Opm
|
||||
template<typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
updateWellState(const BVectorWell& dwells,
|
||||
updateWellState(const SummaryState& summary_state,
|
||||
const BVectorWell& dwells,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
||||
|
||||
updatePrimaryVariablesNewton(dwells, well_state, deferred_logger);
|
||||
const bool zero_rate_target = this->wellUnderZeroProductionRateControl(summary_state, well_state);
|
||||
updatePrimaryVariablesNewton(dwells, zero_rate_target, deferred_logger);
|
||||
|
||||
updateWellStateFromPrimaryVariables(well_state, deferred_logger);
|
||||
Base::calculateReservoirRates(well_state.well(this->index_of_well_));
|
||||
@ -1013,12 +1015,12 @@ namespace Opm
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
updatePrimaryVariablesNewton(const BVectorWell& dwells,
|
||||
const WellState& /* well_state */,
|
||||
const bool zero_rate_target,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
const double dFLimit = this->param_.dwell_fraction_max_;
|
||||
const double dBHPLimit = this->param_.dbhp_max_rel_;
|
||||
this->primary_variables_.updateNewton(dwells, dFLimit, dBHPLimit);
|
||||
this->primary_variables_.updateNewton(dwells, zero_rate_target, dFLimit, dBHPLimit);
|
||||
|
||||
// for the water velocity and skin pressure
|
||||
if constexpr (Base::has_polymermw) {
|
||||
@ -1581,7 +1583,9 @@ namespace Opm
|
||||
template<typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
solveEqAndUpdateWellState(WellState& well_state, DeferredLogger& deferred_logger)
|
||||
solveEqAndUpdateWellState(const SummaryState& summary_state,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
||||
|
||||
@ -1591,7 +1595,7 @@ namespace Opm
|
||||
dx_well[0].resize(this->primary_variables_.numWellEq());
|
||||
this->linSys_.solve( dx_well);
|
||||
|
||||
updateWellState(dx_well, well_state, deferred_logger);
|
||||
updateWellState(summary_state, dx_well, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
@ -1605,7 +1609,8 @@ namespace Opm
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
updatePrimaryVariables(well_state, deferred_logger);
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
updatePrimaryVariables(summary_state, well_state, deferred_logger);
|
||||
initPrimaryVariablesEvaluation();
|
||||
computeWellConnectionPressures(ebosSimulator, well_state, deferred_logger);
|
||||
this->computeAccumWell();
|
||||
@ -1648,7 +1653,8 @@ namespace Opm
|
||||
template<typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
recoverWellSolutionAndUpdateWellState(const BVector& x,
|
||||
recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||
const BVector& x,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
@ -1658,7 +1664,7 @@ namespace Opm
|
||||
xw[0].resize(this->primary_variables_.numWellEq());
|
||||
|
||||
this->linSys_.recoverSolutionWell(x, xw);
|
||||
updateWellState(xw, well_state, deferred_logger);
|
||||
updateWellState(summary_state, xw, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
@ -1754,7 +1760,7 @@ namespace Opm
|
||||
" potentials are computed based on unconverged solution";
|
||||
deferred_logger.debug(msg);
|
||||
}
|
||||
well_copy.updatePrimaryVariables(well_state_copy, deferred_logger);
|
||||
well_copy.updatePrimaryVariables(summary_state, well_state_copy, deferred_logger);
|
||||
well_copy.computeWellConnectionPressures(ebosSimulator, well_state_copy, deferred_logger);
|
||||
well_copy.initPrimaryVariablesEvaluation();
|
||||
well_copy.computeWellRatesWithBhp(ebosSimulator, bhp, well_flux, deferred_logger);
|
||||
@ -1970,11 +1976,14 @@ namespace Opm
|
||||
template<typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_logger)
|
||||
updatePrimaryVariables(const SummaryState& summary_state,
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
||||
|
||||
this->primary_variables_.update(well_state, deferred_logger);
|
||||
const bool zero_rate_target = this->wellUnderZeroProductionRateControl(summary_state, well_state);
|
||||
this->primary_variables_.update(well_state, zero_rate_target, deferred_logger);
|
||||
|
||||
// other primary variables related to polymer injection
|
||||
if constexpr (Base::has_polymermw) {
|
||||
@ -2511,7 +2520,8 @@ namespace Opm
|
||||
}
|
||||
|
||||
++it;
|
||||
solveEqAndUpdateWellState(well_state, deferred_logger);
|
||||
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||
solveEqAndUpdateWellState(summary_state, 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
|
||||
|
@ -43,32 +43,6 @@
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
bool rateControlWithZeroTarget(const Well::ProducerCMode mode,
|
||||
const Well::ProductionControls& controls)
|
||||
{
|
||||
switch (mode) {
|
||||
case Well::ProducerCMode::ORAT:
|
||||
return controls.oil_rate == 0.0;
|
||||
case Well::ProducerCMode::WRAT:
|
||||
return controls.water_rate == 0.0;
|
||||
case Well::ProducerCMode::GRAT:
|
||||
return controls.gas_rate == 0.0;
|
||||
case Well::ProducerCMode::LRAT:
|
||||
return controls.liquid_rate == 0.0;
|
||||
case Well::ProducerCMode::CRAT:
|
||||
// Unsupported, will cause exception elsewhere, treat as nonzero target here.
|
||||
return false;
|
||||
case Well::ProducerCMode::RESV:
|
||||
if (controls.prediction_mode) {
|
||||
return controls.resv_rate == 0.0;
|
||||
} else {
|
||||
return controls.water_rate == 0.0 && controls.oil_rate == 0.0 && controls.gas_rate == 0.0;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<class FluidSystem>
|
||||
WellAssemble<FluidSystem>::
|
||||
WellAssemble(const WellInterfaceFluidSystem<FluidSystem>& well)
|
||||
|
@ -44,10 +44,6 @@ class WellState;
|
||||
class WellInjectionControls;
|
||||
class WellProductionControls;
|
||||
|
||||
/// Helper to avoid singular control equations.
|
||||
bool rateControlWithZeroTarget(const WellProducerCMode mode,
|
||||
const WellProductionControls& controls);
|
||||
|
||||
template<class FluidSystem>
|
||||
class WellAssemble {
|
||||
static constexpr int Water = BlackoilPhases::Aqua;
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Well/WellProductionControls.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellEnums.hpp>
|
||||
|
||||
#include <opm/simulators/wells/ParallelWellInfo.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
@ -168,6 +171,33 @@ DenseMatrix transposeDenseDynMatrix(const DenseMatrix& M)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool rateControlWithZeroTarget(const WellProducerCMode& mode,
|
||||
const WellProductionControls& controls)
|
||||
{
|
||||
switch (mode) {
|
||||
case WellProducerCMode::ORAT:
|
||||
return controls.oil_rate == 0.0;
|
||||
case WellProducerCMode::WRAT:
|
||||
return controls.water_rate == 0.0;
|
||||
case WellProducerCMode::GRAT:
|
||||
return controls.gas_rate == 0.0;
|
||||
case WellProducerCMode::LRAT:
|
||||
return controls.liquid_rate == 0.0;
|
||||
case WellProducerCMode::CRAT:
|
||||
// Unsupported, will cause exception elsewhere, treat as nonzero target here.
|
||||
return false;
|
||||
case WellProducerCMode::RESV:
|
||||
if (controls.prediction_mode) {
|
||||
return controls.resv_rate == 0.0;
|
||||
} else {
|
||||
return controls.water_rate == 0.0 && controls.oil_rate == 0.0 && controls.gas_rate == 0.0;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template class ParallelStandardWellB<double>;
|
||||
|
||||
template<int Dim> using Vec = Dune::BlockVector<Dune::FieldVector<double,Dim>>;
|
||||
|
@ -31,6 +31,8 @@
|
||||
namespace Opm {
|
||||
|
||||
class ParallelWellInfo;
|
||||
enum class WellProducerCMode;
|
||||
class WellProductionControls;
|
||||
|
||||
namespace wellhelpers {
|
||||
|
||||
@ -83,6 +85,10 @@ void sumDistributedWellEntries(Dune::DynamicMatrix<Scalar>& mat,
|
||||
template <class DenseMatrix>
|
||||
DenseMatrix transposeDenseDynMatrix(const DenseMatrix& M);
|
||||
|
||||
/// Helper to check whether the well is under zero production rate control
|
||||
bool rateControlWithZeroTarget(const WellProducerCMode& mode,
|
||||
const WellProductionControls& controls);
|
||||
|
||||
} // namespace wellhelpers
|
||||
} // namespace Opm
|
||||
|
||||
|
@ -156,7 +156,9 @@ public:
|
||||
|
||||
virtual ConvergenceReport getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, DeferredLogger& deferred_logger, const bool relax_tolerance) const = 0;
|
||||
|
||||
virtual void solveEqAndUpdateWellState(WellState& well_state, DeferredLogger& deferred_logger) = 0;
|
||||
virtual void solveEqAndUpdateWellState(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
void assembleWellEq(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
@ -180,7 +182,8 @@ public:
|
||||
|
||||
/// using the solution x to recover the solution xw for wells and applying
|
||||
/// xw to update Well State
|
||||
virtual void recoverWellSolutionAndUpdateWellState(const BVector& x,
|
||||
virtual void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||
const BVector& x,
|
||||
WellState& well_state,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
@ -212,7 +215,9 @@ public:
|
||||
const GroupState& group_state,
|
||||
DeferredLogger& deferred_logger) /* const */;
|
||||
|
||||
virtual void updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_logger) = 0;
|
||||
virtual void updatePrimaryVariables(const SummaryState& summary_state,
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
virtual void calculateExplicitQuantities(const Simulator& ebosSimulator,
|
||||
const WellState& well_state,
|
||||
@ -359,7 +364,8 @@ protected:
|
||||
|
||||
Eval getPerfCellPressure(const FluidState& fs) const;
|
||||
|
||||
|
||||
bool wellUnderZeroProductionRateControl(const SummaryState& summary_state,
|
||||
const WellState& well_state) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
#include <opm/simulators/wells/TargetCalculator.hpp>
|
||||
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
|
||||
#include <opm/simulators/wells/WellHelpers.hpp>
|
||||
|
||||
#include <dune/common/version.hh>
|
||||
|
||||
@ -244,7 +245,7 @@ namespace Opm
|
||||
|
||||
this->well_control_log_.push_back(from);
|
||||
updateWellStateWithTarget(ebos_simulator, group_state, well_state, deferred_logger);
|
||||
updatePrimaryVariables(well_state, deferred_logger);
|
||||
updatePrimaryVariables(summaryState, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
return changed;
|
||||
@ -269,7 +270,8 @@ namespace Opm
|
||||
|
||||
updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger);
|
||||
calculateExplicitQuantities(simulator, well_state_copy, deferred_logger);
|
||||
updatePrimaryVariables(well_state_copy, deferred_logger);
|
||||
const auto& summary_state = simulator.vanguard().summaryState();
|
||||
updatePrimaryVariables(summary_state, well_state_copy, deferred_logger);
|
||||
initPrimaryVariablesEvaluation();
|
||||
|
||||
if (this->isProducer()) {
|
||||
@ -1128,4 +1130,19 @@ namespace Opm
|
||||
return fs.pressure(FluidSystem::gasPhaseIdx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
bool WellInterface<TypeTag>::wellUnderZeroProductionRateControl(const SummaryState& summary_state,
|
||||
const WellState& well_state) const
|
||||
{
|
||||
if (this->wellIsStopped()) return true;
|
||||
|
||||
bool zero_rate_target = false;
|
||||
if (this->well_ecl_.isProducer()) {
|
||||
const auto prod_controls = this->well_ecl_.productionControls(summary_state);
|
||||
zero_rate_target = wellhelpers::rateControlWithZeroTarget(well_state.well(this->index_of_well_).production_cmode, prod_controls);
|
||||
}
|
||||
return zero_rate_target;
|
||||
}
|
||||
} // namespace Opm
|
||||
|
Loading…
Reference in New Issue
Block a user