Merge pull request #2664 from GitPaean/addinginneritartionsstdwell

Adding inner iterations for standard wells.
This commit is contained in:
Atgeirr Flø Rasmussen 2020-08-11 16:37:00 +02:00 committed by GitHub
commit 8d999ad448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 170 additions and 70 deletions

View File

@ -138,6 +138,8 @@ public:
EWOMS_HIDE_PARAM(TypeTag, MaxPressureChangeMsWells); EWOMS_HIDE_PARAM(TypeTag, MaxPressureChangeMsWells);
EWOMS_HIDE_PARAM(TypeTag, UseInnerIterationsMsWells); EWOMS_HIDE_PARAM(TypeTag, UseInnerIterationsMsWells);
EWOMS_HIDE_PARAM(TypeTag, MaxInnerIterMsWells); EWOMS_HIDE_PARAM(TypeTag, MaxInnerIterMsWells);
EWOMS_HIDE_PARAM(TypeTag, UseInnerIterationsWells);
EWOMS_HIDE_PARAM(TypeTag, MaxInnerIterWells);
EWOMS_HIDE_PARAM(TypeTag, MaxSinglePrecisionDays); EWOMS_HIDE_PARAM(TypeTag, MaxSinglePrecisionDays);
EWOMS_HIDE_PARAM(TypeTag, MaxStrictIter); EWOMS_HIDE_PARAM(TypeTag, MaxStrictIter);
EWOMS_HIDE_PARAM(TypeTag, SolveWelleqInitially); EWOMS_HIDE_PARAM(TypeTag, SolveWelleqInitially);

View File

@ -56,6 +56,8 @@ NEW_PROP_TAG(StrictInnerIterMsWells);
NEW_PROP_TAG(RelaxedFlowTolInnerIterMsw); NEW_PROP_TAG(RelaxedFlowTolInnerIterMsw);
NEW_PROP_TAG(RelaxedPressureTolInnerIterMsw); NEW_PROP_TAG(RelaxedPressureTolInnerIterMsw);
NEW_PROP_TAG(RegularizationFactorMsw); NEW_PROP_TAG(RegularizationFactorMsw);
NEW_PROP_TAG(UseInnerIterationsWells);
NEW_PROP_TAG(MaxInnerIterWells);
SET_SCALAR_PROP(FlowModelParameters, DbhpMaxRel, 1.0); SET_SCALAR_PROP(FlowModelParameters, DbhpMaxRel, 1.0);
SET_SCALAR_PROP(FlowModelParameters, DwellFractionMax, 0.2); SET_SCALAR_PROP(FlowModelParameters, DwellFractionMax, 0.2);
@ -77,6 +79,8 @@ SET_SCALAR_PROP(FlowModelParameters, TolerancePressureMsWells, 0.01*1e5);
SET_SCALAR_PROP(FlowModelParameters, MaxPressureChangeMsWells, 10*1e5); SET_SCALAR_PROP(FlowModelParameters, MaxPressureChangeMsWells, 10*1e5);
SET_BOOL_PROP(FlowModelParameters, UseInnerIterationsMsWells, true); SET_BOOL_PROP(FlowModelParameters, UseInnerIterationsMsWells, true);
SET_INT_PROP(FlowModelParameters, MaxInnerIterMsWells, 100); SET_INT_PROP(FlowModelParameters, MaxInnerIterMsWells, 100);
SET_BOOL_PROP(FlowModelParameters, UseInnerIterationsWells, false);
SET_INT_PROP(FlowModelParameters, MaxInnerIterWells, 50);
SET_INT_PROP(FlowModelParameters, StrictInnerIterMsWells, 40); SET_INT_PROP(FlowModelParameters, StrictInnerIterMsWells, 40);
SET_SCALAR_PROP(FlowModelParameters, RegularizationFactorMsw, 1); SET_SCALAR_PROP(FlowModelParameters, RegularizationFactorMsw, 1);
SET_BOOL_PROP(FlowModelParameters, EnableWellOperabilityCheck, true); SET_BOOL_PROP(FlowModelParameters, EnableWellOperabilityCheck, true);
@ -141,6 +145,12 @@ namespace Opm
/// Regularization factor for ms wells /// Regularization factor for ms wells
int regularization_factor_ms_wells_; int regularization_factor_ms_wells_;
/// Whether to use inner iterations for standard wells
bool use_inner_iterations_wells_;
/// Maximum inner iteration number for standard wells
int max_inner_iter_wells_;
/// Maximum iteration number of the well equation solution /// Maximum iteration number of the well equation solution
int max_welleq_iter_; int max_welleq_iter_;
@ -194,6 +204,8 @@ namespace Opm
max_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, MaxInnerIterMsWells); max_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, MaxInnerIterMsWells);
strict_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, StrictInnerIterMsWells); strict_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, StrictInnerIterMsWells);
regularization_factor_ms_wells_ = EWOMS_GET_PARAM(TypeTag, Scalar, RegularizationFactorMsw); regularization_factor_ms_wells_ = EWOMS_GET_PARAM(TypeTag, Scalar, RegularizationFactorMsw);
use_inner_iterations_wells_ = EWOMS_GET_PARAM(TypeTag, bool, UseInnerIterationsWells);
max_inner_iter_wells_ = EWOMS_GET_PARAM(TypeTag, int, MaxInnerIterWells);
maxSinglePrecisionTimeStep_ = EWOMS_GET_PARAM(TypeTag, Scalar, MaxSinglePrecisionDays) *24*60*60; maxSinglePrecisionTimeStep_ = EWOMS_GET_PARAM(TypeTag, Scalar, MaxSinglePrecisionDays) *24*60*60;
max_strict_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxStrictIter); max_strict_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxStrictIter);
solve_welleq_initially_ = EWOMS_GET_PARAM(TypeTag, bool, SolveWelleqInitially); solve_welleq_initially_ = EWOMS_GET_PARAM(TypeTag, bool, SolveWelleqInitially);
@ -223,6 +235,8 @@ namespace Opm
EWOMS_REGISTER_PARAM(TypeTag, bool, UseInnerIterationsMsWells, "Use nested iterations for multi-segment wells"); EWOMS_REGISTER_PARAM(TypeTag, bool, UseInnerIterationsMsWells, "Use nested iterations for multi-segment wells");
EWOMS_REGISTER_PARAM(TypeTag, int, MaxInnerIterMsWells, "Maximum number of inner iterations for multi-segment wells"); EWOMS_REGISTER_PARAM(TypeTag, int, MaxInnerIterMsWells, "Maximum number of inner iterations for multi-segment wells");
EWOMS_REGISTER_PARAM(TypeTag, int, StrictInnerIterMsWells, "Number of inner iterations for multi-segment wells with strict tolerance"); EWOMS_REGISTER_PARAM(TypeTag, int, StrictInnerIterMsWells, "Number of inner iterations for multi-segment wells with strict tolerance");
EWOMS_REGISTER_PARAM(TypeTag, bool, UseInnerIterationsWells, "Use nested iterations for standard wells");
EWOMS_REGISTER_PARAM(TypeTag, int, MaxInnerIterWells, "Maximum number of inner iterations for standard wells");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, RegularizationFactorMsw, "Regularization factor for ms wells"); EWOMS_REGISTER_PARAM(TypeTag, Scalar, RegularizationFactorMsw, "Regularization factor for ms wells");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, MaxSinglePrecisionDays, "Maximum time step size where single precision floating point arithmetic can be used solving for the linear systems of equations"); EWOMS_REGISTER_PARAM(TypeTag, Scalar, MaxSinglePrecisionDays, "Maximum time step size where single precision floating point arithmetic can be used solving for the linear systems of equations");
EWOMS_REGISTER_PARAM(TypeTag, int, MaxStrictIter, "Maximum number of Newton iterations before relaxed tolerances are used for the CNV convergence criterion"); EWOMS_REGISTER_PARAM(TypeTag, int, MaxStrictIter, "Maximum number of Newton iterations before relaxed tolerances are used for the CNV convergence criterion");

View File

@ -407,21 +407,20 @@ namespace Opm
bool accelerationalPressureLossConsidered() const; bool accelerationalPressureLossConsidered() const;
// TODO: try to make ebosSimulator const, as it should be virtual bool iterateWellEqWithControl(const Simulator& ebosSimulator,
void iterateWellEquations(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg, const std::vector<Scalar>& B_avg,
const double dt, const double dt,
const Well::InjectionControls& inj_controls, const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls, const Well::ProductionControls& prod_controls,
WellState& well_state, WellState& well_state,
Opm::DeferredLogger& deferred_logger); Opm::DeferredLogger& deferred_logger) override;
void assembleWellEqWithoutIteration(const Simulator& ebosSimulator, virtual void assembleWellEqWithoutIteration(const Simulator& ebosSimulator,
const double dt, const double dt,
const Well::InjectionControls& inj_controls, const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls, const Well::ProductionControls& prod_controls,
WellState& well_state, WellState& well_state,
Opm::DeferredLogger& deferred_logger); Opm::DeferredLogger& deferred_logger) override;
virtual void wellTestingPhysical(const Simulator& simulator, const std::vector<double>& B_avg, virtual void wellTestingPhysical(const Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const double simulation_time, const int report_step,

View File

@ -258,16 +258,15 @@ namespace Opm
WellState& well_state, WellState& well_state,
Opm::DeferredLogger& deferred_logger) Opm::DeferredLogger& deferred_logger)
{ {
const auto& summary_state = ebosSimulator.vanguard().summaryState();
const auto inj_controls = well_ecl_.isInjector() ? well_ecl_.injectionControls(summary_state) : Well::InjectionControls(0);
const auto prod_controls = well_ecl_.isProducer() ? well_ecl_.productionControls(summary_state) : Well::ProductionControls(0);
const bool use_inner_iterations = param_.use_inner_iterations_ms_wells_; const bool use_inner_iterations = param_.use_inner_iterations_ms_wells_;
if (use_inner_iterations) { if (use_inner_iterations) {
this->iterateWellEquations(ebosSimulator, B_avg, dt, well_state, deferred_logger);
iterateWellEquations(ebosSimulator, B_avg, dt, inj_controls, prod_controls, well_state, deferred_logger);
} }
const auto& summary_state = ebosSimulator.vanguard().summaryState();
const auto inj_controls = well_ecl_.isInjector() ? well_ecl_.injectionControls(summary_state) : Well::InjectionControls(0);
const auto prod_controls = well_ecl_.isProducer() ? well_ecl_.productionControls(summary_state) : Well::ProductionControls(0);
assembleWellEqWithoutIteration(ebosSimulator, dt, inj_controls, prod_controls, well_state, deferred_logger); assembleWellEqWithoutIteration(ebosSimulator, dt, inj_controls, prod_controls, well_state, deferred_logger);
} }
@ -850,7 +849,8 @@ namespace Opm
well_copy.calculateExplicitQuantities(ebosSimulator, well_state_copy, deferred_logger); well_copy.calculateExplicitQuantities(ebosSimulator, well_state_copy, deferred_logger);
const double dt = ebosSimulator.timeStepSize(); const double dt = ebosSimulator.timeStepSize();
// iterate to get a solution at the given bhp. // iterate to get a solution at the given bhp.
well_copy.iterateWellEquations(ebosSimulator, B_avg, dt, inj_controls, prod_controls, well_state_copy, deferred_logger); well_copy.iterateWellEqWithControl(ebosSimulator, B_avg, dt, inj_controls, prod_controls, well_state_copy,
deferred_logger);
// compute the potential and store in the flux vector. // compute the potential and store in the flux vector.
well_flux.clear(); well_flux.clear();
@ -2373,9 +2373,9 @@ namespace Opm
template<typename TypeTag> template<typename TypeTag>
void bool
MultisegmentWell<TypeTag>:: MultisegmentWell<TypeTag>::
iterateWellEquations(const Simulator& ebosSimulator, iterateWellEqWithControl(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg, const std::vector<Scalar>& B_avg,
const double dt, const double dt,
const Well::InjectionControls& inj_controls, const Well::InjectionControls& inj_controls,
@ -2433,7 +2433,7 @@ namespace Opm
converged = true; converged = true;
sstr << " well " << name() << " manages to get converged with relaxed tolerances in " << it << " inner iterations"; sstr << " well " << name() << " manages to get converged with relaxed tolerances in " << it << " inner iterations";
deferred_logger.debug(sstr.str()); deferred_logger.debug(sstr.str());
return; return converged;
} }
} }
} }
@ -2481,6 +2481,8 @@ namespace Opm
#endif #endif
deferred_logger.debug(sstr.str()); deferred_logger.debug(sstr.str());
} }
return converged;
} }

View File

@ -218,6 +218,15 @@ namespace Opm
virtual void addWellContributions(SparseMatrixAdapter& mat) const override; virtual void addWellContributions(SparseMatrixAdapter& mat) const override;
// iterate well equations with the specified control until converged
bool iterateWellEqWithControl(const Simulator& ebosSimulator,
const std::vector<double>& B_avg,
const double dt,
const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) override;
/// \brief Wether the Jacobian will also have well contributions in it. /// \brief Wether the Jacobian will also have well contributions in it.
virtual bool jacobianContainsWellContributions() const override virtual bool jacobianContainsWellContributions() const override
{ {
@ -430,6 +439,13 @@ namespace Opm
const WellState& well_state, const WellState& well_state,
Opm::DeferredLogger& deferred_logger) override; Opm::DeferredLogger& deferred_logger) override;
virtual void assembleWellEqWithoutIteration(const Simulator& ebosSimulator,
const double dt,
const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) override;
// check whether the well is operable under the current reservoir condition // check whether the well is operable under the current reservoir condition
// mostly related to BHP limit and THP limit // mostly related to BHP limit and THP limit
void updateWellOperability(const Simulator& ebos_simulator, void updateWellOperability(const Simulator& ebos_simulator,

View File

@ -509,15 +509,38 @@ namespace Opm
} }
template<typename TypeTag>
void
StandardWell<TypeTag>::
assembleWellEq(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double dt,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
{
const bool use_inner_iterations = param_.use_inner_iterations_wells_;
if (use_inner_iterations) {
this->iterateWellEquations(ebosSimulator, B_avg, dt, well_state, deferred_logger);
}
// TODO: inj_controls and prod_controls are not used in the following function for now
const auto& summary_state = ebosSimulator.vanguard().summaryState();
const auto inj_controls = well_ecl_.isInjector() ? well_ecl_.injectionControls(summary_state) : Well::InjectionControls(0);
const auto prod_controls = well_ecl_.isProducer() ? well_ecl_.productionControls(summary_state) : Well::ProductionControls(0);
assembleWellEqWithoutIteration(ebosSimulator, dt, inj_controls, prod_controls, well_state, deferred_logger);
}
template<typename TypeTag> template<typename TypeTag>
void void
StandardWell<TypeTag>:: StandardWell<TypeTag>::
assembleWellEq(const Simulator& ebosSimulator, assembleWellEqWithoutIteration(const Simulator& ebosSimulator,
const std::vector<Scalar>& /* B_avg */,
const double dt, const double dt,
const Well::InjectionControls& /*inj_controls*/,
const Well::ProductionControls& /*prod_controls*/,
WellState& well_state, WellState& well_state,
Opm::DeferredLogger& deferred_logger) Opm::DeferredLogger& deferred_logger)
{ {
@ -2461,8 +2484,8 @@ namespace Opm
} }
well_state_copy.bhp()[index_of_well_] = bhp; well_state_copy.bhp()[index_of_well_] = bhp;
bool converged = this->solveWellEqUntilConverged(ebosSimulator, B_avg, well_state_copy, deferred_logger); const double dt = ebosSimulator.timeStepSize();
bool converged = this->iterateWellEquations(ebosSimulator, B_avg, dt, well_state_copy, deferred_logger);
if (!converged) { if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well potential calculations " const std::string msg = " well " + name() + " did not get converged during well potential calculations "
"returning zero values for the potential"; "returning zero values for the potential";
@ -3012,7 +3035,8 @@ namespace Opm
calculateExplicitQuantities(ebos_simulator, well_state_copy, deferred_logger); calculateExplicitQuantities(ebos_simulator, well_state_copy, deferred_logger);
const bool converged = this->solveWellEqUntilConverged(ebos_simulator, B_avg, well_state_copy, deferred_logger); const double dt = ebos_simulator.timeStepSize();
const bool converged = this->iterateWellEquations(ebos_simulator, B_avg, dt, well_state_copy, deferred_logger);
if (!converged) { if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well testing for physical reason"; const std::string msg = " well " + name() + " did not get converged during well testing for physical reason";
@ -3779,4 +3803,46 @@ namespace Opm
} }
template<typename TypeTag>
bool
StandardWell<TypeTag>::
iterateWellEqWithControl(const Simulator& ebosSimulator,
const std::vector<double>& B_avg,
const double dt,
const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
{
const int max_iter = param_.max_inner_iter_wells_;
int it = 0;
bool converged;
do {
assembleWellEqWithoutIteration(ebosSimulator, dt, inj_controls, prod_controls, well_state, deferred_logger);
auto report = getWellConvergence(well_state, B_avg, deferred_logger);
converged = report.converged();
if (converged) {
break;
}
++it;
solveEqAndUpdateWellState(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
// this function or we use different functions for the well testing purposes.
// We don't allow for switching well controls while computing well potentials and testing wells
// updateWellControl(ebosSimulator, well_state, deferred_logger);
initPrimaryVariablesEvaluation();
} while (it < max_iter);
return converged;
}
} // namespace Opm } // namespace Opm

View File

@ -451,6 +451,29 @@ namespace Opm
const double simulation_time, const int report_step, const double simulation_time, const int report_step,
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferred_logger) = 0; WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferred_logger) = 0;
virtual void assembleWellEqWithoutIteration(const Simulator& ebosSimulator,
const double dt,
const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) = 0;
// iterate well equations with the specified control until converged
virtual bool iterateWellEqWithControl(const Simulator& ebosSimulator,
const std::vector<double>& B_avg,
const double dt,
const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) = 0;
bool iterateWellEquations(const Simulator& ebosSimulator,
const std::vector<double>& B_avg,
const double dt,
WellState& well_state,
Opm::DeferredLogger& deferred_logger);
void updateWellTestStateEconomic(const WellState& well_state, void updateWellTestStateEconomic(const WellState& well_state,
const double simulation_time, const double simulation_time,
const bool write_message_to_opmlog, const bool write_message_to_opmlog,
@ -467,11 +490,6 @@ namespace Opm
const std::vector<double>& B_avg, const std::vector<double>& B_avg,
Opm::DeferredLogger& deferred_logger); Opm::DeferredLogger& deferred_logger);
bool solveWellEqUntilConverged(const Simulator& ebosSimulator,
const std::vector<double>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger);
void scaleProductivityIndex(const int perfIdx, double& productivity_index, const bool new_well, Opm::DeferredLogger& deferred_logger); void scaleProductivityIndex(const int perfIdx, double& productivity_index, const bool new_well, Opm::DeferredLogger& deferred_logger);
void initCompletions(); void initCompletions();

View File

@ -1284,35 +1284,17 @@ namespace Opm
template<typename TypeTag> template<typename TypeTag>
bool bool
WellInterface<TypeTag>:: WellInterface<TypeTag>::
solveWellEqUntilConverged(const Simulator& ebosSimulator, iterateWellEquations(const Simulator& ebosSimulator,
const std::vector<double>& B_avg, const std::vector<double>& B_avg,
const double dt,
WellState& well_state, WellState& well_state,
Opm::DeferredLogger& deferred_logger) Opm::DeferredLogger& deferred_logger)
{ {
const int max_iter = param_.max_welleq_iter_; const auto& summary_state = ebosSimulator.vanguard().summaryState();
int it = 0; const auto inj_controls = well_ecl_.isInjector() ? well_ecl_.injectionControls(summary_state) : Well::InjectionControls(0);
const double dt = 1.0; //not used for the well tests const auto prod_controls = well_ecl_.isProducer() ? well_ecl_.productionControls(summary_state) : Well::ProductionControls(0);
bool converged;
WellState well_state0 = well_state;
do {
assembleWellEq(ebosSimulator, B_avg, dt, well_state, deferred_logger);
auto report = getWellConvergence(well_state, B_avg, deferred_logger); return this->iterateWellEqWithControl(ebosSimulator, B_avg, dt, inj_controls, prod_controls, well_state, deferred_logger);
converged = report.converged();
if (converged) {
break;
}
++it;
solveEqAndUpdateWellState(well_state, deferred_logger);
// We don't allow for switching well controls while computing well potentials and testing wells
// updateWellControl(ebosSimulator, well_state, deferred_logger);
initPrimaryVariablesEvaluation();
} while (it < max_iter);
return converged;
} }
@ -1365,7 +1347,8 @@ namespace Opm
{ {
// keep a copy of the original well state // keep a copy of the original well state
const WellState well_state0 = well_state; const WellState well_state0 = well_state;
const bool converged = solveWellEqUntilConverged(ebosSimulator, B_avg, well_state, deferred_logger); const double dt = ebosSimulator.timeStepSize();
const bool converged = iterateWellEquations(ebosSimulator, B_avg, dt, well_state, deferred_logger);
if (converged) { if (converged) {
deferred_logger.debug("WellTest: Well equation for well " + name() + " converged"); deferred_logger.debug("WellTest: Well equation for well " + name() + " converged");
} else { } else {