@@ -134,7 +134,7 @@ function substitute_vars!(graph::BipartiteGraph, subs, cache = Int[], callback!
134
134
graph
135
135
end
136
136
137
- function to_mass_matrix_form (neweqs, ieq, graph, fullvars, isdervar:: F ) where F
137
+ function to_mass_matrix_form (neweqs, ieq, graph, fullvars, isdervar:: F , var_to_diff ) where F
138
138
eq = neweqs[ieq]
139
139
if ! (eq. lhs isa Number && eq. lhs == 0 )
140
140
eq = 0 ~ eq. rhs - eq. lhs
@@ -153,16 +153,16 @@ function to_mass_matrix_form(neweqs, ieq, graph, fullvars, isdervar::F) where F
153
153
dervar = var
154
154
end
155
155
end
156
- dervar === nothing && return 0 ~ rhs
156
+ dervar === nothing && return ( 0 ~ rhs), dervar
157
157
new_lhs = var = fullvars[dervar]
158
158
# 0 ~ a * D(x) + b
159
159
# D(x) ~ -b/a
160
160
a, b, islinear = linear_expansion (rhs, var)
161
161
if ! islinear
162
- return 0 ~ rhs
162
+ return ( 0 ~ rhs), nothing
163
163
end
164
164
new_rhs = - b / a
165
- return new_lhs ~ new_rhs
165
+ return ( new_lhs ~ new_rhs), invview (var_to_diff)[dervar]
166
166
else # a number
167
167
if abs (rhs) > 100 eps (float (rhs))
168
168
@warn " The equation $eq is not consistent. It simplifed to 0 == $rhs ."
@@ -423,24 +423,16 @@ function tearing_reassemble(state::TearingState, var_eq_matching; simplify = fal
423
423
empty! (subs)
424
424
end
425
425
426
- diffeq_idxs = BitSet ()
427
- final_eqs = Equation[]
428
- var_rename = zeros (Int, length (var_eq_matching))
426
+ diffeq_idxs = Int[]
427
+ algeeq_idxs = Int[]
428
+ diff_eqs = Equation[]
429
+ alge_eqs = Equation[]
430
+ diff_vars = Int[]
429
431
subeqs = Equation[]
430
432
solved_equations = Int[]
431
433
solved_variables = Int[]
432
434
idx = 0
433
435
# Solve solvable equations
434
- for (iv, ieq) in enumerate (var_eq_matching)
435
- if is_solvable (ieq, iv)
436
- if isdervar (iv)
437
- var_rename[iv] = (idx += 1 )
438
- end
439
- var_rename[iv] = - 1
440
- else
441
- var_rename[iv] = (idx += 1 )
442
- end
443
- end
444
436
neqs = nsrcs (graph)
445
437
for (ieq, iv) in enumerate (invview (var_eq_matching))
446
438
ieq > neqs && break
@@ -450,14 +442,17 @@ function tearing_reassemble(state::TearingState, var_eq_matching; simplify = fal
450
442
# We cannot solve the differential variable like D(x)
451
443
if isdervar (iv)
452
444
# TODO : what if `to_mass_matrix_form(ieq)` returns `nothing`?
453
- push! (final_eqs, to_mass_matrix_form (neweqs, ieq, graph, fullvars, isdervar))
445
+ eq, diffidx = to_mass_matrix_form (neweqs, ieq, graph, fullvars, isdervar, var_to_diff)
446
+ push! (diff_eqs, eq)
454
447
push! (diffeq_idxs, ieq)
448
+ push! (diff_vars, diffidx)
455
449
continue
456
450
end
457
451
eq = neweqs[ieq]
458
452
var = fullvars[iv]
459
453
residual = eq. lhs - eq. rhs
460
454
a, b, islinear = linear_expansion (residual, var)
455
+ @assert islinear
461
456
# 0 ~ a * var + b
462
457
# var ~ -b/a
463
458
if ModelingToolkit. _iszero (a)
@@ -471,11 +466,30 @@ function tearing_reassemble(state::TearingState, var_eq_matching; simplify = fal
471
466
push! (solved_variables, iv)
472
467
end
473
468
else
474
- push! (final_eqs, to_mass_matrix_form (neweqs, ieq, graph, fullvars, isdervar))
469
+ eq, diffidx = to_mass_matrix_form (neweqs, ieq, graph, fullvars, isdervar, var_to_diff)
470
+ if diffidx === nothing
471
+ push! (alge_eqs, eq)
472
+ push! (algeeq_idxs, ieq)
473
+ else
474
+ push! (diff_eqs, eq)
475
+ push! (diffeq_idxs, ieq)
476
+ push! (diff_vars, diffidx)
477
+ end
475
478
end
476
479
end
477
480
# TODO : BLT sorting
478
- neweqs = final_eqs
481
+ neweqs = [diff_eqs; alge_eqs]
482
+ eqsperm = [diffeq_idxs; algeeq_idxs]
483
+ diff_vars_set = BitSet (diff_vars)
484
+ if length (diff_vars_set) != length (diff_vars)
485
+ error (" Tearing internal error: lowering DAE into semi-implicit ODE failed!" )
486
+ end
487
+ invvarsperm = [diff_vars; setdiff (setdiff (1 : ndsts (graph), diff_vars_set), BitSet (solved_variables))]
488
+ varsperm = zeros (Int, ndsts (graph))
489
+ for (i, v) in enumerate (invvarsperm)
490
+ varsperm[v] = i
491
+ end
492
+ @show varsperm
479
493
480
494
if isempty (solved_equations)
481
495
deps = Vector{Int}[]
@@ -493,31 +507,28 @@ function tearing_reassemble(state::TearingState, var_eq_matching; simplify = fal
493
507
494
508
# Contract the vertices in the structure graph to make the structure match
495
509
# the new reality of the system we've just created.
496
- #
497
- # TODO : fix ordering and remove equations
498
- graph = contract_variables (graph, var_eq_matching, solved_variables)
510
+ graph = contract_variables (graph, var_eq_matching, varsperm, solved_variables, eqsperm)
499
511
500
512
# Update system
501
- solved_variables_set = BitSet (solved_variables)
502
- active_vars = setdiff! (setdiff! (BitSet (1 : length (fullvars)), solved_variables_set),
503
- removed_vars)
504
- new_var_to_diff = complete (DiffGraph (length (active_vars)))
513
+ new_var_to_diff = complete (DiffGraph (length (invvarsperm)))
505
514
idx = 0
506
515
for (v, d) in enumerate (var_to_diff)
507
- v′ = var_rename [v]
516
+ v′ = varsperm [v]
508
517
(v′ > 0 && d != = nothing ) || continue
509
- d′ = var_rename [d]
518
+ d′ = varsperm [d]
510
519
new_var_to_diff[v′] = d′ > 0 ? d′ : nothing
511
520
end
521
+ var_to_diff = new_var_to_diff
522
+ diff_to_var = invview (var_to_diff)
512
523
513
524
@set! state. structure. graph = graph
514
525
# Note that `eq_to_diff` is not updated
515
- @set! state. structure. var_to_diff = new_var_to_diff
516
- @set! state. fullvars = [v for (i, v) in enumerate ( fullvars) if i in active_vars ]
526
+ @set! state. structure. var_to_diff = var_to_diff
527
+ @set! state. fullvars = fullvars = fullvars[invvarsperm ]
517
528
518
529
sys = state. sys
519
530
@set! sys. eqs = neweqs
520
- @set! sys. states = [fullvars[i] for i in active_vars if diff_to_var[i] === nothing ]
531
+ @set! sys. states = [v for (i, v) in enumerate (fullvars) if diff_to_var[i] === nothing ]
521
532
deleteat! (oldobs, sort! (removed_obs))
522
533
@set! sys. observed = [oldobs; subeqs]
523
534
@set! sys. substitutions = Substitutions (subeqs, deps)
0 commit comments