From 0b16de7942d7ec0d67feb322348be53fc8219561 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Tue, 16 Jun 2026 06:02:19 -0400 Subject: [PATCH] docs: use AlgebraicMultigrid's automatic (SPQR) coarse solver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that AMG v2.0 is installable alongside the OrdinaryDiffEq v7 stack (LinearSolve >= 3.85.2 allows AlgebraicMultigrid v2), drop the `coarse_solver = LinearSolveWrapper(UMFPACKFactorization())` override from the AMG preconditioner examples and use `ruge_stuben`'s default coarse solver. AMG 2.0's default coarse solver is `QRSolver` (SuiteSparse SPQR for sparse matrices), which handles the non-SPD `W = I - γJ` coarse-grid matrix robustly. The UMFPACK (LU) override was only a workaround for AMG 1.x's default `Pinv` coarse solver, which forms a dense SVD pseudo-inverse and errored (`gesdd!`) on that matrix — and LU is itself less robust than QR on rank-deficient coarse operators. The default is cleaner and the idiomatic AMG usage. Because the examples now rely on AMG 2.0's default coarse solver (AMG 1.x's `Pinv` would crash on the non-SPD W, and the Sundials AMG example here already uses the default coarse solver), bump the docs `[compat]` floor to `AlgebraicMultigrid = "2"` so the build is guaranteed to resolve AMG 2.0 rather than silently falling back to a 1.x that would error. Verified locally on the released stack (AlgebraicMultigrid 2.0.0 + LinearSolve 3.85.2 + OrdinaryDiffEqSDIRK): KenCarp47 + KrylovJL_GMRES with `ruge_stuben` precs (default coarse solver, and with Jacobi smoothers) solves the brusselator problem successfully, no override needed. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/Project.toml | 2 +- docs/src/tutorials/advanced_ode_example.md | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index e082e146d..a4f0acfb7 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -90,7 +90,7 @@ DiffEqDocs = {path = ".."} [compat] ADTypes = "1.7" -AlgebraicMultigrid = "0.5, 0.6, 1, 2" +AlgebraicMultigrid = "2" BSON = "0.3" BVProblemLibrary = "0.1.2" BenchmarkTools = "1" diff --git a/docs/src/tutorials/advanced_ode_example.md b/docs/src/tutorials/advanced_ode_example.md index 777509d5e..3e6fec0fd 100644 --- a/docs/src/tutorials/advanced_ode_example.md +++ b/docs/src/tutorials/advanced_ode_example.md @@ -274,10 +274,7 @@ which is more automatic. The setup is very similar to before: import AlgebraicMultigrid function algebraicmultigrid(W, p) A = convert(AbstractMatrix, W) - # Use a direct (LU) coarse solver: AlgebraicMultigrid's default `Pinv` coarse solver - # forms a dense pseudo-inverse via SVD, which errors on the non-SPD `W = I - γJ`. - Pl = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(A; - coarse_solver = AlgebraicMultigrid.LinearSolveWrapper(LS.UMFPACKFactorization()))) + Pl = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(A)) Pl, LinearAlgebra.I end @@ -294,8 +291,7 @@ function algebraicmultigrid2(W, p) A = convert(AbstractMatrix, W) Pl = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(A, presmoother = AlgebraicMultigrid.Jacobi(rand(size(A, 1))), - postsmoother = AlgebraicMultigrid.Jacobi(rand(size(A, 1))), - coarse_solver = AlgebraicMultigrid.LinearSolveWrapper(LS.UMFPACKFactorization()))) + postsmoother = AlgebraicMultigrid.Jacobi(rand(size(A, 1))))) Pl, LinearAlgebra.I end