@@ -81,83 +81,229 @@ const FMU_DIR = joinpath(@__DIR__, "fmus")
81
81
end
82
82
end
83
83
84
- @testset " IO Model" begin
85
- @testset " v2, ME" begin
86
- fmu = loadFMU (joinpath (FMU_DIR, " SimpleAdder.fmu" ); type = :ME )
87
- @named adder = MTK. FMIComponent (Val (2 ); fmu, type = :ME )
88
- @test MTK. isinput (adder. a)
89
- @test MTK. isinput (adder. b)
90
- @test MTK. isoutput (adder. out)
91
- @test ! MTK. isinput (adder. c) && ! MTK. isoutput (adder. c)
84
+ @mtkmodel SimpleAdder begin
85
+ @variables begin
86
+ a (t)
87
+ b (t)
88
+ c (t)
89
+ out (t)
90
+ out2 (t)
91
+ end
92
+ @parameters begin
93
+ value = 1.0
94
+ end
95
+ @equations begin
96
+ out ~ a + b + value
97
+ D (c) ~ out
98
+ out2 ~ 2 c
99
+ end
100
+ end
101
+
102
+ @mtkmodel StateSpace begin
103
+ @variables begin
104
+ x (t)
105
+ y (t)
106
+ u (t)
107
+ end
108
+ @parameters begin
109
+ A = 1.0
110
+ B = 1.0
111
+ C = 1.0
112
+ _D = 1.0
113
+ end
114
+ @equations begin
115
+ D (x) ~ A * x + B * u
116
+ y ~ C * x + _D * u
117
+ end
118
+ end
92
119
120
+ @testset " IO Model" begin
121
+ function build_simple_adder (adder)
93
122
@variables a (t) b (t) c (t) [guess = 1.0 ]
94
123
@mtkbuild sys = ODESystem (
95
124
[adder. a ~ a, adder. b ~ b, D (a) ~ t,
96
125
D (b) ~ adder. out + adder. c, c^ 2 ~ adder. out + adder. value],
97
126
t;
98
127
systems = [adder])
99
-
100
128
# c will be solved for by initialization
101
129
# this tests that initialization also works with FMUs
102
- prob = ODEProblem (sys, [sys. adder. c => 1.0 , sys. a => 1.0 , sys. b => 1.0 ], (0.0 , 1.0 ))
103
- sol = solve (prob, Rodas5P (autodiff = false ))
130
+ prob = ODEProblem (sys, [sys. adder. c => 2.0 , sys. a => 1.0 , sys. b => 1.0 ],
131
+ (0.0 , 1.0 ), [sys. adder. value => 2.0 ])
132
+ return sys, prob
133
+ end
134
+
135
+ @named adder = SimpleAdder ()
136
+ truesys, trueprob = build_simple_adder (adder)
137
+ truesol = solve (trueprob, abstol = 1e-8 , reltol = 1e-8 )
138
+ @test SciMLBase. successful_retcode (truesol)
139
+
140
+ @testset " v2, ME" begin
141
+ fmu = loadFMU (joinpath (FMU_DIR, " SimpleAdder.fmu" ); type = :ME )
142
+ @named adder = MTK. FMIComponent (Val (2 ); fmu, type = :ME )
143
+ @test MTK. isinput (adder. a)
144
+ @test MTK. isinput (adder. b)
145
+ @test MTK. isoutput (adder. out)
146
+ @test MTK. isoutput (adder. out2)
147
+ @test ! MTK. isinput (adder. c) && ! MTK. isoutput (adder. c)
148
+
149
+ sys, prob = build_simple_adder (adder)
150
+ sol = solve (prob, Rodas5P (autodiff = false ), abstol = 1e-8 , reltol = 1e-8 )
104
151
@test SciMLBase. successful_retcode (sol)
152
+
153
+ @test truesol (sol. t;
154
+ idxs = [truesys. a, truesys. b, truesys. c, truesys. adder. c]). u≈ sol[[
155
+ sys. a, sys. b, sys. c, sys. adder. c]] rtol= 1e-7
105
156
end
106
157
@testset " v2, CS" begin
107
158
fmu = loadFMU (joinpath (FMU_DIR, " SimpleAdder.fmu" ); type = :CS )
108
159
@named adder = MTK. FMIComponent (
109
- Val (2 ); fmu, type = :CS , communication_step_size = 0.001 )
160
+ Val (2 ); fmu, type = :CS , communication_step_size = 1e-3 ,
161
+ reinitializealg = BrownFullBasicInit ())
110
162
@test MTK. isinput (adder. a)
111
163
@test MTK. isinput (adder. b)
112
164
@test MTK. isoutput (adder. out)
165
+ @test MTK. isoutput (adder. out2)
113
166
@test ! MTK. isinput (adder. c) && ! MTK. isoutput (adder. c)
114
- @variables a (t) b (t) c (t) [guess = 1.0 ]
115
- @mtkbuild sys = ODESystem (
116
- [adder. a ~ a, adder. b ~ b, D (a) ~ t,
117
- D (b) ~ adder. out + adder. c, c^ 2 ~ adder. out + adder. value],
118
- t;
119
- systems = [adder])
120
167
121
- # c will be solved for by initialization
122
- # this tests that initialization also works with FMUs
123
- prob = ODEProblem (sys, [sys. adder. c => 1.0 , sys. a => 1.0 , sys. b => 1.0 ],
124
- (0.0 , 1.0 ); use_scc = false )
125
- sol = solve (prob, Rodas5P (autodiff = false ))
168
+ sys, prob = build_simple_adder (adder)
169
+ sol = solve (prob, Rodas5P (autodiff = false ), abstol = 1e-8 , reltol = 1e-8 )
126
170
@test SciMLBase. successful_retcode (sol)
171
+
172
+ @test truesol (sol. t; idxs = [truesys. a, truesys. b, truesys. c]). u≈ sol. u rtol= 1e-2
173
+ # sys.adder.c is a discrete variable
174
+ @test truesol (sol. t; idxs = truesys. adder. c)≈ sol (sol. t; idxs = sys. adder. c) rtol= 1e-3
127
175
end
128
176
177
+ function build_sspace_model (sspace)
178
+ @variables u (t)= 1.0 x (t)= 1.0 y (t) [guess = 1.0 ]
179
+ @mtkbuild sys = ODESystem (
180
+ [sspace. u ~ u, D (u) ~ t, D (x) ~ sspace. x + sspace. y, y^ 2 ~ sspace. y + sspace. x], t;
181
+ systems = [sspace]
182
+ )
183
+
184
+ prob = ODEProblem (
185
+ sys, [sys. sspace. x => 1.0 ], (0.0 , 1.0 ), [sys. sspace. A => 2.0 ]; use_scc = false )
186
+ return sys, prob
187
+ end
188
+
189
+ @named sspace = StateSpace ()
190
+ truesys, trueprob = build_sspace_model (sspace)
191
+ truesol = solve (trueprob, abstol = 1e-8 , reltol = 1e-8 )
192
+ @test SciMLBase. successful_retcode (truesol)
193
+
129
194
@testset " v3, ME" begin
130
195
fmu = loadFMU (joinpath (FMU_DIR, " StateSpace.fmu" ); type = :ME )
131
196
@named sspace = MTK. FMIComponent (Val (3 ); fmu, type = :ME )
132
197
@test MTK. isinput (sspace. u)
133
198
@test MTK. isoutput (sspace. y)
134
199
@test ! MTK. isinput (sspace. x) && ! MTK. isoutput (sspace. x)
135
- @variables u (t)= 1.0 x (t)= 1.0 y (t) [guess = 1.0 ]
136
- @mtkbuild sys = ODESystem (
137
- [sspace. u ~ u, D (u) ~ t, D (x) ~ sspace. x + sspace. y, y^ 2 ~ sspace. y + x], t;
138
- systems = [sspace]
139
- )
140
200
141
- prob = ODEProblem ( sys, [sys . sspace . x => 1.0 ], ( 0.0 , 1.0 ); use_scc = false )
142
- sol = solve (prob, Rodas5P (autodiff = false ))
201
+ sys, prob = build_sspace_model (sspace )
202
+ sol = solve (prob, Rodas5P (autodiff = false ); abstol = 1e-8 , reltol = 1e-8 )
143
203
@test SciMLBase. successful_retcode (sol)
204
+
205
+ @test truesol (sol. t;
206
+ idxs = [truesys. u, truesys. x, truesys. y, truesys. sspace. x]). u≈ sol[[
207
+ sys. u, sys. x, sys. y, sys. sspace. x]] rtol= 1e-7
144
208
end
145
209
146
210
@testset " v3, CS" begin
147
211
fmu = loadFMU (joinpath (FMU_DIR, " StateSpace.fmu" ); type = :CS )
148
212
@named sspace = MTK. FMIComponent (
149
- Val (3 ); fmu, communication_step_size = 1e-3 , type = :CS )
213
+ Val (3 ); fmu, communication_step_size = 1e-4 , type = :CS ,
214
+ reinitializealg = BrownFullBasicInit ())
150
215
@test MTK. isinput (sspace. u)
151
216
@test MTK. isoutput (sspace. y)
152
217
@test ! MTK. isinput (sspace. x) && ! MTK. isoutput (sspace. x)
153
- @variables u (t)= 1.0 x (t)= 1.0 y (t) [guess = 1.0 ]
218
+
219
+ sys, prob = build_sspace_model (sspace)
220
+ sol = solve (prob, Rodas5P (autodiff = false ); abstol = 1e-8 , reltol = 1e-8 )
221
+ @test SciMLBase. successful_retcode (sol)
222
+
223
+ @test truesol (
224
+ sol. t; idxs = [truesys. u, truesys. x, truesys. y]). u≈ sol[[sys. u, sys. x, sys. y]] rtol= 1e-2
225
+ @test truesol (sol. t; idxs = truesys. sspace. x). u≈ sol (sol. t; idxs = sys. sspace. x). u rtol= 1e-2
226
+ end
227
+ end
228
+
229
+ @testset " FMUs in a loop" begin
230
+ function build_looped_adders (adder1, adder2)
231
+ @variables x (t) = 1
154
232
@mtkbuild sys = ODESystem (
155
- [sspace. u ~ u, D (u) ~ t, D (x) ~ sspace. x + sspace. y, y^ 2 ~ sspace. y + x], t;
156
- systems = [sspace]
157
- )
233
+ [D (x) ~ x, adder1. a ~ adder2. out2,
234
+ adder2. a ~ adder1. out2, adder1. b ~ 1.0 , adder2. b ~ 2.0 ],
235
+ t;
236
+ systems = [adder1, adder2])
237
+ prob = ODEProblem (
238
+ sys, [adder1. c => 1.0 , adder2. c => 1.0 , adder1. a => 2.0 ], (0.0 , 1.0 ))
239
+ return sys, prob
240
+ end
241
+ @named adder1 = SimpleAdder ()
242
+ @named adder2 = SimpleAdder ()
243
+ truesys, trueprob = build_looped_adders (adder1, adder2)
244
+ truesol = solve (trueprob, Tsit5 (), reltol = 1e-8 )
245
+ @test SciMLBase. successful_retcode (truesol)
246
+
247
+ @testset " v2, ME" begin
248
+ fmu = loadFMU (joinpath (FMU_DIR, " SimpleAdder.fmu" ); type = :ME )
249
+ @named adder1 = MTK. FMIComponent (Val (2 ); fmu, type = :ME )
250
+ @named adder2 = MTK. FMIComponent (Val (2 ); fmu, type = :ME )
251
+ sys, prob = build_looped_adders (adder1, adder2)
252
+ sol = solve (prob, Rodas5P (autodiff = false ); reltol = 1e-8 )
253
+ @test SciMLBase. successful_retcode (sol)
254
+ @test truesol (sol. t;
255
+ idxs = [truesys. adder1. c, truesys. adder2. c]). u≈ sol (
256
+ sol. t; idxs = [sys. adder1. c, sys. adder2. c]). u rtol= 1e-7
257
+ end
258
+ @testset " v2, CS" begin
259
+ fmu = loadFMU (joinpath (FMU_DIR, " SimpleAdder.fmu" ); type = :CS )
260
+ @named adder1 = MTK. FMIComponent (
261
+ Val (2 ); fmu, type = :CS , communication_step_size = 1e-3 )
262
+ @named adder2 = MTK. FMIComponent (
263
+ Val (2 ); fmu, type = :CS , communication_step_size = 1e-3 )
264
+ sys, prob = build_looped_adders (adder1, adder2)
265
+ sol = solve (prob, Tsit5 (); reltol = 1e-8 )
266
+ @test truesol (sol. t;
267
+ idxs = [truesys. adder1. c, truesys. adder2. c]). u≈ sol (
268
+ sol. t; idxs = [sys. adder1. c, sys. adder2. c]). u rtol= 1e-3
269
+ end
270
+
271
+ function build_looped_sspace (sspace1, sspace2)
272
+ @variables x (t) = 1
273
+ @mtkbuild sys = ODESystem ([D (x) ~ x, sspace1. u ~ sspace2. x, sspace2. u ~ sspace1. y],
274
+ t; systems = [sspace1, sspace2])
275
+ prob = ODEProblem (sys, [sspace1. x => 1.0 , sspace2. x => 1.0 ], (0.0 , 1.0 ))
276
+ return sys, prob
277
+ end
278
+ @named sspace1 = StateSpace ()
279
+ @named sspace2 = StateSpace ()
280
+ truesys, trueprob = build_looped_sspace (sspace1, sspace2)
281
+ truesol = solve (trueprob, Rodas5P (), reltol = 1e-8 )
282
+ @test SciMLBase. successful_retcode (truesol)
283
+
284
+ @testset " v3, ME" begin
285
+ fmu = loadFMU (joinpath (FMU_DIR, " StateSpace.fmu" ); type = :ME )
286
+ @named sspace1 = MTK. FMIComponent (Val (3 ); fmu, type = :ME )
287
+ @named sspace2 = MTK. FMIComponent (Val (3 ); fmu, type = :ME )
288
+ sys, prob = build_looped_sspace (sspace1, sspace2)
289
+ sol = solve (prob, Rodas5P (autodiff = false ); reltol = 1e-8 )
290
+ @test SciMLBase. successful_retcode (sol)
291
+ @test truesol (sol. t;
292
+ idxs = [truesys. sspace1. x, truesys. sspace2. x]). u≈ sol (
293
+ sol. t; idxs = [sys. sspace1. x, sys. sspace2. x]). u rtol= 1e-7
294
+ end
158
295
159
- prob = ODEProblem (sys, [sys. sspace. x => 1.0 ], (0.0 , 1.0 ); use_scc = false )
160
- sol = solve (prob, Rodas5P (autodiff = false ))
296
+ @testset " v3, CS" begin
297
+ fmu = loadFMU (joinpath (FMU_DIR, " StateSpace.fmu" ); type = :CS )
298
+ @named sspace1 = MTK. FMIComponent (
299
+ Val (3 ); fmu, type = :CS , communication_step_size = 1e-4 )
300
+ @named sspace2 = MTK. FMIComponent (
301
+ Val (3 ); fmu, type = :CS , communication_step_size = 1e-4 )
302
+ sys, prob = build_looped_sspace (sspace1, sspace2)
303
+ sol = solve (prob, Rodas5P (autodiff = false ); reltol = 1e-8 )
161
304
@test SciMLBase. successful_retcode (sol)
305
+ @test truesol (sol. t;
306
+ idxs = [truesys. sspace1. x, truesys. sspace2. x]). u≈ sol (
307
+ sol. t; idxs = [sys. sspace1. x, sys. sspace2. x]). u rtol= 1e-2
162
308
end
163
309
end
0 commit comments