2
2
# ## Reassemble: structural information -> system
3
3
# ##
4
4
5
- function pantelides_reassemble (sys:: ODESystem , eqassoc , assign)
5
+ function pantelides_reassemble (sys:: ODESystem , eq_to_diff , assign)
6
6
s = structure (sys)
7
- @unpack fullvars, varassoc = s
7
+ @unpack fullvars, var_to_diff = s
8
8
# Step 1: write derivative equations
9
9
in_eqs = equations (sys)
10
- out_eqs = Vector {Any} (undef, length (eqassoc ))
10
+ out_eqs = Vector {Any} (undef, nv (eq_to_diff ))
11
11
fill! (out_eqs, nothing )
12
12
out_eqs[1 : length (in_eqs)] .= in_eqs
13
13
14
- out_vars = Vector {Any} (undef, length (varassoc ))
14
+ out_vars = Vector {Any} (undef, nv (var_to_diff ))
15
15
fill! (out_vars, nothing )
16
16
out_vars[1 : length (fullvars)] .= fullvars
17
17
18
18
D = Differential (get_iv (sys))
19
19
20
- for (i, v) in enumerate (varassoc)
21
- # fullvars[v] = D(fullvars[i])
22
- v == 0 && continue
23
- vi = out_vars[i]
20
+ for (varidx, diff) in edges (var_to_diff)
21
+ # fullvars[diff] = D(fullvars[var])
22
+ vi = out_vars[varidx]
24
23
@assert vi != = nothing " Something went wrong on reconstructing states from variable association list"
25
24
# `fullvars[i]` needs to be not a `D(...)`, because we want the DAE to be
26
25
# first-order.
27
26
if isdifferential (vi)
28
- vi = out_vars[i ] = diff2term (vi)
27
+ vi = out_vars[varidx ] = diff2term (vi)
29
28
end
30
- out_vars[v ] = D (vi)
29
+ out_vars[diff ] = D (vi)
31
30
end
32
31
33
32
d_dict = Dict (zip (fullvars, 1 : length (fullvars)))
34
33
lhss = Set {Any} ([x. lhs for x in in_eqs if isdiffeq (x)])
35
- for (i, e) in enumerate (eqassoc)
36
- if e === 0
37
- continue
38
- end
39
- # LHS variable is looked up from varassoc
40
- # the varassoc[i]-th variable is the differentiated version of var at i
41
- eq = out_eqs[i]
34
+ for (eqidx, diff) in edges (eq_to_diff)
35
+ # LHS variable is looked up from var_to_diff
36
+ # the var_to_diff[i]-th variable is the differentiated version of var at i
37
+ eq = out_eqs[eqidx]
42
38
lhs = if ! (eq. lhs isa Symbolic)
43
39
0
44
40
elseif isdiffeq (eq)
@@ -58,7 +54,7 @@ function pantelides_reassemble(sys::ODESystem, eqassoc, assign)
58
54
rhs = ModelingToolkit. expand_derivatives (D (eq. rhs))
59
55
substitution_dict = Dict (x. lhs => x. rhs for x in out_eqs if x != = nothing && x. lhs isa Symbolic)
60
56
sub_rhs = substitute (rhs, substitution_dict)
61
- out_eqs[e ] = lhs ~ sub_rhs
57
+ out_eqs[diff ] = lhs ~ sub_rhs
62
58
end
63
59
64
60
final_vars = unique (filter (x-> ! (operation (x) isa Differential), fullvars))
@@ -78,16 +74,18 @@ Perform Pantelides algorithm.
78
74
function pantelides! (sys:: ODESystem ; maxiters = 8000 )
79
75
s = structure (sys)
80
76
# D(j) = assoc[j]
81
- @unpack graph, fullvars, varassoc = s
82
- iv = get_iv (sys)
77
+ @unpack graph, var_to_diff = s
78
+ return (sys, pantelides! (graph, var_to_diff)... )
79
+ end
80
+
81
+ function pantelides! (graph, var_to_diff; maxiters = 8000 )
83
82
neqs = nsrcs (graph)
84
- nvars = length (varassoc )
83
+ nvars = nv (var_to_diff )
85
84
vcolor = falses (nvars)
86
85
ecolor = falses (neqs)
87
- assign = Union{Unassigned, Int}[unassigned for _ = 1 : nvars]
88
- eqassoc = fill ( 0 , neqs)
86
+ var_eq_matching = Matching ( nvars)
87
+ eq_to_diff = DiffGraph ( neqs)
89
88
neqs′ = neqs
90
- D = Differential (iv)
91
89
for k in 1 : neqs′
92
90
eq′ = k
93
91
pathfound = false
@@ -98,46 +96,46 @@ function pantelides!(sys::ODESystem; maxiters = 8000)
98
96
#
99
97
# the derivatives and algebraic variables are zeros in the variable
100
98
# association list
101
- varwhitelist = varassoc .== 0
99
+ varwhitelist = var_to_diff .== nothing
102
100
resize! (vcolor, nvars)
103
101
fill! (vcolor, false )
104
102
resize! (ecolor, neqs)
105
103
fill! (ecolor, false )
106
- pathfound = find_augmenting_path (graph, eq′, assign , varwhitelist, vcolor, ecolor)
104
+ pathfound = find_augmenting_path (graph, eq′, var_eq_matching , varwhitelist, vcolor, ecolor)
107
105
pathfound && break # terminating condition
108
106
for var in eachindex (vcolor); vcolor[var] || continue
109
107
# introduce a new variable
110
108
nvars += 1
111
109
add_vertex! (graph, DST)
112
110
# the new variable is the derivative of `var`
113
- varassoc[var] = nvars
114
- push! (varassoc, 0 )
115
- push! (assign , unassigned)
111
+
112
+ add_edge! (var_to_diff, var, add_vertex! (var_to_diff) )
113
+ push! (var_eq_matching , unassigned)
116
114
end
117
115
118
116
for eq in eachindex (ecolor); ecolor[eq] || continue
119
117
# introduce a new equation
120
118
neqs += 1
121
119
add_vertex! (graph, SRC)
122
120
# the new equation is created by differentiating `eq`
123
- eqassoc[eq] = neqs
121
+ eq_diff = add_vertex! (eq_to_diff)
122
+ add_edge! (eq_to_diff, eq, eq_diff)
124
123
for var in 𝑠neighbors (graph, eq)
125
- add_edge! (graph, neqs , var)
126
- add_edge! (graph, neqs, varassoc [var])
124
+ add_edge! (graph, eq_diff , var)
125
+ add_edge! (graph, eq_diff, var_to_diff [var])
127
126
end
128
- push! (eqassoc, 0 )
129
127
end
130
128
131
129
for var in eachindex (vcolor); vcolor[var] || continue
132
130
# the newly introduced `var`s and `eq`s have the inherits
133
131
# assignment
134
- assign[varassoc [var]] = eqassoc[assign [var]]
132
+ var_eq_matching[var_to_diff [var]] = eq_to_diff[var_eq_matching [var]]
135
133
end
136
- eq′ = eqassoc [eq′]
134
+ eq′ = eq_to_diff [eq′]
137
135
end # for _ in 1:maxiters
138
136
pathfound || error (" maxiters=$maxiters reached! File a bug report if your system has a reasonable index (<100), and you are using the default `maxiters`. Try to increase the maxiters by `pantelides(sys::ODESystem; maxiters=1_000_000)` if your system has an incredibly high index and it is truly extremely large." )
139
137
end # for k in 1:neqs′
140
- return sys, assign, eqassoc
138
+ return var_eq_matching, eq_to_diff
141
139
end
142
140
143
141
"""
@@ -150,6 +148,6 @@ instead, which calls this function internally.
150
148
function dae_index_lowering (sys:: ODESystem ; kwargs... )
151
149
s = get_structure (sys)
152
150
(s isa SystemStructure) || (sys = initialize_system_structure (sys))
153
- sys, assign, eqassoc = pantelides! (sys; kwargs... )
154
- return pantelides_reassemble (sys, eqassoc, assign )
151
+ sys, var_eq_matching, eq_to_diff = pantelides! (sys; kwargs... )
152
+ return pantelides_reassemble (sys, eq_to_diff, var_eq_matching )
155
153
end
0 commit comments