use relaxed tolerance for MSW when solution stagnates

This commit is contained in:
Tor Harald Sandve 2020-05-12 12:05:30 +02:00
parent 55b3a65230
commit cf702a5384
5 changed files with 35 additions and 19 deletions

View File

@ -128,7 +128,7 @@ namespace Opm
Opm::DeferredLogger& deferred_logger) const override;
/// check whether the well equations get converged for this well
virtual ConvergenceReport getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger) const override;
virtual ConvergenceReport getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger, const bool relax_tolerance = false) const override;
/// Ax = Ax - C D^-1 B x
virtual void apply(const BVector& x, BVector& Ax) const override;

View File

@ -536,7 +536,7 @@ namespace Opm
template <typename TypeTag>
ConvergenceReport
MultisegmentWell<TypeTag>::
getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger) const
getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger, const bool relax_tolerance) const
{
assert(int(B_avg.size()) == num_components_);
@ -577,21 +577,28 @@ namespace Opm
if (eq_idx < num_components_) { // phase or component mass equations
const double flux_residual = maximum_residual[eq_idx];
// TODO: the report can not handle the segment number yet.
double relax_factor = 1.0;
if (relax_tolerance)
relax_factor = 1.e4;
if (std::isnan(flux_residual)) {
report.setWellFailed({CR::WellFailure::Type::MassBalance, CR::Severity::NotANumber, eq_idx, name()});
} else if (flux_residual > param_.max_residual_allowed_) {
report.setWellFailed({CR::WellFailure::Type::MassBalance, CR::Severity::TooLarge, eq_idx, name()});
} else if (flux_residual > param_.tolerance_wells_) {
} else if (flux_residual > param_.tolerance_wells_ * relax_factor) {
report.setWellFailed({CR::WellFailure::Type::MassBalance, CR::Severity::Normal, eq_idx, name()});
}
} else { // pressure equation
const double pressure_residual = maximum_residual[eq_idx];
const int dummy_component = -1;
double relax_factor = 1.0;
if (relax_tolerance)
relax_factor = 50;
if (std::isnan(pressure_residual)) {
report.setWellFailed({CR::WellFailure::Type::Pressure, CR::Severity::NotANumber, dummy_component, name()});
} else if (std::isinf(pressure_residual)) {
report.setWellFailed({CR::WellFailure::Type::Pressure, CR::Severity::TooLarge, dummy_component, name()});
} else if (pressure_residual > param_.tolerance_pressure_ms_wells_) {
} else if (pressure_residual > param_.tolerance_pressure_ms_wells_ * relax_factor) {
report.setWellFailed({CR::WellFailure::Type::Pressure, CR::Severity::Normal, dummy_component, name()});
}
}
@ -2369,17 +2376,20 @@ namespace Opm
int it = 0;
// relaxation factor
double relaxation_factor = 1.;
const double min_relaxation_factor = 0.2;
const double min_relaxation_factor = 0.6;
bool converged = false;
int stagnate_count = 0;
bool relax_convergence = false;
for (; it < max_iter_number; ++it, ++debug_cost_counter_) {
assembleWellEqWithoutIteration(ebosSimulator, dt, inj_controls, prod_controls, well_state, deferred_logger);
const BVectorWell dx_well = mswellhelpers::invDXDirect(duneD_, resWell_);
if (it > 40)
relax_convergence = true;
const auto report = getWellConvergence(well_state, B_avg, deferred_logger);
const auto report = getWellConvergence(well_state, B_avg, deferred_logger, relax_convergence);
if (report.converged()) {
converged = true;
break;
@ -2395,19 +2405,22 @@ namespace Opm
// TODO: maybe we should have more sophiscated strategy to recover the relaxation factor,
// for example, to recover it to be bigger
if (!is_stagnate) {
stagnate_count = 0;
}
if (is_oscillate || is_stagnate) {
// HACK!
if (is_stagnate && relaxation_factor == min_relaxation_factor) {
std::ostringstream sstr;
if (relaxation_factor == min_relaxation_factor) {
// Still stagnating, terminate iterations if 5 iterations pass.
++stagnate_count;
if (stagnate_count == 5) {
// break;
if (stagnate_count == 6) {
sstr << " well " << name() << " observes sever stagnation and/or oscillation. We relax the tolerance and check for convergence. \n";
const auto reportStag = getWellConvergence(well_state, B_avg, deferred_logger, true);
if (reportStag.converged()) {
converged = true;
sstr << " well " << name() << " manage to get converged with relaxed tolerances in " << it << " inner iterations";
deferred_logger.debug(sstr.str());
return;
}
}
} else {
stagnate_count = 0;
}
// a factor value to reduce the relaxation_factor
@ -2415,7 +2428,6 @@ namespace Opm
relaxation_factor = std::max(relaxation_factor * reduction_mutliplier, min_relaxation_factor);
// debug output
std::ostringstream sstr;
if (is_stagnate) {
sstr << " well " << name() << " observes stagnation in inner iteration " << it << "\n";
@ -2433,7 +2445,9 @@ namespace Opm
// TODO: we should decide whether to keep the updated well_state, or recover to use the old well_state
if (converged) {
std::ostringstream sstr;
sstr << " well " << name() << " manage to get converged within " << it << " inner iterations";
sstr << " well " << name() << " manage to get converged within " << it << " inner iterations \n";
if (relax_convergence)
sstr << "A relaxed tolerance is used after 40 iterations";
deferred_logger.debug(sstr.str());
} else {
std::ostringstream sstr;

View File

@ -177,7 +177,8 @@ namespace Opm
/// check whether the well equations get converged for this well
virtual ConvergenceReport getWellConvergence(const WellState& well_state,
const std::vector<double>& B_avg,
Opm::DeferredLogger& deferred_logger) const override;
Opm::DeferredLogger& deferred_logger,
const bool relax_tolerance = false) const override;
/// Ax = Ax - C D^-1 B x
virtual void apply(const BVector& x, BVector& Ax) const override;

View File

@ -2087,7 +2087,8 @@ namespace Opm
StandardWell<TypeTag>::
getWellConvergence(const WellState& well_state,
const std::vector<double>& B_avg,
Opm::DeferredLogger& deferred_logger) const
Opm::DeferredLogger& deferred_logger,
const bool relax_tolerance) const
{
// the following implementation assume that the polymer is always after the w-o-g phases
// For the polymer, energy and foam cases, there is one more mass balance equations of reservoir than wells

View File

@ -157,7 +157,7 @@ namespace Opm
virtual void initPrimaryVariablesEvaluation() const = 0;
virtual ConvergenceReport getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger) const = 0;
virtual ConvergenceReport getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger, const bool relax_tolerance = false) const = 0;
virtual void solveEqAndUpdateWellState(WellState& well_state, Opm::DeferredLogger& deferred_logger) = 0;