Skip to content

Commit 32206c9

Browse files
committed
Evaluate/expand instream op at runtime
1 parent 117a0ef commit 32206c9

File tree

1 file changed

+99
-4
lines changed

1 file changed

+99
-4
lines changed

src/systems/connectors.jl

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,39 @@ function collect_instream!(set, expr, occurs=false)
173173
return occurs
174174
end
175175

176-
positivemax(m, ::Any; tol=nothing)= max(m, something(tol, 1e-8))
176+
#positivemax(m, ::Any; tol=nothing)= max(m, something(tol, 1e-8))
177+
#_positivemax(m, tol) = ifelse((-tol <= m) & (m <= tol), ((3 * tol - m) * (tol + m)^3)/(16 * tol^3) + tol, max(m, tol))
178+
function _positivemax(m, si)
179+
T = typeof(m)
180+
relativeTolerance = 1e-4
181+
nominal = one(T)
182+
eps = relativeTolerance * nominal
183+
alpha = if si > eps
184+
one(T)
185+
else
186+
if si > 0
187+
(si/eps)^2*(3-2* si/eps)
188+
else
189+
zero(T)
190+
end
191+
end
192+
alpha * max(m, 0) + (1-alpha)*eps
193+
end
194+
@register _positivemax(m, tol)
195+
positivemax(m, ::Any; tol=nothing) = _positivemax(m, tol)
196+
mydiv(num, den) = if den == 0
197+
error()
198+
else
199+
num / den
200+
end
201+
@register mydiv(n, d)
177202

178203
function expand_connections(sys::AbstractSystem; debug=false, tol=1e-10)
179204
subsys = get_systems(sys)
180205
isempty(subsys) && return sys
181206

182207
# post order traversal
183-
@set! sys.systems = map(s->expand_connections(s, debug=debug), subsys)
208+
@set! sys.systems = map(s->expand_connections(s, debug=debug, tol=tol), subsys)
184209

185210
outer_connectors = Symbol[]
186211
for s in subsys
@@ -288,6 +313,67 @@ function expand_connections(sys::AbstractSystem; debug=false, tol=1e-10)
288313
return sys
289314
end
290315

316+
@generated function _instream_split(::Val{inner_n}, ::Val{outer_n}, vars::NTuple{N}) where {inner_n, outer_n, N}
317+
#instream_rt(innerfvs..., innersvs..., outerfvs..., outersvs...)
318+
ret = Expr(:tuple)
319+
# mj.c.m_flow
320+
inner_f = :(Base.@ntuple $inner_n i -> vars[i])
321+
offset = inner_n
322+
inner_s = :(Base.@ntuple $inner_n i -> vars[$offset+i])
323+
offset += inner_n
324+
# ck.m_flow
325+
outer_f = :(Base.@ntuple $outer_n i -> vars[$offset+i])
326+
offset += outer_n
327+
outer_s = :(Base.@ntuple $outer_n i -> vars[$offset+i])
328+
Expr(:tuple, inner_f, inner_s, outer_f, outer_s)
329+
end
330+
331+
function instream_rt(ins::Val{inner_n}, outs::Val{outer_n}, vars::Vararg{Any,N}) where {inner_n, outer_n, N}
332+
@assert N == 2*(inner_n + outer_n)
333+
334+
# inner: mj.c.m_flow
335+
# outer: ck.m_flow
336+
inner_f, inner_s, outer_f, outer_s = _instream_split(ins, outs, vars)
337+
338+
T = float(first(inner_f))
339+
si = zero(T)
340+
num = den = zero(T)
341+
for f in inner_f
342+
si += max(-f, 0)
343+
end
344+
for f in outer_f
345+
si += max(f, 0)
346+
end
347+
#for (f, s) in zip(inner_f, inner_s)
348+
for j in 1:inner_n
349+
@inbounds f = inner_f[j]
350+
@inbounds s = inner_s[j]
351+
num += _positivemax(-f, si) * s
352+
den += _positivemax(-f, si)
353+
end
354+
#for (f, s) in zip(outer_f, outer_s)
355+
for j in 1:outer_n
356+
@inbounds f = outer_f[j]
357+
@inbounds s = outer_s[j]
358+
num += _positivemax(-f, si) * s
359+
den += _positivemax(-f, si)
360+
end
361+
return num / den
362+
#=
363+
si = sum(max(-mj.c.m_flow,0) for j in cat(1,1:i-1, i+1:N)) +
364+
sum(max(ck.m_flow ,0) for k in 1:M)
365+
366+
inStream(mi.c.h_outflow) =
367+
(sum(positiveMax(-mj.c.m_flow,si)*mj.c.h_outflow)
368+
+ sum(positiveMax(ck.m_flow,s_i)*inStream(ck.h_outflow)))/
369+
(sum(positiveMax(-mj.c.m_flow,s_i))
370+
+ sum(positiveMax(ck.m_flow,s_i)))
371+
for j in 1:N and i <> j and mj.c.m_flow.min < 0,
372+
for k in 1:M and ck.m_flow.max > 0
373+
=#
374+
end
375+
SymbolicUtils.promote_symtype(::typeof(instream_rt), ::Vararg) = Real
376+
291377
function expand_instream(instream_eqs, instream_exprs, connects; debug=false, tol)
292378
sub = Dict()
293379
seen = Set()
@@ -339,6 +425,15 @@ function expand_instream(instream_eqs, instream_exprs, connects; debug=false, to
339425
fv = flowvar(first(connectors))
340426
i = findfirst(c->nameof(c) === connector_name, inner_sc)
341427
if i !== nothing
428+
# mj.c.m_flow
429+
innerfvs = [unwrap(states(s, fv)) for (j, s) in enumerate(inner_sc) if j != i]
430+
innersvs = [unwrap(states(s, sv)) for (j, s) in enumerate(inner_sc) if j != i]
431+
# ck.m_flow
432+
outerfvs = [unwrap(states(s, fv)) for s in outer_sc]
433+
outersvs = [instream(states(s, fv)) for s in outer_sc]
434+
435+
sub[ex] = term(instream_rt, Val(length(innerfvs)), Val(length(outerfvs)), innerfvs..., innersvs..., outerfvs..., outersvs...)
436+
#=
342437
si = isempty(outer_sc) ? 0 : sum(s->max(states(s, fv), 0), outer_sc)
343438
for j in 1:n_inners; j == i && continue
344439
f = states(inner_sc[j], fv)
@@ -359,9 +454,9 @@ function expand_instream(instream_eqs, instream_exprs, connects; debug=false, to
359454
den += tmp
360455
num += tmp * instream(states(outer_sc[k], sv))
361456
end
362-
sub[ex] = num / den
457+
sub[ex] = mydiv(num, den)
458+
=#
363459
end
364-
365460
end
366461
end
367462

0 commit comments

Comments
 (0)