Describe the bug 🐞
Evaluating an observed variable of a non-Markovian ModelingToolkit system over an interpolated vector of times throws a MethodError because SymbolicIndexingInterface.get_history_function is called with a RecursiveArrayTools.DiffEqArray.
The saved solution values can be indexed successfully (sol[sys.y]). The failure occurs only when requesting interpolated values, including through the standard plotting recipe (plot(sol; idxs = sys.y)).
Expected behavior
A symbolic observed variable of a DDEProblem should evaluate successfully at interpolated times and therefore be plottable with plot(sol; idxs = sys.y).
The full AbstractODESolution has a get_history_function implementation, and the observed-function evaluation should retain access to that history when it evaluates a non-Markovian system over interpolated states.
Minimal Reproducible Example 👇
using ModelingToolkit
using DelayDiffEq
using OrdinaryDiffEq
using Plots
@parameters t τ = 1.0
@variables x(..) y(t)
x_t = x(t)
D = Differential(t)
sys = mtkcompile(System(
[
D(x_t) ~ -x_t + x(t - τ),
y ~ x_t,
],
t;
name = :delay_mre,
))
prob = DDEProblem(
sys,
Dict(x_t => 1.0),
(0.0, 2.0);
h = (p, time) -> [1.0],
build_initializeprob = false,
)
sol = solve(prob, MethodOfSteps(Tsit5()))
sol[sys.y] # succeeds: evaluates at saved solution times
times = collect(range(0.0, 2.0; length = 11))
sol(times; idxs = sys.y) # throws MethodError
plot(sol; idxs = sys.y) # throws the same MethodError
Error & Stacktrace ⚠️
ERROR: MethodError: no method matching get_history_function(::RecursiveArrayTools.DiffEqArray{…})
Closest candidates are:
get_history_function(::DelayDiffEq.DDEIntegrator)
get_history_function(::SciMLBase.AbstractDDEProblem)
get_history_function(::SciMLBase.AbstractSDDEProblem)
get_history_function(::SciMLBase.AbstractODESolution)
Stacktrace:
[1] (::SymbolicIndexingInterface.TimeDependentObservedFunction{…})(
::SymbolicIndexingInterface.Timeseries,
::SymbolicIndexingInterface.IndexerBoth,
prob::RecursiveArrayTools.DiffEqArray{…})
@ SymbolicIndexingInterface ~/.julia/packages/SymbolicIndexingInterface/qKPnc/src/state_indexing.jl:99
[2] (::SymbolicIndexingInterface.TimeDependentObservedFunction{…})(
::SymbolicIndexingInterface.Timeseries,
prob::RecursiveArrayTools.DiffEqArray{…})
@ SymbolicIndexingInterface ~/.julia/packages/SymbolicIndexingInterface/qKPnc/src/state_indexing.jl:88
[3] (::SciMLBase.AbstractODESolution)(
t::Vector{Float64}, ::Type{Val{0}}, idxs::Num, continuity::Symbol)
@ SciMLBase ~/.julia/packages/SciMLBase/itmhi/src/solutions/ode_solutions.jl:398
Environment (please complete the following information):
- Output of
using Pkg; Pkg.status()
Status `~/Documents/julia_dcm/docs/Project.toml`
[bcd4f6db] DelayDiffEq v6.1.2
[31c24e10] Distributions v0.25.130
[e30172f5] Documenter v1.17.0
[363c841f] JuliaDCM v0.1.0 `.`
[961ee093] ModelingToolkit v11.39.0
[1dea7af3] OrdinaryDiffEq v7.6.0
[91a5bcdd] Plots v1.41.6
- Output of
using Pkg; Pkg.status(; mode = PKGMODE_MANIFEST)
Status `~/Documents/julia_dcm/Manifest.toml`
[bcd4f6db] DelayDiffEq v6.1.2
[731186ca] RecursiveArrayTools v4.4.0
⌅ [0bca4576] SciMLBase v3.46.1
[2efcf032] SymbolicIndexingInterface v0.3.54
[961ee093] ModelingToolkit v11.39.0
[7771a370] ModelingToolkitBase v1.65.0
[1dea7af3] OrdinaryDiffEq v7.6.0
[b1df2697] OrdinaryDiffEqTsit5 v2.1.3
[91a5bcdd] Plots v1.41.6
[0c5d862f] Symbolics v7.36.0
[d1185830] SymbolicUtils v4.45.0
Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading.
Julia Version 1.12.6
Commit 15346901f00 (2026-04-09 19:20 UTC)
Build Info:
Official https://julialang.org release
Platform Info:
OS: macOS (arm64-apple-darwin24.0.0)
CPU: 8 × Apple M2
WORD_SIZE: 64
LLVM: libLLVM-18.1.7 (ORCJIT, apple-m2)
GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 4 virtual cores)
Additional context
The vector-time symbolic-index path in SciMLBase/src/solutions/ode_solutions.jl obtains getter = getsym(sol, idxs), creates interp_sol = augment(sol.interp(...), sol), and calls getter(interp_sol). For a non-Markovian observed variable, SymbolicIndexingInterface correctly requires get_history_function(interp_sol), but no accessor exists for the resulting DiffEqArray. In contrast, SciMLBase provides get_history_function(sol::AbstractODESolution).
Describe the bug 🐞
Evaluating an observed variable of a non-Markovian ModelingToolkit system over an interpolated vector of times throws a
MethodErrorbecauseSymbolicIndexingInterface.get_history_functionis called with aRecursiveArrayTools.DiffEqArray.The saved solution values can be indexed successfully (
sol[sys.y]). The failure occurs only when requesting interpolated values, including through the standard plotting recipe (plot(sol; idxs = sys.y)).Expected behavior
A symbolic observed variable of a
DDEProblemshould evaluate successfully at interpolated times and therefore be plottable withplot(sol; idxs = sys.y).The full
AbstractODESolutionhas aget_history_functionimplementation, and the observed-function evaluation should retain access to that history when it evaluates a non-Markovian system over interpolated states.Minimal Reproducible Example 👇
Error & Stacktrace⚠️
Environment (please complete the following information):
using Pkg; Pkg.status()using Pkg; Pkg.status(; mode = PKGMODE_MANIFEST)versioninfo()Additional context
The vector-time symbolic-index path in
SciMLBase/src/solutions/ode_solutions.jlobtainsgetter = getsym(sol, idxs), createsinterp_sol = augment(sol.interp(...), sol), and callsgetter(interp_sol). For a non-Markovian observed variable, SymbolicIndexingInterface correctly requiresget_history_function(interp_sol), but no accessor exists for the resultingDiffEqArray. In contrast, SciMLBase providesget_history_function(sol::AbstractODESolution).