Skip to content

Commit acadb7e

Browse files
committed
Add generate_connection_set that behaves like Modelica
1 parent 74abd47 commit acadb7e

File tree

2 files changed

+102
-5
lines changed

2 files changed

+102
-5
lines changed

src/systems/abstractsystem.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ renamespace(sys, eq::Equation) = namespace_equation(eq, sys)
380380

381381
renamespace(names::AbstractVector, x) = foldr(renamespace, names, init=x)
382382
function renamespace(sys, x)
383+
sys === nothing && return x
383384
x = unwrap(x)
384385
if x isa Symbolic
385386
let scope = getmetadata(x, SymScope, LocalScope())

src/systems/connectors.jl

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,43 @@ struct ConnectionSet
232232
set::Vector{Pair{Any, Bool}} # var => isouter
233233
end
234234

235-
function generate_connection_set(sys::AbstractSystem, namespace=nothing)
235+
function Base.show(io::IO, c::ConnectionSet)
236+
print(io, "<")
237+
for i in 1:length(c.set)-1
238+
v, isouter = c.set[i]
239+
print(io, v, "::", isouter ? "outer" : "inner", ", ")
240+
end
241+
v, isouter = last(c.set)
242+
print(io, v, "::", isouter ? "outer" : "inner", ">")
243+
end
244+
245+
@noinline connection_error(ss) = error("Different types of connectors are in one conenction statement: <$(map(nameof, ss))>")
246+
247+
function connection2set!(connectionsets, namespace, ss, isouter)
248+
sts1 = Set(states(first(ss)))
249+
T = Pair{Any,Bool}
250+
csets = [T[] for _ in 1:length(ss)]
251+
for (i, s) in enumerate(ss)
252+
sts = states(s)
253+
i != 1 && ((length(sts1) == length(sts) && all(Base.Fix2(in, sts1), sts)) || connection_error(ss))
254+
io = isouter(s)
255+
for (j, v) in enumerate(sts)
256+
push!(csets[j], T(states(renamespace(namespace, s), v), io))
257+
end
258+
end
259+
for cset in csets
260+
vtype = get_connection_type(first(cset)[1])
261+
for k in 2:length(cset)
262+
vtype === get_connection_type(cset[k][1]) || connection_error(ss)
263+
end
264+
push!(connectionsets, ConnectionSet(cset))
265+
end
266+
end
267+
268+
generate_connection_set(sys::AbstractSystem) = (connectionsets = ConnectionSet[]; generate_connection_set!(connectionsets, sys::AbstractSystem); connectionsets)
269+
function generate_connection_set!(connectionsets, sys::AbstractSystem, namespace=nothing)
236270
subsys = get_systems(sys)
271+
# no connectors if there are no subsystems
237272
isempty(subsys) && return sys
238273

239274
isouter = generate_isouter(sys)
@@ -252,16 +287,77 @@ function generate_connection_set(sys::AbstractSystem, namespace=nothing)
252287
end
253288
end
254289

290+
if namespace !== nothing
291+
# Except for the top level, all connectors are eventually inside
292+
# connectors.
293+
T = Pair{Any,Bool}
294+
for s in subsys
295+
isconnector(s) || continue
296+
for v in states(s)
297+
Flow === get_connection_type(v) || continue
298+
push!(connectionsets, ConnectionSet([T(renamespace(namespace, states(s, v)), false)]))
299+
end
300+
end
301+
end
302+
255303
# if there are no connections, we are done
256304
isempty(cts) && return sys
257305

258-
set = Pair{Any, Bool}[]
259-
306+
for ct in cts
307+
connection2set!(connectionsets, namespace, ct, isouter)
308+
end
260309

261310
# pre order traversal
262-
namespace = renamespace(nameof(sys), namespace)
263-
@set! sys.systems = map(Base.Fix2(generate_connection_set, namespace), subsys)
311+
@set! sys.systems = map(s->generate_connection_set!(connectionsets, s, renamespace(namespace, nameof(s))), subsys)
264312
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+
=#
265361

266362
function expand_connections(sys::AbstractSystem; debug=false, tol=1e-10,
267363
rename=Ref{Union{Nothing,Tuple{Symbol,Int}}}(nothing), stream_connects=[])

0 commit comments

Comments
 (0)