@@ -19,186 +19,6 @@ function tear_graph(sys)
19
19
return sys
20
20
end
21
21
22
- function tearing_sub (expr, dict, s)
23
- expr = ModelingToolkit. fixpoint_sub (expr, dict)
24
- s ? simplify (expr) : expr
25
- end
26
-
27
- function tearing_reassemble (sys; simplify= false )
28
- s = structure (sys)
29
- @unpack fullvars, partitions, var_eq_matching, graph, scc = s
30
- eqs = equations (sys)
31
-
32
- # ## extract partition information
33
- rhss = []
34
- solvars = []
35
- ns, nd = nsrcs (graph), ndsts (graph)
36
- active_eqs = trues (ns)
37
- active_vars = trues (nd)
38
- rvar2reqs = Vector {Vector{Int}} (undef, nd)
39
- # reduction_graph = BipartiteGraph(nsrcs(graph), ndsts(graph), Val(false))
40
- for (ith_scc, partition) in enumerate (partitions)
41
- @unpack e_solved, v_solved, e_residual, v_residual = partition
42
- for ii in eachindex (e_solved)
43
- ieq = e_solved[ii]; ns -= 1
44
- iv = v_solved[ii]; nd -= 1
45
- rvar2reqs[iv] = e_solved
46
-
47
- active_eqs[ieq] = false
48
- active_vars[iv] = false
49
-
50
- eq = eqs[ieq]
51
- var = fullvars[iv]
52
- rhs = value (solve_for (eq, var; simplify= simplify, check= false ))
53
- # if we don't simplify the rhs and the `eq` is not solved properly
54
- (! simplify && occursin (rhs, var)) && (rhs = SymbolicUtils. polynormalize (rhs))
55
- # Since we know `eq` is linear wrt `var`, so the round off must be a
56
- # linear term. We can correct the round off error by a linear
57
- # correction.
58
- rhs -= expand_derivatives (Differential (var)(rhs))* var
59
- @assert ! (var in vars (rhs)) """
60
- When solving
61
- $eq
62
- $var remainded in
63
- $rhs .
64
- """
65
- push! (rhss, rhs)
66
- push! (solvars, var)
67
- end
68
- # DEBUG:
69
- # @show ith_scc solvars .~ rhss
70
- # Main._nlsys[] = eqs[e_solved], fullvars[v_solved]
71
- # ModelingToolkit.topsort_equations(solvars .~ rhss, fullvars)
72
- # empty!(solvars); empty!(rhss)
73
- end
74
-
75
- # ## update SCC
76
- eq_reidx = Vector {Int} (undef, nsrcs (graph))
77
- idx = 0
78
- for (i, active) in enumerate (active_eqs)
79
- eq_reidx[i] = active ? (idx += 1 ) : - 1
80
- end
81
-
82
- rmidxs = Int[]
83
- newscc = Vector{Int}[]; sizehint! (newscc, length (scc))
84
- for component′ in newscc
85
- component = copy (component′)
86
- for (idx, eq) in enumerate (component)
87
- if active_eqs[eq]
88
- component[idx] = eq_reidx[eq]
89
- else
90
- push! (rmidxs, idx)
91
- end
92
- end
93
- push! (newscc, component)
94
- deleteat! (component, rmidxs)
95
- empty! (rmidxs)
96
- end
97
-
98
- # ## update graph
99
- var_reidx = Vector {Int} (undef, ndsts (graph))
100
- idx = 0
101
- for (i, active) in enumerate (active_vars)
102
- var_reidx[i] = active ? (idx += 1 ) : - 1
103
- end
104
-
105
- newgraph = BipartiteGraph (ns, nd, Val (false ))
106
-
107
-
108
- # ## update equations
109
- odestats = []
110
- for idx in eachindex (fullvars); isdervar (s, idx) && continue
111
- push! (odestats, fullvars[idx])
112
- end
113
- newstates = setdiff (odestats, solvars)
114
- varidxmap = Dict (newstates .=> 1 : length (newstates))
115
- neweqs = Vector {Equation} (undef, ns)
116
- newalgeqs = falses (ns)
117
-
118
- dict = Dict (value .(solvars) .=> value .(rhss))
119
-
120
- visited = falses (ndsts (graph))
121
- for ieq in Iterators. flatten (scc); active_eqs[ieq] || continue
122
- eq = eqs[ieq]
123
- ridx = eq_reidx[ieq]
124
-
125
- fill! (visited, false )
126
- compact_graph! (newgraph, graph, visited, ieq, ridx, rvar2reqs, var_reidx, active_vars)
127
-
128
- if isdiffeq (eq)
129
- neweqs[ridx] = eq. lhs ~ tearing_sub (eq. rhs, dict, simplify)
130
- else
131
- newalgeqs[ridx] = true
132
- if ! (eq. lhs isa Number && eq. lhs != 0 )
133
- eq = 0 ~ eq. rhs - eq. lhs
134
- end
135
- rhs = tearing_sub (eq. rhs, dict, simplify)
136
- if rhs isa Symbolic
137
- neweqs[ridx] = 0 ~ rhs
138
- else # a number
139
- if abs (rhs) > 100 eps (float (rhs))
140
- @warn " The equation $eq is not consistent. It simplifed to 0 == $rhs ."
141
- end
142
- neweqs[ridx] = 0 ~ fullvars[invview (var_eq_matching)[ieq]]
143
- end
144
- end
145
- end
146
-
147
- # ## update partitions
148
- newpartitions = similar (partitions, 0 )
149
- emptyintvec = Int[]
150
- for (ii, partition) in enumerate (partitions)
151
- @unpack e_residual, v_residual = partition
152
- isempty (v_residual) && continue
153
- new_e_residual = similar (e_residual)
154
- new_v_residual = similar (v_residual)
155
- for ii in eachindex (e_residual)
156
- new_e_residual[ii] = eq_reidx[ e_residual[ii]]
157
- new_v_residual[ii] = var_reidx[v_residual[ii]]
158
- end
159
- # `emptyintvec` is aliased to save memory
160
- # We need them for type stability
161
- newpart = SystemPartition (emptyintvec, emptyintvec, new_e_residual, new_v_residual)
162
- push! (newpartitions, newpart)
163
- end
164
-
165
- obseqs = solvars .~ rhss
166
-
167
- @set! s. graph = newgraph
168
- @set! s. scc = newscc
169
- @set! s. fullvars = fullvars[active_vars]
170
- @set! s. vartype = s. vartype[active_vars]
171
- @set! s. partitions = newpartitions
172
- @set! s. algeqs = newalgeqs
173
-
174
- @set! sys. structure = s
175
- @set! sys. eqs = neweqs
176
- @set! sys. states = newstates
177
- @set! sys. observed = [observed (sys); obseqs]
178
- return sys
179
- end
180
-
181
- # removes the solved equations and variables
182
- function compact_graph! (newgraph, graph, visited, eq, req, rvar2reqs, var_reidx, active_vars)
183
- for ivar in 𝑠neighbors (graph, eq)
184
- # Note that we need to check `ii` against the rhs states to make
185
- # sure we don't run in circles.
186
- visited[ivar] && continue
187
- visited[ivar] = true
188
-
189
- if active_vars[ivar]
190
- add_edge! (newgraph, req, var_reidx[ivar])
191
- else
192
- # If a state is reduced, then we go to the rhs and collect
193
- # its states.
194
- for ieq in rvar2reqs[ivar]
195
- compact_graph! (newgraph, graph, visited, ieq, req, rvar2reqs, var_reidx, active_vars)
196
- end
197
- end
198
- end
199
- return nothing
200
- end
201
-
202
22
"""
203
23
algebraic_equations_scc(sys)
204
24
@@ -220,12 +40,3 @@ function algebraic_equations_scc(sys)
220
40
@set! sys. structure. scc = components
221
41
return sys
222
42
end
223
-
224
- """
225
- tearing(sys; simplify=false)
226
-
227
- Tear the nonlinear equations in system. When `simplify=true`, we simplify the
228
- new residual residual equations after tearing. End users are encouraged to call [`structural_simplify`](@ref)
229
- instead, which calls this function internally.
230
- """
231
- tearing (sys; simplify= false ) = tearing_reassemble (tear_graph (algebraic_equations_scc (sys)); simplify= simplify)
0 commit comments