@@ -133,7 +133,10 @@ function split_system(ci::ClockInference{S}) where {S}
133
133
tss = similar (cid_to_eq, S)
134
134
for (id, ieqs) in enumerate (cid_to_eq)
135
135
ts_i = system_subset (ts, ieqs)
136
- @set! ts_i. structure. only_discrete = id != continuous_id
136
+ if id != continuous_id
137
+ ts_i = shift_discrete_system (ts_i)
138
+ @set! ts_i. structure. only_discrete = true
139
+ end
137
140
tss[id] = ts_i
138
141
end
139
142
return tss, inputs, continuous_id, id_to_clock
@@ -148,7 +151,7 @@ function generate_discrete_affect(
148
151
end
149
152
use_index_cache = has_index_cache (osys) && get_index_cache (osys) != = nothing
150
153
out = Sym {Any} (:out )
151
- appended_parameters = parameters (syss[continuous_id])
154
+ appended_parameters = full_parameters (syss[continuous_id])
152
155
offset = length (appended_parameters)
153
156
param_to_idx = if use_index_cache
154
157
Dict {Any, ParameterIndex} (p => parameter_index (osys, p)
@@ -157,6 +160,7 @@ function generate_discrete_affect(
157
160
Dict {Any, Int} (reverse (en) for en in enumerate (appended_parameters))
158
161
end
159
162
affect_funs = []
163
+ init_funs = []
160
164
svs = []
161
165
clocks = TimeDomain[]
162
166
for (i, (sys, input)) in enumerate (zip (syss, inputs))
@@ -183,47 +187,38 @@ function generate_discrete_affect(
183
187
if _v in fullvars
184
188
push! (needed_disc_to_cont_obs, _v)
185
189
push! (disc_to_cont_idxs, param_to_idx[v])
190
+ continue
186
191
end
187
192
188
- # In the above case, `_v` was in `observed(sys)`
189
- # It may also be in `unknowns(sys)`, in which case it
190
- # will be shifted back by one step
191
- if istree (v) && (op = operation (v)) isa Shift
192
- _v = arguments (_v)[1 ]
193
- _v = Shift (op. t, op. steps - 1 )(_v)
194
- else
195
- _v = Shift (get_iv (sys), - 1 )(_v)
196
- end
193
+ # If the held quantity is calculated through observed
194
+ # it will be shifted forward by 1
195
+ _v = Shift (get_iv (sys), 1 )(_v)
197
196
if _v in fullvars
198
197
push! (needed_disc_to_cont_obs, _v)
199
198
push! (disc_to_cont_idxs, param_to_idx[v])
199
+ continue
200
200
end
201
201
end
202
- append! (appended_parameters, input, unknowns (sys) )
202
+ append! (appended_parameters, input)
203
203
cont_to_disc_obs = build_explicit_observed_function (
204
204
use_index_cache ? osys : syss[continuous_id],
205
205
needed_cont_to_disc_obs,
206
206
throw = false ,
207
207
expression = true ,
208
208
output_type = SVector)
209
- @set! sys. ps = appended_parameters
210
209
disc_to_cont_obs = build_explicit_observed_function (sys, needed_disc_to_cont_obs,
211
210
throw = false ,
212
211
expression = true ,
213
212
output_type = SVector,
214
213
op = Shift,
215
- ps = reorder_parameters (osys, full_parameters (sys) ))
214
+ ps = reorder_parameters (osys, appended_parameters ))
216
215
ni = length (input)
217
216
ns = length (unknowns (sys))
218
217
disc = Func (
219
218
[
220
219
out,
221
220
DestructuredArgs (unknowns (osys)),
222
- if use_index_cache
223
- DestructuredArgs .(reorder_parameters (osys, full_parameters (osys)))
224
- else
225
- (DestructuredArgs (appended_parameters),)
226
- end ... ,
221
+ DestructuredArgs .(reorder_parameters (osys, full_parameters (osys)))... ,
227
222
get_iv (sys)
228
223
],
229
224
[],
@@ -248,6 +243,36 @@ function generate_discrete_affect(
248
243
end
249
244
end
250
245
empty_disc = isempty (disc_range)
246
+ disc_init = if use_index_cache
247
+ :(function (u, p, t)
248
+ c2d_obs = $ cont_to_disc_obs
249
+ d2c_obs = $ disc_to_cont_obs
250
+ result = c2d_obs (u, p... , t)
251
+ for (val, i) in zip (result, $ cont_to_disc_idxs)
252
+ $ (_set_parameter_unchecked!)(p, val, i; update_dependent = false )
253
+ end
254
+
255
+ disc_state = Tuple ($ (parameter_values)(p, i) for i in $ disc_range)
256
+ result = d2c_obs (disc_state, p... , t)
257
+ for (val, i) in zip (result, $ disc_to_cont_idxs)
258
+ # prevent multiple updates to dependents
259
+ _set_parameter_unchecked! (p, val, i; update_dependent = false )
260
+ end
261
+ discretes, repack, _ = $ (SciMLStructures. canonicalize)(
262
+ $ (SciMLStructures. Discrete ()), p)
263
+ repack (discretes) # to force recalculation of dependents
264
+ end )
265
+ else
266
+ :(function (u, p, t)
267
+ c2d_obs = $ cont_to_disc_obs
268
+ d2c_obs = $ disc_to_cont_obs
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
+ copyto! (c2d_view, c2d_obs (u, p, t))
273
+ copyto! (d2c_view, d2c_obs (disc_unknowns, p, t))
274
+ end )
275
+ end
251
276
252
277
# @show disc_to_cont_idxs
253
278
# @show cont_to_disc_idxs
@@ -270,9 +295,6 @@ function generate_discrete_affect(
270
295
# TODO : find a way to do this without allocating
271
296
disc = $ disc
272
297
273
- push! (saved_values. t, t)
274
- push! (saved_values. saveval, $ save_vec)
275
-
276
298
# Write continuous into to discrete: handles `Sample`
277
299
# Write discrete into to continuous
278
300
# Update discrete unknowns
@@ -322,6 +344,10 @@ function generate_discrete_affect(
322
344
:(copyto! (d2c_view, d2c_obs (disc_unknowns, p, t)))
323
345
end
324
346
)
347
+
348
+ push! (saved_values. t, t)
349
+ push! (saved_values. saveval, $ save_vec)
350
+
325
351
# @show "after d2c", p
326
352
$ (
327
353
if use_index_cache
@@ -335,15 +361,20 @@ function generate_discrete_affect(
335
361
end )
336
362
sv = SavedValues (Float64, Vector{Float64})
337
363
push! (affect_funs, affect!)
364
+ push! (init_funs, disc_init)
338
365
push! (svs, sv)
339
366
end
340
367
if eval_expression
341
368
affects = map (affect_funs) do a
342
369
drop_expr (@RuntimeGeneratedFunction (eval_module, toexpr (LiteralExpr (a))))
343
370
end
371
+ inits = map (init_funs) do a
372
+ drop_expr (@RuntimeGeneratedFunction (eval_module, toexpr (LiteralExpr (a))))
373
+ end
344
374
else
345
375
affects = map (a -> toexpr (LiteralExpr (a)), affect_funs)
376
+ inits = map (a -> toexpr (LiteralExpr (a)), init_funs)
346
377
end
347
378
defaults = Dict {Any, Any} (v => 0.0 for v in Iterators. flatten (inputs))
348
- return affects, clocks, svs, appended_parameters, defaults
379
+ return affects, inits, clocks, svs, appended_parameters, defaults
349
380
end
0 commit comments