Browse Source

Only call solver finalizers if not NULL

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.
pull/5/head
Fredrik Ekre 3 years ago
parent
commit
84dedc4195
  1. 1
      src/Internals.jl
  2. 29
      src/solvers.jl
  3. 3
      test/runtests.jl

1
src/Internals.jl

@ -8,6 +8,7 @@ function check_n_rows end
function copy_check end function copy_check end
function get_comm end function get_comm end
function get_proc_rows end function get_proc_rows end
function safe_finalizer end
function set_options end function set_options end
function set_precond end function set_precond end
function set_precond_defaults end function set_precond_defaults end

29
src/solvers.jl

@ -7,6 +7,16 @@ Abstract super type of all the wrapped HYPRE solvers.
""" """
abstract type HYPRESolver end abstract type HYPRESolver end
function Internals.safe_finalizer(Destroy)
# Only calls the Destroy if pointer not C_NULL
return function(solver)
if solver.solver != C_NULL
Destroy(solver.solver)
solver.solver = C_NULL
end
end
end
# Fallback for the solvers that doesn't have required defaults # Fallback for the solvers that doesn't have required defaults
Internals.set_precond_defaults(::HYPRESolver) = nothing Internals.set_precond_defaults(::HYPRESolver) = nothing
@ -91,7 +101,7 @@ mutable struct BiCGSTAB <: HYPRESolver
@check HYPRE_ParCSRBiCGSTABCreate(comm, solver_ref) @check HYPRE_ParCSRBiCGSTABCreate(comm, solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_ParCSRBiCGSTABDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_ParCSRBiCGSTABDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver
@ -129,7 +139,7 @@ mutable struct BoomerAMG <: HYPRESolver
@check HYPRE_BoomerAMGCreate(solver_ref) @check HYPRE_BoomerAMGCreate(solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_BoomerAMGDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_BoomerAMGDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver
@ -166,7 +176,7 @@ mutable struct FlexGMRES <: HYPRESolver
@check HYPRE_ParCSRFlexGMRESCreate(comm, solver_ref) @check HYPRE_ParCSRFlexGMRESCreate(comm, solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_ParCSRFlexGMRESDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_ParCSRFlexGMRESDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver
@ -241,7 +251,7 @@ mutable struct GMRES <: HYPRESolver
@check HYPRE_ParCSRGMRESCreate(comm, solver_ref) @check HYPRE_ParCSRGMRESCreate(comm, solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_ParCSRGMRESDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_ParCSRGMRESDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver
@ -277,7 +287,7 @@ mutable struct Hybrid <: HYPRESolver
@check HYPRE_ParCSRHybridCreate(solver_ref) @check HYPRE_ParCSRHybridCreate(solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_ParCSRHybridDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_ParCSRHybridDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver
@ -296,6 +306,9 @@ Internals.solve_func(::Hybrid) = HYPRE_ParCSRHybridSolve
function Internals.set_precond(hybrid::Hybrid, p::HYPRESolver) function Internals.set_precond(hybrid::Hybrid, p::HYPRESolver)
solve_f = Internals.solve_func(p) solve_f = Internals.solve_func(p)
setup_f = Internals.setup_func(p) setup_f = Internals.setup_func(p)
# Deactivate the finalizer of p since the HYBRIDDestroy function does this,
# see https://github.com/hypre-space/hypre/issues/699
finalizer(x -> (x.solver = C_NULL), p)
@check HYPRE_ParCSRHybridSetPrecond(hybrid.solver, solve_f, setup_f, p.solver) @check HYPRE_ParCSRHybridSetPrecond(hybrid.solver, solve_f, setup_f, p.solver)
return nothing return nothing
end end
@ -313,7 +326,7 @@ mutable struct ILU <: HYPRESolver
@check HYPRE_ILUCreate(solver_ref) @check HYPRE_ILUCreate(solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_ILUDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_ILUDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver
@ -350,7 +363,7 @@ mutable struct ParaSails <: HYPRESolver
@check HYPRE_ParCSRParaSailsCreate(comm, solver_ref) @check HYPRE_ParCSRParaSailsCreate(comm, solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_ParCSRParaSailsDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_ParCSRParaSailsDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver
@ -377,7 +390,7 @@ mutable struct PCG <: HYPRESolver
@check HYPRE_ParCSRPCGCreate(comm, solver_ref) @check HYPRE_ParCSRPCGCreate(comm, solver_ref)
solver.solver = solver_ref[] solver.solver = solver_ref[]
# Attach a finalizer # Attach a finalizer
finalizer(x -> HYPRE_ParCSRPCGDestroy(x.solver), solver) finalizer(Internals.safe_finalizer(HYPRE_ParCSRPCGDestroy), solver)
# Set the options # Set the options
Internals.set_options(solver, kwargs) Internals.set_options(solver, kwargs)
return solver return solver

3
test/runtests.jl

@ -475,9 +475,8 @@ end
@test x A \ b atol=tol @test x A \ b atol=tol
# Solve with given preconditioner # Solve with given preconditioner
# XXX: https://github.com/hypre-space/hypre/issues/699
precond = HYPRE.BoomerAMG() precond = HYPRE.BoomerAMG()
hybrid = HYPRE.Hybrid(; Tol = tol, SolverType = 3, #= Precond = precond =#) hybrid = HYPRE.Hybrid(; Tol = tol, SolverType = 3, Precond = precond)
x_h = HYPREVector(zeros(100)) x_h = HYPREVector(zeros(100))
HYPRE.solve!(hybrid, x_h, A_h, b_h) HYPRE.solve!(hybrid, x_h, A_h, b_h)
copy!(x, x_h) copy!(x, x_h)

Loading…
Cancel
Save