@@ -186,16 +186,14 @@ function calculate_jacobian(sys::System;
186186 if sparse
187187 jac = sparsejacobian (rhs, dvs; simplify)
188188 if get_iv (sys) != = nothing
189- W_s = W_sparsity (sys)
190- (Is, Js, Vs) = findnz (W_s)
191- # Add nonzeros of W as non-structural zeros of the Jacobian (to ensure equal
192- # results for oop and iip Jacobian)
193- for (i, j) in zip (Is, Js)
194- iszero (jac[i, j]) && begin
195- jac[i, j] = 1
196- jac[i, j] = 0
197- end
198- end
189+ # Add nonzeros of W as non-structural zeros of the Jacobian
190+ # (to ensure equal results for oop and iip Jacobian)
191+ JIs, JJs, JVs = findnz (jac)
192+ WIs, WJs, _ = findnz (W_sparsity (sys))
193+ append! (JIs, WIs) # explicitly put all W's indices also in J,
194+ append! (JJs, WJs) # even if it duplicates some indices
195+ append! (JVs, zeros (eltype (JVs), length (WIs))) # add zero
196+ jac = SparseArrays. sparse (JIs, JJs, JVs) # values at duplicate indices are summed; not overwritten
199197 end
200198 else
201199 jac = jacobian (rhs, dvs; simplify)
@@ -213,21 +211,23 @@ Generate the jacobian function for the equations of a [`System`](@ref).
213211
214212$GENERATE_X_KWARGS
215213- `simplify`, `sparse`: Forwarded to [`calculate_jacobian`](@ref).
214+ - `checkbounds`: Whether to check correctness of indices at runtime if `sparse`.
215+ Also forwarded to `build_function_wrapper`.
216216
217217All other keyword arguments are forwarded to [`build_function_wrapper`](@ref).
218218"""
219219function generate_jacobian (sys:: System ;
220220 simplify = false , sparse = false , eval_expression = false ,
221221 eval_module = @__MODULE__ , expression = Val{true }, wrap_gfw = Val{false },
222- kwargs... )
222+ checkbounds = false , kwargs... )
223223 dvs = unknowns (sys)
224224 jac = calculate_jacobian (sys; simplify, sparse, dvs)
225225 p = reorder_parameters (sys)
226226 t = get_iv (sys)
227- if t === nothing
228- wrap_code = (identity, identity)
227+ if t != = nothing && sparse && checkbounds
228+ wrap_code = assert_jac_length_header (sys) # checking sparse J indices at runtime is expensive for large systems
229229 else
230- wrap_code = sparse ? assert_jac_length_header (sys) : (identity, identity)
230+ wrap_code = (identity, identity)
231231 end
232232 args = (dvs, p... )
233233 nargs = 2
@@ -236,7 +236,7 @@ function generate_jacobian(sys::System;
236236 nargs = 3
237237 end
238238 res = build_function_wrapper (sys, jac, args... ; wrap_code, expression = Val{true },
239- expression_module = eval_module, kwargs... )
239+ expression_module = eval_module, checkbounds, kwargs... )
240240 return maybe_compile_function (
241241 expression, wrap_gfw, (2 , nargs, is_split (sys)), res; eval_expression, eval_module)
242242end
@@ -328,12 +328,14 @@ Generate the `W = γ * M + J` function for the equations of a [`System`](@ref).
328328
329329$GENERATE_X_KWARGS
330330- `simplify`, `sparse`: Forwarded to [`calculate_jacobian`](@ref).
331+ - `checkbounds`: Whether to check correctness of indices at runtime if `sparse`.
332+ Also forwarded to `build_function_wrapper`.
331333
332334All other keyword arguments are forwarded to [`build_function_wrapper`](@ref).
333335"""
334336function generate_W (sys:: System ;
335337 simplify = false , sparse = false , expression = Val{true }, wrap_gfw = Val{false },
336- eval_expression = false , eval_module = @__MODULE__ , kwargs... )
338+ eval_expression = false , eval_module = @__MODULE__ , checkbounds = false , kwargs... )
337339 dvs = unknowns (sys)
338340 ps = parameters (sys; initial_parameters = true )
339341 M = calculate_massmatrix (sys; simplify)
@@ -343,13 +345,15 @@ function generate_W(sys::System;
343345 J = calculate_jacobian (sys; simplify, sparse, dvs)
344346 W = W_GAMMA * M + J
345347 t = get_iv (sys)
346- if t != = nothing
347- wrap_code = sparse ? assert_jac_length_header (sys) : (identity, identity)
348+ if t != = nothing && sparse && checkbounds
349+ wrap_code = assert_jac_length_header (sys)
350+ else
351+ wrap_code = (identity, identity)
348352 end
349353
350354 p = reorder_parameters (sys, ps)
351355 res = build_function_wrapper (sys, W, dvs, p... , W_GAMMA, t; wrap_code,
352- p_end = 1 + length (p), kwargs... )
356+ p_end = 1 + length (p), checkbounds, kwargs... )
353357 return maybe_compile_function (
354358 expression, wrap_gfw, (2 , 4 , is_split (sys)), res; eval_expression, eval_module)
355359end
0 commit comments