Skip to content

Commit adde8c0

Browse files
committed
Use approximate sparsity detection by default
1 parent d7ef4af commit adde8c0

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "NonlinearSolve"
22
uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
33
authors = ["SciML"]
4-
version = "3.0.1"
4+
version = "3.0.2"
55

66
[deps]
77
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
@@ -35,6 +35,7 @@ FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce"
3535
LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891"
3636
MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9"
3737
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
38+
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
3839
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
3940

4041
[extensions]
@@ -43,6 +44,7 @@ NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt"
4344
NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim"
4445
NonlinearSolveMINPACKExt = "MINPACK"
4546
NonlinearSolveNLsolveExt = "NLsolve"
47+
NonlinearSolveSymbolicsExt = "Symbolics"
4648
NonlinearSolveZygoteExt = "Zygote"
4749

4850
[compat]

docs/src/tutorials/large_systems.md

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ broadcast). Use `dx=dy=1/32`.
6060
The resulting `NonlinearProblem` definition is:
6161

6262
```@example ill_conditioned_nlprob
63-
using NonlinearSolve, LinearAlgebra, SparseArrays, LinearSolve, Symbolics
63+
using NonlinearSolve, LinearAlgebra, SparseArrays, LinearSolve
6464
6565
const N = 32
6666
const xyd_brusselator = range(0, stop = 1, length = N)
67+
6768
brusselator_f(x, y) = (((x - 0.3)^2 + (y - 0.6)^2) <= 0.1^2) * 5.0
6869
limit(a, N) = a == N + 1 ? 1 : a == 0 ? N : a
70+
6971
function brusselator_2d_loop(du, u, p)
7072
A, B, alpha, dx = p
7173
alpha = alpha / dx^2
@@ -96,6 +98,7 @@ function init_brusselator_2d(xyd)
9698
end
9799
u
98100
end
101+
99102
u0 = init_brusselator_2d(xyd_brusselator)
100103
prob_brusselator_2d = NonlinearProblem(brusselator_2d_loop, u0, p)
101104
```
@@ -120,6 +123,26 @@ include:
120123
- BandedMatrix ([BandedMatrices.jl](https://github.com/JuliaLinearAlgebra/BandedMatrices.jl))
121124
- BlockBandedMatrix ([BlockBandedMatrices.jl](https://github.com/JuliaLinearAlgebra/BlockBandedMatrices.jl))
122125

126+
## Approximate Sparsity Detection & Sparse Jacobians
127+
128+
In the next section, we will discuss how to declare a sparse Jacobian and how to use
129+
[Symbolics.jl](https://github.com/JuliaSymbolics/Symbolics.jl), to compute exact sparse
130+
jacobians. For this to work it is important to not load `Symbolics.jl`. This is triggered
131+
if you pass in a sparse autodiff type such as `AutoSparseForwardDiff()`.
132+
133+
```@example ill_conditioned_nlprob
134+
using BenchmarkTools # for @btime
135+
136+
@btime solve(prob_brusselator_2d, NewtonRaphson());
137+
@btime solve(prob_brusselator_2d, NewtonRaphson(; autodiff = AutoSparseForwardDiff()));
138+
@btime solve(prob_brusselator_2d,
139+
NewtonRaphson(; autodiff = AutoSparseForwardDiff(),
140+
linsolve = KLUFactorization()));
141+
@btime solve(prob_brusselator_2d,
142+
NewtonRaphson(; autodiff = AutoSparseForwardDiff(),
143+
linsolve = KrylovJL_GMRES()));
144+
```
145+
123146
## Declaring a Sparse Jacobian with Automatic Sparsity Detection
124147

125148
Jacobian sparsity is declared by the `jac_prototype` argument in the `NonlinearFunction`.
@@ -156,7 +179,6 @@ prob_brusselator_2d_sparse = NonlinearProblem(ff, u0, p)
156179
Now let's see how the version with sparsity compares to the version without:
157180

158181
```@example ill_conditioned_nlprob
159-
using BenchmarkTools # for @btime
160182
@btime solve(prob_brusselator_2d, NewtonRaphson());
161183
@btime solve(prob_brusselator_2d_sparse, NewtonRaphson());
162184
@btime solve(prob_brusselator_2d_sparse, NewtonRaphson(linsolve = KLUFactorization()));
@@ -258,10 +280,8 @@ function algebraicmultigrid2(W, du, u, p, t, newW, Plprev, Prprev, solverdata)
258280
if newW === nothing || newW
259281
A = convert(AbstractMatrix, W)
260282
Pl = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(A,
261-
presmoother = AlgebraicMultigrid.Jacobi(rand(size(A,
262-
1))),
263-
postsmoother = AlgebraicMultigrid.Jacobi(rand(size(A,
264-
1)))))
283+
presmoother = AlgebraicMultigrid.Jacobi(rand(size(A, 1))),
284+
postsmoother = AlgebraicMultigrid.Jacobi(rand(size(A, 1)))))
265285
else
266286
Pl = Plprev
267287
end

ext/NonlinearSolveSymbolicsExt.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module NonlinearSolveSymbolicsExt
2+
3+
import NonlinearSolve, Symbolics
4+
5+
NonlinearSolve.is_extension_loaded(::Val{:Symbolics}) = true
6+
7+
end

src/jacobian.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@ sparsity_detection_alg(_, _) = NoSparsityDetection()
1212
function sparsity_detection_alg(f, ad::AbstractSparseADType)
1313
if f.sparsity === nothing
1414
if f.jac_prototype === nothing
15-
return SymbolicsSparsityDetection()
15+
if is_extension_loaded(Val(:Symbolics))
16+
return SymbolicsSparsityDetection()
17+
else
18+
@warn "Symbolics.jl is not loaded and sparse AD mode $(ad) is being used. \
19+
Using approximate sparsity detection using ForwardDiff. This can \
20+
potentially fail or generate incorrect sparsity pattern for \
21+
complicated problems. Use with caution." maxlog=1
22+
return ApproximateJacobianSparsity()
23+
end
1624
else
1725
jac_prototype = f.jac_prototype
1826
end

0 commit comments

Comments
 (0)