mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4531 from GitPaean/trying_to_gurantee_zero_rate
making sure zero rate controlled production wells have zero rate in the simulation results
This commit is contained in:
commit
88e5b235b8
@ -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,9 @@ namespace Opm
|
||||
std::vector<double>& well_potentials,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
void updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_logger) override;
|
||||
|
||||
virtual void solveEqAndUpdateWellState(WellState& well_state, DeferredLogger& deferred_logger) override; // const?
|
||||
void updatePrimaryVariables(const SummaryState& summary_state,
|
||||
const WellState& well_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
virtual void calculateExplicitQuantities(const Simulator& ebosSimulator,
|
||||
const WellState& well_state,
|
||||
@ -171,7 +172,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);
|
||||
}
|
||||
|
||||
|
||||
@ -525,24 +529,6 @@ namespace Opm
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
solveEqAndUpdateWellState(WellState& well_state, DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
||||
|
||||
// We assemble the well equations, then we check the convergence,
|
||||
// which is why we do not put the assembleWellEq here.
|
||||
const BVectorWell dx_well = this->linSys_.solve();
|
||||
|
||||
updateWellState(dx_well, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
@ -619,7 +605,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 +615,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 +638,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 +1482,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,8 +156,6 @@ 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;
|
||||
|
||||
void assembleWellEq(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
WellState& well_state,
|
||||
@ -180,7 +178,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 +211,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 +360,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