@@ -29,7 +29,7 @@ struct StreamConnector <: AbstractConnectorType end
29
29
struct RegularConnector <: AbstractConnectorType end
30
30
31
31
function connector_type (sys:: AbstractSystem )
32
- sts = states (sys)
32
+ sts = get_states (sys)
33
33
# TODO : check the criteria for stream connectors
34
34
n_stream = 0
35
35
n_flow = 0
@@ -191,6 +191,15 @@ function find_connection(connector_name, ogsys, names)
191
191
error (" $connector_name cannot be found in $(nameof (ogsys)) with levels $(names) " )
192
192
end
193
193
194
+ function flowvar (sys:: AbstractSystem , v)
195
+ sts = get_states (sys)
196
+ for s in sts
197
+ vtype = getmetadata (s, ModelingToolkit. VariableConnectType, nothing )
198
+ vtype === Flow && return s
199
+ end
200
+ error (" There in no flow variable in $(nameof (sys)) " )
201
+ end
202
+
194
203
function expand_instream (ogsys, sys:: AbstractSystem = ogsys, names= []; debug= false )
195
204
subsys = get_systems (sys)
196
205
isempty (subsys) && return sys
@@ -211,9 +220,12 @@ function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false
211
220
push! (eqs, eq) # split instreams and equations
212
221
end
213
222
end
214
- @show nameof (sys), names, instream_exprs
223
+ # @show nameof(sys), names, instream_exprs
215
224
isempty (instream_eqs) && return sys
216
225
226
+ sub = Dict ()
227
+ seen = Set ()
228
+ additional_eqs = Equation[]
217
229
for ex in instream_exprs
218
230
var = only (arguments (ex))
219
231
connector_name, streamvar_name = split_sys_var (var)
@@ -222,13 +234,16 @@ function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false
222
234
inner_sc = []
223
235
# find the connect
224
236
parentsys, connect = find_connection (connector_name, ogsys, names)
237
+ connectors = Iterators. flatten ((connect. inners, connect. outers))
238
+ # stream variable
239
+ sv = getproperty (first (connectors), streamvar_name; namespace= false )
225
240
if nameof (parentsys) != nameof (sys)
226
241
# everything is a inner connector w.r.t. `sys`
227
- for s in Iterators . flatten ((connect . inners, connect . outers))
242
+ for s in connectors
228
243
push! (inner_sc, s)
229
244
end
230
245
else
231
- for s in Iterators . flatten ((connect . inners, connect . outers))
246
+ for s in connectors
232
247
if connector_name == split_var (nameof (s))[1 ]
233
248
push! (inner_sc, s)
234
249
else
@@ -239,51 +254,116 @@ function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false
239
254
240
255
n_inners = length (outer_sc)
241
256
n_outers = length (inner_sc)
242
- @show n_inners n_outers
257
+ outer_names = (nameof (s) for s in outer_sc)
258
+ inner_names = (nameof (s) for s in inner_sc)
259
+ if debug
260
+ println (" Expanding: $ex " )
261
+ isempty (inner_names) || println (" Inner connectors: $(collect (inner_names)) " )
262
+ isempty (outer_names) || println (" Outer connectors: $(collect (outer_names)) " )
263
+ end
243
264
244
265
# expand `instream`s
245
- sub = Dict ()
246
- additional_eqs = Equation[]
247
- seen = Set ()
248
266
# https://specification.modelica.org/v3.4/Ch15.html
249
267
# Based on the above requirements, the following implementation is
250
268
# recommended:
251
269
if n_inners == 1 && n_outers == 0
252
- for ex in instream_exprs
253
- var = only (arguments (ex))
254
- connector_name, streamvar_name = split_stream_var (var)
255
- idx = findfirst (isequal (connector_name), inner_names)
256
- idx === nothing || error (" $stream_name is not in any stream connector of $(nameof (sys)) " )
257
- sub[ex] = var # getproperty(inner_sc[idx], streamvar_name)
258
- end
270
+ connector_name === only (inner_names) || error (" $stream_name is not in any stream connector of $(nameof (ogsys)) " )
271
+ sub[ex] = var
259
272
elseif n_inners == 2 && n_outers == 0
260
- for ex in instream_exprs
261
- var = only (arguments (ex))
262
- connector_name, streamvar_name = split_stream_var (var)
263
- idx = findfirst (isequal (connector_name), inner_names)
264
- idx === nothing || error (" $stream_name is not in any stream connector of $(nameof (sys)) " )
265
- other = idx == 1 ? 2 : 1
266
- sub[ex] = getproperty (inner_sc[other], streamvar_name)
267
- end
273
+ connector_name in inner_names || error (" $stream_name is not in any stream connector of $(nameof (ogsys)) " )
274
+ idx = findfirst (c-> nameof (c) === connector_name, inner_sc)
275
+ other = idx == 1 ? 2 : 1
276
+ sub[ex] = states (inner_sc[other], sv)
268
277
elseif n_inners == 1 && n_outers == 1
269
- for ex in instream_exprs
270
- var = only (arguments (ex)) # m_1.c.h_outflow
271
- connector_name, streamvar_name = split_stream_var (var)
272
- idx = findfirst (isequal (connector_name), inner_names)
273
- idx === nothing || error (" $stream_name is not in any stream connector of $(nameof (sys)) " )
274
- outerinstream = getproperty (only (outer_sc), streamvar_name) # c_1.h_outflow
278
+ isinner = connector_name === only (inner_names)
279
+ isouter = connector_name === only (outer_names)
280
+ (isinner || isouter) || error (" $stream_name is not in any stream connector of $(nameof (ogsys)) " )
281
+ if isinner
282
+ outerinstream = states (only (outer_sc), sv) # c_1.h_outflow
275
283
sub[ex] = outerinstream
276
- if var in seen
277
- push! (additional_eqs, outerinstream ~ var)
278
- push! (seen, var)
279
- end
284
+ end
285
+ if var in seen
286
+ push! (additional_eqs, outerinstream ~ var)
287
+ push! (seen, var)
280
288
end
281
289
elseif n_inners == 0 && n_outers == 2
282
- push! (additional_eqs, outerinstream ~ var)
290
+ # we don't expand `instream` in this case.
291
+ if var in seen
292
+ v1 = states (outer_sc[1 ], sv)
293
+ v2 = states (outer_sc[2 ], sv)
294
+ push! (additional_eqs, v1 ~ instream (v2))
295
+ push! (additional_eqs, v2 ~ instream (v1))
296
+ push! (seen, var)
297
+ end
283
298
else
299
+ fv = flowvar (first (connectors))
300
+ idx = findfirst (c-> nameof (c) === connector_name, inner_sc)
301
+ if idx != = nothing
302
+ si = sum (s-> max (states (s, fv), 0 ), outer_sc)
303
+ for j in 1 : n_inners; j == i && continue
304
+ f = states (inner_sc[j], fv)
305
+ si += max (- f, 0 )
306
+ end
307
+
308
+ num = 0
309
+ den = 0
310
+ for j in 1 : n_inners; j == i && continue
311
+ f = states (inner_sc[j], fv)
312
+ tmp = positivemax (- f, si)
313
+ den += tmp
314
+ num += tmp * states (inner_sc[j], sv)
315
+ end
316
+ for k in 1 : n_outers
317
+ f = states (outer_sc[k], fv)
318
+ tmp = positivemax (f, si)
319
+ den += tmp
320
+ num += tmp * instream (states (outer_sc[k], sv))
321
+ end
322
+ sub[ex] = num / den
323
+ end
324
+
325
+ if var in seen
326
+ for q in 1 : n_outers
327
+ sq += sum (s-> max (- states (s, fv), 0 ), inner_sc)
328
+ for k in 1 : n_outers; k == q && continue
329
+ f = states (outer_sc[j], fv)
330
+ si += max (f, 0 )
331
+ end
332
+
333
+ num = 0
334
+ den = 0
335
+ for j in 1 : n_inners
336
+ f = states (inner_sc[j], fv)
337
+ tmp = positivemax (- f, sq)
338
+ den += tmp
339
+ num += tmp * states (inner_sc[j], sv)
340
+ end
341
+ for k in 1 : n_outers; k == q && continue
342
+ f = states (outer_sc[k], fv)
343
+ tmp = positivemax (f, sq)
344
+ den += tmp
345
+ num += tmp * instream (states (outer_sc[k], sv))
346
+ end
347
+ push! (additional_eqs, states (outer_sc[q], sv) ~ num / den)
348
+ end
349
+ push! (seen, var)
350
+ end
284
351
end
285
352
end
286
353
instream_eqs = map (Base. Fix2 (substitute, sub), instream_eqs)
354
+ if debug
355
+ println (" Expanded equations:" )
356
+ for eq in instream_eqs
357
+ print_with_indent (4 , eq)
358
+ end
359
+ if ! isempty (additional_eqs)
360
+ println (" Additional equations:" )
361
+ for eq in additional_eqs
362
+ print_with_indent (4 , eq)
363
+ end
364
+ end
365
+ end
366
+ @set! sys. eqs = [eqs; instream_eqs; additional_eqs]
287
367
return sys
288
368
end
289
369
0 commit comments