Skip to content

Commit 2f8aa2a

Browse files
committed
Draft of various connections
1 parent ec9a51f commit 2f8aa2a

File tree

1 file changed

+115
-35
lines changed

1 file changed

+115
-35
lines changed

src/systems/connectors.jl

Lines changed: 115 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct StreamConnector <: AbstractConnectorType end
2929
struct RegularConnector <: AbstractConnectorType end
3030

3131
function connector_type(sys::AbstractSystem)
32-
sts = states(sys)
32+
sts = get_states(sys)
3333
#TODO: check the criteria for stream connectors
3434
n_stream = 0
3535
n_flow = 0
@@ -191,6 +191,15 @@ function find_connection(connector_name, ogsys, names)
191191
error("$connector_name cannot be found in $(nameof(ogsys)) with levels $(names)")
192192
end
193193

194+
function flowvar(sys::AbstractSystem)
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+
194203
function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false)
195204
subsys = get_systems(sys)
196205
isempty(subsys) && return sys
@@ -211,9 +220,12 @@ function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false
211220
push!(eqs, eq) # split instreams and equations
212221
end
213222
end
214-
@show nameof(sys), names, instream_exprs
223+
#@show nameof(sys), names, instream_exprs
215224
isempty(instream_eqs) && return sys
216225

226+
sub = Dict()
227+
seen = Set()
228+
additional_eqs = Equation[]
217229
for ex in instream_exprs
218230
var = only(arguments(ex))
219231
connector_name, streamvar_name = split_sys_var(var)
@@ -222,13 +234,16 @@ function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false
222234
inner_sc = []
223235
# find the connect
224236
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)
225240
if nameof(parentsys) != nameof(sys)
226241
# everything is a inner connector w.r.t. `sys`
227-
for s in Iterators.flatten((connect.inners, connect.outers))
242+
for s in connectors
228243
push!(inner_sc, s)
229244
end
230245
else
231-
for s in Iterators.flatten((connect.inners, connect.outers))
246+
for s in connectors
232247
if connector_name == split_var(nameof(s))[1]
233248
push!(inner_sc, s)
234249
else
@@ -239,52 +254,117 @@ function expand_instream(ogsys, sys::AbstractSystem=ogsys, names=[]; debug=false
239254

240255
n_inners = length(outer_sc)
241256
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
243264

244265
# expand `instream`s
245-
sub = Dict()
246-
additional_eqs = Equation[]
247-
seen = Set()
248266
# https://specification.modelica.org/v3.4/Ch15.html
249267
# Based on the above requirements, the following implementation is
250268
# recommended:
251269
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
259272
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)
268277
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
275283
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)
280288
end
281289
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
283298
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
284351
end
285352
end
286353
instream_eqs = map(Base.Fix2(substitute, sub), instream_eqs)
287-
return sys
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]
367+
return flatten(sys)
288368
end
289369

290370
function expand_connections(sys::AbstractSystem; debug=false)

0 commit comments

Comments
 (0)