@@ -241,6 +241,32 @@ function substitute_lower_order!(state::TearingState)
241
241
242
242
end
243
243
244
+ # Documenting the differences to structural simplification for discrete systems:
245
+ # In discrete systems the lowest-order term is x_k-i, instead of x(t). In order
246
+ # to substitute dummy variables for x_k-1, x_k-2, ... instead you need to reverse
247
+ # the order. So for discrete systems `var_order` is defined a little differently.
248
+ #
249
+ # The orders will also be off by one. The reason this is is that the dynamics of
250
+ # the system should be given in terms of Shift(t, 1)(x(t), x(t-1), ...). But
251
+ # having the observables be indexed by the next time step is not so nice. So we
252
+ # handle the shifts in the renaming, rather than explicitly.
253
+ #
254
+ # The substitution should look like the following:
255
+ # x(t) -> Shift(t, 1)(x(t))
256
+ # x(k-1) -> x(t)
257
+ # x(k-2) -> x_{t-1}(t)
258
+ # x(k-3) -> x_{t-2}(t)
259
+ # and so on...
260
+ #
261
+ # In the implicit discrete case this shouldn't happen. The simplification should
262
+ # look like a NonlinearSystem.
263
+ #
264
+ # For discrete systems Shift(t, 2)(x(t)) is not equivalent to Shift(t, 1)(Shift(t,1)(x(t))
265
+ # This is different from the continuous case where D(D(x)) can be substituted for
266
+ # by iteratively substituting x_t ~ D(x), then x_tt ~ D(x_t). For this reason the
267
+ # total_sub dict is updated at the time that the renamed variables are written,
268
+ # inside the loop where new variables are generated.
269
+
244
270
import ModelingToolkit: Shift
245
271
function tearing_reassemble (state:: TearingState , var_eq_matching,
246
272
full_var_eq_matching = nothing ; simplify = false , mm = nothing , cse_hack = true , array_hack = true )
@@ -318,9 +344,6 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
318
344
diff_to_var[dv] = nothing
319
345
end
320
346
end
321
- @show var_eq_matching
322
-
323
- println (" Post state selection." )
324
347
325
348
# `SelectedState` information is no longer needed past here. State selection
326
349
# is done. All non-differentiated variables are algebraic variables, and all
@@ -330,26 +353,27 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
330
353
is_solvable = let solvable_graph = solvable_graph
331
354
(eq, iv) -> eq isa Int && iv isa Int && BipartiteEdge (eq, iv) in solvable_graph
332
355
end
333
- idx_to_lowest_shift = Dict {Int, Int} (var => 0 for var in 1 : length (fullvars))
334
- for (i,var) in enumerate (fullvars)
335
- key = (operation (var) isa Shift) ? only (arguments (var)) : var
336
- idx_to_lowest_shift[i] = get (lowest_shift, key, 0 )
356
+
357
+ if is_only_discrete (state. structure)
358
+ idx_to_lowest_shift = Dict {Int, Int} (var => 0 for var in 1 : length (fullvars))
359
+ for (i,var) in enumerate (fullvars)
360
+ key = (operation (var) isa Shift) ? only (arguments (var)) : var
361
+ idx_to_lowest_shift[i] = get (lowest_shift, key, 0 )
362
+ end
337
363
end
338
364
339
365
# if var is like D(x)
340
366
isdervar = let diff_to_var = diff_to_var
341
367
var -> diff_to_var[var] != = nothing
342
368
end
343
- # For discrete variables, we want the substitution to turn
344
- # Shift(t, k)(x(t)) => x_t-k(t)
345
369
var_order = let diff_to_var = diff_to_var
346
370
dv -> begin
347
371
order = 0
348
372
while (dv′ = diff_to_var[dv]) != = nothing
349
373
order += 1
350
374
dv = dv′
351
375
end
352
- is_only_discrete (state. structure) && (order = - idx_to_lowest_shift[dv] - order - 1 )
376
+ is_only_discrete (state. structure) && (order = - idx_to_lowest_shift[dv] - order)
353
377
order, dv
354
378
end
355
379
end
@@ -403,6 +427,7 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
403
427
linear_eqs = mm === nothing ? Dict {Int, Int} () :
404
428
Dict (reverse (en) for en in enumerate (mm. nzrows))
405
429
430
+ total_sub = Dict ()
406
431
for v in 1 : length (var_to_diff)
407
432
is_highest_discrete = begin
408
433
var = fullvars[v]
@@ -442,8 +467,13 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
442
467
end
443
468
dx = fullvars[dv]
444
469
# add `x_t`
445
- order, lv = var_order (dv)
470
+ println ()
471
+ @show order, lv = var_order (dv)
446
472
x_t = lower_name (fullvars[lv], iv, order)
473
+ @show fullvars[v]
474
+ @show fullvars[dv]
475
+ @show fullvars[lv]
476
+ @show dx, x_t
447
477
push! (fullvars, simplify_shifts (x_t))
448
478
v_t = length (fullvars)
449
479
v_t_idx = add_vertex! (var_to_diff)
@@ -466,11 +496,16 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
466
496
add_edge! (solvable_graph, dummy_eq, dv)
467
497
@assert nsrcs (graph) == nsrcs (solvable_graph) == dummy_eq
468
498
@label FOUND_DUMMY_EQ
469
- is_only_discrete (state. structure) && (idx_to_lowest_shift[v_t] = idx_to_lowest_shift[dv])
499
+ is_only_discrete (state. structure) && begin
500
+ idx_to_lowest_shift[v_t] = idx_to_lowest_shift[dv]
501
+ operation (dx) isa Shift && (total_sub[dx] = x_t)
502
+ order == 1 && (total_sub[x_t] = fullvars[var_to_diff[dv]])
503
+ end
470
504
var_to_diff[v_t] = var_to_diff[dv]
471
505
var_eq_matching[dv] = unassigned
472
506
eq_var_matching[dummy_eq] = dv
473
507
end
508
+ @show total_sub
474
509
475
510
# Will reorder equations and unknowns to be:
476
511
# [diffeqs; ...]
@@ -490,15 +525,13 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
490
525
# Solve solvable equations
491
526
println ()
492
527
println (" SOLVING SOLVABLE EQUATIONS." )
493
- @show eq_var_matching
494
528
toporder = topological_sort (DiCMOBiGraph {false} (graph, var_eq_matching))
495
529
eqs = Iterators. reverse (toporder)
496
- @show eqs
497
- @show neweqs
498
- @show fullvars
499
- total_sub = Dict ()
500
530
idep = iv
531
+ @show eq_var_matching
532
+
501
533
for ieq in eqs
534
+ println ()
502
535
iv = eq_var_matching[ieq]
503
536
if is_solvable (ieq, iv)
504
537
# We don't solve differential equations, but we will need to try to
@@ -513,7 +546,6 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
513
546
dx = D (simplify_shifts (lower_name (
514
547
fullvars[lv], idep, order - 1 )))
515
548
@show dx
516
- @show neweqs[ieq]
517
549
eq = dx ~ simplify_shifts (Symbolics. fixpoint_sub (
518
550
Symbolics. symbolic_linear_solve (neweqs[ieq],
519
551
fullvars[iv]),
0 commit comments