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();
|
OPM_BEGIN_PARALLEL_TRY_CATCH();
|
||||||
{
|
{
|
||||||
for (auto& well : well_container_) {
|
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;
|
auto& events = this->wellState().well(well->indexOfWell()).events;
|
||||||
if (events.hasEvent(WellState::event_mask)) {
|
if (events.hasEvent(WellState::event_mask)) {
|
||||||
well->updateWellStateWithTarget(ebosSimulator_, this->groupState(), this->wellState(), deferred_logger);
|
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();
|
well->initPrimaryVariablesEvaluation();
|
||||||
// There is no new well control change input within a report step,
|
// 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.
|
// so next time step, the well does not consider to have effective events anymore.
|
||||||
@ -1733,7 +1735,8 @@ namespace Opm {
|
|||||||
updatePrimaryVariables(DeferredLogger& deferred_logger)
|
updatePrimaryVariables(DeferredLogger& deferred_logger)
|
||||||
{
|
{
|
||||||
for (const auto& well : well_container_) {
|
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
|
/// using the solution x to recover the solution xw for wells and applying
|
||||||
/// xw to update Well State
|
/// xw to update Well State
|
||||||
void recoverWellSolutionAndUpdateWellState(const BVector& x,
|
void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||||
|
const BVector& x,
|
||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger) override;
|
DeferredLogger& deferred_logger) override;
|
||||||
|
|
||||||
@ -118,9 +119,13 @@ namespace Opm
|
|||||||
std::vector<double>& well_potentials,
|
std::vector<double>& well_potentials,
|
||||||
DeferredLogger& deferred_logger) override;
|
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,
|
virtual void calculateExplicitQuantities(const Simulator& ebosSimulator,
|
||||||
const WellState& well_state,
|
const WellState& well_state,
|
||||||
@ -171,7 +176,8 @@ namespace Opm
|
|||||||
mutable int debug_cost_counter_ = 0;
|
mutable int debug_cost_counter_ = 0;
|
||||||
|
|
||||||
// updating the well_state based on well solution dwells
|
// 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,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger,
|
DeferredLogger& deferred_logger,
|
||||||
const double relaxation_factor = 1.0);
|
const double relaxation_factor = 1.0);
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <opm/simulators/wells/MultisegmentWellPrimaryVariables.hpp>
|
#include <opm/simulators/wells/MultisegmentWellPrimaryVariables.hpp>
|
||||||
#include <opm/simulators/wells/WellAssemble.hpp>
|
#include <opm/simulators/wells/WellAssemble.hpp>
|
||||||
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
|
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
|
||||||
|
#include <opm/simulators/wells/WellHelpers.hpp>
|
||||||
#include <opm/simulators/wells/WellInterfaceIndices.hpp>
|
#include <opm/simulators/wells/WellInterfaceIndices.hpp>
|
||||||
#include <opm/simulators/wells/WellState.hpp>
|
#include <opm/simulators/wells/WellState.hpp>
|
||||||
|
|
||||||
@ -163,7 +164,7 @@ assembleControlEq(const WellState& well_state,
|
|||||||
bhp_from_thp,
|
bhp_from_thp,
|
||||||
control_eq,
|
control_eq,
|
||||||
deferred_logger);
|
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.
|
// Production mode, zero target. Treat as STOP.
|
||||||
control_eq = primary_variables.getWQTotal();
|
control_eq = primary_variables.getWQTotal();
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,7 +64,7 @@ init()
|
|||||||
|
|
||||||
template<class FluidSystem, class Indices, class Scalar>
|
template<class FluidSystem, class Indices, class Scalar>
|
||||||
void MultisegmentWellPrimaryVariables<FluidSystem,Indices,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 Water = BlackoilPhases::Aqua;
|
||||||
static constexpr int Gas = BlackoilPhases::Vapour;
|
static constexpr int Gas = BlackoilPhases::Vapour;
|
||||||
@ -104,6 +104,9 @@ update(const WellState& well_state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
value_[seg][WQTotal] = total_seg_rate;
|
value_[seg][WQTotal] = total_seg_rate;
|
||||||
|
if (zero_rate_target && seg == 0) {
|
||||||
|
value_[seg][WQTotal] = 0;
|
||||||
|
}
|
||||||
if (std::abs(total_seg_rate) > 0.) {
|
if (std::abs(total_seg_rate) > 0.) {
|
||||||
if (has_wfrac_variable) {
|
if (has_wfrac_variable) {
|
||||||
const int water_pos = pu.phase_pos[Water];
|
const int water_pos = pu.phase_pos[Water];
|
||||||
@ -152,6 +155,7 @@ void MultisegmentWellPrimaryVariables<FluidSystem,Indices,Scalar>::
|
|||||||
updateNewton(const BVectorWell& dwells,
|
updateNewton(const BVectorWell& dwells,
|
||||||
const double relaxation_factor,
|
const double relaxation_factor,
|
||||||
const double dFLimit,
|
const double dFLimit,
|
||||||
|
const bool zero_rate_target,
|
||||||
const double max_pressure_change)
|
const double max_pressure_change)
|
||||||
{
|
{
|
||||||
const std::vector<std::array<double, numWellEq>> old_primary_variables = value_;
|
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>
|
template<class FluidSystem, class Indices, class Scalar>
|
||||||
|
@ -88,12 +88,13 @@ public:
|
|||||||
void init();
|
void init();
|
||||||
|
|
||||||
//! \brief Copy values from well state.
|
//! \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.
|
//! \brief Update values from newton update vector.
|
||||||
void updateNewton(const BVectorWell& dwells,
|
void updateNewton(const BVectorWell& dwells,
|
||||||
const double relaxation_factor,
|
const double relaxation_factor,
|
||||||
const double DFLimit,
|
const double DFLimit,
|
||||||
|
const bool zero_rate_target,
|
||||||
const double max_pressure_change);
|
const double max_pressure_change);
|
||||||
|
|
||||||
//! \brief Copy values to well state.
|
//! \brief Copy values to well state.
|
||||||
|
@ -148,9 +148,12 @@ namespace Opm
|
|||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
void
|
void
|
||||||
MultisegmentWell<TypeTag>::
|
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>
|
template <typename TypeTag>
|
||||||
void
|
void
|
||||||
MultisegmentWell<TypeTag>::
|
MultisegmentWell<TypeTag>::
|
||||||
recoverWellSolutionAndUpdateWellState(const BVector& x,
|
recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||||
|
const BVector& x,
|
||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger)
|
DeferredLogger& deferred_logger)
|
||||||
{
|
{
|
||||||
@ -250,7 +254,7 @@ namespace Opm
|
|||||||
|
|
||||||
BVectorWell xw(1);
|
BVectorWell xw(1);
|
||||||
this->linSys_.recoverSolutionWell(x, xw);
|
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>
|
template <typename TypeTag>
|
||||||
void
|
void
|
||||||
MultisegmentWell<TypeTag>::
|
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;
|
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
||||||
|
|
||||||
@ -536,7 +542,8 @@ namespace Opm
|
|||||||
// which is why we do not put the assembleWellEq here.
|
// which is why we do not put the assembleWellEq here.
|
||||||
const BVectorWell dx_well = this->linSys_.solve();
|
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>
|
template <typename TypeTag>
|
||||||
void
|
void
|
||||||
MultisegmentWell<TypeTag>::
|
MultisegmentWell<TypeTag>::
|
||||||
updateWellState(const BVectorWell& dwells,
|
updateWellState(const SummaryState& summary_state,
|
||||||
|
const BVectorWell& dwells,
|
||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger,
|
DeferredLogger& deferred_logger,
|
||||||
const double relaxation_factor)
|
const double relaxation_factor)
|
||||||
@ -628,9 +636,11 @@ namespace Opm
|
|||||||
|
|
||||||
const double dFLimit = this->param_.dwell_fraction_max_;
|
const double dFLimit = this->param_.dwell_fraction_max_;
|
||||||
const double max_pressure_change = this->param_.max_pressure_change_ms_wells_;
|
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,
|
this->primary_variables_.updateNewton(dwells,
|
||||||
relaxation_factor,
|
relaxation_factor,
|
||||||
dFLimit,
|
dFLimit,
|
||||||
|
zero_rate_target,
|
||||||
max_pressure_change);
|
max_pressure_change);
|
||||||
|
|
||||||
this->primary_variables_.copyToWellState(*this, getRefDensity(),
|
this->primary_variables_.copyToWellState(*this, getRefDensity(),
|
||||||
@ -649,7 +659,8 @@ namespace Opm
|
|||||||
const WellState& well_state,
|
const WellState& well_state,
|
||||||
DeferredLogger& deferred_logger)
|
DeferredLogger& deferred_logger)
|
||||||
{
|
{
|
||||||
updatePrimaryVariables(well_state, deferred_logger);
|
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||||
|
updatePrimaryVariables(summary_state, well_state, deferred_logger);
|
||||||
initPrimaryVariablesEvaluation();
|
initPrimaryVariablesEvaluation();
|
||||||
computePerfCellPressDiffs(ebosSimulator);
|
computePerfCellPressDiffs(ebosSimulator);
|
||||||
computeInitialSegmentFluids(ebosSimulator);
|
computeInitialSegmentFluids(ebosSimulator);
|
||||||
@ -1492,7 +1503,8 @@ namespace Opm
|
|||||||
this->regularize_ = true;
|
this->regularize_ = true;
|
||||||
deferred_logger.debug(sstr.str());
|
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();
|
initPrimaryVariablesEvaluation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,8 @@ namespace Opm
|
|||||||
|
|
||||||
/// using the solution x to recover the solution xw for wells and applying
|
/// using the solution x to recover the solution xw for wells and applying
|
||||||
/// xw to update Well State
|
/// xw to update Well State
|
||||||
void recoverWellSolutionAndUpdateWellState(const BVector& x,
|
void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||||
|
const BVector& x,
|
||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger) override;
|
DeferredLogger& deferred_logger) override;
|
||||||
|
|
||||||
@ -166,9 +167,13 @@ namespace Opm
|
|||||||
std::vector<double>& well_potentials,
|
std::vector<double>& well_potentials,
|
||||||
DeferredLogger& deferred_logger) /* const */ override;
|
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,
|
virtual void calculateExplicitQuantities(const Simulator& ebosSimulator,
|
||||||
const WellState& well_state,
|
const WellState& well_state,
|
||||||
@ -252,7 +257,8 @@ namespace Opm
|
|||||||
bool regularize_;
|
bool regularize_;
|
||||||
|
|
||||||
// updating the well_state based on well solution dwells
|
// 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,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger);
|
DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
@ -359,7 +365,7 @@ namespace Opm
|
|||||||
DeferredLogger& deferred_logger) const;
|
DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
void updatePrimaryVariablesNewton(const BVectorWell& dwells,
|
void updatePrimaryVariablesNewton(const BVectorWell& dwells,
|
||||||
const WellState& well_state,
|
const bool zero_rate_target,
|
||||||
DeferredLogger& deferred_logger);
|
DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
void updateWellStateFromPrimaryVariables(WellState& well_state, DeferredLogger& deferred_logger) const;
|
void updateWellStateFromPrimaryVariables(WellState& well_state, DeferredLogger& deferred_logger) const;
|
||||||
|
@ -143,7 +143,7 @@ assembleControlEq(const WellState& well_state,
|
|||||||
bhp_from_thp,
|
bhp_from_thp,
|
||||||
control_eq,
|
control_eq,
|
||||||
deferred_logger);
|
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.
|
// Production mode, zero target. Treat as STOP.
|
||||||
control_eq = primary_variables.eval(PrimaryVariables::WQTotal);
|
control_eq = primary_variables.eval(PrimaryVariables::WQTotal);
|
||||||
} else {
|
} else {
|
||||||
|
@ -81,7 +81,7 @@ Scalar relaxationFactorRate(const Scalar old_value,
|
|||||||
const Scalar original_total_rate = old_value;
|
const Scalar original_total_rate = old_value;
|
||||||
const Scalar possible_update_total_rate = old_value - newton_update;
|
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
|
// 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.
|
// always be 1.0, more thoughts might be needed.
|
||||||
if (original_total_rate * possible_update_total_rate < 0.) { // sign changed
|
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>
|
template<class FluidSystem, class Indices, class Scalar>
|
||||||
void StandardWellPrimaryVariables<FluidSystem,Indices,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 Water = BlackoilPhases::Aqua;
|
||||||
static constexpr int Oil = BlackoilPhases::Liquid;
|
static constexpr int Oil = BlackoilPhases::Liquid;
|
||||||
@ -158,6 +160,9 @@ update(const WellState& well_state, DeferredLogger& deferred_logger)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value_[WQTotal] = total_well_rate;
|
value_[WQTotal] = total_well_rate;
|
||||||
|
if (zero_rate_target) {
|
||||||
|
value_[WQTotal] = 0.;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::abs(total_well_rate) > 0.) {
|
if (std::abs(total_well_rate) > 0.) {
|
||||||
@ -240,6 +245,7 @@ updatePolyMW(const WellState& well_state)
|
|||||||
template<class FluidSystem, class Indices, class Scalar>
|
template<class FluidSystem, class Indices, class Scalar>
|
||||||
void StandardWellPrimaryVariables<FluidSystem,Indices,Scalar>::
|
void StandardWellPrimaryVariables<FluidSystem,Indices,Scalar>::
|
||||||
updateNewton(const BVectorWell& dwells,
|
updateNewton(const BVectorWell& dwells,
|
||||||
|
const bool zero_rate_target,
|
||||||
[[maybe_unused]] const double dFLimit,
|
[[maybe_unused]] const double dFLimit,
|
||||||
const double dBHPLimit)
|
const double dBHPLimit)
|
||||||
{
|
{
|
||||||
@ -275,6 +281,10 @@ updateNewton(const BVectorWell& dwells,
|
|||||||
|
|
||||||
// updating the total rates Q_t
|
// updating the total rates Q_t
|
||||||
value_[WQTotal] = value_[WQTotal] - dwells[0][WQTotal] * relaxation_factor_rate;
|
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
|
// updating the bottom hole pressure
|
||||||
const int sign1 = dwells[0][Bhp] > 0 ? 1: -1;
|
const int sign1 = dwells[0][Bhp] > 0 ? 1: -1;
|
||||||
|
@ -101,13 +101,16 @@ public:
|
|||||||
int numWellEq() const { return numWellEq_; }
|
int numWellEq() const { return numWellEq_; }
|
||||||
|
|
||||||
//! \brief Copy values from well state.
|
//! \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.
|
//! \brief Copy polymer molecular weigt values from well state.
|
||||||
void updatePolyMW(const WellState& well_state);
|
void updatePolyMW(const WellState& well_state);
|
||||||
|
|
||||||
//! \brief Update values from newton update vector.
|
//! \brief Update values from newton update vector.
|
||||||
void updateNewton(const BVectorWell& dwells,
|
void updateNewton(const BVectorWell& dwells,
|
||||||
|
const bool zero_rate_target,
|
||||||
const double dFLimit,
|
const double dFLimit,
|
||||||
const double dBHPLimit);
|
const double dBHPLimit);
|
||||||
|
|
||||||
|
@ -993,13 +993,15 @@ namespace Opm
|
|||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
void
|
void
|
||||||
StandardWell<TypeTag>::
|
StandardWell<TypeTag>::
|
||||||
updateWellState(const BVectorWell& dwells,
|
updateWellState(const SummaryState& summary_state,
|
||||||
|
const BVectorWell& dwells,
|
||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger)
|
DeferredLogger& deferred_logger)
|
||||||
{
|
{
|
||||||
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
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);
|
updateWellStateFromPrimaryVariables(well_state, deferred_logger);
|
||||||
Base::calculateReservoirRates(well_state.well(this->index_of_well_));
|
Base::calculateReservoirRates(well_state.well(this->index_of_well_));
|
||||||
@ -1013,12 +1015,12 @@ namespace Opm
|
|||||||
void
|
void
|
||||||
StandardWell<TypeTag>::
|
StandardWell<TypeTag>::
|
||||||
updatePrimaryVariablesNewton(const BVectorWell& dwells,
|
updatePrimaryVariablesNewton(const BVectorWell& dwells,
|
||||||
const WellState& /* well_state */,
|
const bool zero_rate_target,
|
||||||
DeferredLogger& deferred_logger)
|
DeferredLogger& deferred_logger)
|
||||||
{
|
{
|
||||||
const double dFLimit = this->param_.dwell_fraction_max_;
|
const double dFLimit = this->param_.dwell_fraction_max_;
|
||||||
const double dBHPLimit = this->param_.dbhp_max_rel_;
|
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
|
// for the water velocity and skin pressure
|
||||||
if constexpr (Base::has_polymermw) {
|
if constexpr (Base::has_polymermw) {
|
||||||
@ -1581,7 +1583,9 @@ namespace Opm
|
|||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
void
|
void
|
||||||
StandardWell<TypeTag>::
|
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;
|
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return;
|
||||||
|
|
||||||
@ -1591,7 +1595,7 @@ namespace Opm
|
|||||||
dx_well[0].resize(this->primary_variables_.numWellEq());
|
dx_well[0].resize(this->primary_variables_.numWellEq());
|
||||||
this->linSys_.solve( dx_well);
|
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,
|
const WellState& well_state,
|
||||||
DeferredLogger& deferred_logger)
|
DeferredLogger& deferred_logger)
|
||||||
{
|
{
|
||||||
updatePrimaryVariables(well_state, deferred_logger);
|
const auto& summary_state = ebosSimulator.vanguard().summaryState();
|
||||||
|
updatePrimaryVariables(summary_state, well_state, deferred_logger);
|
||||||
initPrimaryVariablesEvaluation();
|
initPrimaryVariablesEvaluation();
|
||||||
computeWellConnectionPressures(ebosSimulator, well_state, deferred_logger);
|
computeWellConnectionPressures(ebosSimulator, well_state, deferred_logger);
|
||||||
this->computeAccumWell();
|
this->computeAccumWell();
|
||||||
@ -1648,7 +1653,8 @@ namespace Opm
|
|||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
void
|
void
|
||||||
StandardWell<TypeTag>::
|
StandardWell<TypeTag>::
|
||||||
recoverWellSolutionAndUpdateWellState(const BVector& x,
|
recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||||
|
const BVector& x,
|
||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger)
|
DeferredLogger& deferred_logger)
|
||||||
{
|
{
|
||||||
@ -1658,7 +1664,7 @@ namespace Opm
|
|||||||
xw[0].resize(this->primary_variables_.numWellEq());
|
xw[0].resize(this->primary_variables_.numWellEq());
|
||||||
|
|
||||||
this->linSys_.recoverSolutionWell(x, xw);
|
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";
|
" potentials are computed based on unconverged solution";
|
||||||
deferred_logger.debug(msg);
|
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.computeWellConnectionPressures(ebosSimulator, well_state_copy, deferred_logger);
|
||||||
well_copy.initPrimaryVariablesEvaluation();
|
well_copy.initPrimaryVariablesEvaluation();
|
||||||
well_copy.computeWellRatesWithBhp(ebosSimulator, bhp, well_flux, deferred_logger);
|
well_copy.computeWellRatesWithBhp(ebosSimulator, bhp, well_flux, deferred_logger);
|
||||||
@ -1970,11 +1976,14 @@ namespace Opm
|
|||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
void
|
void
|
||||||
StandardWell<TypeTag>::
|
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;
|
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
|
// other primary variables related to polymer injection
|
||||||
if constexpr (Base::has_polymermw) {
|
if constexpr (Base::has_polymermw) {
|
||||||
@ -2511,7 +2520,8 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
|
|
||||||
++it;
|
++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
|
// 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
|
// 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
|
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>
|
template<class FluidSystem>
|
||||||
WellAssemble<FluidSystem>::
|
WellAssemble<FluidSystem>::
|
||||||
WellAssemble(const WellInterfaceFluidSystem<FluidSystem>& well)
|
WellAssemble(const WellInterfaceFluidSystem<FluidSystem>& well)
|
||||||
|
@ -44,10 +44,6 @@ class WellState;
|
|||||||
class WellInjectionControls;
|
class WellInjectionControls;
|
||||||
class WellProductionControls;
|
class WellProductionControls;
|
||||||
|
|
||||||
/// Helper to avoid singular control equations.
|
|
||||||
bool rateControlWithZeroTarget(const WellProducerCMode mode,
|
|
||||||
const WellProductionControls& controls);
|
|
||||||
|
|
||||||
template<class FluidSystem>
|
template<class FluidSystem>
|
||||||
class WellAssemble {
|
class WellAssemble {
|
||||||
static constexpr int Water = BlackoilPhases::Aqua;
|
static constexpr int Water = BlackoilPhases::Aqua;
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
|
|
||||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
#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 <opm/simulators/wells/ParallelWellInfo.hpp>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
@ -168,6 +171,33 @@ DenseMatrix transposeDenseDynMatrix(const DenseMatrix& M)
|
|||||||
return tmp;
|
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 class ParallelStandardWellB<double>;
|
||||||
|
|
||||||
template<int Dim> using Vec = Dune::BlockVector<Dune::FieldVector<double,Dim>>;
|
template<int Dim> using Vec = Dune::BlockVector<Dune::FieldVector<double,Dim>>;
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
class ParallelWellInfo;
|
class ParallelWellInfo;
|
||||||
|
enum class WellProducerCMode;
|
||||||
|
class WellProductionControls;
|
||||||
|
|
||||||
namespace wellhelpers {
|
namespace wellhelpers {
|
||||||
|
|
||||||
@ -83,6 +85,10 @@ void sumDistributedWellEntries(Dune::DynamicMatrix<Scalar>& mat,
|
|||||||
template <class DenseMatrix>
|
template <class DenseMatrix>
|
||||||
DenseMatrix transposeDenseDynMatrix(const DenseMatrix& M);
|
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 wellhelpers
|
||||||
} // namespace Opm
|
} // 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 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,
|
void assembleWellEq(const Simulator& ebosSimulator,
|
||||||
const double dt,
|
const double dt,
|
||||||
@ -180,7 +182,8 @@ public:
|
|||||||
|
|
||||||
/// using the solution x to recover the solution xw for wells and applying
|
/// using the solution x to recover the solution xw for wells and applying
|
||||||
/// xw to update Well State
|
/// xw to update Well State
|
||||||
virtual void recoverWellSolutionAndUpdateWellState(const BVector& x,
|
virtual void recoverWellSolutionAndUpdateWellState(const SummaryState& summary_state,
|
||||||
|
const BVector& x,
|
||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger) = 0;
|
DeferredLogger& deferred_logger) = 0;
|
||||||
|
|
||||||
@ -212,7 +215,9 @@ public:
|
|||||||
const GroupState& group_state,
|
const GroupState& group_state,
|
||||||
DeferredLogger& deferred_logger) /* const */;
|
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,
|
virtual void calculateExplicitQuantities(const Simulator& ebosSimulator,
|
||||||
const WellState& well_state,
|
const WellState& well_state,
|
||||||
@ -359,7 +364,8 @@ protected:
|
|||||||
|
|
||||||
Eval getPerfCellPressure(const FluidState& fs) const;
|
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/GroupState.hpp>
|
||||||
#include <opm/simulators/wells/TargetCalculator.hpp>
|
#include <opm/simulators/wells/TargetCalculator.hpp>
|
||||||
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
|
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
|
||||||
|
#include <opm/simulators/wells/WellHelpers.hpp>
|
||||||
|
|
||||||
#include <dune/common/version.hh>
|
#include <dune/common/version.hh>
|
||||||
|
|
||||||
@ -244,7 +245,7 @@ namespace Opm
|
|||||||
|
|
||||||
this->well_control_log_.push_back(from);
|
this->well_control_log_.push_back(from);
|
||||||
updateWellStateWithTarget(ebos_simulator, group_state, well_state, deferred_logger);
|
updateWellStateWithTarget(ebos_simulator, group_state, well_state, deferred_logger);
|
||||||
updatePrimaryVariables(well_state, deferred_logger);
|
updatePrimaryVariables(summaryState, well_state, deferred_logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
@ -269,7 +270,8 @@ namespace Opm
|
|||||||
|
|
||||||
updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger);
|
updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger);
|
||||||
calculateExplicitQuantities(simulator, 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();
|
initPrimaryVariablesEvaluation();
|
||||||
|
|
||||||
if (this->isProducer()) {
|
if (this->isProducer()) {
|
||||||
@ -1128,4 +1130,19 @@ namespace Opm
|
|||||||
return fs.pressure(FluidSystem::gasPhaseIdx);
|
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
|
} // namespace Opm
|
||||||
|
Loading…
Reference in New Issue
Block a user