Skip to content

Commit c14af36

Browse files
authored
Merge pull request #2049 from Deltares/expand_instream
avoid n^2 scaling in expand_instream
2 parents af02552 + 3bec632 commit c14af36

File tree

2 files changed

+72
-25
lines changed

2 files changed

+72
-25
lines changed

src/systems/connectors.jl

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,26 @@ function expand_instream(csets::AbstractVector{<:ConnectionSet}, sys::AbstractSy
378378
end
379379
end
380380

381+
if !isempty(instream_exprs)
382+
# map from a namespaced stream variable to a ConnectionSet
383+
expr_cset = Dict()
384+
for cset in csets
385+
crep = first(cset.set)
386+
current = namespace == crep.sys.namespace
387+
for v in cset.set
388+
if (current || !v.isouter)
389+
expr_cset[namespaced_var(v)] = cset.set
390+
end
391+
end
392+
end
393+
end
394+
381395
for ex in instream_exprs
382-
cset, idx_in_set, sv = get_cset_sv(namespace, ex, csets)
396+
ns_sv = only(arguments(ex))
397+
full_name_sv = renamespace(namespace, ns_sv)
398+
cset = get(expr_cset, full_name_sv, nothing)
399+
cset === nothing && error("$ns_sv is not a variable inside stream connectors")
400+
idx_in_set, sv = get_cset_sv(full_name_sv, cset)
383401

384402
n_inners = n_outers = 0
385403
for (i, e) in enumerate(cset)
@@ -505,17 +523,10 @@ function get_current_var(namespace, cele, sv)
505523
states(renamespace(unnamespace(namespace, cele.sys.namespace), cele.sys.sys), sv)
506524
end
507525

508-
function get_cset_sv(namespace, ex, csets)
509-
ns_sv = only(arguments(ex))
510-
full_name_sv = renamespace(namespace, ns_sv)
511-
512-
for c in csets
513-
crep = first(c.set)
514-
current = namespace == crep.sys.namespace
515-
for (idx_in_set, v) in enumerate(c.set)
516-
if (current || !v.isouter) && isequal(namespaced_var(v), full_name_sv)
517-
return c.set, idx_in_set, v.v
518-
end
526+
function get_cset_sv(full_name_sv, cset)
527+
for (idx_in_set, v) in enumerate(cset)
528+
if isequal(namespaced_var(v), full_name_sv)
529+
return idx_in_set, v.v
519530
end
520531
end
521532
error("$ns_sv is not a variable inside stream connectors")

test/stream_connectors.jl

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,6 @@ function AdiabaticStraightPipe(; name,
4545

4646
eqns = Equation[]
4747

48-
#=
49-
push!(eqns, port_a.P ~ port_b.P)
50-
push!(eqns, 0 ~ port_a.m_flow + port_b.m_flow)
51-
push!(eqns, port_b.h_outflow ~ instream(port_a.h_outflow))
52-
push!(eqns, port_a.h_outflow ~ instream(port_b.h_outflow))
53-
=#
54-
5548
push!(eqns, connect(port_a, port_b))
5649
sys = ODESystem(eqns, t, vars, pars; name = name)
5750
sys = compose(sys, subs)
@@ -101,15 +94,49 @@ end
10194
@named pipe = AdiabaticStraightPipe()
10295
@named sink = MassFlowSource_h(m_flow_in = -0.01, h_in = 400e3)
10396

104-
streams_a = [n1m1.port_a, pipe.port_a]
105-
streams_b = [pipe.port_b, sink.port]
106-
10797
eqns = [connect(n1m1.port_a, pipe.port_a)
10898
connect(pipe.port_b, sink.port)]
10999

110100
@named sys = ODESystem(eqns, t)
111101
@named n1m1Test = compose(sys, n1m1, pipe, sink)
112102
@test_nowarn structural_simplify(n1m1Test)
103+
@unpack source, port_a = n1m1
104+
@test sort(equations(expand_connections(n1m1)), by = string) == [0 ~ port_a.m_flow
105+
0 ~ source.port1.m_flow - port_a.m_flow
106+
source.port1.P ~ port_a.P
107+
source.port1.P ~ source.P
108+
source.port1.h_outflow ~ port_a.h_outflow
109+
source.port1.h_outflow ~ source.h]
110+
@unpack port_a, port_b = pipe
111+
@test sort(equations(expand_connections(pipe)), by = string) ==
112+
[0 ~ -port_a.m_flow - port_b.m_flow
113+
0 ~ port_a.m_flow
114+
0 ~ port_b.m_flow
115+
port_a.P ~ port_b.P
116+
port_a.h_outflow ~ instream(port_b.h_outflow)
117+
port_b.h_outflow ~ instream(port_a.h_outflow)]
118+
@test sort(equations(expand_connections(sys)), by = string) ==
119+
[0 ~ n1m1.port_a.m_flow + pipe.port_a.m_flow
120+
0 ~ pipe.port_b.m_flow + sink.port.m_flow
121+
n1m1.port_a.P ~ pipe.port_a.P
122+
pipe.port_b.P ~ sink.port.P]
123+
@test sort(equations(expand_connections(n1m1Test)), by = string) ==
124+
[0 ~ -pipe.port_a.m_flow - pipe.port_b.m_flow
125+
0 ~ n1m1.port_a.m_flow + pipe.port_a.m_flow
126+
0 ~ n1m1.source.port1.m_flow - n1m1.port_a.m_flow
127+
0 ~ pipe.port_b.m_flow + sink.port.m_flow
128+
n1m1.port_a.P ~ pipe.port_a.P
129+
n1m1.source.port1.P ~ n1m1.port_a.P
130+
n1m1.source.port1.P ~ n1m1.source.P
131+
n1m1.source.port1.h_outflow ~ n1m1.port_a.h_outflow
132+
n1m1.source.port1.h_outflow ~ n1m1.source.h
133+
pipe.port_a.P ~ pipe.port_b.P
134+
pipe.port_a.h_outflow ~ sink.port.h_outflow
135+
pipe.port_b.P ~ sink.port.P
136+
pipe.port_b.h_outflow ~ n1m1.port_a.h_outflow
137+
sink.port.P ~ sink.P
138+
sink.port.h_outflow ~ sink.h_in
139+
sink.port.m_flow ~ -sink.m_flow_in]
113140

114141
# N1M2 model and test code.
115142
function N1M2(; name,
@@ -165,9 +192,6 @@ function N2M2(; name,
165192
@named port_b = TwoPhaseFluidPort()
166193
@named pipe = AdiabaticStraightPipe()
167194

168-
streams_a = [port_a, pipe.port_a]
169-
streams_b = [pipe.port_b, port_b]
170-
171195
subs = [port_a; port_b; pipe]
172196

173197
eqns = Equation[]
@@ -190,6 +214,18 @@ eqns = [connect(source.port, n2m2.port_a)
190214
@named n2m2Test = compose(sys, n2m2, source, sink)
191215
@test_nowarn structural_simplify(n2m2Test)
192216

217+
# stream var
218+
@named sp1 = TwoPhaseFluidPort()
219+
@named sp2 = TwoPhaseFluidPort()
220+
@named sys = ODESystem([connect(sp1, sp2)], t)
221+
sys_exp = expand_connections(compose(sys, [sp1, sp2]))
222+
@test sort(equations(sys_exp), by = string) == [0 ~ -sp1.m_flow - sp2.m_flow
223+
0 ~ sp1.m_flow
224+
0 ~ sp2.m_flow
225+
sp1.P ~ sp2.P
226+
sp1.h_outflow ~ ModelingToolkit.instream(sp2.h_outflow)
227+
sp2.h_outflow ~ ModelingToolkit.instream(sp1.h_outflow)]
228+
193229
# array var
194230
@connector function VecPin(; name)
195231
sts = @variables v(t)[1:2]=[1.0, 0.0] i(t)[1:2]=1.0 [connect = Flow]

0 commit comments

Comments
 (0)