libMesh / libmesh

libMesh github repository
http://libmesh.github.io
GNU Lesser General Public License v2.1
643 stars 285 forks source link

Adding an absolute tolerance for the `LinearSolver`-s #3623

Closed grmnptr closed 1 year ago

grmnptr commented 1 year ago

I encountered a problem where I would like to set an absolute tolerance for PetscLinearSolver in MOOSE. Right now, the solve function takes a relative tolerance only:

std::pair< unsigned int, Real > libMesh::PetscLinearSolver< T >::solve( SparseMatrix< T > &  matrix,
        SparseMatrix< T > &  preconditioner,
        NumericVector< T > &  solution,
        NumericVector< T > &  rhs,
        const double  tol,
        const unsigned int  m_its 
    )   

and assigns the default petsc option for the absolute tolerance:

// Set the tolerances for the iterative solver.  Use the user-supplied
// tolerance for the relative residual & leave the others at default values.
ierr = KSPSetTolerances (_ksp, tol, PETSC_DEFAULT,
                            PETSC_DEFAULT, max_its);
LIBMESH_CHKERR(ierr);

I am thinking about either of these two:

  1. Adding a new parameter to the solve function with a default value of 0 or a small number supported by all derived classes.
  2. Creating a new virtual function which has both toleraces and errors for derived classes if the one with the abolute tolerance is not implemented.

What do you think @lindsayad , @roystgnr , @jwpeterson ?

grmnptr commented 1 year ago

Some solvers in derived classes don't use absolute/relative tolerance (like LaspackLinearSolver). So maybe adding a new function is the way to go.

jwpeterson commented 1 year ago

Hmm, it appears you are correct. And for PetscNonlinearSolver, I think things are a bit more involved because the tolerances used for the linear solver can depend on the current nonlinear residual norm, but we have the same pattern repeated there:

  ierr = KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT,
                           PETSC_DEFAULT, this->max_linear_iterations);

So I would be in favor adding support for a user-defined absolute tolerance, but it would probably be a pain to do this while keeping backwards compatibility for all the different overridden LinearSolver::solve() APIs. Maybe we should deprecate the tol that is currently passed in to solve() in favor of a more general approach that allows multiple tolerances to be set on the base class and then used by derived classes as appropriate.

jwpeterson commented 1 year ago

Also, I'm sure you are already aware, but if you just want to quickly control the absolute tolerance used by the PETSc linear solvers without making a big libmesh change, I think you should be able to do this with the -ksp_atol command line argument.

lindsayad commented 1 year ago

Maybe we should deprecate the tol that is currently passed in to solve() in favor of a more general approach that allows multiple tolerances to be set on the base class and then used by derived classes as appropriate.

This seems like a good suggestion to me