Skip to content

Commit

Permalink
Add HYPRE.GetFinalRelativeResidualNorm and HYPRE.GetNumIterations (
Browse files Browse the repository at this point in the history
…#14)

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.
  • Loading branch information
fredrikekre authored Jan 20, 2023
1 parent b5cacd9 commit f8298e9
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- New function `HYPRE.GetFinalRelativeResidualNorm(s::HYPRESolver)` for getting the final
residual norm from a solver. This function dispatches on the solver to the corresponding
C API wrapper `LibHYPRE.HYPRE_${Solver}GetFinalRelativeResidualNorm`. ([#14][github-14])
- New function `HYPRE.GetNumIterations(s::HYPRESolver)` for getting the number of
iterations from a solver. This function dispatches on the solver to the corresponding C
API wrapper `LibHYPRE.HYPRE_${Solver}GetNumIterations`. ([#14][github-14])

## [1.3.1] - 2023-01-14
### Fixed
Expand Down Expand Up @@ -58,6 +65,7 @@ Initial release of HYPRE.jl.
[github-8]: https://github.com/fredrikekre/HYPRE.jl/pull/8
[github-12]: https://github.com/fredrikekre/HYPRE.jl/pull/12
[github-13]: https://github.com/fredrikekre/HYPRE.jl/pull/13
[github-14]: https://github.com/fredrikekre/HYPRE.jl/pull/14

[1.0.0]: https://github.com/fredrikekre/HYPRE.jl/releases/tag/v1.0.0
[1.1.0]: https://github.com/fredrikekre/HYPRE.jl/compare/v1.0.0...v1.1.0
Expand Down
65 changes: 65 additions & 0 deletions src/solvers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,68 @@ function Internals.set_precond(pcg::PCG, p::HYPRESolver)
@check HYPRE_ParCSRPCGSetPrecond(pcg, solve_f, setup_f, p)
return nothing
end


##########################################################
# Extracting information about the solution from solvers #
##########################################################

"""
HYPRE.GetFinalRelativeResidualNorm(s::HYPRESolver)
Return the final relative residual norm from the last solve with solver `s`.
This function dispatches on the solver to the corresponding C API wrapper
`LibHYPRE.HYPRE_\$(Solver)GetFinalRelativeResidualNorm`.
"""
function GetFinalRelativeResidualNorm(s::HYPRESolver)
r = Ref{HYPRE_Real}()
if s isa BiCGSTAB
@check HYPRE_ParCSRBiCGSTABGetFinalRelativeResidualNorm(s, r)
elseif s isa BoomerAMG
@check HYPRE_BoomerAMGGetFinalRelativeResidualNorm(s, r)
elseif s isa FlexGMRES
@check HYPRE_ParCSRFlexGMRESGetFinalRelativeResidualNorm(s, r)
elseif s isa GMRES
@check HYPRE_ParCSRGMRESGetFinalRelativeResidualNorm(s, r)
elseif s isa Hybrid
@check HYPRE_ParCSRHybridGetFinalRelativeResidualNorm(s, r)
elseif s isa ILU
@check HYPRE_ILUGetFinalRelativeResidualNorm(s, r)
elseif s isa PCG
@check HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(s, r)
else
throw(ArgumentError("cannot get residual norm for $(typeof(s))"))
end
return r[]
end

"""
HYPRE.GetNumIterations(s::HYPRESolver)
Return number of iterations during the last solve with solver `s`.
This function dispatches on the solver to the corresponding C API wrapper
`LibHYPRE.HYPRE_\$(Solver)GetNumIterations`.
"""
function GetNumIterations(s::HYPRESolver)
r = Ref{HYPRE_Int}()
if s isa BiCGSTAB
@check HYPRE_ParCSRBiCGSTABGetNumIterations(s, r)
elseif s isa BoomerAMG
@check HYPRE_BoomerAMGGetNumIterations(s, r)
elseif s isa FlexGMRES
@check HYPRE_ParCSRFlexGMRESGetNumIterations(s, r)
elseif s isa GMRES
@check HYPRE_ParCSRGMRESGetNumIterations(s, r)
elseif s isa Hybrid
@check HYPRE_ParCSRHybridGetNumIterations(s, r)
elseif s isa ILU
@check HYPRE_ILUGetNumIterations(s, r)
elseif s isa PCG
@check HYPRE_ParCSRPCGGetNumIterations(s, r)
else
throw(ArgumentError("cannot get number of iterations for $(typeof(s))"))
end
return r[]
end
25 changes: 25 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ end
x_h = HYPRE.solve(bicg, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
# Test solver queries
@test HYPRE.GetFinalRelativeResidualNorm(bicg) < tol
@test HYPRE.GetNumIterations(bicg) > 0

# Solve with preconditioner
precond = HYPRE.BoomerAMG(; MaxIter = 1, Tol = 0.0)
Expand Down Expand Up @@ -440,6 +443,9 @@ end
x_h = HYPRE.solve(amg, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol = tol * norm(b)
# Test solver queries
@test HYPRE.GetFinalRelativeResidualNorm(amg) < tol
@test HYPRE.GetNumIterations(amg) > 0
end

@testset "FlexGMRES" begin
Expand All @@ -466,6 +472,9 @@ end
x_h = HYPRE.solve(gmres, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
# Test solver queries
@test HYPRE.GetFinalRelativeResidualNorm(gmres) < tol
@test HYPRE.GetNumIterations(gmres) > 0

# Solve with preconditioner
precond = HYPRE.BoomerAMG()
Expand Down Expand Up @@ -506,6 +515,9 @@ end
x_h = HYPRE.solve(gmres, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
# Test solver queries
@test HYPRE.GetFinalRelativeResidualNorm(gmres) < tol
@test HYPRE.GetNumIterations(gmres) > 0

# Solve with preconditioner
precond = HYPRE.BoomerAMG(; MaxIter = 1, Tol = 0.0)
Expand Down Expand Up @@ -545,6 +557,9 @@ end
x_h = HYPRE.solve(hybrid, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
# Test solver queries
@test HYPRE.GetFinalRelativeResidualNorm(hybrid) < tol
@test HYPRE.GetNumIterations(hybrid) > 0

# Solve with given preconditioner
precond = HYPRE.BoomerAMG()
Expand Down Expand Up @@ -585,6 +600,9 @@ end
x_h = HYPRE.solve(ilu, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
# Test solver queries
@test HYPRE.GetFinalRelativeResidualNorm(ilu) < tol
@test HYPRE.GetNumIterations(ilu) > 0

# Use as preconditioner to PCG
precond = HYPRE.ILU()
Expand Down Expand Up @@ -623,6 +641,9 @@ end
copy!(x, x_h)
# Test result with direct solver
@test x A \ b atol=tol
# Test solver queries (should error)
@test_throws ArgumentError("cannot get residual norm for HYPRE.ParaSails") HYPRE.GetFinalRelativeResidualNorm(parasails)
@test_throws ArgumentError("cannot get number of iterations for HYPRE.ParaSails") HYPRE.GetNumIterations(parasails)
end

@testset "(ParCSR)PCG" begin
Expand Down Expand Up @@ -650,6 +671,10 @@ end
x_h = HYPRE.solve(pcg, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
# Test solver queries
@test HYPRE.GetFinalRelativeResidualNorm(pcg) < tol
@test HYPRE.GetNumIterations(pcg) > 0

# Solve with AMG preconditioner
precond = HYPRE.BoomerAMG(; MaxIter = 1, Tol = 0.0)
pcg = HYPRE.PCG(; Tol = tol, Precond = precond)
Expand Down

0 comments on commit f8298e9

Please sign in to comment.