Skip to content

Commit 7cff503

Browse files
refactor: fix and document delay_to_function, implement it for System
1 parent 961e1b4 commit 7cff503

File tree

2 files changed

+71
-47
lines changed

2 files changed

+71
-47
lines changed

src/systems/codegen_utils.jl

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,74 @@ function array_variable_assignments(args...; argument_name = generated_argument_
8686
return assignments
8787
end
8888

89+
"""
90+
$(TYPEDSIGNATURES)
91+
92+
Check if the variable `var` is a delayed variable, where `iv` is the independent
93+
variable.
94+
"""
95+
function isdelay(var, iv)
96+
iv === nothing && return false
97+
isvariable(var) || return false
98+
isparameter(var) && return false
99+
if iscall(var) && !ModelingToolkit.isoperator(var, Symbolics.Operator)
100+
args = arguments(var)
101+
length(args) == 1 || return false
102+
isequal(args[1], iv) || return true
103+
end
104+
return false
105+
end
106+
107+
"""
108+
The argument of generated functions corresponding to the history function.
109+
"""
110+
const DDE_HISTORY_FUN = Sym{Symbolics.FnType{Tuple{Any, <:Real}, Vector{Real}}}(:___history___)
111+
112+
"""
113+
$(TYPEDSIGNATURES)
114+
115+
Turn delayed unknowns in `eqs` into calls to `DDE_HISTORY_FUNCTION`.
116+
117+
# Arguments
118+
119+
- `sys`: The system of DDEs.
120+
- `eqs`: The equations to convert.
121+
122+
# Keyword Arguments
123+
124+
- `param_arg`: The name of the variable containing the parameter object.
125+
"""
126+
function delay_to_function(
127+
sys::AbstractSystem, eqs = full_equations(sys); param_arg = MTKPARAMETERS_ARG)
128+
delay_to_function(eqs,
129+
get_iv(sys),
130+
Dict{Any, Int}(operation(s) => i for (i, s) in enumerate(unknowns(sys))),
131+
parameters(sys),
132+
DDE_HISTORY_FUN; param_arg)
133+
end
134+
function delay_to_function(eqs::Vector, iv, sts, ps, h; param_arg = MTKPARAMETERS_ARG)
135+
delay_to_function.(eqs, (iv,), (sts,), (ps,), (h,); param_arg)
136+
end
137+
function delay_to_function(eq::Equation, iv, sts, ps, h; param_arg = MTKPARAMETERS_ARG)
138+
delay_to_function(eq.lhs, iv, sts, ps, h; param_arg) ~ delay_to_function(
139+
eq.rhs, iv, sts, ps, h; param_arg)
140+
end
141+
function delay_to_function(expr, iv, sts, ps, h; param_arg = MTKPARAMETERS_ARG)
142+
if isdelay(expr, iv)
143+
v = operation(expr)
144+
time = arguments(expr)[1]
145+
idx = sts[v]
146+
return term(getindex, h(param_arg, time), idx, type = Real)
147+
elseif iscall(expr)
148+
return maketerm(typeof(expr),
149+
operation(expr),
150+
map(x -> delay_to_function(x, iv, sts, ps, h; param_arg), arguments(expr)),
151+
metadata(expr))
152+
else
153+
return expr
154+
end
155+
end
156+
89157
"""
90158
$(TYPEDSIGNATURES)
91159
@@ -138,11 +206,11 @@ function build_function_wrapper(sys::AbstractSystem, expr, args...; p_start = 2,
138206
obs = filter(filter_observed, observed(sys))
139207
# turn delayed unknowns into calls to the history function
140208
if wrap_delays
141-
history_arg = is_split(sys) ? MTKPARAMETERS_ARG : generated_argument_name(p_start)
209+
param_arg = is_split(sys) ? MTKPARAMETERS_ARG : generated_argument_name(p_start)
142210
obs = map(obs) do eq
143-
delay_to_function(sys, eq; history_arg)
211+
delay_to_function(sys, eq; param_arg)
144212
end
145-
expr = delay_to_function(sys, expr; history_arg)
213+
expr = delay_to_function(sys, expr; param_arg)
146214
# add extra argument
147215
args = (args[1:(p_start - 1)]..., DDE_HISTORY_FUN, args[p_start:end]...)
148216
p_start += 1

src/systems/diffeqs/abstractodesystem.jl

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -200,50 +200,6 @@ function generate_function(sys::AbstractODESystem, dvs = unknowns(sys),
200200
end
201201
end
202202

203-
function isdelay(var, iv)
204-
iv === nothing && return false
205-
isvariable(var) || return false
206-
isparameter(var) && return false
207-
if iscall(var) && !ModelingToolkit.isoperator(var, Symbolics.Operator)
208-
args = arguments(var)
209-
length(args) == 1 || return false
210-
isequal(args[1], iv) || return true
211-
end
212-
return false
213-
end
214-
const DDE_HISTORY_FUN = Sym{Symbolics.FnType{Tuple{Any, <:Real}, Vector{Real}}}(:___history___)
215-
const DEFAULT_PARAMS_ARG = Sym{Any}(:ˍ₋arg3)
216-
function delay_to_function(
217-
sys::AbstractODESystem, eqs = full_equations(sys); history_arg = DEFAULT_PARAMS_ARG)
218-
delay_to_function(eqs,
219-
get_iv(sys),
220-
Dict{Any, Int}(operation(s) => i for (i, s) in enumerate(unknowns(sys))),
221-
parameters(sys),
222-
DDE_HISTORY_FUN; history_arg)
223-
end
224-
function delay_to_function(eqs::Vector, iv, sts, ps, h; history_arg = DEFAULT_PARAMS_ARG)
225-
delay_to_function.(eqs, (iv,), (sts,), (ps,), (h,); history_arg)
226-
end
227-
function delay_to_function(eq::Equation, iv, sts, ps, h; history_arg = DEFAULT_PARAMS_ARG)
228-
delay_to_function(eq.lhs, iv, sts, ps, h; history_arg) ~ delay_to_function(
229-
eq.rhs, iv, sts, ps, h; history_arg)
230-
end
231-
function delay_to_function(expr, iv, sts, ps, h; history_arg = DEFAULT_PARAMS_ARG)
232-
if isdelay(expr, iv)
233-
v = operation(expr)
234-
time = arguments(expr)[1]
235-
idx = sts[v]
236-
return term(getindex, h(history_arg, time), idx, type = Real) # BIG BIG HACK
237-
elseif iscall(expr)
238-
return maketerm(typeof(expr),
239-
operation(expr),
240-
map(x -> delay_to_function(x, iv, sts, ps, h; history_arg), arguments(expr)),
241-
metadata(expr))
242-
else
243-
return expr
244-
end
245-
end
246-
247203
function calculate_massmatrix(sys::AbstractODESystem; simplify = false)
248204
eqs = [eq for eq in equations(sys)]
249205
M = zeros(length(eqs), length(eqs))

0 commit comments

Comments
 (0)