Skip to content

Commit 89c8f13

Browse files
authored
Merge pull request #1804 from Keno/kf/pantelidesrobust
Make pantelides robust against unused derivative vars
2 parents f51297c + 80849cf commit 89c8f13

File tree

7 files changed

+45
-15
lines changed

7 files changed

+45
-15
lines changed

src/inputoutput.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,8 @@ function inputs_to_parameters!(state::TransformationState, io)
269269
@assert new_v > 0
270270
new_var_to_diff[new_i] = new_v
271271
end
272-
@set! structure.var_to_diff = new_var_to_diff
273-
@set! structure.graph = new_graph
272+
@set! structure.var_to_diff = complete(new_var_to_diff)
273+
@set! structure.graph = complete(new_graph)
274274

275275
@set! sys.eqs = map(Base.Fix2(substitute, input_to_parameters), equations(sys))
276276
@set! sys.states = setdiff(states(sys), keys(input_to_parameters))

src/structural_transformation/StructuralTransformations.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ using ModelingToolkit: ODESystem, AbstractSystem, var_from_nested_derivative, Di
2121
ExtraVariablesSystemException,
2222
get_postprocess_fbody, vars!,
2323
IncrementalCycleTracker, add_edge_checked!, topological_sort,
24-
invalidate_cache!, Substitutions, get_or_construct_tearing_state
24+
invalidate_cache!, Substitutions, get_or_construct_tearing_state,
25+
AliasGraph
2526

2627
using ModelingToolkit.BipartiteGraphs
2728
import .BipartiteGraphs: invview

src/structural_transformation/pantelides.jl

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,37 @@ end
7474
7575
Perform Pantelides algorithm.
7676
"""
77-
function pantelides!(state::TransformationState; maxiters = 8000)
77+
function pantelides!(state::TransformationState, ag::Union{AliasGraph, Nothing} = nothing;
78+
maxiters = 8000)
7879
@unpack graph, solvable_graph, var_to_diff, eq_to_diff = state.structure
7980
neqs = nsrcs(graph)
8081
nvars = nv(var_to_diff)
8182
vcolor = falses(nvars)
8283
ecolor = falses(neqs)
8384
var_eq_matching = Matching(nvars)
8485
neqs′ = neqs
86+
nnonemptyeqs = count(eq -> !isempty(𝑠neighbors(graph, eq)), 1:neqs′)
87+
88+
# Allow matching for the highest differentiated variable that
89+
# currently appears in an equation (or implicit equation in a side ag)
90+
varwhitelist = falses(nvars)
91+
for var in 1:nvars
92+
if var_to_diff[var] === nothing
93+
while isempty(𝑑neighbors(graph, var)) && (ag === nothing || !haskey(ag, var))
94+
var′ = invview(var_to_diff)[var]
95+
var′ === nothing && break
96+
var = var′
97+
end
98+
if !isempty(𝑑neighbors(graph, var)) || (ag !== nothing && haskey(ag, var))
99+
varwhitelist[var] = true
100+
end
101+
end
102+
end
103+
104+
if nnonemptyeqs > count(varwhitelist)
105+
throw(InvalidSystemException("System is structurally singular"))
106+
end
107+
85108
for k in 1:neqs′
86109
eq′ = k
87110
isempty(𝑠neighbors(graph, eq′)) && continue
@@ -93,7 +116,6 @@ function pantelides!(state::TransformationState; maxiters = 8000)
93116
#
94117
# the derivatives and algebraic variables are zeros in the variable
95118
# association list
96-
varwhitelist = var_to_diff .== nothing
97119
resize!(vcolor, nvars)
98120
fill!(vcolor, false)
99121
resize!(ecolor, neqs)
@@ -103,11 +125,16 @@ function pantelides!(state::TransformationState; maxiters = 8000)
103125
pathfound && break # terminating condition
104126
for var in eachindex(vcolor)
105127
vcolor[var] || continue
106-
# introduce a new variable
107-
nvars += 1
108-
var_diff = var_derivative!(state, var)
109-
push!(var_eq_matching, unassigned)
110-
@assert length(var_eq_matching) == var_diff
128+
if var_to_diff[var] === nothing
129+
# introduce a new variable
130+
nvars += 1
131+
var_diff = var_derivative!(state, var)
132+
push!(var_eq_matching, unassigned)
133+
push!(varwhitelist, false)
134+
@assert length(var_eq_matching) == var_diff
135+
end
136+
varwhitelist[var] = false
137+
varwhitelist[var_to_diff[var]] = true
111138
end
112139

113140
for eq in eachindex(ecolor)

src/structural_transformation/partial_state_selection.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
function partial_state_selection_graph!(state::TransformationState)
1+
function partial_state_selection_graph!(state::TransformationState;
2+
ag::Union{AliasGraph, Nothing} = nothing)
23
find_solvables!(state; allow_symbolic = true)
3-
var_eq_matching = complete(pantelides!(state))
4+
var_eq_matching = complete(pantelides!(state, ag))
45
complete!(state.structure)
56
partial_state_selection_graph!(state.structure, var_eq_matching)
67
end

src/structural_transformation/symbolics_tearing.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ function tearing_reassemble(state::TearingState, var_eq_matching; simplify = fal
567567
eq_to_diff = new_eq_to_diff
568568
diff_to_var = invview(var_to_diff)
569569

570-
@set! state.structure.graph = graph
570+
@set! state.structure.graph = complete(graph)
571571
@set! state.structure.var_to_diff = var_to_diff
572572
@set! state.structure.eq_to_diff = eq_to_diff
573573
@set! state.fullvars = fullvars = fullvars[invvarsperm]

src/systems/systemstructure.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ function TearingState(sys; quick_cancel = false, check = true)
350350
eq_to_diff = DiffGraph(nsrcs(graph))
351351

352352
return TearingState(sys, fullvars,
353-
SystemStructure(var_to_diff, eq_to_diff, graph, nothing), Any[])
353+
SystemStructure(complete(var_to_diff), complete(eq_to_diff),
354+
complete(graph), nothing), Any[])
354355
end
355356

356357
function linear_subsys_adjmat(state::TransformationState)

test/structural_transformation/utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ StructuralTransformations.find_solvables!(state)
2121
sss = state.structure
2222
@unpack graph, solvable_graph, var_to_diff = sss
2323
@test graph.fadjlist == [[1, 7], [2, 8], [3, 5, 9], [4, 6, 9], [5, 6]]
24-
@test graph.badjlist == 9
24+
@test length(graph.badjlist) == 9
2525
@test ne(graph) == nnz(incidence_matrix(graph)) == 12
2626
@test nv(solvable_graph) == 9 + 5
2727
let N = nothing

0 commit comments

Comments
 (0)