Browse Source

Add FlexGMRES solver.

pull/5/head
Fredrik Ekre 3 years ago
parent
commit
6bea57d124
  1. 1
      gen/solver_options.jl
  2. 30
      src/solver_options.jl
  3. 38
      src/solvers.jl
  4. 40
      test/runtests.jl

1
gen/solver_options.jl

@ -55,6 +55,7 @@ open(joinpath(@__DIR__, "..", "src", "solver_options.jl"), "w") do io @@ -55,6 +55,7 @@ open(joinpath(@__DIR__, "..", "src", "solver_options.jl"), "w") do io
generate_options(io, "BiCGSTAB", "HYPRE_ParCSRBiCGSTABSet", "HYPRE_BiCGSTABSet")
generate_options(io, "BoomerAMG", "HYPRE_BoomerAMGSet")
generate_options(io, "FlexGMRES", "HYPRE_ParCSRFlexGMRESSet", "HYPRE_FlexGMRESSet")
# generate_options(io, "FSAI", "HYPRE_FSAISet")
generate_options(io, "GMRES", "HYPRE_ParCSRGMRESSet", "HYPRE_GMRESSet")
generate_options(io, "ILU", "HYPRE_ILUSet")

30
src/solver_options.jl

@ -289,6 +289,36 @@ function Internals.set_options(s::BoomerAMG, kwargs) @@ -289,6 +289,36 @@ function Internals.set_options(s::BoomerAMG, kwargs)
end
end
function Internals.set_options(s::FlexGMRES, kwargs)
solver = s.solver
for (k, v) in kwargs
if k === :ConvergenceFactorTol
@check HYPRE_FlexGMRESSetConvergenceFactorTol(solver, v)
elseif k === :AbsoluteTol
@check HYPRE_ParCSRFlexGMRESSetAbsoluteTol(solver, v)
elseif k === :KDim
@check HYPRE_ParCSRFlexGMRESSetKDim(solver, v)
elseif k === :Logging
@check HYPRE_ParCSRFlexGMRESSetLogging(solver, v)
elseif k === :MaxIter
@check HYPRE_ParCSRFlexGMRESSetMaxIter(solver, v)
elseif k === :MinIter
@check HYPRE_ParCSRFlexGMRESSetMinIter(solver, v)
elseif k === :ModifyPC
@check HYPRE_ParCSRFlexGMRESSetModifyPC(solver, v)
elseif k === :Precond
Internals.set_precond_defaults(v)
Internals.set_precond(s, v)
elseif k === :PrintLevel
@check HYPRE_ParCSRFlexGMRESSetPrintLevel(solver, v)
elseif k === :Tol
@check HYPRE_ParCSRFlexGMRESSetTol(solver, v)
else
throw(ArgumentError("unknown option $k for HYPRE.FlexGMRES"))
end
end
end
function Internals.set_options(s::GMRES, kwargs)
solver = s.solver
for (k, v) in kwargs

38
src/solvers.jl

@ -152,6 +152,44 @@ function Internals.set_precond_defaults(amg::BoomerAMG) @@ -152,6 +152,44 @@ function Internals.set_precond_defaults(amg::BoomerAMG)
end
#############
# FlexGMRES #
#############
mutable struct FlexGMRES <: HYPRESolver
comm::MPI.Comm
solver::HYPRE_Solver
function FlexGMRES(comm::MPI.Comm=MPI.COMM_NULL; kwargs...)
# comm defaults to COMM_NULL since it is unused in HYPRE_ParCSRFlexGMRESCreate
solver = new(comm, C_NULL)
solver_ref = Ref{HYPRE_Solver}(C_NULL)
@check HYPRE_ParCSRFlexGMRESCreate(comm, solver_ref)
solver.solver = solver_ref[]
# Attach a finalizer
finalizer(x -> HYPRE_ParCSRFlexGMRESDestroy(x.solver), solver)
# Set the options
Internals.set_options(solver, kwargs)
return solver
end
end
function solve!(flex::FlexGMRES, x::HYPREVector, A::HYPREMatrix, b::HYPREVector)
@check HYPRE_ParCSRFlexGMRESSetup(flex.solver, A.parmatrix, b.parvector, x.parvector)
@check HYPRE_ParCSRFlexGMRESSolve(flex.solver, A.parmatrix, b.parvector, x.parvector)
return x
end
Internals.setup_func(::FlexGMRES) = HYPRE_ParCSRFlexGMRESSetup
Internals.solve_func(::FlexGMRES) = HYPRE_ParCSRFlexGMRESSolve
function Internals.set_precond(flex::FlexGMRES, p::HYPRESolver)
solve_f = Internals.solve_func(p)
setup_f = Internals.setup_func(p)
@check HYPRE_ParCSRFlexGMRESSetPrecond(flex.solver, solve_f, setup_f, p.solver)
return nothing
end
#########
## FSAI #
#########

40
test/runtests.jl

@ -370,6 +370,46 @@ end @@ -370,6 +370,46 @@ end
@test x A \ b atol=tol
end
@testset "FlexGMRES" begin
# Solver constructor and options
@test_throws(
ArgumentError("unknown option UnknownOption for HYPRE.FlexGMRES"),
HYPRE.FlexGMRES(; UnknownOption = 1)
)
# Setup
A = sprand(100, 100, 0.05); A = A'A + 5I
b = rand(100)
x = zeros(100)
A_h = HYPREMatrix(A)
b_h = HYPREVector(b)
x_h = HYPREVector(x)
# Solve
tol = 1e-9
gmres = HYPRE.FlexGMRES(; Tol = tol)
HYPRE.solve!(gmres, x_h, A_h, b_h)
copy!(x, x_h)
# Test result with direct solver
@test x A \ b atol=tol
# Test without passing initial guess
x_h = HYPRE.solve(gmres, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
# Solve with preconditioner
precond = HYPRE.BoomerAMG()
gmres = HYPRE.FlexGMRES(; Tol = tol, Precond = precond)
x_h = HYPREVector(zeros(100))
HYPRE.solve!(gmres, x_h, A_h, b_h)
copy!(x, x_h)
# Test result with direct solver
@test x A \ b atol=tol
# Test without passing initial guess
x_h = HYPRE.solve(gmres, A_h, b_h)
copy!(x, x_h)
@test x A \ b atol=tol
end
@testset "GMRES" begin
# Solver constructor and options
@test_throws(

Loading…
Cancel
Save