@@ -126,49 +126,6 @@ isstreamconnection(c::Connection) = any(isstreamconnector, c.inners) || any(isst
126
126
127
127
print_with_indent (n, x) = println (" " ^ n, x)
128
128
129
- function get_stream_connectors! (sc, sys:: AbstractSystem )
130
- subsys = get_systems (sys)
131
- isempty (subsys) && return nothing
132
- for s in subsys; isstreamconnector (s) || continue
133
- push! (sc, renamespace (sys, s))
134
- end
135
- for s in subsys
136
- get_stream_connectors! (sc, renamespace (sys, s))
137
- end
138
- nothing
139
- end
140
-
141
- collect_instream! (set, eq:: Equation ) = collect_instream! (set, eq. lhs) | collect_instream! (set, eq. rhs)
142
-
143
- function collect_instream! (set, expr, occurs= false )
144
- istree (expr) || return occurs
145
- op = operation (expr)
146
- op === instream && (push! (set, expr); occurs = true )
147
- for a in SymbolicUtils. unsorted_arguments (expr)
148
- occurs |= collect_instream! (set, a, occurs)
149
- end
150
- return occurs
151
- end
152
-
153
- function split_var (var)
154
- name = string (nameof (var))
155
- map (Symbol, split (name, ' ₊' ))
156
- end
157
-
158
- # inclusive means the first level of `var` is `sys`
159
- function get_sys_var (sys:: AbstractSystem , var; inclusive= true )
160
- lvs = split_var (var)
161
- if inclusive
162
- sysn, lvs = Iterator. peel (lvs)
163
- sysn === nameof (sys) || error (" $(nameof (sys)) doesn't have $var! " )
164
- end
165
- newsys = getproperty (sys, first (lvs))
166
- for i in 2 : length (lvs)- 1
167
- newsys = getproperty (newsys, lvs[i])
168
- end
169
- newsys, lvs[end ]
170
- end
171
-
172
129
function split_sys_var (var)
173
130
var_name = string (getname (var))
174
131
sidx = findlast (isequal (' ₊' ), var_name)
@@ -187,209 +144,26 @@ function flowvar(sys::AbstractSystem)
187
144
error (" There in no flow variable in $(nameof (sys)) " )
188
145
end
189
146
190
- positivemax (m, :: Any ; tol= nothing )= max (m, something (tol, 1e-8 ))
191
-
192
- #=
193
- function find_connection(connector_name, ogsys, names)
194
- cs = get_connections(ogsys)
195
- cs === nothing || for c in cs
196
- renamespace(names, connector_name) in c && return names, c
197
- end
198
- innersys = ogsys
199
- for (i, n) in enumerate(names)
200
- innersys = getproperty(innersys, n)
201
- cs = get_connections(innersys)
202
- cs === nothing || for c in cs
203
- nn = @view names[i+1:end]
204
- renamespace(nn, connector_name) in c && return nn, c
205
- end
206
- end
207
- error("$connector_name cannot be found in $(nameof(ogsys)) with levels $(names)")
208
- end
209
-
210
- function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false, tol=nothing)
211
- subsys = get_systems(sys)
212
- isempty(subsys) && return sys
213
-
214
- # post order traversal
215
- @set! sys.systems = map(subsys) do s
216
- n = nameof(s)
217
- expand_instream(ogsys, s, [names; n], debug=debug)
218
- end
219
-
220
- sys = flatten(sys)
221
- eqs′ = get_eqs(sys)
222
- eqs = Equation[]
223
- instream_eqs = Equation[]
224
- instream_exprs = Set()
225
- for eq in eqs′
226
- if collect_instream!(instream_exprs, eq)
227
- push!(instream_eqs, eq)
228
- else
229
- push!(eqs, eq) # split instreams and equations
230
- end
231
- end
232
- #@show nameof(sys), names, instream_exprs
233
- isempty(instream_eqs) && return sys
234
-
235
- sub = Dict()
236
- seen = Set()
237
- #additional_eqs = Equation[]
238
- for ex in instream_exprs
239
- var = only(arguments(ex))
240
- connector_name, streamvar_name = split_sys_var(var)
241
-
242
- # find the connect
243
- connect_namespaces, connect = find_connection(connector_name, ogsys, names)
244
- connectors = Iterators.flatten((connect.inners, connect.outers))
245
- # stream variable
246
- sv = getproperty(first(connectors), streamvar_name; namespace=false)
247
- if connect_namespaces !== names
248
- inner_sc = []
249
- for s in connectors
250
- push!(inner_sc, s)
251
- end
252
- outer_sc = []
253
- else
254
- inner_sc = connect.inners
255
- outer_sc = connect.outers
256
- end
257
-
258
- n_outers = length(outer_sc)
259
- n_inners = length(inner_sc)
260
- outer_names = (nameof(s) for s in outer_sc)
261
- inner_names = (nameof(s) for s in inner_sc)
262
- if debug
263
- @show connect_namespaces
264
- println("Expanding: $ex")
265
- isempty(inner_names) || println("Inner connectors: $(collect(inner_names))")
266
- isempty(outer_names) || println("Outer connectors: $(collect(outer_names))")
267
- end
268
-
269
- cn = renamespace(connect_namespaces, connector_name)
270
- # expand `instream`s
271
- # https://specification.modelica.org/v3.4/Ch15.html
272
- # Based on the above requirements, the following implementation is
273
- # recommended:
274
- if n_inners == 1 && n_outers == 0
275
- cn === only(inner_names) || error("$var is not in any stream connector of $(nameof(ogsys))")
276
- sub[ex] = var
277
- elseif n_inners == 2 && n_outers == 0
278
- @info names cn collect(inner_names) length(inner_sc)
279
- cn in inner_names || error("$var is not in any stream connector of $(nameof(ogsys))")
280
- idx = findfirst(c->nameof(c) === cn, inner_sc)
281
- other = idx == 1 ? 2 : 1
282
- sub[ex] = states(inner_sc[other], sv)
283
- elseif n_inners == 1 && n_outers == 1
284
- isinner = cn === only(inner_names)
285
- isouter = cn === only(outer_names)
286
- (isinner || isouter) || error("$var is not in any stream connector of $(nameof(ogsys))")
287
- if isinner
288
- outerinstream = states(only(outer_sc), sv) # c_1.h_outflow
289
- sub[ex] = outerinstream
290
- end
291
- if var in seen
292
- #push!(additional_eqs, outerinstream ~ var)
293
- push!(seen, var)
294
- end
295
- elseif n_inners == 0 && n_outers == 2
296
- # we don't expand `instream` in this case.
297
- #=
298
- if var in seen
299
- v1 = states(outer_sc[1], sv)
300
- v2 = states(outer_sc[2], sv)
301
- push!(additional_eqs, v1 ~ instream(v2))
302
- push!(additional_eqs, v2 ~ instream(v1))
303
- push!(seen, var)
304
- end
305
- =#
306
- else
307
- fv = flowvar(first(connectors))
308
- idx = findfirst(c->nameof(c) === cn, inner_sc)
309
- if idx !== nothing
310
- si = sum(s->max(states(s, fv), 0), outer_sc)
311
- for j in 1:n_inners; j == i && continue
312
- f = states(inner_sc[j], fv)
313
- si += max(-f, 0)
314
- end
315
-
316
- num = 0
317
- den = 0
318
- for j in 1:n_inners; j == i && continue
319
- f = states(inner_sc[j], fv)
320
- tmp = positivemax(-f, si; tol=tol)
321
- den += tmp
322
- num += tmp * states(inner_sc[j], sv)
323
- end
324
- for k in 1:n_outers
325
- f = states(outer_sc[k], fv)
326
- tmp = positivemax(f, si; tol=tol)
327
- den += tmp
328
- num += tmp * instream(states(outer_sc[k], sv))
329
- end
330
- sub[ex] = num / den
331
- end
332
-
333
- #=
334
- if var in seen
335
- for q in 1:n_outers
336
- sq += sum(s->max(-states(s, fv), 0), inner_sc)
337
- for k in 1:n_outers; k == q && continue
338
- f = states(outer_sc[j], fv)
339
- si += max(f, 0)
340
- end
147
+ collect_instream! (set, eq:: Equation ) = collect_instream! (set, eq. lhs) | collect_instream! (set, eq. rhs)
341
148
342
- num = 0
343
- den = 0
344
- for j in 1:n_inners
345
- f = states(inner_sc[j], fv)
346
- tmp = positivemax(-f, sq; tol=tol)
347
- den += tmp
348
- num += tmp * states(inner_sc[j], sv)
349
- end
350
- for k in 1:n_outers; k == q && continue
351
- f = states(outer_sc[k], fv)
352
- tmp = positivemax(f, sq; tol=tol)
353
- den += tmp
354
- num += tmp * instream(states(outer_sc[k], sv))
355
- end
356
- push!(additional_eqs, states(outer_sc[q], sv) ~ num / den)
357
- end
358
- push!(seen, var)
359
- end
360
- =#
361
- end
362
- end
363
- instream_eqs = map(Base.Fix2(substitute, sub), instream_eqs)
364
- if debug
365
- println("Expanded equations:")
366
- for eq in instream_eqs
367
- print_with_indent(4, eq)
368
- end
369
- if !isempty(additional_eqs)
370
- println("Additional equations:")
371
- for eq in additional_eqs
372
- print_with_indent(4, eq)
373
- end
374
- end
149
+ function collect_instream! (set, expr, occurs= false )
150
+ istree (expr) || return occurs
151
+ op = operation (expr)
152
+ op === instream && (push! (set, expr); occurs = true )
153
+ for a in SymbolicUtils. unsorted_arguments (expr)
154
+ occurs |= collect_instream! (set, a, occurs)
375
155
end
376
- @set! sys.eqs = [eqs; instream_eqs; additional_eqs]
377
- return sys
156
+ return occurs
378
157
end
379
- =#
380
158
381
- function expand_connections (sys:: AbstractSystem ; debug= false )
382
- sys = collect_connections (sys; debug= debug)
383
- # sys = expand_instream(sys; debug=debug)
384
- return sys
385
- end
159
+ positivemax (m, :: Any ; tol= nothing )= max (m, something (tol, 1e-8 ))
386
160
387
- function collect_connections (sys:: AbstractSystem ; debug= false , tol= 1e-10 )
161
+ function expand_connections (sys:: AbstractSystem ; debug= false , tol= 1e-10 )
388
162
subsys = get_systems (sys)
389
163
isempty (subsys) && return sys
390
164
391
165
# post order traversal
392
- @set! sys. systems = map (s-> collect_connections (s, debug= debug), subsys)
166
+ @set! sys. systems = map (s-> expand_connections (s, debug= debug), subsys)
393
167
394
168
outer_connectors = Symbol[]
395
169
for s in subsys
@@ -494,7 +268,6 @@ function collect_connections(sys::AbstractSystem; debug=false, tol=1e-10)
494
268
495
269
# stream variables
496
270
stream_connects = filter (isstreamconnection, narg_connects)
497
- @show length (stream_connects)
498
271
instream_eqs, additional_eqs = expand_instream (instream_eqs, instream_exprs, stream_connects; debug= debug, tol= tol)
499
272
500
273
@set! sys. eqs = [eqs; instream_eqs; additional_eqs]
0 commit comments