Skip to content

Commit fb791eb

Browse files
committed
WIP
1 parent 8d7b2d1 commit fb791eb

File tree

4 files changed

+110
-53
lines changed

4 files changed

+110
-53
lines changed

src/ModelingToolkit.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export JumpProblem, DiscreteProblem
173173
export NonlinearSystem, OptimizationSystem
174174
export ControlSystem
175175
export alias_elimination, flatten
176-
export connect, @connector, Connection, Flow, Stream
176+
export connect, @connector, Connection, Flow, Stream, instream
177177
export ode_order_lowering, liouville_transform
178178
export runge_kutta_discretize
179179
export PDESystem

src/systems/abstractsystem.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ for prop in [
220220
:ivs
221221
:dvs
222222
:connector_type
223+
:connections
223224
:preface
224225
]
225226
fname1 = Symbol(:get_, prop)
@@ -355,6 +356,7 @@ GlobalScope(sym::Union{Num, Symbolic}) = setmetadata(sym, SymScope, GlobalScope(
355356

356357
renamespace(sys, eq::Equation) = namespace_equation(eq, sys)
357358

359+
renamespace(names::AbstractVector, x) = foldr(renamespace, names, init=x)
358360
function renamespace(sys, x)
359361
x = unwrap(x)
360362
if x isa Symbolic

src/systems/connectors.jl

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ end
5050
# everything is inner by default until we expand the connections
5151
Connection(syss) = Connection(inners=syss)
5252
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
5357

5458
const EMPTY_VEC = []
5559

@@ -137,7 +141,7 @@ function collect_instream!(set, expr, occurs=false)
137141
istree(expr) || return occurs
138142
op = operation(expr)
139143
op === instream && (push!(set, expr); occurs = true)
140-
for a in unsorted_arguments(expr)
144+
for a in SymbolicUtils.unsorted_arguments(expr)
141145
occurs |= collect_instream!(set, a, occurs)
142146
end
143147
return occurs
@@ -162,42 +166,42 @@ function get_sys_var(sys::AbstractSystem, var; inclusive=true)
162166
newsys, lvs[end]
163167
end
164168

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)
166197
subsys = get_systems(sys)
167198
isempty(subsys) && return sys
168199

169200
# 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
174202
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)
182204
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-
201205
eqs′ = get_eqs(sys)
202206
eqs = Equation[]
203207
instream_eqs = Equation[]
@@ -209,47 +213,87 @@ function expand_instream(sys::AbstractSystem; debug=false)
209213
push!(eqs, eq) # split instreams and equations
210214
end
211215
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
218232
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)")
219239
220240
# expand `instream`s
221241
sub = Dict()
222-
n_outers = length(outer_names)
223-
n_inners = length(inner_names)
242+
additional_eqs = Equation[]
243+
seen = Set()
224244
# https://specification.modelica.org/v3.4/Ch15.html
225245
# Based on the above requirements, the following implementation is
226246
# recommended:
227247
if n_inners == 1 && n_outers == 0
228248
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)
232254
end
233255
elseif n_inners == 2 && n_outers == 0
234256
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)
239263
end
240264
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
241277
elseif n_inners == 0 && n_outers == 2
278+
push!(additional_eqs, outerinstream ~ var)
242279
else
243280
end
244281
instream_eqs = map(Base.Fix2(substitute, sub), instream_eqs)
282+
=#
245283
end
246284

247285
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)
248292
subsys = get_systems(sys)
249293
isempty(subsys) && return sys
250294

251295
# 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)
253297

254298
outer_connectors = Symbol[]
255299
for s in subsys
@@ -273,6 +317,9 @@ function expand_connections(sys::AbstractSystem; debug=false)
273317
eq.lhs isa Connection ? push!(cts, get_systems(eq.rhs)) : push!(eqs, eq) # split connections and equations
274318
end
275319

320+
# if there are no connections, we are done
321+
isempty(cts) && return sys
322+
276323
sys2idx = Dict{Symbol,Int}() # system (name) to n-th connect statement
277324
narg_connects = Connection[]
278325
for (i, syss) in enumerate(cts)
@@ -305,6 +352,10 @@ function expand_connections(sys::AbstractSystem; debug=false)
305352
end
306353
end
307354

355+
isempty(narg_connects) && error("Unreachable reached. Please file an issue.")
356+
357+
@set! sys.connections = narg_connects
358+
308359
# Bad things happen when there are more than one intersections
309360
for c in narg_connects
310361
@unpack outers, inners = c
@@ -314,7 +365,7 @@ function expand_connections(sys::AbstractSystem; debug=false)
314365
length(dups) == 0 || error("$(Connection(syss)) has duplicated connections: $(dups).")
315366
end
316367

317-
if debug && !isempty(narg_connects)
368+
if debug
318369
println("============BEGIN================")
319370
println("Connections for [$(nameof(sys))]:")
320371
foreach(Base.Fix1(print_with_indent, 4), narg_connects)
@@ -327,7 +378,7 @@ function expand_connections(sys::AbstractSystem; debug=false)
327378
append!(eqs, ceqs)
328379
end
329380

330-
if debug && !isempty(narg_connects)
381+
if debug
331382
println("Connection equations:")
332383
foreach(Base.Fix1(print_with_indent, 4), connection_eqs)
333384
println("=============END=================")

src/systems/diffeqs/odesystem.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ struct ODESystem <: AbstractODESystem
8484
"""
8585
connector_type::Any
8686
"""
87+
connections: connections in a system
88+
"""
89+
connections::Any
90+
"""
8791
preface: inject assignment statements before the evaluation of the RHS function.
8892
"""
8993
preface::Any
@@ -93,15 +97,15 @@ struct ODESystem <: AbstractODESystem
9397
"""
9498
continuous_events::Vector{SymbolicContinuousCallback}
9599

96-
function ODESystem(deqs, iv, dvs, ps, var_to_name, ctrls, observed, tgrad, jac, ctrl_jac, Wfact, Wfact_t, name, systems, defaults, structure, connector_type, preface, events; checks::Bool = true)
100+
function ODESystem(deqs, iv, dvs, ps, var_to_name, ctrls, observed, tgrad, jac, ctrl_jac, Wfact, Wfact_t, name, systems, defaults, structure, connector_type, connections, preface, events; checks::Bool = true)
97101
if checks
98102
check_variables(dvs,iv)
99103
check_parameters(ps,iv)
100104
check_equations(deqs,iv)
101105
check_equations(equations(events),iv)
102106
all_dimensionless([dvs;ps;iv]) || check_units(deqs)
103107
end
104-
new(deqs, iv, dvs, ps, var_to_name, ctrls, observed, tgrad, jac, ctrl_jac, Wfact, Wfact_t, name, systems, defaults, structure, connector_type, preface, events)
108+
new(deqs, iv, dvs, ps, var_to_name, ctrls, observed, tgrad, jac, ctrl_jac, Wfact, Wfact_t, name, systems, defaults, structure, connector_type, connections, preface, events)
105109
end
106110
end
107111

@@ -148,7 +152,7 @@ function ODESystem(
148152
throw(ArgumentError("System names must be unique."))
149153
end
150154
cont_callbacks = SymbolicContinuousCallbacks(continuous_events)
151-
ODESystem(deqs, iv′, dvs′, ps′, var_to_name, ctrl′, observed, tgrad, jac, ctrl_jac, Wfact, Wfact_t, name, systems, defaults, nothing, connector_type, preface, cont_callbacks, checks = checks)
155+
ODESystem(deqs, iv′, dvs′, ps′, var_to_name, ctrl′, observed, tgrad, jac, ctrl_jac, Wfact, Wfact_t, name, systems, defaults, nothing, connector_type, nothing, preface, cont_callbacks, checks = checks)
152156
end
153157

154158
function ODESystem(eqs, iv=nothing; kwargs...)

0 commit comments

Comments
 (0)