add run time parameters for msw convergence tuning. Default values are set to minimize convergence failures for model2 based tests. These parameters are also tested on bigger models with good results

This commit is contained in:
Tor Harald Sandve 2020-05-20 16:36:05 +02:00
parent ec7c6e236d
commit 8a5c9e82df
3 changed files with 46 additions and 14 deletions

View File

@ -55,6 +55,10 @@ NEW_PROP_TAG(TolerancePressureMsWells);
NEW_PROP_TAG(MaxPressureChangeMsWells);
NEW_PROP_TAG(UseInnerIterationsMsWells);
NEW_PROP_TAG(MaxInnerIterMsWells);
NEW_PROP_TAG(StrictInnerIterMsWells);
NEW_PROP_TAG(RelaxedFlowTolInnerIterMsw);
NEW_PROP_TAG(RelaxedPressureTolInnerIterMsw);
NEW_PROP_TAG(RegularizationFactorMsw);
SET_SCALAR_PROP(FlowModelParameters, DbhpMaxRel, 1.0);
SET_SCALAR_PROP(FlowModelParameters, DwellFractionMax, 0.2);
@ -76,8 +80,13 @@ SET_SCALAR_PROP(FlowModelParameters, TolerancePressureMsWells, 0.01*1e5);
SET_SCALAR_PROP(FlowModelParameters, MaxPressureChangeMsWells, 10*1e5);
SET_BOOL_PROP(FlowModelParameters, UseInnerIterationsMsWells, true);
SET_INT_PROP(FlowModelParameters, MaxInnerIterMsWells, 100);
SET_INT_PROP(FlowModelParameters, StrictInnerIterMsWells, 40);
SET_SCALAR_PROP(FlowModelParameters, RegularizationFactorMsw, 10);
SET_BOOL_PROP(FlowModelParameters, EnableWellOperabilityCheck, true);
SET_SCALAR_PROP(FlowModelParameters, RelaxedFlowTolInnerIterMsw, 1);
SET_SCALAR_PROP(FlowModelParameters, RelaxedPressureTolInnerIterMsw, 0.5e5);
// if openMP is available, determine the number threads per process automatically.
#if _OPENMP
SET_INT_PROP(FlowModelParameters, ThreadsPerProcess, -1);
@ -114,6 +123,12 @@ namespace Opm
double tolerance_well_control_;
/// Tolerance for the pressure equations for multisegment wells
double tolerance_pressure_ms_wells_;
/// Relaxed tolerance for the inner iteration for the MSW flow solution
double relaxed_inner_tolerance_flow_ms_well_;
/// Relaxed tolerance for the inner iteration for the MSW pressure solution
double relaxed_inner_tolerance_pressure_ms_well_;
/// Maximum pressure change over an iteratio for ms wells
double max_pressure_change_ms_wells_;
@ -123,6 +138,12 @@ namespace Opm
/// Maximum inner iteration number for ms wells
int max_inner_iter_ms_wells_;
/// Strict inner iteration number for ms wells
int strict_inner_iter_ms_wells_;
/// Regularization factor for ms wells
int regularization_factor_ms_wells_;
/// Maximum iteration number of the well equation solution
int max_welleq_iter_;
@ -169,9 +190,13 @@ namespace Opm
max_welleq_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxWelleqIter);
use_multisegment_well_ = EWOMS_GET_PARAM(TypeTag, bool, UseMultisegmentWell);
tolerance_pressure_ms_wells_ = EWOMS_GET_PARAM(TypeTag, Scalar, TolerancePressureMsWells);
relaxed_inner_tolerance_flow_ms_well_ = EWOMS_GET_PARAM(TypeTag, Scalar, RelaxedFlowTolInnerIterMsw);
relaxed_inner_tolerance_pressure_ms_well_ = EWOMS_GET_PARAM(TypeTag, Scalar, RelaxedPressureTolInnerIterMsw);
max_pressure_change_ms_wells_ = EWOMS_GET_PARAM(TypeTag, Scalar, MaxPressureChangeMsWells);
use_inner_iterations_ms_wells_ = EWOMS_GET_PARAM(TypeTag, bool, UseInnerIterationsMsWells);
max_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, MaxInnerIterMsWells);
strict_inner_iter_ms_wells_ = EWOMS_GET_PARAM(TypeTag, int, StrictInnerIterMsWells);
regularization_factor_ms_wells_ = EWOMS_GET_PARAM(TypeTag, Scalar, RegularizationFactorMsw);
maxSinglePrecisionTimeStep_ = EWOMS_GET_PARAM(TypeTag, Scalar, MaxSinglePrecisionDays) *24*60*60;
max_strict_iter_ = EWOMS_GET_PARAM(TypeTag, int, MaxStrictIter);
solve_welleq_initially_ = EWOMS_GET_PARAM(TypeTag, bool, SolveWelleqInitially);
@ -195,9 +220,13 @@ namespace Opm
EWOMS_REGISTER_PARAM(TypeTag, int, MaxWelleqIter, "Maximum number of iterations to determine solution the well equations");
EWOMS_REGISTER_PARAM(TypeTag, bool, UseMultisegmentWell, "Use the well model for multi-segment wells instead of the one for single-segment wells");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, TolerancePressureMsWells, "Tolerance for the pressure equations for multi-segment wells");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, RelaxedFlowTolInnerIterMsw, "Relaxed tolerance for the inner iteration for the MSW flow solution");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, RelaxedPressureTolInnerIterMsw, "Relaxed tolerance for the inner iteration for the MSW pressure solution");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, MaxPressureChangeMsWells, "Maximum relative pressure change for a single iteration of the multi-segment well model");
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, StrictInnerIterMsWells, "Number of inner iterations for multi-segment wells with strict tolerance");
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, int, MaxStrictIter, "Maximum number of Newton iterations before relaxed tolerances are used for the CNV convergence criterion");
EWOMS_REGISTER_PARAM(TypeTag, bool, SolveWelleqInitially, "Fully solve the well equations before each iteration of the reservoir model");

View File

@ -578,27 +578,25 @@ namespace Opm
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_ * relax_factor) {
} else if (!relax_tolerance && flux_residual > param_.tolerance_wells_) {
report.setWellFailed({CR::WellFailure::Type::MassBalance, CR::Severity::Normal, eq_idx, name()});
} else if (flux_residual > param_.relaxed_inner_tolerance_flow_ms_well_) {
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_ * relax_factor) {
} else if (!relax_tolerance && pressure_residual > param_.tolerance_pressure_ms_wells_) {
report.setWellFailed({CR::WellFailure::Type::Pressure, CR::Severity::Normal, dummy_component, name()});
} else if (pressure_residual > param_.relaxed_inner_tolerance_pressure_ms_well_) {
report.setWellFailed({CR::WellFailure::Type::Pressure, CR::Severity::Normal, dummy_component, name()});
}
}
@ -2386,7 +2384,7 @@ namespace Opm
const BVectorWell dx_well = mswellhelpers::invDXDirect(duneD_, resWell_);
if (it > 40)
if (it > param_.strict_inner_iter_ms_wells_)
relax_convergence = true;
const auto report = getWellConvergence(well_state, B_avg, deferred_logger, relax_convergence);
@ -2412,11 +2410,11 @@ namespace Opm
// Still stagnating, terminate iterations if 5 iterations pass.
++stagnate_count;
if (stagnate_count == 6) {
sstr << " well " << name() << " observes sever stagnation and/or oscillation. We relax the tolerance and check for convergence. \n";
sstr << " well " << name() << " observes severe 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";
sstr << " well " << name() << " manages to get converged with relaxed tolerances in " << it << " inner iterations";
deferred_logger.debug(sstr.str());
return;
}
@ -2509,9 +2507,14 @@ namespace Opm
// TODO: without considering the efficiencty factor for now
{
const EvalWell segment_surface_volume = getSegmentSurfaceVolume(ebosSimulator, seg);
// Add a regularization_factor to increase the accumulation term
// This will make the system less stiff and help convergence for
// difficult cases
const Scalar regularization_factor = param_.regularization_factor_ms_wells_;
// for each component
for (int comp_idx = 0; comp_idx < num_components_; ++comp_idx) {
const EvalWell accumulation_term = (segment_surface_volume * surfaceVolumeFraction(seg, comp_idx)
const EvalWell accumulation_term = regularization_factor * (segment_surface_volume * surfaceVolumeFraction(seg, comp_idx)
- segment_fluid_initial_[seg][comp_idx]) / dt;
resWell_[seg][comp_idx] += accumulation_term.value();
@ -2833,7 +2836,7 @@ namespace Opm
}
// We increase the segment volume with a factor 10 to stabilize the system.
const double volume = segmentSet()[seg_idx].volume() * 10;
const double volume = segmentSet()[seg_idx].volume();
return volume / vol_ratio;
}

View File

@ -2088,7 +2088,7 @@ namespace Opm
getWellConvergence(const WellState& well_state,
const std::vector<double>& B_avg,
Opm::DeferredLogger& deferred_logger,
const bool relax_tolerance) const
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