@@ -200,19 +200,14 @@ function generate_discrete_affect(
200
200
@static if VERSION < v " 1.7"
201
201
error (" The `generate_discrete_affect` function requires at least Julia 1.7" )
202
202
end
203
- use_index_cache = has_index_cache (osys) && get_index_cache (osys) != = nothing
203
+ has_index_cache (osys) && get_index_cache (osys) != = nothing ||
204
+ error (" Hybrid systems require `split = true`" )
204
205
out = Sym {Any} (:out )
205
206
appended_parameters = full_parameters (syss[continuous_id])
206
207
offset = length (appended_parameters)
207
- param_to_idx = if use_index_cache
208
- Dict {Any, ParameterIndex} (p => parameter_index (osys, p)
209
- for p in appended_parameters)
210
- else
211
- Dict {Any, Int} (reverse (en) for en in enumerate (appended_parameters))
212
- end
208
+ param_to_idx = Dict {Any, ParameterIndex} (p => parameter_index (osys, p)
209
+ for p in appended_parameters)
213
210
affect_funs = []
214
- init_funs = []
215
- svs = []
216
211
clocks = TimeDomain[]
217
212
for (i, (sys, input)) in enumerate (zip (syss, inputs))
218
213
i == continuous_id && continue
@@ -228,11 +223,7 @@ function generate_discrete_affect(
228
223
push! (fullvars, s)
229
224
end
230
225
needed_disc_to_cont_obs = []
231
- if use_index_cache
232
- disc_to_cont_idxs = ParameterIndex[]
233
- else
234
- disc_to_cont_idxs = Int[]
235
- end
226
+ disc_to_cont_idxs = ParameterIndex[]
236
227
for v in inputs[continuous_id]
237
228
_v = arguments (v)[1 ]
238
229
if _v in fullvars
@@ -252,7 +243,7 @@ function generate_discrete_affect(
252
243
end
253
244
append! (appended_parameters, input)
254
245
cont_to_disc_obs = build_explicit_observed_function (
255
- use_index_cache ? osys : syss[continuous_id] ,
246
+ osys,
256
247
needed_cont_to_disc_obs,
257
248
throw = false ,
258
249
expression = true ,
@@ -274,76 +265,20 @@ function generate_discrete_affect(
274
265
],
275
266
[],
276
267
let_block) |> toexpr
277
- if use_index_cache
278
- cont_to_disc_idxs = [parameter_index (osys, sym) for sym in input]
279
- disc_range = [parameter_index (osys, sym) for sym in unknowns (sys)]
280
- else
281
- cont_to_disc_idxs = (offset + 1 ): (offset += ni)
282
- input_offset = offset
283
- disc_range = (offset + 1 ): (offset += ns)
284
- end
285
- save_vec = Expr (:ref , :Float64 )
286
- if use_index_cache
287
- for unk in unknowns (sys)
288
- idx = parameter_index (osys, unk)
289
- push! (save_vec. args, :($ (parameter_values)(p, $ idx)))
290
- end
291
- else
292
- for i in 1 : ns
293
- push! (save_vec. args, :(p[$ (input_offset + i)]))
294
- end
295
- end
268
+ cont_to_disc_idxs = [parameter_index (osys, sym) for sym in input]
269
+ disc_range = [parameter_index (osys, sym) for sym in unknowns (sys)]
270
+ save_expr = :($ (SciMLBase. save_discretes!)(integrator, $ (i - 1 )))
296
271
empty_disc = isempty (disc_range)
297
- disc_init = if use_index_cache
298
- :(function (u, p, t)
299
- c2d_obs = $ cont_to_disc_obs
300
- d2c_obs = $ disc_to_cont_obs
301
- result = c2d_obs (u, p... , t)
302
- for (val, i) in zip (result, $ cont_to_disc_idxs)
303
- $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
304
- end
305
-
306
- disc_state = Tuple ($ (parameter_values)(p, i) for i in $ disc_range)
307
- result = d2c_obs (disc_state, p... , t)
308
- for (val, i) in zip (result, $ disc_to_cont_idxs)
309
- # prevent multiple updates to dependents
310
- _set_parameter_unchecked! (p, val, i; update_dependent = false )
311
- end
312
- discretes, repack, _ = $ (SciMLStructures. canonicalize)(
313
- $ (SciMLStructures. Discrete ()), p)
314
- repack (discretes) # to force recalculation of dependents
315
- end )
316
- else
317
- :(function (u, p, t)
318
- c2d_obs = $ cont_to_disc_obs
319
- d2c_obs = $ disc_to_cont_obs
320
- c2d_view = view (p, $ cont_to_disc_idxs)
321
- d2c_view = view (p, $ disc_to_cont_idxs)
322
- disc_unknowns = view (p, $ disc_range)
323
- copyto! (c2d_view, c2d_obs (u, p, t))
324
- copyto! (d2c_view, d2c_obs (disc_unknowns, p, t))
325
- end )
326
- end
327
272
328
273
# @show disc_to_cont_idxs
329
274
# @show cont_to_disc_idxs
330
275
# @show disc_range
331
- affect! = :(function (integrator, saved_values )
276
+ affect! = :(function (integrator)
332
277
@unpack u, p, t = integrator
333
278
c2d_obs = $ cont_to_disc_obs
334
279
d2c_obs = $ disc_to_cont_obs
335
- $ (
336
- if use_index_cache
337
- :(disc_unknowns = [$ (parameter_values)(p, i) for i in $ disc_range])
338
- else
339
- quote
340
- c2d_view = view (p, $ cont_to_disc_idxs)
341
- d2c_view = view (p, $ disc_to_cont_idxs)
342
- disc_unknowns = view (p, $ disc_range)
343
- end
344
- end
345
- )
346
280
# TODO : find a way to do this without allocating
281
+ disc_unknowns = [$ (parameter_values)(p, i) for i in $ disc_range]
347
282
disc = $ disc
348
283
349
284
# Write continuous into to discrete: handles `Sample`
@@ -355,77 +290,41 @@ function generate_discrete_affect(
355
290
# d2c comes last
356
291
# @show t
357
292
# @show "incoming", p
358
- $ (
359
- if use_index_cache
293
+ result = c2d_obs (integrator. u, p... , t)
294
+ for (val, i) in zip (result, $ cont_to_disc_idxs)
295
+ $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
296
+ end
297
+ $ (if ! empty_disc
360
298
quote
361
- result = c2d_obs ( integrator. u, p... , t)
362
- for (val, i) in zip (result , $ cont_to_disc_idxs )
299
+ disc (disc_unknowns, integrator. u, p... , t)
300
+ for (val, i) in zip (disc_unknowns , $ disc_range )
363
301
$ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
364
302
end
365
303
end
366
- else
367
- :(copyto! (c2d_view, c2d_obs (integrator. u, p, t)))
368
- end
369
- )
304
+ end )
370
305
# @show "after c2d", p
371
- $ (
372
- if use_index_cache
373
- quote
374
- if ! $ empty_disc
375
- disc (disc_unknowns, integrator. u, p... , t)
376
- for (val, i) in zip (disc_unknowns, $ disc_range)
377
- $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
378
- end
379
- end
380
- end
381
- else
382
- :($ empty_disc || disc (disc_unknowns, disc_unknowns, p, t))
383
- end
384
- )
385
306
# @show "after state update", p
386
- $ (
387
- if use_index_cache
388
- quote
389
- result = d2c_obs (disc_unknowns, p... , t)
390
- for (val, i) in zip (result, $ disc_to_cont_idxs)
391
- $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
392
- end
393
- end
394
- else
395
- :(copyto! (d2c_view, d2c_obs (disc_unknowns, p, t)))
307
+ result = d2c_obs (disc_unknowns, p... , t)
308
+ for (val, i) in zip (result, $ disc_to_cont_idxs)
309
+ $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
396
310
end
397
- )
398
311
399
- push! (saved_values. t, t)
400
- push! (saved_values. saveval, $ save_vec)
312
+ $ save_expr
401
313
402
314
# @show "after d2c", p
403
- $ (
404
- if use_index_cache
405
- quote
406
- discretes, repack, _ = $ (SciMLStructures. canonicalize)(
407
- $ (SciMLStructures. Discrete ()), p)
408
- repack (discretes)
409
- end
410
- end
411
- )
315
+ discretes, repack, _ = $ (SciMLStructures. canonicalize)(
316
+ $ (SciMLStructures. Discrete ()), p)
317
+ repack (discretes)
412
318
end )
413
- sv = SavedValues (Float64, Vector{Float64})
414
319
push! (affect_funs, affect!)
415
- push! (init_funs, disc_init)
416
- push! (svs, sv)
417
320
end
418
321
if eval_expression
419
322
affects = map (affect_funs) do a
420
323
drop_expr (@RuntimeGeneratedFunction (eval_module, toexpr (LiteralExpr (a))))
421
324
end
422
- inits = map (init_funs) do a
423
- drop_expr (@RuntimeGeneratedFunction (eval_module, toexpr (LiteralExpr (a))))
424
- end
425
325
else
426
326
affects = map (a -> toexpr (LiteralExpr (a)), affect_funs)
427
- inits = map (a -> toexpr (LiteralExpr (a)), init_funs)
428
327
end
429
328
defaults = Dict {Any, Any} (v => 0.0 for v in Iterators. flatten (inputs))
430
- return affects, inits, clocks, svs , appended_parameters, defaults
329
+ return affects, clocks, appended_parameters, defaults
431
330
end
0 commit comments