Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Started the Convergence system #28848

Open
wants to merge 5 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions framework/doc/content/bib/moose.bib
Original file line number Diff line number Diff line change
Expand Up @@ -609,3 +609,15 @@ @article{liu2015finite
year={2015},
publisher={Taylor \& Francis}
}

@article{rao2018stopping,
title = {A stopping criterion for the iterative solution of partial differential equations},
journal = {Journal of Computational Physics},
volume = {352},
pages = {265-284},
year = {2018},
issn = {0021-9991},
doi = {https://doi.org/10.1016/j.jcp.2017.09.033},
url = {https://www.sciencedirect.com/science/article/pii/S0021999117306939},
author = {Kaustubh Rao and Paul Malan and J. Blair Perot}
}
5 changes: 5 additions & 0 deletions framework/doc/content/source/actions/AddConvergenceAction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# AddConvergenceAction

Adds a [Convergence](syntax/Convergence/index.md) object to the `Problem`.

!syntax parameters /Convergence/AddConvergenceAction
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# AddDefaultConvergenceAction

This action adds a default [Convergence](syntax/Convergence/index.md) object if requested
by the `Problem`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# DefaultNonlinearConvergence

This [Convergence](Convergence/index.md) is the default convergence for
[/FEProblem.md], using a combination of criteria to determine convergence.

!alert warning title=Shared executioner parameters
This object shares several parameters with the executioner. If one of these
parameters is set by the user in the executioner and not in the convergence
object, then the value is taken from the executioner, rather than the default
value. If a parameter is set by the user in both the executioner and the convergence
object, an error is thrown.

Consider the system of algebraic equations:

!equation
\mathbf{r}(\mathbf{u}) = \mathbf{0} \,.

This class reports convergence of the solution to this system if
any of the following conditions are true:

!equation
\|\mathbf{r}\|_2 < \tau_\text{abs} \,,

!equation
\frac{\|\mathbf{r}\|_2}{\|\mathbf{r}_0\|_2} < \tau_\text{rel} \,,

!equation
\frac{\|\mathbf{\delta u}\|_2}{\|\mathbf{u}\|_2} < \tau_{\delta u,\text{rel}} \,.

This class reports divergence if any of the following conditions are true:

!equation
\|\mathbf{r}\|_2 = \text{NaN} \,,

!equation
n_\text{evals} \geq n_\text{evals,max} \,,

!equation
\|\mathbf{r}\|_2 > \tau_\text{div,abs} \,,

!equation
\frac{\|\mathbf{r}\|_2}{\|\mathbf{r}_0\|_2} > \tau_\text{div,rel} \,,

!equation
n_\text{ping} > n_\text{ping,max} \,,

where

- $\|\cdot\|_2$ is the discrete $L_2$ norm,
- $\mathbf{r}_0$ is the initial (guess) residual vector,
- $\mathbf{\delta u} = \mathbf{u}^{(\ell)} - \mathbf{u}^{(\ell-1)}$ is the solution step vector,
- "NaN" is a not-a-number value,
- $\tau_\text{abs}$ is the absolute residual tolerance, specified with the
[!param](/Convergence/DefaultNonlinearConvergence/nl_abs_tol) parameter.
- $\tau_\text{rel}$ is the relative residual tolerance, provided by
[!param](/Convergence/DefaultNonlinearConvergence/nl_rel_tol).
- $\tau_{\delta u,\text{abs}}$ is the relative step tolerance., provided by
[!param](/Convergence/DefaultNonlinearConvergence/nl_rel_step_tol).
- $\tau_\text{div,abs}$ is the absolute residual divergence tolerance, provided by
[!param](/Convergence/DefaultNonlinearConvergence/nl_abs_div_tol).
- $\tau_\text{div,rel}$ is the relative residual divergence tolerance, provided by
[!param](/Convergence/DefaultNonlinearConvergence/nl_div_tol).
- $n_\text{evals}$ is the number of residual evaluations.
- $n_\text{evals,max}$ is the maximum number of residual evaluations, provided by
[!param](/Convergence/DefaultNonlinearConvergence/nl_max_funcs).
- $n_\text{ping}$ is the number of ping-pong iterations.
- $n_\text{ping,max}$ is the maximum number of ping-pong iterations, provided by
[!param](/Convergence/DefaultNonlinearConvergence/n_max_nonlinear_pingpong).

!syntax parameters /Convergence/DefaultNonlinearConvergence

!syntax inputs /Convergence/DefaultNonlinearConvergence

!syntax children /Convergence/DefaultNonlinearConvergence
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# IterationCountConvergence
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an object you or someone else actually wants?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, it's kind of serving as a commonly used intermediate base class (PostprocessorConvergence inherits from it, for example). I think we want it in some form.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I d use it for debugging for sure. Setting a fixed number of iterations is helpful


This [Convergence](Convergence/index.md) specifies:

- $\ell_\text{max}$, the maximum number of iterations,
via [!param](/Convergence/IterationCountConvergence/max_iterations), and
- $\ell_\text{min}$, the minimum number of iterations,
via [!param](/Convergence/IterationCountConvergence/min_iterations).

If [!param](/Convergence/IterationCountConvergence/converge_at_max_iterations)
is set to `true`, then the solve will converge when $\ell = \ell_\text{max}$
instead of diverge.

## Design

Other `Convergence` objects may inherit from this class and override
`checkConvergenceInner(iter)` instead of the usual `checkConvergence(iter)`,
to inherit the iteration bounds. An example is [/PostprocessorConvergence.md].

GiudGiud marked this conversation as resolved.
Show resolved Hide resolved
!syntax parameters /Convergence/IterationCountConvergence

!syntax inputs /Convergence/IterationCountConvergence

!syntax children /Convergence/IterationCountConvergence
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# PostprocessorConvergence

This [Convergence](Convergence/index.md) derives from [/IterationCountConvergence.md]
and compares a [Postprocessor](Postprocessors/index.md) value $y$ to a tolerance $\tau$:

!equation
y \leq \tau \,.

For this to work as expected, the `execute_on` parameter of the post-processor
must include values that trigger execution before the desired check. For example, for nonlinear
convergence, the value `NONLINEAR_CONVERGENCE` should be used.

Typically the post-processor used should attempt to approximate the error in a system,
such as [/AverageVariableChange.md].

!syntax parameters /Convergence/PostprocessorConvergence

!syntax inputs /Convergence/PostprocessorConvergence

!syntax children /Convergence/PostprocessorConvergence
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# ReferenceResidualConvergence

This [Convergence](Convergence/index.md) is a [/DefaultNonlinearConvergence.md] with a
customized reference residual for its relative convergence checks. See
[ReferenceResidualProblem.md] for more information.

!syntax parameters /Convergence/ReferenceResidualConvergence

!syntax inputs /Convergence/ReferenceResidualConvergence

!syntax children /Convergence/ReferenceResidualConvergence
12 changes: 6 additions & 6 deletions framework/doc/content/source/postprocessors/PseudoTimestep.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ This object computes a timestep to accelerate the convergence to steady-state us
The change in timestep is determined by the steady-state residual behavior from one iteration to another, i.e., small changes in residual indicate larger timesteps are allowed. In contrast, significant changes in the residual indicate a timestep decrease is necessary.
Following [!citep](bucker2009cfl), we recognize and implement three methods.

The user must make a method choice, between `SER`, `EXP` and `RDM`, which are implemented as listed below.
All methods require a parameter [!param](/Postprocessors/PseudoTimestep/alpha), which controls how sensitive the timestep should be with respect to residual changes, and [!param](/Postprocessors/PseudoTimestep/initial_dt) to provide a first timestep length.
The user must make a method choice, between `SER`, `EXP` and `RDM`, which are implemented as listed below.
All methods require a parameter [!param](/Postprocessors/PseudoTimestep/alpha), which controls how sensitive the timestep should be with respect to residual changes, and [!param](/Postprocessors/PseudoTimestep/initial_dt) to provide a first timestep length.
If nothing is known about the problem we recommend `initial_dt = 1` and `alpha = 2`, keeping in mind that a high [!param](/Postprocessors/PseudoTimestep/alpha) corresponds to a higher sensitivity to residual changes. More specific choices for fluid dynamics problems are available in [!citep](bucker2009cfl) or [!citep](ceze2013pseudo). The parameter [!param](/Postprocessors/PseudoTimestep/alpha) is always larger than 0, noting that for some versions of Pseudo Timestep Continuation methods it can be lower than 1. We refer the user to the literature, or to perform a preliminary study for their specific problem.

Methods supported include:
Expand Down Expand Up @@ -46,17 +46,17 @@ Methods supported include:

where $\alpha$ is a user chosen parameter, $k$ is the current iteration step.

As noted also in [!citep](bucker2009cfl) the EXP method has an infinite growth, so for this method a [!param](/Postprocessors/PseudoTimestep/max_dt) parameter may be recommended. If no [!param](/Postprocessors/PseudoTimestep/max_dt) is provided by the user then infinite growth of the timestep is not bounded and the user will be informed by a message at the console. Ideally this method is used in conjunction with a steady state detection, i.e. setting [!param](/Executioner/Transient/steady_state_detection) to `true` and a [!param](/Executioner/Transient/steady_state_tolerance).
As noted also in [!citep](bucker2009cfl) the EXP method has an infinite growth, so for this method a [!param](/Postprocessors/PseudoTimestep/max_dt) parameter may be recommended. If no [!param](/Postprocessors/PseudoTimestep/max_dt) is provided by the user then infinite growth of the timestep is not bounded and the user will be informed by a message at the console. Ideally this method is used in conjunction with a steady state detection, i.e. setting [!param](/Executioner/Transient/steady_state_detection) to `true` and a [!param](/Executioner/Transient/steady_state_tolerance).

## Example Input File Syntax

!listing test/tests/postprocessors/pseudotimestep/fv_burgers_pseudo.i
block=Postprocessors
!listing test/tests/postprocessors/pseudotimestep/fv_burgers_pseudo.i
block=Postprocessors

!syntax parameters /Postprocessors/PseudoTimestep

!syntax inputs /Postprocessors/PseudoTimestep

!syntax children /Postprocessors/PseudoTimestep

!bibtex bibliography
!bibtex bibliography
125 changes: 125 additions & 0 deletions framework/doc/content/syntax/Convergence/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Convergence System

The Convergence system allows users to customize the stopping criteria for the
iteration in various solves:

- Nonlinear system solves
- Linear system solves (not yet implemented)
- Steady-state detection in [Transient.md] (not yet implemented)
- Fixed point solves with [MultiApps](syntax/MultiApps/index.md) (not yet implemented)
- Fixed point solves with multiple systems (not yet implemented)

Instead of supplying convergence-related parameters directly to the executioner,
the user creates `Convergence` objects whose names are then supplied to the
executioner, e.g.,

```
[Convergence]
[my_convergence1]
type = MyCustomConvergenceClass
# some convergence parameters, like tolerances
[]
[]

[Executioner]
type = Steady
nonlinear_convergence = my_convergence1
[]
```

Currently only the nonlinear solve convergence is supported, but others are planned
for the near future. If the `nonlinear_convergence` parameter is not specified,
then the default `Convergence` associated with the problem is created internally.

!syntax list /Convergence objects=True actions=False subsystems=False

!syntax list /Convergence objects=False actions=False subsystems=True

!syntax list /Convergence objects=False actions=True subsystems=False

## Convergence Criteria Design Considerations

Here we provide some considerations to make in designing convergence criteria
and choosing appropriate parameter values.
Consider a system of algebraic system of equations

!equation
\mathbf{r}(\mathbf{u}) = \mathbf{0} \,,

where $\mathbf{u}$ is the unknown solution vector, and $\mathbf{r}$ is the residual
function. To solve this system using an iterative method, we must decide on
criteria to stop the iteration.
In general, iteration for a solve should halt when the approximate solution $\tilde{\mathbf{u}}$
has reached a satisfactory level of error $\mathbf{e} \equiv \tilde{\mathbf{u}} - \mathbf{u}$,
using a condition such as

!equation id=error_criteria
\|\mathbf{e}\| \leq \tau_u \,,

where $\|\cdot\|$ denotes some norm, and $\tau_u$ denotes some tolerance.
Unfortunately, since we do not know $\mathbf{u}$, the error $\mathbf{e}$ is
also unknown and thus may not be computed directly. Thus some approximation of
the condition [!eqref](error_criteria) must be made. This may entail some
approximation of the error $\mathbf{e}$ or some criteria which implies the
desired criteria. For example, a very common approach is to use a residual
criteria such as

!equation
\|\mathbf{r}\| \leq \tau_{r,\text{abs}} \,.

While it is true that $\|\mathbf{r}\| = 0$ implies $\|\mathbf{e}\| = 0$, a
zero-tolerance is impractical, and the translation between the tolerance
$\tau_u$ to the tolerance is $\tau_r$ is difficult. The "acceptable" absolute
residual tolerance is tricky to determine and is highly dependent on the
equations being solved. To attempt to circumvent this issue, relative residual
criteria have been used, dividing the residual norm by another value in an
attempt to normalize it. A common approach that has been used is to use the
initial residual vector $\mathbf{r}_0$ to normalize:

!equation
\frac{\|\mathbf{r}\|}{\|\mathbf{r}_0\|} \leq \tau_{r,\text{rel}} \,,

where $\tau_{r,\text{rel}}$ is the relative residual tolerance. The disadvantage
with this particular choice is that this is highly dependent on how good the
initial guess is: if the initial guess is very good, it will be nearly impossible
to converge to the tolerance, and if the initial guess is very bad, it will be
too easy to converge to the tolerance, resulting in an erroneous solution.

Some other considerations are the following:

- Consider round-off error: if error ever reaches values around round-off error,
the solve should definitely be considered converged, as iterating further
provides no benefit.
- Consider the other sources of error in the model that produced the system of
algebraic equations that you're solving. For example, if solving a system of
partial differential equations, consider the model error and the discretization
error; it is not beneficial to require algebraic error less than the other
sources of error.
- Since each convergence criteria typically has some weak point where they break
down, it is usually advisable to use a combination of criteria.

For more information on convergence criteria, see [!cite](rao2018stopping) for
example.

!alert tip title=Create your own convergence action
The `Convergence` system provides a lot of flexibility by providing several
pieces that can be combined together to create a desired set of convergence
criteria. Since this may involve a large number of objects (including objects
from other systems), it may be beneficial to create an [Action](/Action.md)
to create more compact and convenient syntax for your application.

## Implementing a New Convergence Class

`Convergence` objects are responsible for overriding the virtual method

```
MooseConvergenceStatus checkConvergence(unsigned int iter)
```

The returned type `MooseConvergenceStatus` is one of the following values:

- `CONVERGED`: The system has converged.
- `DIVERGED`: The system has diverged.
- `ITERATING`: The system has neither converged nor diverged and thus will
continue to iterate.

25 changes: 25 additions & 0 deletions framework/include/actions/AddConvergenceAction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "MooseObjectAction.h"

/**
* Add a Convergence object to the simulation.
*/
class AddConvergenceAction : public MooseObjectAction
{
public:
static InputParameters validParams();

AddConvergenceAction(const InputParameters & params);

virtual void act() override;
};
25 changes: 25 additions & 0 deletions framework/include/actions/AddDefaultConvergenceAction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "Action.h"

/**
* Add a default Convergence object to the simulation.
*/
class AddDefaultConvergenceAction : public Action
{
public:
static InputParameters validParams();

AddDefaultConvergenceAction(const InputParameters & params);

virtual void act() override;
};
Loading