mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
ec7c6e236d
commit
8a5c9e82df
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user