@@ -237,8 +237,49 @@ function check_diff_graph(var_to_diff, fullvars)
237237end
238238=#
239239
240- function substitute_lower_order! (state:: TearingState )
241-
240+
241+ function substitute_dummy_derivatives! (fullvars, var_to_diff, diff_to_var, var_eq_matching, neweqs)
242+ # Dummy derivatives may determine that some differential variables are
243+ # algebraic variables in disguise. The derivative of such variables are
244+ # called dummy derivatives.
245+
246+ # Step 1:
247+ # Replace derivatives of non-selected unknown variables by dummy derivatives
248+
249+ dummy_sub = Dict ()
250+ for var in 1 : length (fullvars)
251+ dv = var_to_diff[var]
252+ dv === nothing && continue
253+ if var_eq_matching[var] != = SelectedState ()
254+ dd = fullvars[dv]
255+ v_t = setio (diff2term_with_unit (unwrap (dd), unwrap (iv)), false , false )
256+ for eq in 𝑑neighbors (graph, dv)
257+ dummy_sub[dd] = v_t
258+ neweqs[eq] = fast_substitute (neweqs[eq], dd => v_t)
259+ end
260+ fullvars[dv] = v_t
261+ # If we have:
262+ # x -> D(x) -> D(D(x))
263+ # We need to to transform it to:
264+ # x x_t -> D(x_t)
265+ # update the structural information
266+ dx = dv
267+ x_t = v_t
268+ while (ddx = var_to_diff[dx]) != = nothing
269+ dx_t = D (x_t)
270+ for eq in 𝑑neighbors (graph, ddx)
271+ neweqs[eq] = fast_substitute (neweqs[eq], fullvars[ddx] => dx_t)
272+ end
273+ fullvars[ddx] = dx_t
274+ dx = ddx
275+ x_t = dx_t
276+ end
277+ diff_to_var[dv] = nothing
278+ end
279+ end
280+ end
281+
282+ function generate_derivative_variables! ()
242283end
243284
244285# Documenting the differences to structural simplification for discrete systems:
@@ -281,88 +322,50 @@ function tearing_reassemble(state::TearingState, var_eq_matching,
281322 end
282323 end
283324
284- neweqs = collect (equations (state))
285- lower_name = is_only_discrete (state. structure) ? lower_varname_withshift : lower_varname_with_unit
286-
287- # Terminology and Definition:
288- #
289- # A general DAE is in the form of `F(u'(t), u(t), p, t) == 0`. We can
290- # characterize variables in `u(t)` into two classes: differential variables
291- # (denoted `v(t)`) and algebraic variables (denoted `z(t)`). Differential
292- # variables are marked as `SelectedState` and they are differentiated in the
293- # DAE system, i.e. `v'(t)` are all the variables in `u'(t)` that actually
294- # appear in the system. Algebraic variables are variables that are not
295- # differential variables.
296- #
297- # Dummy derivatives may determine that some differential variables are
298- # algebraic variables in disguise. The derivative of such variables are
299- # called dummy derivatives.
300-
301- # Step 1:
302- # Replace derivatives of non-selected unknown variables by dummy derivatives
303-
304325 if ModelingToolkit. has_iv (state. sys)
305326 iv = get_iv (state. sys)
306327 if is_only_discrete (state. structure)
307328 D = Shift (iv, 1 )
329+ lower_name = lower_varname_withshift
330+ idx_to_lowest_shift = Dict {Int, Int} (var => 0 for var in 1 : length (fullvars))
331+ for (i,var) in enumerate (fullvars)
332+ key = (operation (var) isa Shift) ? only (arguments (var)) : var
333+ idx_to_lowest_shift[i] = get (lowest_shift, key, 0 )
334+ end
308335 else
309336 D = Differential (iv)
337+ lower_name = lower_varname_with_unit
310338 end
311339 else
312340 iv = D = nothing
341+ lower_name = lower_varname_with_unit
313342 end
343+
314344 diff_to_var = invview (var_to_diff)
345+ neweqs = collect (equations (state))
315346
316- dummy_sub = Dict ()
317- for var in 1 : length (fullvars)
318- dv = var_to_diff[var]
319- dv === nothing && continue
320- if var_eq_matching[var] != = SelectedState ()
321- dd = fullvars[dv]
322- v_t = setio (diff2term_with_unit (unwrap (dd), unwrap (iv)), false , false )
323- for eq in 𝑑neighbors (graph, dv)
324- dummy_sub[dd] = v_t
325- neweqs[eq] = fast_substitute (neweqs[eq], dd => v_t)
326- end
327- fullvars[dv] = v_t
328- # If we have:
329- # x -> D(x) -> D(D(x))
330- # We need to to transform it to:
331- # x x_t -> D(x_t)
332- # update the structural information
333- dx = dv
334- x_t = v_t
335- while (ddx = var_to_diff[dx]) != = nothing
336- dx_t = D (x_t)
337- for eq in 𝑑neighbors (graph, ddx)
338- neweqs[eq] = fast_substitute (neweqs[eq], fullvars[ddx] => dx_t)
339- end
340- fullvars[ddx] = dx_t
341- dx = ddx
342- x_t = dx_t
343- end
344- diff_to_var[dv] = nothing
345- end
346- end
347+ # Terminology and Definition:
348+ #
349+ # A general DAE is in the form of `F(u'(t), u(t), p, t) == 0`. We can
350+ # characterize variables in `u(t)` into two classes: differential variables
351+ # (denoted `v(t)`) and algebraic variables (denoted `z(t)`). Differential
352+ # variables are marked as `SelectedState` and they are differentiated in the
353+ # DAE system, i.e. `v'(t)` are all the variables in `u'(t)` that actually
354+ # appear in the system. Algebraic variables are variables that are not
355+ # differential variables.
347356
357+ substitute_dummy_derivatives! (fullvars, var_to_diff, diff_to_var, var_eq_matching, neweqs)
358+
348359 # `SelectedState` information is no longer needed past here. State selection
349360 # is done. All non-differentiated variables are algebraic variables, and all
350361 # variables that appear differentiated are differential variables.
351362
352- # ## extract partition information
363+ # ## Extract partition information
353364 is_solvable = let solvable_graph = solvable_graph
354365 (eq, iv) -> eq isa Int && iv isa Int && BipartiteEdge (eq, iv) in solvable_graph
355366 end
356367
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
363- end
364-
365- # if var is like D(x)
368+ # if var is like D(x) or Shift(t, 1)(x)
366369 isdervar = let diff_to_var = diff_to_var
367370 var -> diff_to_var[var] != = nothing
368371 end
0 commit comments