@@ -228,44 +228,66 @@ function generate_isouter(sys::AbstractSystem)
228
228
end
229
229
end
230
230
231
+ struct LazyNamespace
232
+ namespace:: Union{Nothing,Symbol}
233
+ sys
234
+ end
235
+
236
+ Base. copy (l:: LazyNamespace ) = renamespace (l. namespace, l. sys)
237
+ Base. nameof (l:: LazyNamespace ) = renamespace (l. namespace, nameof (l. sys))
238
+
239
+ struct ConnectionElement
240
+ sys:: LazyNamespace
241
+ v
242
+ isouter:: Bool
243
+ end
244
+ Base. hash (l:: ConnectionElement , salt:: UInt ) = hash (nameof (l. sys)) ⊻ hash (l. v) ⊻ hash (l. isouter) ⊻ salt
245
+ Base. isequal (l1:: ConnectionElement , l2:: ConnectionElement ) = l1 == l2
246
+ Base.:(== )(l1:: ConnectionElement , l2:: ConnectionElement ) = nameof (l1. sys) == nameof (l2. sys) && isequal (l1. v, l2. v) && l1. isouter == l2. isouter
247
+ function namespaced_var (l:: ConnectionElement )
248
+ @unpack sys, v = l
249
+ states (copy (sys), v)
250
+ end
251
+
231
252
struct ConnectionSet
232
- set:: Vector{Pair{Any, Bool}} # var => isouter
253
+ set:: Vector{ConnectionElement} # namespace.sys, var, isouter
233
254
end
234
255
235
256
function Base. show (io:: IO , c:: ConnectionSet )
236
257
print (io, " <" )
237
258
for i in 1 : length (c. set)- 1
238
- v, isouter = c. set[i]
239
- print (io, v, " ::" , isouter ? " outer" : " inner" , " , " )
259
+ @unpack sys, v, isouter = c. set[i]
260
+ print (io, nameof (sys), " . " , v, " ::" , isouter ? " outer" : " inner" , " , " )
240
261
end
241
- v, isouter = last (c. set)
242
- print (io, v, " ::" , isouter ? " outer" : " inner" , " >" )
262
+ @unpack sys, v, isouter = last (c. set)
263
+ print (io, nameof (sys), " . " , v, " ::" , isouter ? " outer" : " inner" , " >" )
243
264
end
244
265
245
266
@noinline connection_error (ss) = error (" Different types of connectors are in one conenction statement: <$(map (nameof, ss)) >" )
246
267
247
268
function connection2set! (connectionsets, namespace, ss, isouter)
269
+ nn = map (nameof, ss)
248
270
sts1 = Set (states (first (ss)))
249
- T = Pair{Any,Bool}
250
- csets = [T[] for _ in 1 : length (ss )]
271
+ T = ConnectionElement
272
+ csets = [T[] for _ in 1 : length (sts1 )]
251
273
for (i, s) in enumerate (ss)
252
274
sts = states (s)
253
275
i != 1 && ((length (sts1) == length (sts) && all (Base. Fix2 (in, sts1), sts)) || connection_error (ss))
254
276
io = isouter (s)
255
277
for (j, v) in enumerate (sts)
256
- push! (csets[j], T (states ( renamespace ( namespace, s), v) , io))
278
+ push! (csets[j], T (LazyNamespace ( namespace, s), v, io))
257
279
end
258
280
end
259
281
for cset in csets
260
- vtype = get_connection_type (first (cset)[ 1 ] )
282
+ vtype = get_connection_type (first (cset). v )
261
283
for k in 2 : length (cset)
262
- vtype === get_connection_type (cset[k][ 1 ] ) || connection_error (ss)
284
+ vtype === get_connection_type (cset[k]. v ) || connection_error (ss)
263
285
end
264
286
push! (connectionsets, ConnectionSet (cset))
265
287
end
266
288
end
267
289
268
- generate_connection_set (sys:: AbstractSystem ) = (connectionsets = ConnectionSet[]; generate_connection_set! (connectionsets, sys:: AbstractSystem ); connectionsets)
290
+ generate_connection_set (sys:: AbstractSystem ) = (connectionsets = ConnectionSet[]; ( generate_connection_set! (connectionsets, sys:: AbstractSystem ), connectionsets) )
269
291
function generate_connection_set! (connectionsets, sys:: AbstractSystem , namespace= nothing )
270
292
subsys = get_systems (sys)
271
293
# no connectors if there are no subsystems
@@ -290,12 +312,12 @@ function generate_connection_set!(connectionsets, sys::AbstractSystem, namespace
290
312
if namespace != = nothing
291
313
# Except for the top level, all connectors are eventually inside
292
314
# connectors.
293
- T = Pair{Any,Bool}
315
+ T = ConnectionElement
294
316
for s in subsys
295
317
isconnector (s) || continue
296
318
for v in states (s)
297
319
Flow === get_connection_type (v) || continue
298
- push! (connectionsets, ConnectionSet ([T (renamespace (namespace, states (s , v)) , false )]))
320
+ push! (connectionsets, ConnectionSet ([T (LazyNamespace (namespace, s) , v, false )]))
299
321
end
300
322
end
301
323
end
@@ -309,61 +331,14 @@ function generate_connection_set!(connectionsets, sys::AbstractSystem, namespace
309
331
310
332
# pre order traversal
311
333
@set! sys. systems = map (s-> generate_connection_set! (connectionsets, s, renamespace (namespace, nameof (s))), subsys)
334
+ @set! sys. eqs = eqs
312
335
end
313
- #=
314
-
315
- <load₊p₊i(t)::inner>
316
- {<load.p.i, inside>}
317
-
318
- <load₊n₊i(t)::inner>
319
- {<load.n.i, inside>}
320
-
321
- <ground₊g₊i(t)::inner>
322
- {<ground.p.i, inside>}
323
-
324
- <load₊resistor₊p₊i(t)::inner>
325
- {<load.resistor.p.i, inside>}
326
-
327
- <load₊resistor₊n₊i(t)::inner>
328
- {<load.resistor.n.i, inside>}
329
-
330
- <resistor₊p₊i(t)::inner>
331
- {<resistor.p.i, inside>}
332
-
333
- <resistor₊n₊i(t)::inner>
334
- {<resistor.n.i, inside>}
335
-
336
-
337
- <resistor.p.i(t)::inner, ground.g.i(t)::inner>
338
- {<resistor.p.i, inside>, <ground.p.i, inside>}
339
-
340
- <resistor.p.v(t)::inner, ground.g.v(t)::inner>
341
- {<resistor.p.v, inside>, <ground.p.v, inside>}
342
-
343
- <load.p.i(t)::inner, ground.g.i(t)::inner>
344
- {<load.p.i, inside>, <ground.p.i, inside>}
345
-
346
- <load.p.v(t)::inner, ground.g.v(t)::inner>
347
- {<load.p.v, inside>, <ground.p.v, inside>}
348
-
349
- <load.p.i(t)::outer, load.resistor.p.i(t)::inner>
350
- {<load.p.i, outside>, <load.resistor.p.i, inside>}
351
-
352
- <load.p.v(t)::outer, load.resistor.p.v(t)::inner>
353
- {<load.p.v, outside>, <load.resistor.p.v, inside>}
354
-
355
- <load.resistor.n.i(t)::inner, load.n.i(t)::outer>
356
- {<load.n.i, outside>, <load.resistor.n.i, inside>}
357
-
358
- <load.resistor.n.v(t)::inner, load.n.v(t)::outer>
359
- {<load.n.v, outside>, <load.resistor.n.v, inside>}
360
- =#
361
336
362
337
function Base. merge (csets:: AbstractVector{<:ConnectionSet} )
363
338
mcsets = ConnectionSet[]
364
339
# FIXME : this is O(m n^3)
365
340
for cset in csets
366
- idx = findfirst (mcset-> any (s-> any (z-> isequal (z, s) , cset. set), mcset. set), mcsets)
341
+ idx = findfirst (mcset-> any (s-> any (z-> z == s , cset. set), mcset. set), mcsets)
367
342
if idx === nothing
368
343
push! (mcsets, cset)
369
344
else
@@ -373,26 +348,30 @@ function Base.merge(csets::AbstractVector{<:ConnectionSet})
373
348
mcsets
374
349
end
375
350
376
- function generate_connection_equations (csets:: AbstractVector{<:ConnectionSet} )
351
+ function generate_connection_equations_and_stream_connections (csets:: AbstractVector{<:ConnectionSet} )
377
352
eqs = Equation[]
353
+ stream_connections = ConnectionSet[]
378
354
for cset in csets
379
- vtype = get_connection_type (cset. set[1 ][1 ])
380
- vtype === Stream && continue
381
- if vtype === Flow
355
+ vtype = get_connection_type (cset. set[1 ]. v)
356
+ if vtype === Stream
357
+ push! (stream_connections, cset)
358
+ continue
359
+ elseif vtype === Flow
382
360
rhs = 0
383
- for (v, isouter) in cset. set
384
- rhs += isouter ? - v : v
361
+ for ele in cset. set
362
+ v = namespaced_var (ele)
363
+ rhs += ele. isouter ? - v : v
385
364
end
386
365
push! (eqs, 0 ~ rhs)
387
366
else # Equality
388
- base = cset. set[1 ][ 1 ]
367
+ base = namespaced_var ( cset. set[1 ])
389
368
for i in 2 : length (cset. set)
390
- v = cset. set[i][ 1 ]
369
+ v = namespaced_var ( cset. set[i])
391
370
push! (eqs, base ~ v)
392
371
end
393
372
end
394
373
end
395
- eqs
374
+ eqs, stream_connections
396
375
end
397
376
398
377
function expand_connections (sys:: AbstractSystem ; debug= false , tol= 1e-10 ,
0 commit comments