@@ -173,6 +173,13 @@ A cache for computing the Jacobian of type `AbstractMaybeSparseJacobianCache`.
173
173
"""
174
174
function sparse_jacobian_cache end
175
175
176
+ function sparse_jacobian_static_array (ad, cache, f, x:: SArray )
177
+ # Not the most performant fallback
178
+ J = init_jacobian (cache)
179
+ sparse_jacobian! (J, ad, cache, f, MArray (x))
180
+ return J
181
+ end
182
+
176
183
"""
177
184
sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection, f, x; fx=nothing)
178
185
sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection, f!, fx, x)
@@ -189,20 +196,29 @@ function sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection,
189
196
sparse_jacobian! (J, ad, cache, args... )
190
197
return J
191
198
end
199
+ function sparse_jacobian (ad:: AbstractADType , sd:: AbstractMaybeSparsityDetection , f,
200
+ x:: SArray ; kwargs... )
201
+ cache = sparse_jacobian_cache (ad, sd, f, x; kwargs... )
202
+ return sparse_jacobian_static_array (ad, cache, f, x)
203
+ end
192
204
193
205
"""
194
206
sparse_jacobian(ad::AbstractADType, cache::AbstractMaybeSparseJacobianCache, f, x)
195
207
sparse_jacobian(ad::AbstractADType, cache::AbstractMaybeSparseJacobianCache, f!, fx, x)
196
208
197
209
Use the sparsity detection `cache` for computing the sparse Jacobian. This allocates a new
198
- Jacobian at every function call
210
+ Jacobian at every function call.
199
211
"""
200
212
function sparse_jacobian (ad:: AbstractADType , cache:: AbstractMaybeSparseJacobianCache ,
201
213
args... )
202
214
J = init_jacobian (cache)
203
215
sparse_jacobian! (J, ad, cache, args... )
204
216
return J
205
217
end
218
+ function sparse_jacobian (ad:: AbstractADType , cache:: AbstractMaybeSparseJacobianCache , f,
219
+ x:: SArray )
220
+ return sparse_jacobian_static_array (ad, cache, f, x)
221
+ end
206
222
207
223
"""
208
224
sparse_jacobian!(J::AbstractMatrix, ad::AbstractADType, sd::AbstractSparsityDetection,
@@ -247,14 +263,18 @@ function __chunksize(::Union{AutoSparseForwardDiff{C}, AutoForwardDiff{C}}, x) w
247
263
C isa ForwardDiff. Chunk && return C
248
264
return __chunksize (Val (C), x)
249
265
end
250
- __chunksize (:: Val{nothing} , x) = ForwardDiff . Chunk (x)
266
+ __chunksize (:: Val{nothing} , x) = __chunksize (x)
251
267
function __chunksize (:: Val{C} , x) where {C}
252
268
if C isa Integer && ! (C isa Bool)
253
- return C ≤ 0 ? ForwardDiff . Chunk (x) : ForwardDiff. Chunk {C} ()
269
+ return C ≤ 0 ? __chunksize (x) : ForwardDiff. Chunk {C} ()
254
270
else
255
271
error (" $(C) ::$(typeof (C)) is not a valid chunksize!" )
256
272
end
257
273
end
274
+
275
+ __chunksize (x) = ForwardDiff. Chunk (x)
276
+ __chunksize (x:: StaticArray ) = ForwardDiff. Chunk {ForwardDiff.pickchunksize(prod(Size(x)))} ()
277
+
258
278
function __chunksize (:: Union{AutoSparseForwardDiff{C}, AutoForwardDiff{C}} ) where {C}
259
279
C === nothing && return nothing
260
280
C isa Integer && ! (C isa Bool) && return C ≤ 0 ? nothing : Val (C)
@@ -273,18 +293,36 @@ end
273
293
return :(nothing )
274
294
end
275
295
276
- function init_jacobian (c:: AbstractMaybeSparseJacobianCache )
296
+ """
297
+ init_jacobian(cache::AbstractMaybeSparseJacobianCache;
298
+ preserve_immutable::Val = Val(false))
299
+
300
+ Initialize the Jacobian based on the cache. Uses sparse jacobians if possible.
301
+
302
+ If `preserve_immutable` is `true`, then the Jacobian returned might be immutable, this is
303
+ relevant if the inputs are immutable like `StaticArrays`.
304
+ """
305
+ function init_jacobian (c:: AbstractMaybeSparseJacobianCache ;
306
+ preserve_immutable:: Val = Val (false ))
277
307
T = promote_type (eltype (c. fx), eltype (c. x))
278
- return init_jacobian (__getfield (c, Val (:jac_prototype )), T, c. fx, c. x)
308
+ return init_jacobian (__getfield (c, Val (:jac_prototype )), T, c. fx, c. x;
309
+ preserve_immutable)
279
310
end
280
- init_jacobian (:: Nothing , :: Type{T} , fx, x) where {T} = similar (fx, T, length (fx), length (x))
281
- function init_jacobian (:: Nothing , :: Type{T} , fx:: StaticArray , x:: StaticArray ) where {T}
282
- # We want to construct a MArray to preserve types
283
- J = StaticArrays. MArray {Tuple{length(fx), length(x)}, T} (undef)
284
- return J
311
+ function init_jacobian (:: Nothing , :: Type{T} , fx, x; kwargs... ) where {T}
312
+ return similar (fx, T, length (fx), length (x))
313
+ end
314
+ function init_jacobian (:: Nothing , :: Type{T} , fx:: StaticArray , x:: StaticArray ;
315
+ preserve_immutable:: Val{PI} = Val (true )) where {T, PI}
316
+ if PI
317
+ return StaticArrays. SArray {Tuple{length(fx), length(x)}, T} (I)
318
+ else
319
+ return StaticArrays. MArray {Tuple{length(fx), length(x)}, T} (undef)
320
+ end
321
+ end
322
+ function init_jacobian (J, :: Type{T} , fx, x; kwargs... ) where {T}
323
+ return similar (J, T, size (J, 1 ), size (J, 2 ))
285
324
end
286
- init_jacobian (J, :: Type{T} , _, _) where {T} = similar (J, T, size (J, 1 ), size (J, 2 ))
287
- init_jacobian (J:: SparseMatrixCSC , :: Type{T} , _, _) where {T} = T .(J)
325
+ init_jacobian (J:: SparseMatrixCSC , :: Type{T} , fx, x; kwargs... ) where {T} = T .(J)
288
326
289
327
__maybe_copy_x (_, x) = x
290
328
__maybe_copy_x (_, :: Nothing ) = nothing
0 commit comments