@@ -24,43 +24,22 @@ macro connector(expr)
24
24
esc (with_connector_type (expr))
25
25
end
26
26
27
- function connector_type (sys :: AbstractSystem )
28
- states (sys)
29
- end
27
+ abstract type AbstractConnectorType end
28
+ struct StreamConnector <: AbstractConnectorType end
29
+ struct RegularConnector <: AbstractConnectorType end
30
30
31
- promote_connect_rule (:: Type{T} , :: Type{S} ) where {T, S} = Union{}
32
- promote_connect_rule (:: Type{T} , :: Type{T} ) where {T} = T
33
- promote_connect_type (t1:: Type , t2:: Type , ts:: Type... ) = promote_connect_type (promote_connect_rule (t1, t2), ts... )
34
- @inline function promote_connect_type (:: Type{T} , :: Type{S} ) where {T,S}
35
- promote_connect_result (
36
- T,
37
- S,
38
- promote_connect_rule (T,S),
39
- promote_connect_rule (S,T)
40
- )
41
- end
42
-
43
- promote_connect_result (:: Type , :: Type , :: Type{T} , :: Type{Union{}} ) where {T} = T
44
- promote_connect_result (:: Type , :: Type , :: Type{Union{}} , :: Type{S} ) where {S} = S
45
- promote_connect_result (:: Type , :: Type , :: Type{T} , :: Type{T} ) where {T} = T
46
- function promote_connect_result (:: Type{T} , :: Type{S} , :: Type{P1} , :: Type{P2} ) where {T,S,P1,P2}
47
- throw (ArgumentError (" connection promotion for $T and $S resulted in $P1 and $P2 . " *
48
- " Define promotion only in one direction." ))
49
- end
50
-
51
- throw_connector_promotion (T, S) = throw (ArgumentError (" Don't know how to connect systems of type $S and $T " ))
52
- promote_connect_result (:: Type{T} ,:: Type{S} ,:: Type{Union{}} ,:: Type{Union{}} ) where {T,S} = throw_connector_promotion (T,S)
53
-
54
- promote_connect_type (:: Type{T} , :: Type{T} ) where {T} = T
55
- function promote_connect_type (T, S)
56
- error (" Don't know how to connect systems of type $S and $T " )
31
+ function connector_type (sys:: AbstractSystem )
32
+ sts = states (sys)
33
+ # TODO : check the criteria for stream connectors
34
+ any (s-> getmetadata (s, ModelingToolkit. VariableConnectType, nothing ) === Stream, sts) ? StreamConnector () : RegularConnector ()
57
35
end
58
36
59
37
Base. @kwdef struct Connection
60
38
inners = nothing
61
39
outers = nothing
62
40
end
63
41
42
+ # everything is inner by default until we expand the connections
64
43
Connection (syss) = Connection (inners= syss)
65
44
get_systems (c:: Connection ) = c. inners
66
45
@@ -78,12 +57,51 @@ function Base.show(io::IO, c::Connection)
78
57
end
79
58
end
80
59
81
- function connect (syss... )
60
+ function connect (syss:: AbstractSystem ... )
82
61
length (syss) >= 2 || error (" connect takes at least two systems!" )
83
62
length (unique (nameof, syss)) == length (syss) || error (" connect takes distinct systems!" )
84
63
Equation (Connection (), Connection (syss)) # the RHS are connected systems
85
64
end
86
65
66
+ function connect (c:: Connection ; check= true )
67
+ @unpack inners, outers = c
68
+
69
+ flow_eqs = Equation[]
70
+ other_eqs = Equation[]
71
+
72
+ cnts = Iterators. flatten ((inners, outers))
73
+ fs, ss = Iterators. peel (cnts)
74
+ splitting_idx = length (inners) # anything after the splitting_idx is outer.
75
+ first_sts = get_states (fs)
76
+ first_sts_set = Set (getname .(first_sts))
77
+ for sys in ss
78
+ current_sts = getname .(get_states (sys))
79
+ Set (current_sts) == first_sts_set || error (" $(nameof (sys)) ($current_sts ) doesn't match the connection type of $(nameof (fs)) ($first_sts )." )
80
+ end
81
+
82
+ ceqs = Equation[]
83
+ for s in first_sts
84
+ name = getname (s)
85
+ isflow = getmetadata (s, VariableConnectType, Equality) === Flow
86
+ rhs = 0 # only used for flow variables
87
+ fix_val = getproperty (fs, name) # used for equality connections
88
+ for (i, c) in enumerate (cnts)
89
+ isinner = i <= splitting_idx
90
+ # https://specification.modelica.org/v3.4/Ch15.html
91
+ var = getproperty (c, name)
92
+ if isflow
93
+ rhs += isinner ? var : - var
94
+ else
95
+ i == 1 && continue # skip the first iteration
96
+ push! (ceqs, fix_val ~ getproperty (c, name))
97
+ end
98
+ end
99
+ isflow && push! (ceqs, 0 ~ rhs)
100
+ end
101
+
102
+ return ceqs
103
+ end
104
+
87
105
isconnector (s:: AbstractSystem ) = has_connector_type (s) && get_connector_type (s) != = nothing
88
106
89
107
function isouterconnector (sys:: AbstractSystem ; check= true )
@@ -165,8 +183,7 @@ function expand_connections(sys::AbstractSystem; debug=false)
165
183
end
166
184
167
185
for c in narg_connects
168
- T = promote_connect_type (map (get_connector_type, c. outers)... , map (get_connector_type, c. inners)... )
169
- ceqs = connect (T, c)
186
+ ceqs = connect (c)
170
187
ceqs isa Equation ? push! (eqs, ceqs) : append! (eqs, ceqs)
171
188
end
172
189
0 commit comments