@@ -133,7 +133,10 @@ function split_system(ci::ClockInference{S}) where {S}
133133 tss = similar (cid_to_eq, S)
134134 for (id, ieqs) in enumerate (cid_to_eq)
135135 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
137140 tss[id] = ts_i
138141 end
139142 return tss, inputs, continuous_id, id_to_clock
@@ -148,7 +151,7 @@ function generate_discrete_affect(
148151 end
149152 use_index_cache = has_index_cache (osys) && get_index_cache (osys) != = nothing
150153 out = Sym {Any} (:out )
151- appended_parameters = parameters (syss[continuous_id])
154+ appended_parameters = full_parameters (syss[continuous_id])
152155 offset = length (appended_parameters)
153156 param_to_idx = if use_index_cache
154157 Dict {Any, ParameterIndex} (p => parameter_index (osys, p)
@@ -157,6 +160,7 @@ function generate_discrete_affect(
157160 Dict {Any, Int} (reverse (en) for en in enumerate (appended_parameters))
158161 end
159162 affect_funs = []
163+ init_funs = []
160164 svs = []
161165 clocks = TimeDomain[]
162166 for (i, (sys, input)) in enumerate (zip (syss, inputs))
@@ -183,47 +187,38 @@ function generate_discrete_affect(
183187 if _v in fullvars
184188 push! (needed_disc_to_cont_obs, _v)
185189 push! (disc_to_cont_idxs, param_to_idx[v])
190+ continue
186191 end
187192
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)
197196 if _v in fullvars
198197 push! (needed_disc_to_cont_obs, _v)
199198 push! (disc_to_cont_idxs, param_to_idx[v])
199+ continue
200200 end
201201 end
202- append! (appended_parameters, input, unknowns (sys) )
202+ append! (appended_parameters, input)
203203 cont_to_disc_obs = build_explicit_observed_function (
204204 use_index_cache ? osys : syss[continuous_id],
205205 needed_cont_to_disc_obs,
206206 throw = false ,
207207 expression = true ,
208208 output_type = SVector)
209- @set! sys. ps = appended_parameters
210209 disc_to_cont_obs = build_explicit_observed_function (sys, needed_disc_to_cont_obs,
211210 throw = false ,
212211 expression = true ,
213212 output_type = SVector,
214213 op = Shift,
215- ps = reorder_parameters (osys, full_parameters (sys) ))
214+ ps = reorder_parameters (osys, appended_parameters ))
216215 ni = length (input)
217216 ns = length (unknowns (sys))
218217 disc = Func (
219218 [
220219 out,
221220 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)))... ,
227222 get_iv (sys)
228223 ],
229224 [],
@@ -248,6 +243,36 @@ function generate_discrete_affect(
248243 end
249244 end
250245 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
251276
252277 # @show disc_to_cont_idxs
253278 # @show cont_to_disc_idxs
@@ -270,9 +295,6 @@ function generate_discrete_affect(
270295 # TODO : find a way to do this without allocating
271296 disc = $ disc
272297
273- push! (saved_values. t, t)
274- push! (saved_values. saveval, $ save_vec)
275-
276298 # Write continuous into to discrete: handles `Sample`
277299 # Write discrete into to continuous
278300 # Update discrete unknowns
@@ -322,6 +344,10 @@ function generate_discrete_affect(
322344 :(copyto! (d2c_view, d2c_obs (disc_unknowns, p, t)))
323345 end
324346 )
347+
348+ push! (saved_values. t, t)
349+ push! (saved_values. saveval, $ save_vec)
350+
325351 # @show "after d2c", p
326352 $ (
327353 if use_index_cache
@@ -335,15 +361,20 @@ function generate_discrete_affect(
335361 end )
336362 sv = SavedValues (Float64, Vector{Float64})
337363 push! (affect_funs, affect!)
364+ push! (init_funs, disc_init)
338365 push! (svs, sv)
339366 end
340367 if eval_expression
341368 affects = map (affect_funs) do a
342369 drop_expr (@RuntimeGeneratedFunction (eval_module, toexpr (LiteralExpr (a))))
343370 end
371+ inits = map (init_funs) do a
372+ drop_expr (@RuntimeGeneratedFunction (eval_module, toexpr (LiteralExpr (a))))
373+ end
344374 else
345375 affects = map (a -> toexpr (LiteralExpr (a)), affect_funs)
376+ inits = map (a -> toexpr (LiteralExpr (a)), init_funs)
346377 end
347378 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
349380end
0 commit comments