Skip to content

allow setting both absolute and relative tolerance of sparse iterative solvers #7624

@rc

Description

@rc

Currently a single tolerance (tol argument) is used, which is impractical, when using an iterative solver as a preconditioner. In that case it is desirable to set a relative tolerance to some not-so-small value (e.g. 1e-2), without caring about the absolute tolerance. The current behaviour prevents that, as something like setting tol=1e-2 often leads to absolute convergence in iteration zero of the preconditioner, hence no preconditioning done at all.

This behaviour breaks the IMHO very good lgmres solver. For example, the following happens when using lgmres with cg (tol=1e-2) as a preconditioner for symmetric positive definite diagonal blocks:

<snip>
sfepy: cg-s: iteration 1
sfepy: cg-s: iteration 2
sfepy: cg-s: iteration 3
sfepy: cg-s: iteration 4
sfepy: cg-s: iteration 5
sfepy: cg-s: iteration 6
sfepy: cg-s: cg convergence: 0 (successful exit)
rhs norm: 8.751133e-02, solution norm: 4.484927e+00
sfepy: iterative-s: iteration 4: |Ax-b| = 2.323006e-03
sfepy: cg-s: iteration 1
sfepy: cg-s: cg convergence: 0 (successful exit)
rhs norm: 4.101975e-04, solution norm: 0.000000e+00
sfepy: cg-s: iteration 1
sfepy: cg-s: cg convergence: 0 (successful exit)
rhs norm: 2.286502e-03, solution norm: 0.000000e+00
Traceback (most recent call last):
<snip>
  File "....local/lib/python2.7/site-packages/scipy/sparse/linalg/isolve/lgmres.py", line 145, in lgmres
    "|v| ~ %.1g, |M v| = 0" % rnorm)
RuntimeError: Preconditioner returned a zero vector; |v| ~ 0.002, |M v| = 0

This happened because the rhs norm was 2.286502e-03 < 1e-2 (see the line above the traceback), so no solution was attempted.

So I propose having both rtol and atol arguments (or allow tol to be a tuple), and possibly adding a tol_mode argument - either 'and' or 'or', defaulting to 'or', that tell whether both tolerances have to be met ('and' mode) or a single one is enough.

I can make a PR implementing this for lgmres, as it is written in Python. I am not sure if I am brave enough to dive into the legacy fortran of the other solvers.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions