From 1cd2e36e20ddb077c936d1022c5f435b646577bf Mon Sep 17 00:00:00 2001 From: JordiManyer Date: Tue, 3 Oct 2023 18:47:52 +1100 Subject: [PATCH] Added AbstractTrees interface for krylov solvers --- src/LinearSolvers/Krylov/CGSolvers.jl | 2 ++ src/LinearSolvers/Krylov/FGMRESSolvers.jl | 8 +++++--- src/LinearSolvers/Krylov/GMRESSolvers.jl | 2 ++ src/LinearSolvers/Krylov/MINRESSolvers.jl | 2 ++ src/LinearSolvers/LinearSolvers.jl | 1 + src/SolverInterfaces/GridapExtras.jl | 9 --------- src/SolverInterfaces/SolverInfos.jl | 24 +++++++++++++++++++---- src/SolverInterfaces/SolverInterfaces.jl | 5 +++-- src/SolverInterfaces/SolverTolerances.jl | 4 ++++ test/seq/SolverInterfacesTests.jl | 9 ++++----- 10 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/LinearSolvers/Krylov/CGSolvers.jl b/src/LinearSolvers/Krylov/CGSolvers.jl index a237c41a..73f42d17 100644 --- a/src/LinearSolvers/Krylov/CGSolvers.jl +++ b/src/LinearSolvers/Krylov/CGSolvers.jl @@ -11,6 +11,8 @@ function CGSolver(Pl;maxiter=1000,atol=1e-12,rtol=1.e-6,flexible=false,verbose=0 return CGSolver(Pl,log,flexible) end +AbstractTrees.children(s::CGSolver) = [s.Pl] + struct CGSymbolicSetup <: Gridap.Algebra.SymbolicSetup solver end diff --git a/src/LinearSolvers/Krylov/FGMRESSolvers.jl b/src/LinearSolvers/Krylov/FGMRESSolvers.jl index 2e775619..d14bcd62 100644 --- a/src/LinearSolvers/Krylov/FGMRESSolvers.jl +++ b/src/LinearSolvers/Krylov/FGMRESSolvers.jl @@ -1,9 +1,9 @@ # FGMRES Solver struct FGMRESSolver <: Gridap.Algebra.LinearSolver - m :: Int - Pr :: Gridap.Algebra.LinearSolver - Pl :: Union{Gridap.Algebra.LinearSolver,Nothing} + m :: Int + Pr :: Gridap.Algebra.LinearSolver + Pl :: Union{Gridap.Algebra.LinearSolver,Nothing} outer_log :: ConvergenceLog{Float64} inner_log :: ConvergenceLog{Float64} end @@ -16,6 +16,8 @@ function FGMRESSolver(m,Pr;Pl=nothing,maxiter=100,atol=1e-12,rtol=1.e-6,verbose= return FGMRESSolver(m,Pr,Pl,outer_log,inner_log) end +AbstractTrees.children(s::FGMRESSolver) = [s.Pr,s.Pl] + struct FGMRESSymbolicSetup <: Gridap.Algebra.SymbolicSetup solver end diff --git a/src/LinearSolvers/Krylov/GMRESSolvers.jl b/src/LinearSolvers/Krylov/GMRESSolvers.jl index 79919481..88967db0 100644 --- a/src/LinearSolvers/Krylov/GMRESSolvers.jl +++ b/src/LinearSolvers/Krylov/GMRESSolvers.jl @@ -15,6 +15,8 @@ function GMRESSolver(m;Pr=nothing,Pl=nothing,maxiter=100,atol=1e-12,rtol=1.e-6,v return GMRESSolver(m,Pr,Pl,outer_log,inner_log) end +AbstractTrees.children(s::GMRESSolver) = [s.Pr,s.Pl] + struct GMRESSymbolicSetup <: Gridap.Algebra.SymbolicSetup solver end diff --git a/src/LinearSolvers/Krylov/MINRESSolvers.jl b/src/LinearSolvers/Krylov/MINRESSolvers.jl index 9f5df74b..6eb68140 100644 --- a/src/LinearSolvers/Krylov/MINRESSolvers.jl +++ b/src/LinearSolvers/Krylov/MINRESSolvers.jl @@ -11,6 +11,8 @@ function MINRESSolver(;Pr=nothing,Pl=nothing,maxiter=1000,atol=1e-12,rtol=1.e-6, return MINRESSolver(Pr,Pl,log) end +AbstractTrees.children(s::MINRESSolver) = [s.Pr,s.Pl] + struct MINRESSymbolicSetup <: Gridap.Algebra.SymbolicSetup solver end diff --git a/src/LinearSolvers/LinearSolvers.jl b/src/LinearSolvers/LinearSolvers.jl index dac207bc..e8381d30 100644 --- a/src/LinearSolvers/LinearSolvers.jl +++ b/src/LinearSolvers/LinearSolvers.jl @@ -1,6 +1,7 @@ module LinearSolvers using Printf +using AbstractTrees using LinearAlgebra using SparseArrays using SparseMatricesCSR diff --git a/src/SolverInterfaces/GridapExtras.jl b/src/SolverInterfaces/GridapExtras.jl index 252e91b7..508ae5f1 100644 --- a/src/SolverInterfaces/GridapExtras.jl +++ b/src/SolverInterfaces/GridapExtras.jl @@ -1,12 +1,3 @@ -# Solver Hierarchies - -AbstractTrees.children(s::Gridap.Algebra.LinearSolver) = [] -AbstractTrees.nodevalue(s::Gridap.Algebra.LinearSolver) = get_solver_info(s) - - -#function Base.show(io::IO,a::Gridap.Algebra.LinearSolver) -# AbstractTrees.print_tree(io,a) -#end # LinearSolvers that depend on the non-linear solution diff --git a/src/SolverInterfaces/SolverInfos.jl b/src/SolverInterfaces/SolverInfos.jl index 4a5fb416..8d679aeb 100644 --- a/src/SolverInterfaces/SolverInfos.jl +++ b/src/SolverInterfaces/SolverInfos.jl @@ -1,13 +1,20 @@ -struct SolverInfo{T<:Real} +struct SolverInfo name :: String data :: Dict{Symbol, Any} end SolverInfo(name::String) = SolverInfo(name,Dict{Symbol, Any}()) -function get_solver_info(::Gridap.Algebra.LinearSolver) - return SolverInfo("Empty solver info") +function get_solver_info(solver::Gridap.Algebra.LinearSolver) + return SolverInfo(string(typeof(solver))) +end + +function merge_info!(a::SolverInfo,b::SolverInfo;prefix="") + for (key,val) in b.data + a.data[Symbol(prefix,key)] = val + end + return a end function add_info!(a::SolverInfo,key::Union{Symbol,String},val;prefix="") @@ -18,7 +25,7 @@ end function add_convergence_info!(a::SolverInfo,log::ConvergenceLog;prefix="") prefix = string(prefix,log.name) add_info!(a,:num_iters,log.num_iters,prefix=prefix) - add_info!(a,:residuals,log.residuals,prefix=prefix) + add_info!(a,:residuals,copy(log.residuals),prefix=prefix) end function add_tolerance_info!(a::SolverInfo,tols::SolverTolerances;prefix="") @@ -31,3 +38,12 @@ function add_tolerance_info!(a::SolverInfo,log::ConvergenceLog;prefix="") prefix = string(prefix,log.name) add_tolerance_info!(a,log.tols,prefix=prefix) end + +Base.summary(info::SolverInfo) = info.name + +AbstractTrees.children(s::Gridap.Algebra.LinearSolver) = [] +AbstractTrees.nodevalue(s::Gridap.Algebra.LinearSolver) = summary(get_solver_info(s)) + +function Base.show(io::IO,a::Gridap.Algebra.LinearSolver) + AbstractTrees.print_tree(io,a) +end diff --git a/src/SolverInterfaces/SolverInterfaces.jl b/src/SolverInterfaces/SolverInterfaces.jl index 914c210b..812bf868 100644 --- a/src/SolverInterfaces/SolverInterfaces.jl +++ b/src/SolverInterfaces/SolverInterfaces.jl @@ -12,9 +12,10 @@ include("SolverTolerances.jl") include("ConvergenceLogs.jl") include("SolverInfos.jl") +export SolverVerboseLevel, SolverConvergenceFlag +export SolverTolerances, get_solver_tolerances, set_solver_tolerances! export ConvergenceLog, init!, update!, finalize!, reset! -export SolverInfo, SolverTolerances -export SolverVerboseLevel, SolverConvergenceFlag +export SolverInfo end \ No newline at end of file diff --git a/src/SolverInterfaces/SolverTolerances.jl b/src/SolverInterfaces/SolverTolerances.jl index e92b2a68..4e6a4a99 100644 --- a/src/SolverInterfaces/SolverTolerances.jl +++ b/src/SolverInterfaces/SolverTolerances.jl @@ -18,6 +18,10 @@ end get_solver_tolerances(s::Gridap.Algebra.LinearSolver) = @abstractmethod +function set_solver_tolerances!(s::Gridap.Algebra.LinearSolver;kwargs...) + set_solver_tolerances!(get_solver_tolerances(s);kwargs...) +end + function set_solver_tolerances!(a::SolverTolerances{T}; maxiter = 1000, atol = eps(T), diff --git a/test/seq/SolverInterfacesTests.jl b/test/seq/SolverInterfacesTests.jl index b0f04481..679c34fe 100644 --- a/test/seq/SolverInterfacesTests.jl +++ b/test/seq/SolverInterfacesTests.jl @@ -27,12 +27,11 @@ op = AffineFEOperator(a,l,Uh,Vh) A, b = get_matrix(op), get_vector(op); P = JacobiLinearSolver() -solver = LinearSolvers.CGSolver(P;rtol=1.e-8,verbose=true) -ns = numerical_setup(symbolic_setup(solver,A),A) -x = LinearSolvers.allocate_col_vector(A) -solve!(x,ns,b) - solver = LinearSolvers.GMRESSolver(10;Pl=P,rtol=1.e-8,verbose=2) ns = numerical_setup(symbolic_setup(solver,A),A) x = LinearSolvers.allocate_col_vector(A) solve!(x,ns,b) + + + +using AbstractTrees