Skip to content

Commit e45aabf

Browse files
fix: remove delayed terms in initialization system of DDEs
1 parent c3af9ee commit e45aabf

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

src/systems/nonlinear/initializesystem.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ function generate_initializesystem(sys::AbstractSystem;
1717
eqs = Equation[x for x in eqs if x isa Equation]
1818
end
1919
trueobs, eqs = unhack_observed(observed(sys), eqs)
20+
# remove any observed equations that directly or indirectly contain
21+
# delayed unknowns
22+
isempty(trueobs) || filter_delay_equations_variables!(sys, trueobs)
2023
vars = unique([unknowns(sys); getfield.(trueobs, :lhs)])
2124
vars_set = Set(vars) # for efficient in-lookup
2225

@@ -261,6 +264,50 @@ function get_initial_value_parameter(sym)
261264
return toparam(newvar)
262265
end
263266

267+
"""
268+
$(TYPEDSIGNATURES)
269+
270+
Given `sys` and a list of observed equations `trueobs`, remove all the equations that
271+
directly or indirectly contain a delayed unknown of `sys`.
272+
"""
273+
function filter_delay_equations_variables!(sys::AbstractSystem, trueobs::Vector{Equation})
274+
banned_vars = Set()
275+
idxs_to_remove = Int[]
276+
for (i, eq) in enumerate(trueobs)
277+
_has_delays(sys, eq.rhs, banned_vars) || continue
278+
push!(idxs_to_remove, i)
279+
push!(banned_vars, eq.lhs)
280+
end
281+
return deleteat!(trueobs, idxs_to_remove)
282+
end
283+
284+
"""
285+
$(TYPEDSIGNATURES)
286+
287+
Check if the expression `ex` contains a delayed unknown of `sys` or a term in
288+
`banned`.
289+
"""
290+
function _has_delays(sys::AbstractSystem, ex, banned)
291+
ex = unwrap(ex)
292+
ex in banned && return true
293+
if symbolic_type(ex) == NotSymbolic()
294+
if is_array_of_symbolics(ex)
295+
return any(x -> _has_delays(sys, x, banned), ex)
296+
end
297+
return false
298+
end
299+
iscall(ex) || return false
300+
op = operation(ex)
301+
args = arguments(ex)
302+
if iscalledparameter(ex)
303+
return any(x -> _has_delays(sys, x, banned), args)
304+
end
305+
if issym(op) && length(args) == 1 && is_variable(sys, op(get_iv(sys))) && iscall(args[1]) && get_iv(sys) in vars(args[1])
306+
return true
307+
end
308+
return any(x -> _has_delays(sys, x, banned), args)
309+
end
310+
264311
struct ReconstructInitializeprob
265312
getter::Any
266313
setter::Any

0 commit comments

Comments
 (0)