Skip to content

Commit b0c2295

Browse files
Merge pull request #3556 from AayushSabharwal/as/jac-header-fix
fix: fix `assert_jac_length_header`
2 parents 8e69dc9 + 875837b commit b0c2295

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed

src/ModelingToolkit.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,8 @@ export structural_simplify, expand_connections, linearize, linearization_functio
303303
LinearizationProblem
304304
export solve
305305

306-
export calculate_jacobian, generate_jacobian, generate_function, generate_custom_function, generate_W
306+
export calculate_jacobian, generate_jacobian, generate_function, generate_custom_function,
307+
generate_W
307308
export calculate_control_jacobian, generate_control_jacobian
308309
export calculate_tgrad, generate_tgrad
309310
export calculate_gradient, generate_gradient

src/systems/diffeqs/abstractodesystem.jl

+13-10
Original file line numberDiff line numberDiff line change
@@ -141,23 +141,25 @@ end
141141

142142
function assert_jac_length_header(sys)
143143
W = W_sparsity(sys)
144-
identity, expr -> Func([expr.args...], [], LiteralExpr(quote
145-
@assert $(findnz)($(expr.args[1]))[1:2] == $(findnz)($W)[1:2]
146-
$(expr.body)
147-
end))
144+
identity,
145+
function add_header(expr)
146+
Func(expr.args, [], expr.body,
147+
[:(@assert $(SymbolicUtils.Code.toexpr(term(findnz, expr.args[1])))[1:2] ==
148+
$(findnz(W)[1:2]))])
149+
end
148150
end
149151

150-
function generate_W(sys::AbstractODESystem, γ = 1., dvs = unknowns(sys),
151-
ps = parameters(sys; initial_parameters = true);
152+
function generate_W(sys::AbstractODESystem, γ = 1.0, dvs = unknowns(sys),
153+
ps = parameters(sys; initial_parameters = true);
152154
simplify = false, sparse = false, kwargs...)
153155
@variables ˍ₋gamma
154156
M = calculate_massmatrix(sys; simplify)
155157
sparse && (M = SparseArrays.sparse(M))
156158
J = calculate_jacobian(sys; simplify, sparse, dvs)
157-
W = ˍ₋gamma*M + J
159+
W = ˍ₋gamma * M + J
158160

159161
p = reorder_parameters(sys, ps)
160-
return build_function_wrapper(sys, W,
162+
return build_function_wrapper(sys, W,
161163
dvs,
162164
p...,
163165
ˍ₋gamma,
@@ -302,11 +304,12 @@ function jacobian_dae_sparsity(sys::AbstractODESystem)
302304
J1 + J2
303305
end
304306

305-
function W_sparsity(sys::AbstractODESystem)
307+
function W_sparsity(sys::AbstractODESystem)
306308
jac_sparsity = jacobian_sparsity(sys)
307309
(n, n) = size(jac_sparsity)
308310
M = calculate_massmatrix(sys)
309-
M_sparsity = M isa UniformScaling ? sparse(I(n)) : SparseMatrixCSC{Bool, Int64}((!iszero).(M))
311+
M_sparsity = M isa UniformScaling ? sparse(I(n)) :
312+
SparseMatrixCSC{Bool, Int64}((!iszero).(M))
310313
jac_sparsity .| M_sparsity
311314
end
312315

test/jacobiansparsity.jl

+25-4
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ f = DiffEqBase.ODEFunction(sys, u0 = nothing, sparse = true, jac = false)
7474
# test when u0 is not Float64
7575
u0 = similar(init_brusselator_2d(xyd_brusselator), Float32)
7676
prob_ode_brusselator_2d = ODEProblem(brusselator_2d_loop,
77-
u0, (0.0, 11.5), p)
77+
u0, (0.0, 11.5), p)
7878
sys = complete(modelingtoolkitize(prob_ode_brusselator_2d))
7979

8080
prob = ODEProblem(sys, u0, (0, 11.5), sparse = true, jac = false)
@@ -94,7 +94,8 @@ prob = ODEProblem(sys, u0, (0, 11.5), sparse = true, jac = true)
9494
@mtkbuild pend = ODESystem(eqs, t)
9595

9696
u0 = [x => 1, y => 0]
97-
prob = ODEProblem(pend, u0, (0, 11.5), [g => 1], guesses ==> 1], sparse = true, jac = true)
97+
prob = ODEProblem(
98+
pend, u0, (0, 11.5), [g => 1], guesses ==> 1], sparse = true, jac = true)
9899
jac, jac! = generate_jacobian(pend; expression = Val{false}, sparse = true)
99100
jac_prototype = ModelingToolkit.jacobian_sparsity(pend)
100101
W_prototype = ModelingToolkit.W_sparsity(pend)
@@ -109,8 +110,28 @@ prob = ODEProblem(sys, u0, (0, 11.5), sparse = true, jac = true)
109110
@test_throws AssertionError jac!(similar(jac_prototype, Float64), u, p, t)
110111

111112
W, W! = generate_W(pend; expression = Val{false}, sparse = true)
112-
γ = .1
113+
γ = 0.1
113114
M = sparse(calculate_massmatrix(pend))
114115
@test_throws AssertionError W!(similar(jac_prototype, Float64), u, p, γ, t)
115-
@test W!(similar(W_prototype, Float64), u, p, γ, t) == 0.1 * M + jac!(similar(W_prototype, Float64), u, p, t)
116+
@test W!(similar(W_prototype, Float64), u, p, γ, t) ==
117+
0.1 * M + jac!(similar(W_prototype, Float64), u, p, t)
118+
end
119+
120+
@testset "Issue#3556: Numerical accuracy" begin
121+
t = ModelingToolkit.t_nounits
122+
D = ModelingToolkit.D_nounits
123+
@parameters g
124+
@variables x(t) y(t) [state_priority = 10] λ(t)
125+
eqs = [D(D(x)) ~ λ * x
126+
D(D(y)) ~ λ * y - g
127+
x^2 + y^2 ~ 1]
128+
@mtkbuild pend = ODESystem(eqs, t)
129+
prob = ODEProblem(pend, [x => 0.0, D(x) => 1.0], (0.0, 1.0), [g => 1.0];
130+
guesses = [y => 1.0, λ => 1.0], jac = true, sparse = true)
131+
J = deepcopy(prob.f.jac_prototype)
132+
prob.f.jac(J, prob.u0, prob.p, 1.0)
133+
# this currently works but may not continue to do so
134+
# see https://github.com/SciML/ModelingToolkit.jl/pull/3556#issuecomment-2792664039
135+
@test J == prob.f.jac(prob.u0, prob.p, 1.0)
136+
@test J prob.f.jac(prob.u0, prob.p, 1.0)
116137
end

0 commit comments

Comments
 (0)