@@ -175,55 +175,55 @@ function dummy_derivative_graph!(state::TransformationState, jac = nothing;
175
175
dummy_derivative_graph! (state. structure, var_eq_matching, jac, state_priority)
176
176
end
177
177
178
- function compute_diff_level (diff_to_x)
179
- nxs = length (diff_to_x)
180
- xlevel = zeros (Int, nxs)
181
- maxlevel = 0
182
- for i in 1 : nxs
183
- level = 0
184
- x = i
185
- while diff_to_x[x] != = nothing
186
- x = diff_to_x[x]
187
- level += 1
188
- end
189
- maxlevel = max (maxlevel, level)
190
- xlevel[i] = level
191
- end
192
- return xlevel, maxlevel
193
- end
194
-
195
178
function dummy_derivative_graph! (structure:: SystemStructure , var_eq_matching, jac,
196
179
state_priority)
197
180
@unpack eq_to_diff, var_to_diff, graph = structure
198
181
diff_to_eq = invview (eq_to_diff)
199
182
diff_to_var = invview (var_to_diff)
200
183
invgraph = invview (graph)
201
184
202
- eqlevel, _ = compute_diff_level (diff_to_eq)
203
-
204
185
var_sccs = find_var_sccs (graph, var_eq_matching)
205
186
eqcolor = falses (nsrcs (graph))
206
187
dummy_derivatives = Int[]
207
188
col_order = Int[]
208
189
nvars = ndsts (graph)
190
+ eqs = Int[]
191
+ next_eq_idxs = Int[]
192
+ next_var_idxs = Int[]
193
+ new_eqs = Int[]
194
+ new_vars = Int[]
195
+ eqs_set = BitSet ()
209
196
for vars in var_sccs
210
- eqs = [var_eq_matching[var] for var in vars if var_eq_matching[var] != = unassigned]
197
+ empty! (eqs)
198
+ for var in vars
199
+ eq = var_eq_matching[var]
200
+ eq isa Int || continue
201
+ diff_to_eq[eq] === nothing && continue
202
+ push! (eqs, eq)
203
+ end
211
204
isempty (eqs) && continue
212
- maxlevel = maximum (Base. Fix1 (getindex, eqlevel), eqs)
213
- iszero (maxlevel) && continue
214
205
215
206
rank_matching = Matching (nvars)
216
207
isfirst = true
217
- for _ in maxlevel: - 1 : 1
218
- eqs = filter (eq -> diff_to_eq[eq] != = nothing , eqs)
208
+ if jac === nothing
209
+ J = nothing
210
+ else
211
+ _J = jac (eqs, vars)
212
+ # only accecpt small intergers to avoid overflow
213
+ is_all_small_int = all (_J) do x′
214
+ x = unwrap (x′)
215
+ x isa Number || return false
216
+ isinteger (x) && typemin (Int8) <= x <= typemax (Int8)
217
+ end
218
+ J = is_all_small_int ? Int .(unwrap .(_J)) : nothing
219
+ end
220
+ while true
219
221
nrows = length (eqs)
220
222
iszero (nrows) && break
221
- eqs_set = BitSet (eqs)
222
223
223
224
if state_priority != = nothing && isfirst
224
225
sort! (vars, by = state_priority)
225
226
end
226
- isfirst = false
227
227
# TODO : making the algorithm more robust
228
228
# 1. If the Jacobian is a integer matrix, use Bareiss to check
229
229
# linear independence. (done)
@@ -232,14 +232,18 @@ function dummy_derivative_graph!(structure::SystemStructure, var_eq_matching, ja
232
232
# state selection.)
233
233
#
234
234
# 3. If the Jacobian is a polynomial matrix, use Gröbner basis (?)
235
- if jac != = nothing && (_J = jac (eqs, vars); all (x -> unwrap (x) isa Integer, _J))
236
- J = Int .(unwrap .(_J))
235
+ if J != = nothing
236
+ if ! isfirst
237
+ J = J[next_eq_idxs, next_var_idxs]
238
+ end
237
239
N = ModelingToolkit. nullspace (J; col_order) # modifies col_order
238
240
rank = length (col_order) - size (N, 2 )
239
241
for i in 1 : rank
240
242
push! (dummy_derivatives, vars[col_order[i]])
241
243
end
242
244
else
245
+ empty! (eqs_set)
246
+ union! (eqs_set, eqs)
243
247
rank = 0
244
248
for var in vars
245
249
eqcolor .= false
@@ -255,12 +259,39 @@ function dummy_derivative_graph!(structure::SystemStructure, var_eq_matching, ja
255
259
fill! (rank_matching, unassigned)
256
260
end
257
261
if rank != nrows
258
- @warn " The DAE system is structurally singular!"
262
+ @warn " The DAE system is singular!"
259
263
end
260
264
261
265
# prepare the next iteration
262
- eqs = map (eq -> diff_to_eq[eq], eqs)
263
- vars = [diff_to_var[var] for var in vars if diff_to_var[var] != = nothing ]
266
+ if J != = nothing
267
+ empty! (next_eq_idxs)
268
+ empty! (next_var_idxs)
269
+ end
270
+ empty! (new_eqs)
271
+ empty! (new_vars)
272
+ for (i, eq) in enumerate (eqs)
273
+ ∫eq = diff_to_eq[eq]
274
+ # descend by one diff level, but the next iteration of equations
275
+ # must still be differentiated
276
+ ∫eq === nothing && continue
277
+ ∫∫eq = diff_to_eq[∫eq]
278
+ ∫∫eq === nothing && continue
279
+ if J != = nothing
280
+ push! (next_eq_idxs, i)
281
+ end
282
+ push! (new_eqs, ∫eq)
283
+ end
284
+ for (i, var) in enumerate (vars)
285
+ ∫var = diff_to_var[var]
286
+ ∫var === nothing && continue
287
+ if J != = nothing
288
+ push! (next_var_idxs, i)
289
+ end
290
+ push! (new_vars, ∫var)
291
+ end
292
+ eqs, new_eqs = new_eqs, eqs
293
+ vars, new_vars = new_vars, vars
294
+ isfirst = false
264
295
end
265
296
end
266
297
0 commit comments