@@ -173,6 +173,13 @@ A cache for computing the Jacobian of type `AbstractMaybeSparseJacobianCache`.
173173"""
174174function sparse_jacobian_cache end
175175
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+
176183"""
177184 sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection, f, x; fx=nothing)
178185 sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection, f!, fx, x)
@@ -189,20 +196,29 @@ function sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection,
189196 sparse_jacobian! (J, ad, cache, args... )
190197 return J
191198end
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
192204
193205"""
194206 sparse_jacobian(ad::AbstractADType, cache::AbstractMaybeSparseJacobianCache, f, x)
195207 sparse_jacobian(ad::AbstractADType, cache::AbstractMaybeSparseJacobianCache, f!, fx, x)
196208
197209Use 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.
199211"""
200212function sparse_jacobian (ad:: AbstractADType , cache:: AbstractMaybeSparseJacobianCache ,
201213 args... )
202214 J = init_jacobian (cache)
203215 sparse_jacobian! (J, ad, cache, args... )
204216 return J
205217end
218+ function sparse_jacobian (ad:: AbstractADType , cache:: AbstractMaybeSparseJacobianCache , f,
219+ x:: SArray )
220+ return sparse_jacobian_static_array (ad, cache, f, x)
221+ end
206222
207223"""
208224 sparse_jacobian!(J::AbstractMatrix, ad::AbstractADType, sd::AbstractSparsityDetection,
@@ -247,14 +263,18 @@ function __chunksize(::Union{AutoSparseForwardDiff{C}, AutoForwardDiff{C}}, x) w
247263 C isa ForwardDiff. Chunk && return C
248264 return __chunksize (Val (C), x)
249265end
250- __chunksize (:: Val{nothing} , x) = ForwardDiff . Chunk (x)
266+ __chunksize (:: Val{nothing} , x) = __chunksize (x)
251267function __chunksize (:: Val{C} , x) where {C}
252268 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} ()
254270 else
255271 error (" $(C) ::$(typeof (C)) is not a valid chunksize!" )
256272 end
257273end
274+
275+ __chunksize (x) = ForwardDiff. Chunk (x)
276+ __chunksize (x:: StaticArray ) = ForwardDiff. Chunk {ForwardDiff.pickchunksize(prod(Size(x)))} ()
277+
258278function __chunksize (:: Union{AutoSparseForwardDiff{C}, AutoForwardDiff{C}} ) where {C}
259279 C === nothing && return nothing
260280 C isa Integer && ! (C isa Bool) && return C ≤ 0 ? nothing : Val (C)
@@ -273,18 +293,36 @@ end
273293 return :(nothing )
274294end
275295
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 ))
277307 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)
279310end
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 ))
285324end
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)
288326
289327__maybe_copy_x (_, x) = x
290328__maybe_copy_x (_, :: Nothing ) = nothing
0 commit comments