@@ -9,18 +9,110 @@ abstract type AbstractSparsityDetection <: AbstractMaybeSparsityDetection end
99
1010struct NoSparsityDetection <: AbstractMaybeSparsityDetection end
1111
12+ """
13+ SymbolicsSparsityDetection(; alg = GreedyD1Color())
14+
15+ Use Symbolics to compute the sparsity pattern of the Jacobian. This requires `Symbolics.jl`
16+ to be explicitly loaded.
17+
18+ ## Keyword Arguments
19+
20+ - `alg`: The algorithm used for computing the matrix colors
21+
22+ See Also: [JacPrototypeSparsityDetection](@ref), [PrecomputedJacobianColorvec](@ref)
23+ """
1224Base. @kwdef struct SymbolicsSparsityDetection{A <: ArrayInterface.ColoringAlgorithm } < :
1325 AbstractSparsityDetection
1426 alg:: A = GreedyD1Color ()
1527end
1628
29+ """
30+ JacPrototypeSparsityDetection(; jac_prototype, alg = GreedyD1Color())
31+
32+ Use a pre-specified `jac_prototype` to compute the matrix colors of the Jacobian.
33+
34+ ## Keyword Arguments
35+
36+ - `jac_prototype`: The prototype Jacobian used for computing the matrix colors
37+ - `alg`: The algorithm used for computing the matrix colors
38+
39+ See Also: [SymbolicsSparsityDetection](@ref), [PrecomputedJacobianColorvec](@ref)
40+ """
1741Base. @kwdef struct JacPrototypeSparsityDetection{
18- J, A <: ArrayInterface.ColoringAlgorithm ,
19- } <: AbstractSparsityDetection
42+ J, A <: ArrayInterface.ColoringAlgorithm } <: AbstractSparsityDetection
2043 jac_prototype:: J
2144 alg:: A = GreedyD1Color ()
2245end
2346
47+ """
48+ PrecomputedJacobianColorvec(jac_prototype, row_colorvec, col_colorvec)
49+
50+ Use a pre-specified `colorvec` which can be directly used for sparse differentiation. Based
51+ on whether a reverse mode or forward mode or finite differences is used, the corresponding
52+ `row_colorvec` or `col_colorvec` is used. Atmost one of them can be set to `nothing`.
53+
54+ ## Arguments
55+
56+ - `jac_prototype`: The prototype Jacobian used for computing structural nonzeros
57+ - `row_colorvec`: The row colorvec of the Jacobian
58+ - `col_colorvec`: The column colorvec of the Jacobian
59+
60+ See Also: [SymbolicsSparsityDetection](@ref), [JacPrototypeSparsityDetection](@ref)
61+ """
62+ struct PrecomputedJacobianColorvec{J, RC, CC} <: AbstractSparsityDetection
63+ jac_prototype:: J
64+ row_colorvec:: RC
65+ col_colorvec:: CC
66+ end
67+
68+ """
69+ PrecomputedJacobianColorvec(; jac_prototype, partition_by_rows::Bool = false,
70+ colorvec = missing, row_colorvec = missing, col_colorvec = missing)
71+
72+ Use a pre-specified `colorvec` which can be directly used for sparse differentiation. Based
73+ on whether a reverse mode or forward mode or finite differences is used, the corresponding
74+ `row_colorvec` or `col_colorvec` is used. Atmost one of them can be set to `nothing`.
75+
76+ ## Keyword Arguments
77+
78+ - `jac_prototype`: The prototype Jacobian used for computing structural nonzeros
79+ - `partition_by_rows`: Whether to partition the Jacobian by rows or columns (row
80+ partitioning is used for reverse mode AD)
81+ - `colorvec`: The colorvec of the Jacobian. If `partition_by_rows` is `true` then this
82+ is the row colorvec, otherwise it is the column colorvec
83+ - `row_colorvec`: The row colorvec of the Jacobian
84+ - `col_colorvec`: The column colorvec of the Jacobian
85+
86+ See Also: [SymbolicsSparsityDetection](@ref), [JacPrototypeSparsityDetection](@ref)
87+ """
88+ function PrecomputedJacobianColorvec (; jac_prototype, partition_by_rows:: Bool = false ,
89+ colorvec = missing , row_colorvec = missing , col_colorvec = missing )
90+ if colorvec === missing
91+ @assert row_colorvec != = missing || col_colorvec != = missing " Either `colorvec` or `row_colorvec` and `col_colorvec` must be specified!"
92+ row_colorvec = row_colorvec === missing ? nothing : row_colorvec
93+ col_colorvec = col_colorvec === missing ? nothing : col_colorvec
94+ return PrecomputedJacobianColorvec (jac_prototype, row_colorvec, col_colorvec)
95+ else
96+ @assert row_colorvec === missing && col_colorvec === missing " Specifying `colorvec` is incompatible with specifying `row_colorvec` or `col_colorvec`!"
97+ row_colorvec = partition_by_rows ? colorvec : nothing
98+ col_colorvec = partition_by_rows ? nothing : colorvec
99+ return PrecomputedJacobianColorvec (jac_prototype, row_colorvec, col_colorvec)
100+ end
101+ end
102+
103+ function _get_colorvec (alg:: PrecomputedJacobianColorvec , ad)
104+ cvec = alg. col_colorvec
105+ @assert cvec!= = nothing " `col_colorvec` is nothing, but Forward Mode AD or Finite Differences is being used!"
106+ return cvec
107+ end
108+
109+ function _get_colorvec (alg:: PrecomputedJacobianColorvec , :: AbstractReverseMode )
110+ cvec = alg. row_colorvec
111+ @assert cvec!= = nothing " `row_colorvec` is nothing, but Reverse Mode AD is being used!"
112+ return cvec
113+ end
114+
115+ # No one should be using this currently
24116Base. @kwdef struct AutoSparsityDetection{A <: ArrayInterface.ColoringAlgorithm } < :
25117 AbstractSparsityDetection
26118 alg:: A = GreedyD1Color ()
@@ -41,7 +133,8 @@ Inplace update the matrix `J` with the Jacobian of `f` at `x` using the AD backe
41133function sparse_jacobian! end
42134
43135"""
44- sparse_jacobian_cache(ad::AbstractADType, sd::AbstractSparsityDetection, f, x; fx=nothing)
136+ sparse_jacobian_cache(ad::AbstractADType, sd::AbstractSparsityDetection, f, x;
137+ fx=nothing)
45138 sparse_jacobian_cache(ad::AbstractADType, sd::AbstractSparsityDetection, f!, fx, x)
46139
47140Takes the underlying AD backend `ad`, sparsity detection algorithm `sd`, function `f`,
@@ -67,7 +160,7 @@ with the same cache to compute the jacobian.
67160function sparse_jacobian (ad:: AbstractADType , sd:: AbstractMaybeSparsityDetection , args... ;
68161 kwargs... )
69162 cache = sparse_jacobian_cache (ad, sd, args... ; kwargs... )
70- J = __init_𝒥 (cache)
163+ J = init_jacobian (cache)
71164 return sparse_jacobian! (J, ad, cache, args... )
72165end
73166
@@ -80,7 +173,7 @@ Jacobian at every function call
80173"""
81174function sparse_jacobian (ad:: AbstractADType , cache:: AbstractMaybeSparseJacobianCache ,
82175 args... )
83- J = __init_𝒥 (cache)
176+ J = init_jacobian (cache)
84177 return sparse_jacobian! (J, ad, cache, args... )
85178end
86179
@@ -106,7 +199,20 @@ function __gradient end
106199function __gradient! end
107200function __jacobian! end
108201
109- function __init_𝒥 end
202+ """
203+ init_jacobian(cache::AbstractMaybeSparseJacobianCache)
204+
205+ Initialize the Jacobian based on the cache. Uses sparse jacobians if possible.
206+
207+ !!! note
208+ This function doesn't alias the provided jacobian prototype. It always initializes a
209+ fresh jacobian that can be mutated without any side effects.
210+ """
211+ function init_jacobian end
212+
213+ # Never thought this was a useful function externally, but I ended up using it in quite a
214+ # few places. Keeping this till I remove uses of those.
215+ const __init_𝒥 = init_jacobian
110216
111217# Misc Functions
112218__chunksize (:: AutoSparseForwardDiff{C} ) where {C} = C
@@ -123,12 +229,12 @@ end
123229 return :(nothing )
124230end
125231
126- function __init_𝒥 (c:: AbstractMaybeSparseJacobianCache )
232+ function init_jacobian (c:: AbstractMaybeSparseJacobianCache )
127233 T = promote_type (eltype (c. fx), eltype (c. x))
128- return __init_𝒥 (__getfield (c, Val (:jac_prototype )), T, c. fx, c. x)
234+ return init_jacobian (__getfield (c, Val (:jac_prototype )), T, c. fx, c. x)
129235end
130- __init_𝒥 (:: Nothing , :: Type{T} , fx, x) where {T} = similar (fx, T, length (fx), length (x))
131- __init_𝒥 (J, :: Type{T} , _, _) where {T} = similar (J, T, size (J, 1 ), size (J, 2 ))
236+ init_jacobian (:: Nothing , :: Type{T} , fx, x) where {T} = similar (fx, T, length (fx), length (x))
237+ init_jacobian (J, :: Type{T} , _, _) where {T} = similar (J, T, size (J, 1 ), size (J, 2 ))
132238
133239__maybe_copy_x (_, x) = x
134240__maybe_copy_x (_, :: Nothing ) = nothing
0 commit comments