This patch adds the functions
`HYPRE.GetFinalRelativeResidualNorm(::HYPRESolver)` and
`HYPRE.GetNumIterations(::HYPRESolver)` for querying final residual norm
and number of iterations from solvers. These functions dispatches on the
solver to the corresponding C API wrappers
`LibHYPRE.HYPRE_${Solver}GetFinalRelativeResidualNorm` and
`LibHYPRE.HYPRE_${Solver}GetNumIterations`, respectively.
This patch adds methods for `Base.unsafe_convert` for `HYPREMatrix`,
`HYPREVector`, and `HYPRESolver`. This means that those objects can be
passed directly to `ccall` and be "converted" (i.e. extracting the
pointer that is stored in the structs) to the appropriate type expected
by the HYPRE C-library. The advantage is that `ccall` then guarantees
that the objects are kept alive for the duration of the call.
This patch tracks all created HYPRE objects (`HYPREMatrix`,
`HYPREVector`, and `HYPRESolver`s) in a global `WeakKeyDict` to make
sure they are all finalized **before** MPI and/or HYPRE is finalized.
These libraries are typically finalized in Julia atexit hooks, but at
that point the object finalizers might yet not have been run. This patch
make sure to explicitly call `finalize` on any remaining HYPRE objects
before finalizing the library.
This patch wraps the HYPRE_Destroy functions for the HYPRESolvers in a
functtion that checks if the pointer is NULL before calling the Destroy
function. While this makes sense on it self, it also makes it possible
to override a finalizer by adding a second one that sets the pointer to
NULL. This is utilized in the set_precond(::Hybrid, p) function, since
the Hybrid solver currently frees the provied preconditioner too.
This patch stores the MPI communicator in the solvers structs. The
default communicator is changed from COMM_WORLD to COMM_NULL, for
BiCGSTAB, GMRES, and PCG, since their respective HYPRE_Create functions
simply ignore this argument.
This patch adds the following methods:
solve( ::HYPRESolver, ::PSparseMatrix, ::PVector)
solve!(::HYPRESolver, ::PVector, ::PSparseMatrix, ::PVector)
which automatically converts to/from HYPRE(Matrix|Vector).
This patch adds a function
solve(::HYPRESolver, ::HYPREMatrix, ::HYPREVector) which initializes an
output vector initialized to 0 and pass it to solve!.
Settings are passed as keyword arguments, just like BoomerAMG. The
Precond argument (corresponding to PCGSetPrecond) is handled separately,
and lets you pass another solver directly, instead of the solver
pointer, the setup and solve functions, as in the SetPrecond C function.
Example:
precond = BoomerAMG(; options...)
solver = PCG(; Precond = precond, options...)
This commits contains the solver interface:
A = HYPREMatrix(...)
b = HYPREVector(...)
x = HYPREVector(...)
solver = HYPRESolver(; options...)
solve!(solver, x, A, b)
where the abstract type HYPRESolver is replaced by a concrete solver
implementation (this commit includes the concrete
implementation/wrapping of BoomerAMG <: HYPRESolver).
Solver settings are passed as keyword arguments to the solver
constructor, cf. SetXXX functions in HYPRE.
For example, to create a BoomerAMG solver, and setting the tolerance:
solver = BoomerAMG(Tol = 1e-7)
Keyword argument names correspond directly to the solvers SetXXX
function in HYPRE; passing Tol corresponds to
HYPRE_BoomerAMGSetTol(solver, 1e-7).