50
50
# everything is inner by default until we expand the connections
51
51
Connection (syss) = Connection (inners= syss)
52
52
get_systems (c:: Connection ) = c. inners
53
+ function Base. in (e:: Symbol , c:: Connection )
54
+ f = isequal (e)
55
+ any (f, c. inners) || any (f, c. outers)
56
+ end
53
57
54
58
const EMPTY_VEC = []
55
59
@@ -137,7 +141,7 @@ function collect_instream!(set, expr, occurs=false)
137
141
istree (expr) || return occurs
138
142
op = operation (expr)
139
143
op === instream && (push! (set, expr); occurs = true )
140
- for a in unsorted_arguments (expr)
144
+ for a in SymbolicUtils . unsorted_arguments (expr)
141
145
occurs |= collect_instream! (set, a, occurs)
142
146
end
143
147
return occurs
@@ -162,42 +166,42 @@ function get_sys_var(sys::AbstractSystem, var; inclusive=true)
162
166
newsys, lvs[end ]
163
167
end
164
168
165
- function expand_instream (sys:: AbstractSystem ; debug= false )
169
+ function split_stream_var (var)
170
+ var_name = string (getname (var))
171
+ @show var_name
172
+ sidx = findlast (isequal (' ₊' ), var_name)
173
+ sidx === nothing && error (" $var is not a stream variable" )
174
+ connector_name = Symbol (var_name[1 : prevind (var_name, sidx)])
175
+ streamvar_name = Symbol (var_name[nextind (var_name, sidx): end ])
176
+ connector_name, streamvar_name
177
+ end
178
+
179
+ function find_connection (connector_name, ogsys, names)
180
+ cs = get_connections (ogsys)
181
+ cs === nothing || for c in cs
182
+ @show renamespace (names, connector_name)
183
+ renamespace (names, connector_name) in c && return c
184
+ end
185
+ innersys = ogsys
186
+ for n in names
187
+ innersys = getproperty (innersys, n)
188
+ cs = get_connections (innersys)
189
+ cs === nothing || for c in cs
190
+ connector_name in c && return c
191
+ end
192
+ end
193
+ error (" $connector_name cannot be found in $(nameof (ogsys)) with levels $(names) " )
194
+ end
195
+
196
+ function expand_instream (ogsys, sys:: AbstractSystem = ogsys, names= []; debug= false )
166
197
subsys = get_systems (sys)
167
198
isempty (subsys) && return sys
168
199
169
200
# post order traversal
170
- @set! sys. systems = map (s-> expand_connections (s, debug= debug), subsys)
171
-
172
- outer_sc = []
173
- for s in subsys
201
+ @set! sys. systems = map (subsys) do s
174
202
n = nameof (s)
175
- isstreamconnector (s) && push! (outer_sc, n)
176
- end
177
-
178
- # the number of stream connectors excluding the current level
179
- inner_sc = []
180
- for s in subsys
181
- get_stream_connectors! (inner_sc, renamespace (sys, s))
203
+ expand_instream (ogsys, s, [names; n], debug= debug)
182
204
end
183
-
184
- # error checking
185
- # TODO : Error might never be possible anyway, because subsystem names must
186
- # be distinct.
187
- outer_names, dup = find_duplicates ((nameof (s) for s in outer_sc), Val (true ))
188
- isempty (dup) || error (" $dup are duplicate stream connectors!" )
189
- inner_names, dup = find_duplicates ((nameof (s) for s in inner_sc), Val (true ))
190
- isempty (dup) || error (" $dup are duplicate stream connectors!" )
191
-
192
- foreach (Base. Fix1 (get_stream_connectors!, inner_sc), subsys)
193
- isouterstream = let stream_connectors= outer_sc
194
- function isstream (sys):: Bool
195
- s = string (nameof (sys))
196
- isstreamconnector (sys) || error (" $s is not a stream connector!" )
197
- s in stream_connectors
198
- end
199
- end
200
-
201
205
eqs′ = get_eqs (sys)
202
206
eqs = Equation[]
203
207
instream_eqs = Equation[]
@@ -209,47 +213,87 @@ function expand_instream(sys::AbstractSystem; debug=false)
209
213
push! (eqs, eq) # split instreams and equations
210
214
end
211
215
end
212
-
213
- function check_in_stream_connectors (stream, sc)
214
- stream = only (arguments (ex))
215
- stream_name = string (nameof (stream))
216
- connector_name = stream_name[1 : something (findlast (' ₊' , stream_name), end )]
217
- connector_name in sc || error (" $stream_name is not in any stream connector of $(nameof (sys)) " )
216
+ @show nameof (sys), names, instream_exprs
217
+ isempty (instream_eqs) && return sys
218
+
219
+ for ex in instream_exprs
220
+ var = only (arguments (ex))
221
+ connector_name, streamvar_name = split_stream_var (var)
222
+
223
+ n_inners = 0
224
+ n_outers = 0
225
+ outer_names = Symbol[]
226
+ inner_names = Symbol[]
227
+ outer_sc = Symbol[]
228
+ inner_sc = Symbol[]
229
+ # find the connect
230
+ connect = find_connection (connector_name, ogsys, names)
231
+ @show connect
218
232
end
233
+ return sys
234
+ #=
235
+
236
+ #splitting_idx
237
+
238
+ #n_inners + n_outers <= 0 && error("Model $(nameof(sys)) has no stream connectors, yet there are equations with `instream` functions: $(instream_eqs)")
219
239
220
240
# expand `instream`s
221
241
sub = Dict()
222
- n_outers = length (outer_names)
223
- n_inners = length (inner_names )
242
+ additional_eqs = Equation[]
243
+ seen = Set( )
224
244
# https://specification.modelica.org/v3.4/Ch15.html
225
245
# Based on the above requirements, the following implementation is
226
246
# recommended:
227
247
if n_inners == 1 && n_outers == 0
228
248
for ex in instream_exprs
229
- stream = only (arguments (ex))
230
- check_in_stream_connectors (stream, inner_names)
231
- sub[ex] = stream
249
+ var = only(arguments(ex))
250
+ connector_name, streamvar_name = split_stream_var(var)
251
+ idx = findfirst(isequal(connector_name), inner_names)
252
+ idx === nothing || error("$stream_name is not in any stream connector of $(nameof(sys))")
253
+ sub[ex] = var #getproperty(inner_sc[idx], streamvar_name)
232
254
end
233
255
elseif n_inners == 2 && n_outers == 0
234
256
for ex in instream_exprs
235
- stream = only (arguments (ex))
236
- check_in_stream_connectors (stream, inner_names)
237
-
238
- sub[ex] = stream
257
+ var = only(arguments(ex))
258
+ connector_name, streamvar_name = split_stream_var(var)
259
+ idx = findfirst(isequal(connector_name), inner_names)
260
+ idx === nothing || error("$stream_name is not in any stream connector of $(nameof(sys))")
261
+ other = idx == 1 ? 2 : 1
262
+ sub[ex] = getproperty(inner_sc[other], streamvar_name)
239
263
end
240
264
elseif n_inners == 1 && n_outers == 1
265
+ for ex in instream_exprs
266
+ var = only(arguments(ex)) # m_1.c.h_outflow
267
+ connector_name, streamvar_name = split_stream_var(var)
268
+ idx = findfirst(isequal(connector_name), inner_names)
269
+ idx === nothing || error("$stream_name is not in any stream connector of $(nameof(sys))")
270
+ outerinstream = getproperty(only(outer_sc), streamvar_name) # c_1.h_outflow
271
+ sub[ex] = outerinstream
272
+ if var in seen
273
+ push!(additional_eqs, outerinstream ~ var)
274
+ push!(seen, var)
275
+ end
276
+ end
241
277
elseif n_inners == 0 && n_outers == 2
278
+ push!(additional_eqs, outerinstream ~ var)
242
279
else
243
280
end
244
281
instream_eqs = map(Base.Fix2(substitute, sub), instream_eqs)
282
+ =#
245
283
end
246
284
247
285
function expand_connections (sys:: AbstractSystem ; debug= false )
286
+ sys = collect_connections (sys; debug= debug)
287
+ sys = expand_instream (sys; debug= debug)
288
+ return sys
289
+ end
290
+
291
+ function collect_connections (sys:: AbstractSystem ; debug= false )
248
292
subsys = get_systems (sys)
249
293
isempty (subsys) && return sys
250
294
251
295
# post order traversal
252
- @set! sys. systems = map (s-> expand_connections (s, debug= debug), subsys)
296
+ @set! sys. systems = map (s-> collect_connections (s, debug= debug), subsys)
253
297
254
298
outer_connectors = Symbol[]
255
299
for s in subsys
@@ -273,6 +317,9 @@ function expand_connections(sys::AbstractSystem; debug=false)
273
317
eq. lhs isa Connection ? push! (cts, get_systems (eq. rhs)) : push! (eqs, eq) # split connections and equations
274
318
end
275
319
320
+ # if there are no connections, we are done
321
+ isempty (cts) && return sys
322
+
276
323
sys2idx = Dict {Symbol,Int} () # system (name) to n-th connect statement
277
324
narg_connects = Connection[]
278
325
for (i, syss) in enumerate (cts)
@@ -305,6 +352,10 @@ function expand_connections(sys::AbstractSystem; debug=false)
305
352
end
306
353
end
307
354
355
+ isempty (narg_connects) && error (" Unreachable reached. Please file an issue." )
356
+
357
+ @set! sys. connections = narg_connects
358
+
308
359
# Bad things happen when there are more than one intersections
309
360
for c in narg_connects
310
361
@unpack outers, inners = c
@@ -314,7 +365,7 @@ function expand_connections(sys::AbstractSystem; debug=false)
314
365
length (dups) == 0 || error (" $(Connection (syss)) has duplicated connections: $(dups) ." )
315
366
end
316
367
317
- if debug && ! isempty (narg_connects)
368
+ if debug
318
369
println (" ============BEGIN================" )
319
370
println (" Connections for [$(nameof (sys)) ]:" )
320
371
foreach (Base. Fix1 (print_with_indent, 4 ), narg_connects)
@@ -327,7 +378,7 @@ function expand_connections(sys::AbstractSystem; debug=false)
327
378
append! (eqs, ceqs)
328
379
end
329
380
330
- if debug && ! isempty (narg_connects)
381
+ if debug
331
382
println (" Connection equations:" )
332
383
foreach (Base. Fix1 (print_with_indent, 4 ), connection_eqs)
333
384
println (" =============END=================" )
0 commit comments