Skip to content

Commit f9ea92c

Browse files
committed
fix: sparse jacobian
1 parent 1c3f387 commit f9ea92c

File tree

2 files changed

+18
-15
lines changed

2 files changed

+18
-15
lines changed

docs/src/tutorials/code_optimization.md

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ Take for example a prototypical small nonlinear solver code in its out-of-place
3333
```@example small_opt
3434
using NonlinearSolve
3535
36-
function f(u, p)
37-
u .* u .- p
38-
end
36+
f(u, p) = u .* u .- p
3937
u0 = [1.0, 1.0]
4038
p = 2.0
4139
prob = NonlinearProblem(f, u0, p)
@@ -53,9 +51,7 @@ using BenchmarkTools
5351
Note that this way of writing the function is a shorthand for:
5452

5553
```@example small_opt
56-
function f(u, p)
57-
[u[1] * u[1] - p, u[2] * u[2] - p]
58-
end
54+
f(u, p) = [u[1] * u[1] - p, u[2] * u[2] - p]
5955
```
6056

6157
where the function `f` returns an array. This is a common pattern from things like MATLAB's
@@ -71,7 +67,7 @@ by hand, this looks like:
7167
function f(du, u, p)
7268
du[1] = u[1] * u[1] - p
7369
du[2] = u[2] * u[2] - p
74-
nothing
70+
return nothing
7571
end
7672
7773
prob = NonlinearProblem(f, u0, p)
@@ -84,6 +80,7 @@ the `.=` in-place broadcasting.
8480
```@example small_opt
8581
function f(du, u, p)
8682
du .= u .* u .- p
83+
return nothing
8784
end
8885
8986
@benchmark sol = solve(prob, NewtonRaphson())
@@ -114,6 +111,7 @@ to normal array expressions, for example:
114111

115112
```@example small_opt
116113
using StaticArrays
114+
117115
A = SA[2.0, 3.0, 5.0]
118116
typeof(A)
119117
```
@@ -135,22 +133,20 @@ want to use the out-of-place allocating form, but this time we want to output a
135133
array. Doing it with broadcasting looks like:
136134

137135
```@example small_opt
138-
function f_SA(u, p)
139-
u .* u .- p
140-
end
136+
f_SA(u, p) = u .* u .- p
137+
141138
u0 = SA[1.0, 1.0]
142139
p = 2.0
143140
prob = NonlinearProblem(f_SA, u0, p)
141+
144142
@benchmark solve(prob, NewtonRaphson())
145143
```
146144

147145
Note that only change here is that `u0` is made into a StaticArray! If we needed to write
148146
`f` out for a more complex nonlinear case, then we'd simply do the following:
149147

150148
```@example small_opt
151-
function f_SA(u, p)
152-
SA[u[1] * u[1] - p, u[2] * u[2] - p]
153-
end
149+
f_SA(u, p) = SA[u[1] * u[1] - p, u[2] * u[2] - p]
154150
155151
@benchmark solve(prob, NewtonRaphson())
156152
```

src/internal/jacobian.jl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,14 @@ function JacobianCache(prob, alg, f::F, fu_, u, p; stats, autodiff = nothing,
9595
else
9696
if f.jac_prototype === nothing
9797
if !sparse_jac
98-
__similar(fu, promote_type(eltype(fu), eltype(u)), length(fu), length(u))
98+
# While this is technically wasteful, it gives out the type of the Jacobian
99+
# which is needed to create the linear solver cache
100+
stats.njacs += 1
101+
if iip
102+
DI.jacobian(f, fu, di_extras, autodiff, u, Constant(p))
103+
else
104+
DI.jacobian(f, autodiff, u, Constant(p))
105+
end
99106
else
100107
zero(init_jacobian(sdifft_extras; preserve_immutable = Val(true)))
101108
end
@@ -154,7 +161,7 @@ function (cache::JacobianCache{iip})(
154161
cache.f, cache.fu, J, cache.di_extras, cache.autodiff, u, Constant(p))
155162
else
156163
uf = JacobianWrapper{iip}(cache.f, p)
157-
sparse_jacobian!(J, cache.autodiff, cache.jac_cache, uf, cache.fu, u)
164+
sparse_jacobian!(J, cache.autodiff, cache.sdifft_extras, uf, cache.fu, u)
158165
end
159166
return J
160167
else

0 commit comments

Comments
 (0)