@@ -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,59 @@ 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
+ iv === nothing && return false
163
+ isvariable (var) || return false
164
+ if istree (var) && ! ModelingToolkit. isoperator (var, Symbolics. Operator)
165
+ args = arguments (var)
166
+ length (args) == 1 || return false
167
+ isequal (args[1 ], iv) || return true
168
+ end
169
+ return false
170
+ end
171
+ const DDE_HISTORY_FUN = Sym {Symbolics.FnType{Tuple{Any, <:Real}, Vector{Real}}} (:___history___ )
172
+ function delay_to_function (sys:: AbstractODESystem )
173
+ delay_to_function (full_equations (sys),
174
+ get_iv (sys),
175
+ Dict {Any, Int} (operation (s) => i for (i, s) in enumerate (states (sys))),
176
+ parameters (sys),
177
+ DDE_HISTORY_FUN)
178
+ end
179
+ function delay_to_function (eqs:: Vector{<:Equation} , iv, sts, ps, h)
180
+ delay_to_function .(eqs, (iv,), (sts,), (ps,), (h,))
181
+ end
182
+ function delay_to_function (eq:: Equation , iv, sts, ps, h)
183
+ delay_to_function (eq. lhs, iv, sts, ps, h) ~ delay_to_function (eq. rhs, iv, sts, ps, h)
184
+ end
185
+ function delay_to_function (expr, iv, sts, ps, h)
186
+ if isdelay (expr, iv)
187
+ v = operation (expr)
188
+ time = arguments (expr)[1 ]
189
+ idx = sts[v]
190
+ return term (getindex, h (Sym {Any} (:ˍ₋arg3 ), time), idx, type = Real) # BIG BIG HACK
191
+ elseif istree (expr)
192
+ return similarterm (expr,
193
+ operation (expr),
194
+ map (x -> delay_to_function (x, iv, sts, ps, h), arguments (expr)))
145
195
else
146
- build_function (rhss, u, p, t; postprocess_fbody = pre, states = sol_states,
147
- kwargs... )
196
+ return expr
148
197
end
149
198
end
150
199
@@ -485,6 +534,30 @@ function DiffEqBase.DAEFunction{iip}(sys::AbstractODESystem, dvs = states(sys),
485
534
observed = observedfun)
486
535
end
487
536
537
+ function DiffEqBase. DDEFunction (sys:: AbstractODESystem , args... ; kwargs... )
538
+ DDEFunction {true} (sys, args... ; kwargs... )
539
+ end
540
+
541
+ function DiffEqBase. DDEFunction {iip} (sys:: AbstractODESystem , dvs = states (sys),
542
+ ps = parameters (sys), u0 = nothing ;
543
+ eval_module = @__MODULE__ ,
544
+ checkbounds = false ,
545
+ kwargs... ) where {iip}
546
+ f_gen = generate_function (sys, dvs, ps; isdde = true ,
547
+ expression = Val{true },
548
+ expression_module = eval_module, checkbounds = checkbounds,
549
+ kwargs... )
550
+ f_oop, f_iip = (drop_expr (@RuntimeGeneratedFunction (eval_module, ex)) for ex in f_gen)
551
+ f (u, p, h, t) = f_oop (u, p, h, t)
552
+ f (du, u, p, h, t) = f_iip (du, u, p, h, t)
553
+
554
+ DDEFunction {iip} (f,
555
+ sys = sys,
556
+ syms = Symbol .(dvs),
557
+ indepsym = Symbol (get_iv (sys)),
558
+ paramsyms = Symbol .(ps))
559
+ end
560
+
488
561
"""
489
562
```julia
490
563
ODEFunctionExpr{iip}(sys::AbstractODESystem, dvs = states(sys),
577
650
"""
578
651
u0, p, defs = get_u0_p(sys, u0map, parammap; use_union=false, tofloat=!use_union)
579
652
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.
653
+ 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
654
"""
582
- function get_u0_p (sys, u0map, parammap; use_union = false , tofloat = ! use_union)
655
+ function get_u0_p (sys,
656
+ u0map,
657
+ parammap;
658
+ use_union = false ,
659
+ tofloat = ! use_union,
660
+ symbolic_u0 = false )
583
661
eqs = equations (sys)
584
662
dvs = states (sys)
585
663
ps = parameters (sys)
@@ -588,7 +666,11 @@ function get_u0_p(sys, u0map, parammap; use_union = false, tofloat = !use_union)
588
666
defs = mergedefaults (defs, parammap, ps)
589
667
defs = mergedefaults (defs, u0map, dvs)
590
668
591
- u0 = varmap_to_vars (u0map, dvs; defaults = defs, tofloat = true )
669
+ if symbolic_u0
670
+ u0 = varmap_to_vars (u0map, dvs; defaults = defs, tofloat = false , use_union = false )
671
+ else
672
+ u0 = varmap_to_vars (u0map, dvs; defaults = defs, tofloat = true )
673
+ end
592
674
p = varmap_to_vars (parammap, ps; defaults = defs, tofloat, use_union)
593
675
p = p === nothing ? SciMLBase. NullParameters () : p
594
676
u0, p, defs
@@ -604,13 +686,14 @@ function process_DEProblem(constructor, sys::AbstractODESystem, u0map, parammap;
604
686
eval_expression = true ,
605
687
use_union = false ,
606
688
tofloat = ! use_union,
689
+ symbolic_u0 = false ,
607
690
kwargs... )
608
691
eqs = equations (sys)
609
692
dvs = states (sys)
610
693
ps = parameters (sys)
611
694
iv = get_iv (sys)
612
695
613
- u0, p, defs = get_u0_p (sys, u0map, parammap; tofloat, use_union)
696
+ u0, p, defs = get_u0_p (sys, u0map, parammap; tofloat, use_union, symbolic_u0 )
614
697
615
698
if implicit_dae && du0map != = nothing
616
699
ddvs = map (Differential (iv), dvs)
@@ -802,6 +885,62 @@ function DiffEqBase.DAEProblem{iip}(sys::AbstractODESystem, du0map, u0map, tspan
802
885
end
803
886
end
804
887
888
+ function generate_history (sys:: AbstractODESystem , u0; kwargs... )
889
+ build_function (u0, parameters (sys), get_iv (sys); expression = Val{false }, kwargs... )
890
+ end
891
+
892
+ function DiffEqBase. DDEProblem (sys:: AbstractODESystem , args... ; kwargs... )
893
+ DDEProblem {true} (sys, args... ; kwargs... )
894
+ end
895
+ function DiffEqBase. DDEProblem {iip} (sys:: AbstractODESystem , u0map = [],
896
+ tspan = get_tspan (sys),
897
+ parammap = DiffEqBase. NullParameters ();
898
+ callback = nothing ,
899
+ check_length = true ,
900
+ kwargs... ) where {iip}
901
+ has_difference = any (isdifferenceeq, equations (sys))
902
+ f, u0, p = process_DEProblem (DDEFunction{iip}, sys, u0map, parammap;
903
+ t = tspan != = nothing ? tspan[1 ] : tspan,
904
+ has_difference = has_difference,
905
+ symbolic_u0 = true ,
906
+ check_length, kwargs... )
907
+ h_oop, h_iip = generate_history (sys, u0)
908
+ h = h_oop
909
+ u0 = h (p, tspan[1 ])
910
+ cbs = process_events (sys; callback, has_difference, kwargs... )
911
+ if has_discrete_subsystems (sys) && (dss = get_discrete_subsystems (sys)) != = nothing
912
+ affects, clocks, svs = ModelingToolkit. generate_discrete_affect (dss... )
913
+ discrete_cbs = map (affects, clocks, svs) do affect, clock, sv
914
+ if clock isa Clock
915
+ PeriodicCallback (DiscreteSaveAffect (affect, sv), clock. dt)
916
+ else
917
+ error (" $clock is not a supported clock type." )
918
+ end
919
+ end
920
+ if cbs === nothing
921
+ if length (discrete_cbs) == 1
922
+ cbs = only (discrete_cbs)
923
+ else
924
+ cbs = CallbackSet (discrete_cbs... )
925
+ end
926
+ else
927
+ cbs = CallbackSet (cbs, discrete_cbs)
928
+ end
929
+ else
930
+ svs = nothing
931
+ end
932
+ kwargs = filter_kwargs (kwargs)
933
+
934
+ kwargs1 = (;)
935
+ if cbs != = nothing
936
+ kwargs1 = merge (kwargs1, (callback = cbs,))
937
+ end
938
+ if svs != = nothing
939
+ kwargs1 = merge (kwargs1, (disc_saved_values = svs,))
940
+ end
941
+ DDEProblem {iip} (f, u0, h, tspan, p; kwargs1... , kwargs... )
942
+ end
943
+
805
944
"""
806
945
```julia
807
946
ODEProblemExpr{iip}(sys::AbstractODESystem, u0map, tspan,
0 commit comments