@@ -146,12 +146,15 @@ function generate_discrete_affect(
146
146
@static if VERSION < v " 1.7"
147
147
error (" The `generate_discrete_affect` function requires at least Julia 1.7" )
148
148
end
149
- has_index_cache (osys) && get_index_cache (osys) != = nothing || error ( " System must have index_cache for clock support " )
149
+ use_index_cache = has_index_cache (osys) && get_index_cache (osys) != = nothing
150
150
out = Sym {Any} (:out )
151
151
appended_parameters = parameters (syss[continuous_id])
152
- param_to_idx = Dict {Any, ParameterIndex} (p => parameter_index (osys, p)
153
- for p in appended_parameters)
154
152
offset = length (appended_parameters)
153
+ param_to_idx = if use_index_cache
154
+ Dict {Any, ParameterIndex} (p => parameter_index (osys, p) for p in appended_parameters)
155
+ else
156
+ Dict {Any, Int} (reverse (en) for en in enumerate (appended_parameters))
157
+ end
155
158
affect_funs = []
156
159
init_funs = []
157
160
svs = []
@@ -170,18 +173,20 @@ function generate_discrete_affect(
170
173
push! (fullvars, s)
171
174
end
172
175
needed_disc_to_cont_obs = []
173
- disc_to_cont_idxs = ParameterIndex[]
176
+ if use_index_cache
177
+ disc_to_cont_idxs = ParameterIndex[]
178
+ else
179
+ disc_to_cont_idxs = Int[]
180
+ end
174
181
for v in inputs[continuous_id]
175
182
vv = arguments (v)[1 ]
176
183
if vv in fullvars
177
184
push! (needed_disc_to_cont_obs, vv)
178
- # @show param_to_idx[v] v
179
- # @assert param_to_idx[v].portion isa SciMLStructures.Discrete # TOOD: remove
180
185
push! (disc_to_cont_idxs, param_to_idx[v])
181
186
end
182
187
end
183
188
append! (appended_parameters, input, unknowns (sys))
184
- cont_to_disc_obs = build_explicit_observed_function (osys,
189
+ cont_to_disc_obs = build_explicit_observed_function (use_index_cache ? osys : syss[continuous_id] ,
185
190
needed_cont_to_disc_obs,
186
191
throw = false ,
187
192
expression = true ,
@@ -192,36 +197,62 @@ function generate_discrete_affect(
192
197
expression = true ,
193
198
output_type = SVector,
194
199
ps = reorder_parameters (osys, parameters (sys)))
200
+ ni = length (input)
201
+ ns = length (unknowns (sys))
195
202
disc = Func (
196
203
[
197
204
out,
198
205
DestructuredArgs (unknowns (osys)),
199
- DestructuredArgs .(reorder_parameters (osys, parameters (osys)))... ,
200
- # DestructuredArgs(appended_parameters),
206
+ if use_index_cache
207
+ DestructuredArgs .(reorder_parameters (osys, parameters (osys)))
208
+ else
209
+ (DestructuredArgs (appended_parameters),)
210
+ end ... ,
201
211
get_iv (sys)
202
212
],
203
213
[],
204
214
let_block)
205
- cont_to_disc_idxs = [parameter_index (osys, sym) for sym in input]
206
- disc_range = [parameter_index (osys, sym) for sym in unknowns (sys)]
215
+ if use_index_cache
216
+ cont_to_disc_idxs = [parameter_index (osys, sym) for sym in input]
217
+ disc_range = [parameter_index (osys, sym) for sym in unknowns (sys)]
218
+ else
219
+ cont_to_disc_idxs = (offset + 1 ): (offset += ni)
220
+ input_offset = offset
221
+ disc_range = (offset + 1 ): (offset += ns)
222
+ end
207
223
save_vec = Expr (:ref , :Float64 )
208
- for unk in unknowns (sys)
209
- idx = parameter_index (osys, unk)
210
- push! (save_vec. args, :($ (parameter_values)(p, $ idx)))
224
+ if use_index_cache
225
+ for unk in unknowns (sys)
226
+ idx = parameter_index (osys, unk)
227
+ push! (save_vec. args, :($ (parameter_values)(p, $ idx)))
228
+ end
229
+ else
230
+ for i in 1 : ns
231
+ push! (save_vec. args, :(p[$ (input_offset + i)]))
232
+ end
211
233
end
212
234
empty_disc = isempty (disc_range)
213
- disc_init = :(function (p, t)
214
- d2c_obs = $ disc_to_cont_obs
215
- disc_state = Tuple ($ (parameter_values)(p, i) for i in $ disc_range)
216
- result = d2c_obs (disc_state, p... , t)
217
- for (val, i) in zip (result, $ disc_to_cont_idxs)
218
- # prevent multiple updates to dependents
219
- _set_parameter_unchecked! (p, val, i; update_dependent = false )
220
- end
221
- discretes, repack, _ = $ (SciMLStructures. canonicalize)(
222
- $ (SciMLStructures. Discrete ()), p)
223
- repack (discretes) # to force recalculation of dependents
224
- end )
235
+ disc_init = if use_index_cache
236
+ :(function (p, t)
237
+ d2c_obs = $ disc_to_cont_obs
238
+ disc_state = Tuple ($ (parameter_values)(p, i) for i in $ disc_range)
239
+ result = d2c_obs (disc_state, p... , t)
240
+ for (val, i) in zip (result, $ disc_to_cont_idxs)
241
+ # prevent multiple updates to dependents
242
+ _set_parameter_unchecked! (p, val, i; update_dependent = false )
243
+ end
244
+ discretes, repack, _ = $ (SciMLStructures. canonicalize)(
245
+ $ (SciMLStructures. Discrete ()), p)
246
+ repack (discretes) # to force recalculation of dependents
247
+ end )
248
+ else
249
+ :(function (p, t)
250
+ d2c_obs = $ disc_to_cont_obs
251
+ d2c_view = view (p, $ disc_to_cont_idxs)
252
+ disc_state = view (p, $ disc_range)
253
+ copyto! (d2c_view, d2c_obs (disc_state, p, t))
254
+ end )
255
+ end
225
256
226
257
# @show disc_to_cont_idxs
227
258
# @show cont_to_disc_idxs
@@ -230,8 +261,18 @@ function generate_discrete_affect(
230
261
@unpack u, p, t = integrator
231
262
c2d_obs = $ cont_to_disc_obs
232
263
d2c_obs = $ disc_to_cont_obs
264
+ $ (
265
+ if use_index_cache
266
+ :(disc_unknowns = [$ (parameter_values)(p, i) for i in $ disc_range])
267
+ else
268
+ quote
269
+ c2d_view = view (p, $ cont_to_disc_idxs)
270
+ d2c_view = view (p, $ disc_to_cont_idxs)
271
+ disc_unknowns = view (p, $ disc_range)
272
+ end
273
+ end
274
+ )
233
275
# TODO : find a way to do this without allocating
234
- disc_unknowns = [$ (parameter_values)(p, i) for i in $ disc_range]
235
276
disc = $ disc
236
277
237
278
push! (saved_values. t, t)
@@ -246,26 +287,56 @@ function generate_discrete_affect(
246
287
# d2c comes last
247
288
# @show t
248
289
# @show "incoming", p
249
- result = c2d_obs (integrator. u, p... , t)
250
- for (val, i) in zip (result, $ cont_to_disc_idxs)
251
- $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
252
- end
290
+ $ (
291
+ if use_index_cache
292
+ quote
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
+ end
298
+ else
299
+ :(copyto! (c2d_view, c2d_obs (integrator. u, p, t)))
300
+ end
301
+ )
253
302
# @show "after c2d", p
254
- if ! $ empty_disc
255
- disc (disc_unknowns, integrator. u, p... , t)
256
- for (val, i) in zip (disc_unknowns, $ disc_range)
257
- $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
303
+ $ (
304
+ if use_index_cache
305
+ quote
306
+ if ! $ empty_disc
307
+ disc (disc_unknowns, integrator. u, p... , t)
308
+ for (val, i) in zip (disc_unknowns, $ disc_range)
309
+ $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
310
+ end
311
+ end
312
+ end
313
+ else
314
+ :($ empty_disc || disc (disc_unknowns, disc_unknowns, p, t))
258
315
end
259
- end
316
+ )
260
317
# @show "after state update", p
261
- result = d2c_obs (disc_unknowns, p... , t)
262
- for (val, i) in zip (result, $ disc_to_cont_idxs)
263
- $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
264
- end
318
+ $ (
319
+ if use_index_cache
320
+ quote
321
+ result = d2c_obs (disc_unknowns, p... , t)
322
+ for (val, i) in zip (result, $ disc_to_cont_idxs)
323
+ $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
324
+ end
325
+ end
326
+ else
327
+ :(copyto! (d2c_view, d2c_obs (disc_unknowns, p, t)))
328
+ end
329
+ )
265
330
# @show "after d2c", p
266
- discretes, repack, _ = $ (SciMLStructures. canonicalize)(
267
- $ (SciMLStructures. Discrete ()), p)
268
- repack (discretes)
331
+ $ (
332
+ if use_index_cache
333
+ quote
334
+ discretes, repack, _ = $ (SciMLStructures. canonicalize)(
335
+ $ (SciMLStructures. Discrete ()), p)
336
+ repack (discretes)
337
+ end
338
+ end
339
+ )
269
340
end )
270
341
sv = SavedValues (Float64, Vector{Float64})
271
342
push! (affect_funs, affect!)
0 commit comments