@@ -3,16 +3,49 @@ function tearing_sub(expr, dict, s)
3
3
s ? simplify (expr) : expr
4
4
end
5
5
6
- function tearing_reassemble (sys, var_eq_matching; simplify= false )
6
+ function tearing_reassemble (sys, var_eq_matching, eq_to_diff = nothing ; simplify= false )
7
7
s = structure (sys)
8
- @unpack fullvars, solvable_graph, graph = s
8
+ @unpack fullvars, solvable_graph, var_to_diff, graph = s
9
9
10
10
eqs = equations (sys)
11
11
12
+ # ## Add the differentiated equations and variables
13
+ D = Differential (get_iv (sys))
14
+ if length (fullvars) != length (var_to_diff)
15
+ for i = (length (fullvars)+ 1 ): length (var_to_diff)
16
+ push! (fullvars, D (fullvars[invview (var_to_diff)[i]]))
17
+ end
18
+ end
19
+
20
+ # ## Add the differentiated equations
21
+ neweqs = copy (eqs)
22
+ if eq_to_diff != = nothing
23
+ eq_to_diff = complete (eq_to_diff)
24
+ for i = (length (eqs)+ 1 ): length (eq_to_diff)
25
+ eq = neweqs[invview (eq_to_diff)[i]]
26
+ push! (neweqs, ModelingToolkit. expand_derivatives (0 ~ D (eq. rhs - eq. lhs)))
27
+ end
28
+
29
+ # ## Replace derivatives of non-selected states by dumy derivatives
30
+ dummy_subs = Dict ()
31
+ for var = 1 : length (fullvars)
32
+ invview (var_to_diff)[var] === nothing && continue
33
+ if var_eq_matching[invview (var_to_diff)[var]] != = SelectedState ()
34
+ fullvar = fullvars[var]
35
+ subst_fullvar = tearing_sub (fullvar, dummy_subs, simplify)
36
+ dummy_subs[fullvar] = fullvars[var] = diff2term (unwrap (subst_fullvar))
37
+ var_to_diff[invview (var_to_diff)[var]] = nothing
38
+ end
39
+ end
40
+ neweqs = map (neweqs) do eq
41
+ 0 ~ tearing_sub (eq. rhs - eq. lhs, dummy_subs, simplify)
42
+ end
43
+ end
44
+
12
45
# ## extract partition information
13
46
function solve_equation (ieq, iv)
14
47
var = fullvars[iv]
15
- eq = eqs [ieq]
48
+ eq = neweqs [ieq]
16
49
rhs = value (solve_for (eq, var; simplify= simplify, check= false ))
17
50
18
51
if var in vars (rhs)
@@ -30,7 +63,7 @@ function tearing_reassemble(sys, var_eq_matching; simplify=false)
30
63
end
31
64
var => rhs
32
65
end
33
- is_solvable (eq, iv) = eq != = unassigned && BipartiteEdge (eq, iv) in solvable_graph
66
+ is_solvable (eq, iv) = isa (eq, Int) && BipartiteEdge (eq, iv) in solvable_graph
34
67
35
68
solved_equations = Int[]
36
69
solved_variables = Int[]
@@ -41,32 +74,31 @@ function tearing_reassemble(sys, var_eq_matching; simplify=false)
41
74
push! (solved_equations, ieq); push! (solved_variables, iv)
42
75
end
43
76
77
+ isdiffvar (var) = invview (var_to_diff)[var] != = nothing && var_eq_matching[invview (var_to_diff)[var]] === SelectedState ()
44
78
solved = Dict (solve_equation (ieq, iv) for (ieq, iv) in zip (solved_equations, solved_variables))
45
79
obseqs = [var ~ rhs for (var, rhs) in solved]
46
80
47
81
# Rewrite remaining equations in terms of solved variables
48
82
function substitute_equation (ieq)
49
- eq = eqs[ieq]
50
- if isdiffeq (eq)
51
- return eq. lhs ~ tearing_sub (eq. rhs, solved, simplify)
52
- else
53
- if ! (eq. lhs isa Number && eq. lhs == 0 )
54
- eq = 0 ~ eq. rhs - eq. lhs
55
- end
56
- rhs = tearing_sub (eq. rhs, solved, simplify)
57
- if rhs isa Symbolic
58
- return 0 ~ rhs
59
- else # a number
60
- if abs (rhs) > 100 eps (float (rhs))
61
- @warn " The equation $eq is not consistent. It simplifed to 0 == $rhs ."
62
- end
63
- return nothing
83
+ eq = neweqs[ieq]
84
+ if ! (eq. lhs isa Number && eq. lhs == 0 )
85
+ eq = 0 ~ eq. rhs - eq. lhs
86
+ end
87
+ rhs = tearing_sub (eq. rhs, solved, simplify)
88
+ if rhs isa Symbolic
89
+ return 0 ~ rhs
90
+ else # a number
91
+ if abs (rhs) > 100 eps (float (rhs))
92
+ @warn " The equation $eq is not consistent. It simplifed to 0 == $rhs ."
64
93
end
94
+ return nothing
65
95
end
66
96
end
67
97
68
- neweqs = Any[substitute_equation (ieq) for ieq in 1 : length (eqs) if ! (ieq in solved_equations)]
98
+ diffeqs = [fullvars[iv] ~ tearing_sub (solved[fullvars[iv]], solved, simplify) for iv in solved_variables if isdiffvar (iv)]
99
+ neweqs = Any[substitute_equation (ieq) for ieq in 1 : length (neweqs) if ! (ieq in solved_equations)]
69
100
filter! (! isnothing, neweqs)
101
+ prepend! (neweqs, diffeqs)
70
102
71
103
# Contract the vertices in the structure graph to make the structure match
72
104
# the new reality of the system we've just created.
@@ -78,30 +110,17 @@ function tearing_reassemble(sys, var_eq_matching; simplify=false)
78
110
79
111
@set! s. graph = graph
80
112
@set! s. fullvars = [v for (i, v) in enumerate (fullvars) if i in active_vars]
113
+ @set! s. var_to_diff = DiffGraph (Union{Int, Nothing}[v for (i, v) in enumerate (s. var_to_diff) if i in active_vars])
81
114
@set! s. vartype = [v for (i, v) in enumerate (s. vartype) if i in active_vars]
82
115
@set! s. algeqs = [e for (i, e) in enumerate (s. algeqs) if i in active_eqs]
83
116
84
117
@set! sys. structure = s
85
118
@set! sys. eqs = neweqs
86
- @set! sys. states = [s . fullvars[idx ] for idx in 1 : length (s . fullvars) if ! isdervar (s, idx) ]
119
+ @set! sys. states = [fullvars[i ] for i in active_vars ]
87
120
@set! sys. observed = [observed (sys); obseqs]
88
121
return sys
89
122
end
90
123
91
- """
92
- tearing(sys; simplify=false)
93
-
94
- Tear the nonlinear equations in system. When `simplify=true`, we simplify the
95
- new residual residual equations after tearing. End users are encouraged to call [`structural_simplify`](@ref)
96
- instead, which calls this function internally.
97
- """
98
- function tearing (sys; simplify= false )
99
- sys = init_for_tearing (sys)
100
- var_eq_matching = tear_graph (sys)
101
-
102
- tearing_reassemble (sys, var_eq_matching; simplify= simplify)
103
- end
104
-
105
124
function init_for_tearing (sys)
106
125
s = get_structure (sys)
107
126
if ! (s isa SystemStructure)
119
138
function tear_graph (sys)
120
139
s = structure (sys)
121
140
@unpack graph, solvable_graph = s
122
- tear_graph_modia (graph, solvable_graph;
123
- varfilter= var-> isalgvar (s, var), eqfilter= eq-> s. algeqs[eq])
141
+ var_eq_matching = Matching {Union{Unassigned, SelectedState}} (tear_graph_modia (graph, solvable_graph;
142
+ varfilter= var-> isalgvar (s, var), eqfilter= eq-> s. algeqs[eq]))
143
+ for var in 1 : ndsts (graph)
144
+ if ! isalgvar (s, var)
145
+ var_eq_matching[var] = SelectedState ()
146
+ end
147
+ end
148
+ var_eq_matching
149
+ end
150
+
151
+ """
152
+ tearing(sys; simplify=false)
153
+
154
+ Tear the nonlinear equations in system. When `simplify=true`, we simplify the
155
+ new residual residual equations after tearing. End users are encouraged to call [`structural_simplify`](@ref)
156
+ instead, which calls this function internally.
157
+ """
158
+ function tearing (sys; simplify= false )
159
+ sys = init_for_tearing (sys)
160
+ var_eq_matching = tear_graph (sys)
161
+
162
+ tearing_reassemble (sys, var_eq_matching; simplify= simplify)
163
+ end
164
+
165
+ """
166
+ tearing(sys; simplify=false)
167
+
168
+ Perform partial state selection and tearing.
169
+ """
170
+ function partial_state_selection (sys; simplify= false )
171
+ sys = init_for_tearing (sys)
172
+ sys, var_eq_matching, eq_to_diff = partial_state_selection_graph! (sys)
173
+
174
+ tearing_reassemble (sys, var_eq_matching, eq_to_diff; simplify= simplify)
124
175
end
0 commit comments