diff --git a/Project.toml b/Project.toml index 09c9c05..d064638 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "1.7.0" CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" HYPRE_jll = "0a602bbd-b08b-5d75-8d32-0de6eef44785" Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" [weakdeps] @@ -20,17 +21,19 @@ HYPRESparseMatricesCSR = ["SparseArrays", "SparseMatricesCSR"] [compat] CEnum = "0.4, 0.5" +LinearAlgebra = "1" +LinearSolve = "3" MPI = "0.19, 0.20" PartitionedArrays = "0.5" SparseMatricesCSR = "0.6" julia = "1.10" [extras] -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" PartitionedArrays = "5a9dfac6-5c52-46f7-8278-5e2210713be9" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" SparseMatricesCSR = "a0a7dd2c-ebf4-11e9-1f05-cf50bc540ca1" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["LinearAlgebra", "PartitionedArrays", "SparseArrays", "SparseMatricesCSR", "Test"] +test = ["LinearSolve", "PartitionedArrays", "SparseArrays", "SparseMatricesCSR", "Test"] diff --git a/docs/Manifest.toml b/docs/Manifest.toml index 089ea11..fb1aad3 100644 --- a/docs/Manifest.toml +++ b/docs/Manifest.toml @@ -1,6 +1,6 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.11.0" +julia_version = "1.11.3" manifest_format = "2.0" project_hash = "59b08f4b60c862a102ba6a5a40dd11b11cb0ae51" @@ -38,9 +38,9 @@ version = "1.1.0" [[deps.CodecZlib]] deps = ["TranscodingStreams", "Zlib_jll"] -git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759" +git-tree-sha1 = "962834c22b66e32aa10f7611c08c8ca4e20749a9" uuid = "944b1d66-785c-5afd-91f1-9de20f533193" -version = "0.7.6" +version = "0.7.8" [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] @@ -65,9 +65,9 @@ version = "0.9.3" [[deps.Documenter]] deps = ["ANSIColoredPrinters", "AbstractTrees", "Base64", "CodecZlib", "Dates", "DocStringExtensions", "Downloads", "Git", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "MarkdownAST", "Pkg", "PrecompileTools", "REPL", "RegistryInstances", "SHA", "TOML", "Test", "Unicode"] -git-tree-sha1 = "5a1ee886566f2fa9318df1273d8b778b9d42712d" +git-tree-sha1 = "30f520c66490393bf4e4ff2bb144db65f569d974" uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "1.7.0" +version = "1.9.0" [[deps.Downloads]] deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] @@ -76,9 +76,9 @@ version = "1.6.0" [[deps.Expat_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "1c6317308b9dc757616f0b5cb379db10494443a7" +git-tree-sha1 = "d55dffd9ae73ff72f1c0482454dcf2ec6c6c4a63" uuid = "2e619515-83b5-522b-bb60-26c02a35a201" -version = "2.6.2+0" +version = "2.6.5+0" [[deps.FileWatching]] uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" @@ -92,12 +92,12 @@ version = "1.3.1" [[deps.Git_jll]] deps = ["Artifacts", "Expat_jll", "JLLWrappers", "LibCURL_jll", "Libdl", "Libiconv_jll", "OpenSSL_jll", "PCRE2_jll", "Zlib_jll"] -git-tree-sha1 = "ea372033d09e4552a04fd38361cd019f9003f4f4" +git-tree-sha1 = "399f4a308c804b446ae4c91eeafadb2fe2c54ff9" uuid = "f8c6e375-362e-5223-8a59-34ff63f689eb" -version = "2.46.2+0" +version = "2.47.1+0" [[deps.HYPRE]] -deps = ["CEnum", "HYPRE_jll", "Libdl", "MPI"] +deps = ["CEnum", "HYPRE_jll", "Libdl", "LinearAlgebra", "MPI"] path = ".." uuid = "b5ffcf37-a2bd-41ab-a3da-4bd9bc8ad771" version = "1.7.0" @@ -120,9 +120,9 @@ version = "2.23.1+1" [[deps.Hwloc_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "dd3b49277ec2bb2c6b94eb1604d4d0616016f7a6" +git-tree-sha1 = "f93a9ce66cd89c9ba7a4695a47fd93b4c6bc59fa" uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8" -version = "2.11.2+0" +version = "2.12.0+0" [[deps.IOCapture]] deps = ["Logging", "Random"] @@ -137,9 +137,9 @@ version = "1.11.0" [[deps.JLLWrappers]] deps = ["Artifacts", "Preferences"] -git-tree-sha1 = "f389674c99bfcde17dc57454011aa44d5a260a40" +git-tree-sha1 = "a007feb38b422fbdab534406aeca1b86823cb4d6" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.6.0" +version = "1.7.0" [[deps.JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] @@ -149,14 +149,14 @@ version = "0.21.4" [[deps.LAPACK_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "libblastrampoline_jll"] -git-tree-sha1 = "1b25c30fa49db281be615793e0f85282a8f22822" +git-tree-sha1 = "47a6ccfc4b78494669cd7c502ba112ee2b24eb45" uuid = "51474c39-65e3-53ba-86ba-03b1b862ec14" -version = "3.12.0+2" +version = "3.12.0+3" [[deps.LazilyInitializedFields]] -git-tree-sha1 = "8f7f3cabab0fd1800699663533b6d5cb3fc0e612" +git-tree-sha1 = "0f2da712350b020bc3957f269c9caad516383ee0" uuid = "0e77f7df-68c5-4e49-93ce-4cd80f5598bf" -version = "1.2.2" +version = "1.3.0" [[deps.LazyArtifacts]] deps = ["Artifacts", "Pkg"] @@ -194,9 +194,14 @@ version = "1.11.0" [[deps.Libiconv_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "f9557a255370125b405568f9767d6d195822a175" +git-tree-sha1 = "be484f5c92fad0bd8acfef35fe017900b0b73809" uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" -version = "1.17.0+0" +version = "1.18.0+0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +version = "1.11.0" [[deps.Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" @@ -218,9 +223,9 @@ version = "0.20.22" [[deps.MPICH_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] -git-tree-sha1 = "7715e65c47ba3941c502bffb7f266a41a7f54423" +git-tree-sha1 = "3aa3210044138a1749dbd350a9ba8680869eb503" uuid = "7cb0a576-ebde-5e09-9194-50597f1243b4" -version = "4.2.3+0" +version = "4.3.0+1" [[deps.MPIPreferences]] deps = ["Libdl", "Preferences"] @@ -230,9 +235,9 @@ version = "0.1.11" [[deps.MPItrampoline_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] -git-tree-sha1 = "70e830dab5d0775183c99fc75e4c24c614ed7142" +git-tree-sha1 = "ff91ca13c7c472cef700f301c8d752bc2aaff1a8" uuid = "f1f71cc9-e9ae-5b93-9b94-4fe0e1ad3748" -version = "5.5.1+0" +version = "5.5.3+0" [[deps.Markdown]] deps = ["Base64"] @@ -252,9 +257,9 @@ version = "2.28.6+0" [[deps.MicrosoftMPI_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "f12a29c4400ba812841c6ace3f4efbb6dbb3ba01" +git-tree-sha1 = "bc95bf4149bf535c09602e3acdf950d9b4376227" uuid = "9237b28f-5490-5468-be7b-bb81f5f5e6cf" -version = "10.1.4+2" +version = "10.1.4+3" [[deps.Mmap]] uuid = "a63ad114-7e13-5084-954f-fe012c677804" @@ -275,15 +280,15 @@ version = "0.3.27+1" [[deps.OpenMPI_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML", "Zlib_jll"] -git-tree-sha1 = "bfce6d523861a6c562721b262c0d1aaeead2647f" +git-tree-sha1 = "da913f03f17b449951e0461da960229d4a3d1a8c" uuid = "fe0851c0-eecd-5654-98d4-656369965a5c" -version = "5.0.5+0" +version = "5.0.7+1" [[deps.OpenSSL_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "7493f61f55a6cce7325f197443aa80d32554ba10" +git-tree-sha1 = "a9697f1d06cc3eb3fb3ad49cc67f2cfabaac31ea" uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" -version = "3.0.15+1" +version = "3.0.16+0" [[deps.PCRE2_jll]] deps = ["Artifacts", "Libdl"] @@ -346,9 +351,9 @@ version = "0.1.0" [[deps.Requires]] deps = ["UUIDs"] -git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +git-tree-sha1 = "62389eeff14780bfe55195b7204c0d8738436d64" uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.3.0" +version = "1.3.1" [[deps.SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" diff --git a/docs/src/api.md b/docs/src/api.md index ca6b8fb..a43b0c3 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -37,3 +37,7 @@ HYPRE.ParaSails HYPRE.GetNumIterations HYPRE.GetFinalRelativeResidualNorm ``` + +```@docs +HYPRE.BoomerAMGPrecBuilder +``` diff --git a/docs/src/index.md b/docs/src/index.md index 83134eb..8226e0b 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -15,6 +15,28 @@ interface. The high level interface does not (currently) provide access to all of HYPREs functionality, but it can easily be combined with the low level interface when necessary. +BoomerAMG can also be used as preconditioner for Julia iterative solvers via LinearSolve.jl as follows: + +```julia +using HYPRE, LinearSolve + +# Helper to set BoomerAMG options after construction +function set_debug_printlevel(amg, A, p) + HYPRE.HYPRE_BoomerAMGSetPrintLevel(amg, 3) +end + +# kwargs will be passed into the BoomerAMG constructor +bamg = HYPRE.BoomerAMGPrecBuilder( + set_debug_printlevel; + Tol = 1e-9, +) + +# Setup and solve linear problem via LinearSolve as usual +prob = LinearProblem(A, b) +solver = KrylovJL_CG(precs = bamg) +x = solve(prob, solver, atol=1.0e-14) +``` + ---- ##### Low level interface diff --git a/src/HYPRE.jl b/src/HYPRE.jl index 3b5f04e..7a6f4f9 100644 --- a/src/HYPRE.jl +++ b/src/HYPRE.jl @@ -3,10 +3,10 @@ module HYPRE using MPI: MPI +import LinearAlgebra export HYPREMatrix, HYPREVector - # Clang.jl auto-generated bindings and some manual methods include("LibHYPRE.jl") using .LibHYPRE @@ -420,4 +420,7 @@ end include("solvers.jl") include("solver_options.jl") +# LinearSolve preconditioner interface +include("precs.jl") + end # module HYPRE diff --git a/src/precs.jl b/src/precs.jl new file mode 100644 index 0000000..1e8920d --- /dev/null +++ b/src/precs.jl @@ -0,0 +1,46 @@ +struct BoomerAMGPrecWrapper{MatType} + P::BoomerAMG + A::MatType +end + +function LinearAlgebra.ldiv!(y::AbstractVector, prec::BoomerAMGPrecWrapper, x::AbstractVector) + fill!(y, eltype(y)(0.0)) + return solve!(prec.P, y, prec.A, x) +end + +""" + HYPRE.BoomerAMGPrecBuilder(settings_fun; kwargs...) + +LinearSolve.jl compatible constructor for BoomerAMG preconditioners. +Here `settings_fun(bamg::HYPRE.BoomerAMG, A::AbstractMatrix, p)` will be called on construction to +allow users setting options directly in BoomerAMG via the internal interface. The `kwargs` will be +passed into the BoomerAMG constructor. + +## Example + +```julia +function set_debug_printlevel(bamg, A, p) + HYPRE.HYPRE_BoomerAMGSetPrintLevel(bamg, 3) +end +bamg = HYPRE.BoomerAMGPrecBuilder( + set_debug_printlevel; + Tol = 1e-9, +) +``` +""" +struct BoomerAMGPrecBuilder{SFun, Tk} + settings_fun!::SFun + kwargs::Tk +end + +# Syntactic sugar wth some defaults +function BoomerAMGPrecBuilder(settings_fun! = (amg, A, p) -> nothing; kwargs...) + return BoomerAMGPrecBuilder(settings_fun!, kwargs) +end + +function (b::BoomerAMGPrecBuilder)(A, p) + amg = BoomerAMG(; b.kwargs...) + Internals.set_precond_defaults(amg) + b.settings_fun!(amg, A, p) + return (BoomerAMGPrecWrapper(amg, A), LinearAlgebra.I) +end diff --git a/test/runtests.jl b/test/runtests.jl index e28e8f5..7199260 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,6 +9,7 @@ using PartitionedArrays using SparseArrays using SparseMatricesCSR using Test +using LinearSolve include("test_utils.jl") @@ -20,6 +21,28 @@ HYPRE.Init() @test LibHYPRE.VERSION.major == 2 end +@testset "use as LinearSolve.jl preconditioner" begin + # Setup + A = sprand(100, 100, 0.05); A = A'A + 5I + b = rand(100) + x = zeros(100) + # Solve + tol = 1.0e-9 + # function set_debug_printlevel(amg, A, p) + # HYPRE.HYPRE_BoomerAMGSetPrintLevel(amg, 3) + # end + bamg = HYPRE.BoomerAMGPrecBuilder( + (amg, A, p) -> nothing; + MaxIter = 1, + Tol = tol, + ) + prob = LinearProblem(A, b) + solver = KrylovJL_CG(precs = bamg) + x = solve(prob, solver, atol = 1.0e-14) + @test x ≈ A \ b atol = √tol +end + + @testset "HYPREMatrix" begin H = HYPREMatrix(MPI.COMM_WORLD, 1, 5) @test H.ijmatrix != HYPRE_IJMatrix(C_NULL)