Skip to content

Commit

Permalink
Merge pull request #8 from j-fu/v1
Browse files Browse the repository at this point in the history
support `precs` API of LinearSolve
  • Loading branch information
j-fu authored Aug 23, 2024
2 parents 4a12e82 + a636b7b commit 8e058fc
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 43 deletions.
9 changes: 3 additions & 6 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ jobs:
fail-fast: false
matrix:
version:
- '1.9' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
# - '1.9' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
- '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
- 'nightly'
os:
- ubuntu-latest
- windows-latest
- macOS-13 # intel
- macOS-14 # arm
- macOS-latest
arch:
- x64
- aarch64
Expand All @@ -31,9 +30,7 @@ jobs:
arch: aarch64
- os: windows-latest
arch: aarch64
- os: macOS-13
arch: aarch64
- os: macOS-14
- os: macOS-latest
arch: x64
steps:
- uses: actions/checkout@v4
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Changelog

## v1.0, 2024-08-XX
- Support `precs` API of LinearSolve
- Not really breaking, but transition to genuine semantig versioning


## v0.4, 2024-07-15
- Fix SparseMatrixCSR from CSC for nonsymmetric matrices
- Add Aqua, ExplicitImports tests, ci on apple silicon
- Require julia 1.9

## v0.3, 2024-01-15
- LinearSolve extension, solver support via a LinearSolveFunction
- Change default for RLXPrecon to ILU0

## v0.2, 2024-01-09
- Finalization of API, exception handling

## v0.1, 2024-01-08
- Initial registered version
14 changes: 7 additions & 7 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "AMGCLWrap"
uuid = "4f76b812-4ba5-496d-b042-d70715554288"
authors = ["Jürgen Fuhrmann <juergen-fuhrmann@web.de> and contributors"]
version = "0.4.0"
version = "1.0.0"

[deps]
AMGCL_C_jll = "e3ba5bb7-5aef-5326-9a13-9617383dcacb"
Expand All @@ -12,19 +12,19 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
SparseMatricesCSR = "a0a7dd2c-ebf4-11e9-1f05-cf50bc540ca1"

[weakdeps]
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"

[compat]
AMGCL_C_jll = "0.3.0"
CompositeStructs = "0.1.5"
DocStringExtensions = "0.9"
JSON3 = "1.14.0"
LinearAlgebra = "1.6"
LinearSolve = "2.22"
SparseArrays = "1.6"
LinearAlgebra = "1.9"
LinearSolve = "2.33"
SparseArrays = "1.9"
SparseMatricesCSR = "0.6.7"
julia = "1.9"

[extensions]
AMGCLWrapLinearSolveExt = "LinearSolve"

[weakdeps]
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[deps]
AMGCLWrap = "4f76b812-4ba5-496d-b042-d70715554288"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
3 changes: 2 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ DocMeta.setdocmeta!(AMGCLWrap, :DocTestSetup, :(using AMGCLWrap); recursive = tr
makedocs(;
modules = [AMGCLWrap],
authors = "Jürgen Fuhrmann <juergen-fuhrmann@web.de> and contributors",
repo = "https://github.com/j-fu/AMGCLWrap.jl/blob/{commit}{path}#{line}",
repo = "https://github.com/j-fu/AMGCLWrap.jl/",
sitename = "AMGCLWrap.jl",
clean = false,
format = Documenter.HTML(;
Expand All @@ -19,6 +19,7 @@ makedocs(;
"preconditioners.md"
"parameters.md"
"misc.md"
"Changelog" => "changelog.md"
],)

deploydocs(; repo = "github.com/j-fu/AMGCLWrap.jl", devbranch = "main")
4 changes: 4 additions & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
````@eval
using Markdown
Markdown.parse(read("../../CHANGELOG.md",String))
````
2 changes: 2 additions & 0 deletions docs/src/preconditioners.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

```@docs
AMGPrecon
AMGPreconditioner
RLXPrecon
RLXPreconditioner
```

3 changes: 2 additions & 1 deletion src/AMGCLWrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module AMGCLWrap

using AMGCL_C_jll: AMGCL_C_jll, libamgcl_c
using DocStringExtensions: DocStringExtensions, TYPEDEF, TYPEDFIELDS
using LinearAlgebra: LinearAlgebra, issymmetric, ldiv!, transpose
using LinearAlgebra: LinearAlgebra, issymmetric, ldiv!, transpose, I
using SparseArrays: SparseArrays, AbstractSparseMatrix, SparseMatrixCSC, sparse
using SparseMatricesCSR: SparseMatricesCSR, SparseMatrixCSR, getoffset
using CompositeStructs: @composite
Expand All @@ -18,6 +18,7 @@ include("parameters.jl")
include("struct_api.jl")

export AMGSolver, RLXSolver, AMGPrecon, RLXPrecon, blocksize_instantiated, error_state
export AMGPreconditioner, RLXPreconditioner
export AMGSolverAlgorithm, RLXSolverAlgorithm


Expand Down
70 changes: 50 additions & 20 deletions src/struct_api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const matrixparam="""
"""

const stdparams = """
- `sparsematrix`: `SparseArrays.AbstractSparseMatrixCSC` or `SparseMatricesCSR.SparseMatrixCSR`.
- `blocksize`: If blocksize >1, group unknowns into blocks of given size and cast the matrix internally to a sparse matrix of `blocksize x blocksize` static matrices. Block sizes 1...8 are instantiated.
- `verbose`: if true, print generated JSON string passed to amgcl.
- `param:` Ignored if `nothing` (default). Otherwise, any object (e.g. Tuple, Dict or JSON string) which can be turned into a JSON string by `JSON3.write`.
Expand Down Expand Up @@ -55,7 +54,6 @@ function AMGSolver(sparsematrix::AbstractSparseMatrix;
AMGSolver(sparsematrix, param; blocksize)
end

@static if VERSION >=v"1.9.0"

Base.@kwdef mutable struct AMGSolverAlgorithmData
param = nothing
Expand All @@ -75,8 +73,6 @@ function (data::AMGSolverAlgorithmData)(A, b, u, p, newA, Pl, Pr, solverdata; ve
ldiv!(u,data.instance,b)
end


end # @static if

"""
AMGSolverAlgorithm(;blocksize::Int=1,
Expand All @@ -90,9 +86,6 @@ Algebraic multigrid preconditioned Krylov subspace solver algorithm for LinearSo
Parameters:
$(stdparams)
$(amgsolverparams)
!!! compat
Only available for Julia version >=1.9
"""
function AMGSolverAlgorithm end

Expand Down Expand Up @@ -128,8 +121,6 @@ function RLXSolver(sparsematrix::AbstractSparseMatrix;
end


@static if VERSION >=v"1.9.0"

Base.@kwdef mutable struct RLXSolverAlgorithmData
param = nothing
verbose::Bool = false
Expand All @@ -147,9 +138,6 @@ function (data::RLXSolverAlgorithmData)(A, b, u, p, newA, Pl, Pr, solverdata; ve
ldiv!(u,data.instance,b)
end

end # @static if



"""
RLXSolverAlgorithm(;blocksize::Int=1,
Expand All @@ -162,9 +150,6 @@ Algebraic multigrid preconditioned Krylov subspace solver algorithm for LinearSo
Parameters:
$(stdparams)
$(rlxsolverparams)
!!! compat
Only available for Julia version >=1.9
"""
function RLXSolverAlgorithm end

Expand Down Expand Up @@ -202,6 +187,32 @@ function AMGPrecon(sparsematrix::AbstractSparseMatrix;
AMGPrecon(sparsematrix, param; blocksize)
end

"""
$(TYPEDEF)
Preconditioner strategy (e.g. for the new `precs` kwarg in LinearSolve) for interfacing
[`AMGPrecon`](@ref).
Fields (for documentation, see [`AMGPrecon`](@ref)):
$(TYPEDFIELDS)
"""
Base.@kwdef struct AMGPreconditioner
param = nothing
verbose::Bool = false
blocksize::Int = 1
coarsening::Union{AbstractCoarsening, NamedTuple} = SmoothedAggregationCoarsening()
relax::Union{AbstractRelaxation, NamedTuple} = SPAI0Relaxation()
end

function (amg::AMGPreconditioner)(A::AbstractSparseMatrix)
(;param, verbose, blocksize, coarsening, relax)=amg
AMGPrecon(A; param, verbose, blocksize, coarsening, relax)
end

(amg::AMGPreconditioner)(A,p)=(amg(A),I)

#################################################################################################
# Relaxation Preconditioner
"""
RLXPrecon(sparsematrix::AbstractSparseMatrix;
blocksize::Int=1,
Expand All @@ -213,12 +224,8 @@ $(docs["AMGCLWrap.RLXPrecon"])
Parameters:
$(matrixparam)
$(stdparams)
- `precond`: A [preconditioned method](#Relaxation/Preconditioner-parameters)
- `precond`: A [preconditioning method](#Relaxation/Preconditioner-parameters)
"""

#################################################################################################
# Relaxation Preconditioner

function RLXPrecon(sparsematrix::AbstractSparseMatrix;
param = nothing,
verbose::Bool = false,
Expand All @@ -233,3 +240,26 @@ function RLXPrecon(sparsematrix::AbstractSparseMatrix;
RLXPrecon(sparsematrix, param; blocksize)
end

"""
$(TYPEDEF)
Preconditioner strategy (e.g. for the new `precs` kwarg in LinearSolve) for interfacing
[`RLXPrecon`](@ref).
Fields (for documentation, see [`RLXPrecon`](@ref)):
$(TYPEDFIELDS)
"""
Base.@kwdef struct RLXPreconditioner
param = nothing
verbose::Bool = false
blocksize::Int = 1
precond::Union{AbstractRelaxation, NamedTuple} = ILU0Relaxation()
end

function (rlx::RLXPreconditioner)(A::AbstractSparseMatrix)
(;param, verbose, blocksize, precond)=rlx
RLXPrecon(A; param, verbose, blocksize, precond)
end

(rlx::RLXPreconditioner)(A,p)=(rlx(A),I)
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Krylov = "0.9.5"
LinearAlgebra = "1.6"
SparseArrays = "1.6"
LinearSolve = "2.32"
34 changes: 26 additions & 8 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,7 @@ import ExplicitImports, Aqua
end

@testset "Aqua" begin
Aqua.test_ambiguities(AMGCLWrap)
Aqua.test_unbound_args(AMGCLWrap)
Aqua.test_undefined_exports(AMGCLWrap)
Aqua.test_project_extras(AMGCLWrap)
Aqua.test_stale_deps(AMGCLWrap)
Aqua.test_deps_compat(AMGCLWrap)
Aqua.test_piracies(AMGCLWrap)
Aqua.test_persistent_tasks(AMGCLWrap)
Aqua.test_all(AMGCLWrap)
end

if isdefined(Docs,:undocumented_names) # >=1.11
Expand All @@ -31,6 +24,7 @@ end


A B = kron(I(size(B, 1)), A) + kron(B, I(size(A, 1)))

function lattice(n; Tv = Float64)
d = fill(2 * one(Tv), n)
d[1] = one(Tv)
Expand Down Expand Up @@ -227,6 +221,17 @@ function test_linsolve_amgprecon(Ti, dim, n, bsize = 1)
norm(u0 - u) < 1000 * sqrt(eps(Float64))
end


function test_linsolve_amgprecs(Ti, dim, n, bsize = 1)
A = dlattice(dim, n; Ti)
u0 = rand(size(A, 1))
prb=LinearProblem(A,A*u0)
u = solve(prb,KrylovJL_CG(precs=AMGPreconditioner(blocksize = bsize)))
@show norm(u0 - u)
norm(u0 - u) < 1000 * sqrt(eps(Float64))
end


function test_linsolve_rlxprecon(Ti, dim, n, bsize = 1)
A = dlattice(dim, n; Ti)
u0 = rand(size(A, 1))
Expand All @@ -238,14 +243,27 @@ function test_linsolve_rlxprecon(Ti, dim, n, bsize = 1)
norm(u0 - u) < 1.0e4 * sqrt(eps(Float64))
end

function test_linsolve_rlxprecs(Ti, dim, n, bsize = 1)
A = dlattice(dim, n; Ti)
u0 = rand(size(A, 1))
prb=LinearProblem(A,A*u0)

rlx =
u = solve(prb,KrylovJL_CG(precs= RLXPreconditioner(blocksize = bsize, precond=(type="ilu0",))))
@show norm(u0 - u)
norm(u0 - u) < 1.0e4 * sqrt(eps(Float64))
end



for Ti in [Int32, Int64]
@testset "LinearSolve, $Ti" begin
@test test_linsolve_amg(Ti, 2, NTest)
@test test_linsolve_rlx(Ti, 2, NTest)
@test test_linsolve_amgprecon(Ti, 2, NTest)
@test test_linsolve_amgprecs(Ti, 2, NTest)
@test test_linsolve_rlxprecon(Ti, 2, NTest)
@test test_linsolve_rlxprecs(Ti, 2, NTest)
end

end

0 comments on commit 8e058fc

Please sign in to comment.