https://mooseframework.inl.gov
Loading...
Searching...
No Matches
DefaultNonlinearConvergence.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10// MOOSE includes
12#include "FEProblemBase.h"
13#include "PetscSupport.h"
14#include "NonlinearSystemBase.h"
16
17#include "libmesh/equation_systems.h"
18
19// PETSc includes
20#include <petsc.h>
21#include <petscmat.h>
22#include <petscsnes.h>
23
25
28{
31
32 params.addPrivateParam<bool>("added_as_default", false);
33
34 params.addClassDescription("Default convergence criteria for FEProblem.");
35
36 return params;
37}
38
40 : DefaultConvergenceBase(parameters),
41 _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
42 _nl_abs_div_tol(getSharedExecutionerParam<Real>("nl_abs_div_tol")),
43 _nl_rel_div_tol(getSharedExecutionerParam<Real>("nl_div_tol")),
44 _div_threshold(std::numeric_limits<Real>::max()),
45 _nl_forced_its(getSharedExecutionerParam<unsigned int>("nl_forced_its")),
46 _nl_max_pingpong(getSharedExecutionerParam<unsigned int>("n_max_nonlinear_pingpong")),
47 _nl_current_pingpong(0)
48{
49 EquationSystems & es = _fe_problem.es();
50
51 es.parameters.set<unsigned int>("nonlinear solver maximum iterations") =
52 getSharedExecutionerParam<unsigned int>("nl_max_its");
53 es.parameters.set<unsigned int>("nonlinear solver maximum function evaluations") =
54 getSharedExecutionerParam<unsigned int>("nl_max_funcs");
55 es.parameters.set<Real>("nonlinear solver absolute residual tolerance") =
56 getSharedExecutionerParam<Real>("nl_abs_tol");
57 es.parameters.set<Real>("nonlinear solver relative residual tolerance") =
58 getSharedExecutionerParam<Real>("nl_rel_tol");
59 es.parameters.set<Real>("nonlinear solver divergence tolerance") =
60 getSharedExecutionerParam<Real>("nl_div_tol");
61 es.parameters.set<Real>("nonlinear solver absolute step tolerance") =
62 getSharedExecutionerParam<Real>("nl_abs_step_tol");
63 es.parameters.set<Real>("nonlinear solver relative step tolerance") =
64 getSharedExecutionerParam<Real>("nl_rel_step_tol");
65}
66
67void
69{
71
73 mooseError("DefaultNonlinearConvergence can only be used with nonlinear solves.");
74}
75
81
82bool
84 const Real fnorm,
85 const Real ref_norm,
86 const Real rel_tol,
87 const Real abs_tol,
88 std::ostringstream & oss)
89{
90 if (fnorm < abs_tol)
91 {
92 oss << "Converged due to absolute residual " << fnorm << " < absolute tolerance (" << abs_tol
93 << ")\n";
94 return true;
95 }
96 else if (n_iter && fnorm <= ref_norm * rel_tol)
97 {
98 oss << "Converged due to relative/normalized residual norm " << fnorm / ref_norm
99 << " < relative tolerance (" << rel_tol << ")\n";
100 return true;
101 }
102 else
103 return false;
104}
105
108{
109 TIME_SECTION(_perfid_check_convergence);
110
113
114 SNES snes = system.getSNES();
115
116 // ||u||
117 PetscReal xnorm;
118 LibmeshPetscCallA(_fe_problem.comm().get(), SNESGetSolutionNorm(snes, &xnorm));
119
120 // ||r||
121 PetscReal fnorm;
122 LibmeshPetscCallA(_fe_problem.comm().get(), SNESGetFunctionNorm(snes, &fnorm));
123
124 // ||du||
125 PetscReal snorm;
126 LibmeshPetscCallA(_fe_problem.comm().get(), SNESGetUpdateNorm(snes, &snorm));
127
128 // Get current number of function evaluations done by SNES
129 PetscInt nfuncs;
130 LibmeshPetscCallA(_fe_problem.comm().get(), SNESGetNumberFunctionEvals(snes, &nfuncs));
131
132 // Get tolerances from SNES
133 PetscReal rel_step_tol;
134 PetscInt max_its, max_funcs;
135 LibmeshPetscCallA(
136 _fe_problem.comm().get(),
137 SNESGetTolerances(snes, &_abs_tol, &_rel_tol, &rel_step_tol, &max_its, &max_funcs));
138
139#if !PETSC_VERSION_LESS_THAN(3, 8, 4)
140 PetscBool force_iteration = PETSC_FALSE;
141 LibmeshPetscCallA(_fe_problem.comm().get(), SNESGetForceIteration(snes, &force_iteration));
142
143 // if PETSc says to force iteration, then force at least one iteration
144 if (force_iteration && !(_nl_forced_its))
145 _nl_forced_its = 1;
146
147 // if specified here to force iteration, but PETSc doesn't know, tell it
148 if (!force_iteration && (_nl_forced_its))
149 {
150 LibmeshPetscCallA(_fe_problem.comm().get(), SNESSetForceIteration(snes, PETSC_TRUE));
151 }
152#endif
153
154 // See if SNESSetFunctionDomainError() has been called.
155 // Note: SNESSetFunctionDomainError() and SNESGetFunctionDomainError() were added
156 // in different releases of PETSc. The latter was removed in PETSc 3.25.0.
157#if PETSC_VERSION_LESS_THAN(3, 25, 0)
158 PetscBool domainerror;
159 LibmeshPetscCallA(_fe_problem.comm().get(), SNESGetFunctionDomainError(snes, &domainerror));
160 if (domainerror)
162#else
163 SNESConvergedReason reason;
164 LibmeshPetscCallA(_fe_problem.comm().get(), SNESGetConvergedReason(snes, &reason));
165 if (reason == SNES_DIVERGED_FUNCTION_DOMAIN)
167#endif
168
169 // Needed by ResidualReferenceConvergence
171
172 Real fnorm_old;
173 // This is the first residual before any iterations have been done, but after
174 // solution-modifying objects (if any) have been imposed on the solution vector.
175 // We save it, and use it to detect convergence if system.usePreSMOResidual() == false.
176 if (n_iter == 0)
177 {
178 system.setInitialResidual(fnorm);
179 fnorm_old = fnorm;
181 }
182 else
183 fnorm_old = system._last_nl_rnorm;
184
185 // Check for nonlinear residual ping-pong.
186 // Ping-pong will always start from a residual increase
187 if ((_nl_current_pingpong % 2 == 1 && !(fnorm > fnorm_old)) ||
188 (_nl_current_pingpong % 2 == 0 && fnorm > fnorm_old))
190 else
192
193 const auto ref_residual = system.referenceResidual();
194 std::ostringstream oss;
195 if (n_iter < _nl_forced_its)
196 oss << "Number of forced iterations not yet reached: " << n_iter << " < " << _nl_forced_its
197 << '\n';
198 else if (fnorm != fnorm)
199 {
200 oss << "Failed to converge, residual norm is NaN\n";
202 }
203 else if (checkResidualConvergence(n_iter, fnorm, ref_residual, _rel_tol, _abs_tol, oss))
205 else if (nfuncs >= max_funcs)
206 {
207 oss << "Exceeded maximum number of residual evaluations: " << nfuncs << " > " << max_funcs
208 << '\n';
210 }
211 else if ((n_iter >= _nl_forced_its) && n_iter && fnorm > system._last_nl_rnorm &&
212 fnorm >= _div_threshold)
213 {
214 oss << "Nonlinear solve was blowing up!\n";
216 }
217 else if (snorm < rel_step_tol * xnorm)
218 {
219 oss << "Converged due to small update length: " << snorm << " < " << rel_step_tol << " * "
220 << xnorm << '\n';
222 }
223 else if (_nl_rel_div_tol > 0 && fnorm > ref_residual * _nl_rel_div_tol)
224 {
225 oss << "Diverged due to relative residual " << ref_residual << " > divergence tolerance "
226 << _nl_rel_div_tol << " * relative residual " << ref_residual << '\n';
228 }
229 else if (_nl_abs_div_tol > 0 && fnorm > _nl_abs_div_tol)
230 {
231 oss << "Diverged due to residual " << fnorm << " > absolute divergence tolerance "
232 << _nl_abs_div_tol << '\n';
234 }
236 {
237 oss << "Diverged due to maximum nonlinear residual pingpong achieved" << '\n';
239 }
240
241 system._last_nl_rnorm = fnorm;
242 system._current_nl_its = static_cast<unsigned int>(n_iter);
243
244 std::string msg;
245 msg = oss.str();
246 if (_app.multiAppLevel() > 0)
248 if (msg.length() > 0)
249#if !PETSC_VERSION_LESS_THAN(3, 17, 0)
250 LibmeshPetscCallA(_fe_problem.comm().get(), PetscInfo(snes, "%s", msg.c_str()));
251#else
252 LibmeshPetscCallA(_fe_problem.comm().get(), PetscInfo(snes, msg.c_str()));
253#endif
254
255 verboseOutput(oss);
256
257 return status;
258}
registerMooseObject("MooseApp", DefaultNonlinearConvergence)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
void ErrorVector unsigned int
PerfID _perfid_check_convergence
Performance ID for checkConvergence.
Definition Convergence.h:80
void verboseOutput(std::ostringstream &oss)
Outputs the stream to the console if verbose output is enabled.
Definition Convergence.C:51
MooseConvergenceStatus
Status returned by calls to checkConvergence.
Definition Convergence.h:34
virtual void checkIterationType(IterationType) const
Perform checks related to the iteration type.
Definition Convergence.h:48
Base class for default convergence criteria.
static InputParameters validParams()
Default nonlinear convergence criteria for FEProblem.
const Real _nl_rel_div_tol
Nonlinear relative divergence tolerance.
unsigned int _nl_current_pingpong
Current number of nonlinear ping-pong iterations for the current solve.
const Real _nl_abs_div_tol
Nonlinear absolute divergence tolerance.
unsigned int _nl_forced_its
Number of iterations to force.
PetscReal _rel_tol
Nonlinear relative tolerance.
virtual NonlinearSystemBase & nonlinearSystem()
Nonlinear system whose convergence state should be checked.
virtual bool checkResidualConvergence(const unsigned int n_iter, const Real fnorm, const Real ref_norm, const Real rel_tol, const Real abs_tol, std::ostringstream &oss)
Check the absolute and relative convergence of the nonlinear solution.
DefaultNonlinearConvergence(const InputParameters &parameters)
virtual void nonlinearConvergenceSetup()
Performs setup necessary for each call to checkConvergence.
virtual void checkIterationType(IterationType it_type) const override
Perform checks related to the iteration type.
const Real _div_threshold
Divergence threshold value.
const unsigned int _nl_max_pingpong
Maximum number of nonlinear ping-pong iterations for a solve.
PetscReal _abs_tol
Nonlinear absolute tolerance.
virtual MooseConvergenceStatus checkConvergence(unsigned int n_iter) override
Returns convergence status.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual libMesh::EquationSystems & es() override
NonlinearSystemBase & currentNonlinearSystem()
static InputParameters feProblemDefaultConvergenceParams()
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
unsigned int multiAppLevel() const
The MultiApp Level.
Definition MooseApp.h:855
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
Class for containing MooseEnum item information.
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
Nonlinear system to be solved.
Real referenceResidual() const
The reference residual used in relative convergence check.
virtual SNES getSNES()=0
void setInitialResidual(Real r)
Record the initial residual (for later relative convergence check)
const Parallel::Communicator & comm() const
T & set(const std::string &)
void indentMessage(const std::string &prefix, std::string &message, const char *color, bool indent_first_line, const std::string &post_prefix)
Definition MooseUtils.C:749