@@ -240,3 +240,87 @@ ci, varmap = infer_clocks(cl)
240
240
@test varmap[f. u] == Clock (t, 0.5 )
241
241
@test varmap[p. u] == Continuous ()
242
242
@test varmap[c. r] == Clock (t, 0.5 )
243
+
244
+
245
+ # # Multiple clock rates
246
+ @info " Testing multi-rate hybrid system"
247
+ dt = 0.1
248
+ dt2 = 0.2
249
+ @variables t x (t)= 0 y (t)= 0 u (t)= 0 r (t)= 1 yd1 (t)= 0 ud1 (t)= 0 yd2 (t)= 0 ud2 (t)= 0
250
+ @parameters kp= 1
251
+ D = Differential (t)
252
+
253
+ eqs = [
254
+ # controller (time discrete part `dt=0.1`)
255
+ yd1 ~ Sample (t, dt)(y)
256
+ ud1 ~ kp * (Sample (t, dt)(r) - yd1)
257
+ # controller (time discrete part `dt=0.2`)
258
+ yd2 ~ Sample (t, dt2)(y)
259
+ ud2 ~ kp * (Sample (t, dt2)(r) - yd2)
260
+
261
+ # plant (time continuous part)
262
+ u ~ Hold (ud1) + Hold (ud2)
263
+ D (x) ~ - x + u
264
+ y ~ x
265
+ ]
266
+
267
+ @named cl = ODESystem (eqs, t)
268
+
269
+ d = Clock (t, dt)
270
+ d2 = Clock (t, dt2)
271
+
272
+ ci, varmap = infer_clocks (cl)
273
+ @test varmap[yd1] == d
274
+ @test varmap[ud1] == d
275
+ @test varmap[yd2] == d2
276
+ @test varmap[ud2] == d2
277
+ @test varmap[r] == Continuous ()
278
+ @test varmap[x] == Continuous ()
279
+ @test varmap[y] == Continuous ()
280
+ @test varmap[u] == Continuous ()
281
+
282
+ ss = structural_simplify (cl)
283
+
284
+ prob = ODEProblem (ss, [x=> 0.0 ], (0.0 , 1.0 ), [kp => 1.0 ])
285
+ sol = solve (prob, Tsit5 (), kwargshandle = KeywordArgSilent)
286
+
287
+ function foo! (dx, x, p, t)
288
+ kp, ud1, ud2 = p
289
+ dx[1 ] = - x[1 ] + ud1 + ud2
290
+ end
291
+
292
+ function affect1! (integrator, saved_values)
293
+ kp = integrator. p[1 ]
294
+ y = integrator. u[1 ]
295
+ r = 1.0
296
+ ud1 = kp * (r - y)
297
+ push! (saved_values. t, integrator. t)
298
+ push! (saved_values. saveval, [integrator. p[4 ]])
299
+ integrator. p[2 ] = ud1
300
+ nothing
301
+ end
302
+ function affect2! (integrator, saved_values)
303
+ kp = integrator. p[1 ]
304
+ y = integrator. u[1 ]
305
+ r = 1.0
306
+ ud2 = kp * (r - y)
307
+ push! (saved_values. t, integrator. t)
308
+ push! (saved_values. saveval, [integrator. p[5 ]])
309
+ integrator. p[3 ] = ud2
310
+ nothing
311
+ end
312
+ saved_values1 = SavedValues (Float64, Vector{Float64})
313
+ saved_values2 = SavedValues (Float64, Vector{Float64})
314
+ cb1 = PeriodicCallback (Base. Fix2 (affect1!, saved_values1), dt)
315
+ cb2 = PeriodicCallback (Base. Fix2 (affect2!, saved_values2), dt2)
316
+ cb = CallbackSet (cb1, cb2)
317
+ prob = ODEProblem (foo!, [0.0 ], (0.0 , 1.0 ), [1.0 , 0.0 , 0.0 , 0.0 , 0.0 ], callback = cb)
318
+ sol2 = solve (prob, Tsit5 ())
319
+
320
+
321
+ @test sol. u == sol2. u
322
+ @test saved_values1. t == sol. prob. kwargs[:disc_saved_values ][1 ]. t
323
+ @test saved_values1. saveval == sol. prob. kwargs[:disc_saved_values ][1 ]. saveval
324
+
325
+ @test saved_values2. t == sol. prob. kwargs[:disc_saved_values ][2 ]. t
326
+ @test saved_values2. saveval == sol. prob. kwargs[:disc_saved_values ][2 ]. saveval
0 commit comments