Skip to content

Commit 96c4ddc

Browse files
authored
Merge pull request #1890 from Keno/kf/knotty
state_selection: Correct is_not_present condition
2 parents 7bfbcbb + 7df0532 commit 96c4ddc

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

src/structural_transformation/partial_state_selection.jl

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ function dummy_derivative_graph!(structure::SystemStructure, var_eq_matching, ja
267267
end
268268
dummy_derivatives_set = BitSet(dummy_derivatives)
269269

270+
irreducible_set = BitSet()
270271
if ag !== nothing
271272
function isreducible(x)
272273
# `k` is reducible if all lower differentiated variables are.
@@ -277,27 +278,46 @@ function dummy_derivative_graph!(structure::SystemStructure, var_eq_matching, ja
277278
end
278279
x = diff_to_var[x]
279280
x === nothing && break
281+
# We deliberately do not check `isempty(𝑑neighbors(graph, x))`
282+
# because when `D(x)` appears in the alias graph, and `x`
283+
# doesn't appear in any equations nor in the alias graph, `D(x)`
284+
# is not reducible. Consider the system `D(x) ~ 0`.
280285
if !haskey(ag, x)
281286
isred = false
282287
end
283288
end
284289
isred
285290
end
286-
irreducible_set = BitSet()
287-
for (k, (_, v)) in ag
291+
for (k, (c, v)) in ag
288292
isreducible(k) || push!(irreducible_set, k)
289293
isreducible(k) || push!(irreducible_set, k)
294+
iszero(c) && continue
290295
push!(irreducible_set, v)
291296
end
292297
end
293298

294-
is_not_present = v -> isempty(𝑑neighbors(graph, v)) &&
295-
(ag === nothing || (haskey(ag, v) && !(v in irreducible_set)))
299+
is_not_present_non_rec = let graph = graph, irreducible_set = irreducible_set
300+
v -> begin
301+
not_in_eqs = isempty(𝑑neighbors(graph, v))
302+
ag === nothing && return not_in_eqs
303+
isirreducible = v in irreducible_set
304+
return not_in_eqs && !isirreducible
305+
end
306+
end
307+
308+
is_not_present = let var_to_diff = var_to_diff
309+
v -> while true
310+
# if a higher derivative is present, then it's present
311+
is_not_present_non_rec(v) || return false
312+
v = var_to_diff[v]
313+
v === nothing && return true
314+
end
315+
end
316+
296317
# Derivatives that are either in the dummy derivatives set or ended up not
297318
# participating in the system at all are not considered differential
298319
is_some_diff = let dummy_derivatives_set = dummy_derivatives_set
299-
v -> !(v in dummy_derivatives_set) &&
300-
!(var_to_diff[v] === nothing && is_not_present(v))
320+
v -> !(v in dummy_derivatives_set) && !is_not_present(v)
301321
end
302322

303323
# We don't want tearing to give us `y_t ~ D(y)`, so we skip equations with
@@ -309,7 +329,7 @@ function dummy_derivative_graph!(structure::SystemStructure, var_eq_matching, ja
309329
# We can eliminate variables that are not a selected state (differential
310330
# variables). Selected states are differentiated variables that are not
311331
# dummy derivatives.
312-
can_eliminate = let var_to_diff = var_to_diff
332+
can_eliminate = let var_to_diff = var_to_diff, ag = ag
313333
v -> begin
314334
if ag !== nothing
315335
haskey(ag, v) && return false

test/structural_transformation/tearing.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ u0 = [mass.s => 0.0
218218
mass.v => 1.0]
219219

220220
sys = structural_simplify(ms_model)
221-
@test sys.jac[] === ModelingToolkit.EMPTY_JAC
222-
@test sys.tgrad[] === ModelingToolkit.EMPTY_TGRAD
221+
@test ModelingToolkit.get_jac(sys)[] === ModelingToolkit.EMPTY_JAC
222+
@test ModelingToolkit.get_tgrad(sys)[] === ModelingToolkit.EMPTY_TGRAD
223223
prob_complex = ODAEProblem(sys, u0, (0, 1.0))
224224
sol = solve(prob_complex, Tsit5())
225225
@test all(sol[mass.v] .== 1)

0 commit comments

Comments
 (0)