@@ -81,83 +81,229 @@ const FMU_DIR = joinpath(@__DIR__, "fmus")
8181 end
8282end
8383
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
92119
120+ @testset " IO Model" begin
121+ function build_simple_adder (adder)
93122 @variables a (t) b (t) c (t) [guess = 1.0 ]
94123 @mtkbuild sys = ODESystem (
95124 [adder. a ~ a, adder. b ~ b, D (a) ~ t,
96125 D (b) ~ adder. out + adder. c, c^ 2 ~ adder. out + adder. value],
97126 t;
98127 systems = [adder])
99-
100128 # c will be solved for by initialization
101129 # 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 )
104151 @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
105156 end
106157 @testset " v2, CS" begin
107158 fmu = loadFMU (joinpath (FMU_DIR, " SimpleAdder.fmu" ); type = :CS )
108159 @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 ())
110162 @test MTK. isinput (adder. a)
111163 @test MTK. isinput (adder. b)
112164 @test MTK. isoutput (adder. out)
165+ @test MTK. isoutput (adder. out2)
113166 @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])
120167
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 )
126170 @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
127175 end
128176
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+
129194 @testset " v3, ME" begin
130195 fmu = loadFMU (joinpath (FMU_DIR, " StateSpace.fmu" ); type = :ME )
131196 @named sspace = MTK. FMIComponent (Val (3 ); fmu, type = :ME )
132197 @test MTK. isinput (sspace. u)
133198 @test MTK. isoutput (sspace. y)
134199 @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- )
140200
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 )
143203 @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
144208 end
145209
146210 @testset " v3, CS" begin
147211 fmu = loadFMU (joinpath (FMU_DIR, " StateSpace.fmu" ); type = :CS )
148212 @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 ())
150215 @test MTK. isinput (sspace. u)
151216 @test MTK. isoutput (sspace. y)
152217 @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
154232 @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
158295
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 )
161304 @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
162308 end
163309end
0 commit comments