@@ -120,9 +120,14 @@ function generate_function(sys::AbstractODESystem, dvs = states(sys), ps = param
120
120
implicit_dae = false ,
121
121
ddvs = implicit_dae ? map (Differential (get_iv (sys)), dvs) :
122
122
nothing ,
123
+ isdde = false ,
123
124
has_difference = false ,
124
125
kwargs... )
125
- eqs = [eq for eq in equations (sys) if ! isdifferenceeq (eq)]
126
+ if isdde
127
+ eqs = delay_to_function (sys)
128
+ else
129
+ eqs = [eq for eq in equations (sys) if ! isdifferenceeq (eq)]
130
+ end
126
131
if ! implicit_dae
127
132
check_operator_variables (eqs, Differential)
128
133
check_lhs (eqs, Differential, Set (dvs))
@@ -136,15 +141,58 @@ function generate_function(sys::AbstractODESystem, dvs = states(sys), ps = param
136
141
p = map (x -> time_varying_as_func (value (x), sys), ps)
137
142
t = get_iv (sys)
138
143
139
- pre, sol_states = get_substitutions_and_solved_states (sys,
140
- no_postprocess = has_difference)
144
+ if isdde
145
+ build_function (rhss, u, DDE_HISTORY_FUN, p, t; kwargs... )
146
+ else
147
+ pre, sol_states = get_substitutions_and_solved_states (sys,
148
+ no_postprocess = has_difference)
141
149
142
- if implicit_dae
143
- build_function (rhss, ddvs, u, p, t; postprocess_fbody = pre, states = sol_states,
144
- kwargs... )
150
+ if implicit_dae
151
+ build_function (rhss, ddvs, u, p, t; postprocess_fbody = pre,
152
+ states = sol_states,
153
+ kwargs... )
154
+ else
155
+ build_function (rhss, u, p, t; postprocess_fbody = pre, states = sol_states,
156
+ kwargs... )
157
+ end
158
+ end
159
+ end
160
+
161
+ function isdelay (var, iv)
162
+ isvariable (var) || return false
163
+ if istree (var) && ! ModelingToolkit. isoperator (var, Symbolics. Operator)
164
+ args = arguments (var)
165
+ length (args) == 1 || return false
166
+ isequal (args[1 ], iv) || return true
167
+ end
168
+ return false
169
+ end
170
+ const DDE_HISTORY_FUN = Sym {Symbolics.FnType{Tuple{Any, <:Real}, Vector{Real}}} (:___history___ )
171
+ function delay_to_function (sys:: AbstractODESystem )
172
+ delay_to_function (full_equations (sys),
173
+ get_iv (sys),
174
+ Dict {Any, Int} (operation (s) => i for (i, s) in enumerate (states (sys))),
175
+ parameters (sys),
176
+ DDE_HISTORY_FUN)
177
+ end
178
+ function delay_to_function (eqs:: Vector{<:Equation} , iv, sts, ps, h)
179
+ delay_to_function .(eqs, (iv,), (sts,), (ps,), (h,))
180
+ end
181
+ function delay_to_function (eq:: Equation , iv, sts, ps, h)
182
+ delay_to_function (eq. lhs, iv, sts, ps, h) ~ delay_to_function (eq. rhs, iv, sts, ps, h)
183
+ end
184
+ function delay_to_function (expr, iv, sts, ps, h)
185
+ if isdelay (expr, iv)
186
+ v = operation (expr)
187
+ time = arguments (expr)[1 ]
188
+ idx = sts[v]
189
+ return term (getindex, h (Sym {Any} (:ˍ₋arg3 ), time), idx, type = Real) # BIG BIG HACK
190
+ elseif istree (expr)
191
+ return similarterm (expr,
192
+ operation (expr),
193
+ map (x -> delay_to_function (x, iv, sts, ps, h), arguments (expr)))
145
194
else
146
- build_function (rhss, u, p, t; postprocess_fbody = pre, states = sol_states,
147
- kwargs... )
195
+ return expr
148
196
end
149
197
end
150
198
@@ -485,6 +533,30 @@ function DiffEqBase.DAEFunction{iip}(sys::AbstractODESystem, dvs = states(sys),
485
533
observed = observedfun)
486
534
end
487
535
536
+ function DiffEqBase. DDEFunction (sys:: AbstractODESystem , args... ; kwargs... )
537
+ DDEFunction {true} (sys, args... ; kwargs... )
538
+ end
539
+
540
+ function DiffEqBase. DDEFunction {iip} (sys:: AbstractODESystem , dvs = states (sys),
541
+ ps = parameters (sys), u0 = nothing ;
542
+ eval_module = @__MODULE__ ,
543
+ checkbounds = false ,
544
+ kwargs... ) where {iip}
545
+ f_gen = generate_function (sys, dvs, ps; isdde = true ,
546
+ expression = Val{true },
547
+ expression_module = eval_module, checkbounds = checkbounds,
548
+ kwargs... )
549
+ f_oop, f_iip = (drop_expr (@RuntimeGeneratedFunction (eval_module, ex)) for ex in f_gen)
550
+ f (u, p, h, t) = f_oop (u, p, h, t)
551
+ f (du, u, p, h, t) = f_iip (du, u, p, h, t)
552
+
553
+ DDEFunction {iip} (f,
554
+ sys = sys,
555
+ syms = Symbol .(dvs),
556
+ indepsym = Symbol (get_iv (sys)),
557
+ paramsyms = Symbol .(ps))
558
+ end
559
+
488
560
"""
489
561
```julia
490
562
ODEFunctionExpr{iip}(sys::AbstractODESystem, dvs = states(sys),
577
649
"""
578
650
u0, p, defs = get_u0_p(sys, u0map, parammap; use_union=false, tofloat=!use_union)
579
651
580
- Take dictionaries with initial conditions and parameters and convert them to numeric arrays `u0` and `p`. Also return the merged dictionary `defs` containing the entire operating point.
652
+ Take dictionaries with initial conditions and parameters and convert them to numeric arrays `u0` and `p`. Also return the merged dictionary `defs` containing the entire operating point.
581
653
"""
582
654
function get_u0_p (sys, u0map, parammap; use_union = false , tofloat = ! use_union)
583
655
eqs = equations (sys)
@@ -802,6 +874,55 @@ function DiffEqBase.DAEProblem{iip}(sys::AbstractODESystem, du0map, u0map, tspan
802
874
end
803
875
end
804
876
877
+ function DiffEqBase. DDEProblem (sys:: AbstractODESystem , args... ; kwargs... )
878
+ DDEProblem {true} (sys, args... ; kwargs... )
879
+ end
880
+ function DiffEqBase. DDEProblem {iip} (sys:: AbstractODESystem , u0map = [],
881
+ h = (u, p) -> zeros (length (states (sts))),
882
+ tspan = get_tspan (sys),
883
+ parammap = DiffEqBase. NullParameters ();
884
+ callback = nothing ,
885
+ check_length = true ,
886
+ kwargs... ) where {iip}
887
+ has_difference = any (isdifferenceeq, equations (sys))
888
+ f, u0, p = process_DEProblem (DDEFunction{iip}, sys, u0map, parammap;
889
+ t = tspan != = nothing ? tspan[1 ] : tspan,
890
+ has_difference = has_difference,
891
+ check_length, kwargs... )
892
+ cbs = process_events (sys; callback, has_difference, kwargs... )
893
+ if has_discrete_subsystems (sys) && (dss = get_discrete_subsystems (sys)) != = nothing
894
+ affects, clocks, svs = ModelingToolkit. generate_discrete_affect (dss... )
895
+ discrete_cbs = map (affects, clocks, svs) do affect, clock, sv
896
+ if clock isa Clock
897
+ PeriodicCallback (DiscreteSaveAffect (affect, sv), clock. dt)
898
+ else
899
+ error (" $clock is not a supported clock type." )
900
+ end
901
+ end
902
+ if cbs === nothing
903
+ if length (discrete_cbs) == 1
904
+ cbs = only (discrete_cbs)
905
+ else
906
+ cbs = CallbackSet (discrete_cbs... )
907
+ end
908
+ else
909
+ cbs = CallbackSet (cbs, discrete_cbs)
910
+ end
911
+ else
912
+ svs = nothing
913
+ end
914
+ kwargs = filter_kwargs (kwargs)
915
+
916
+ kwargs1 = (;)
917
+ if cbs != = nothing
918
+ kwargs1 = merge (kwargs1, (callback = cbs,))
919
+ end
920
+ if svs != = nothing
921
+ kwargs1 = merge (kwargs1, (disc_saved_values = svs,))
922
+ end
923
+ DDEProblem {iip} (f, u0, h, tspan, p; kwargs1... , kwargs... )
924
+ end
925
+
805
926
"""
806
927
```julia
807
928
ODEProblemExpr{iip}(sys::AbstractODESystem, u0map, tspan,
0 commit comments