Skip to content

Type inference on solution output fails for DAE with callback #2594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Ickaser opened this issue Feb 10, 2025 · 20 comments
Open

Type inference on solution output fails for DAE with callback #2594

Ickaser opened this issue Feb 10, 2025 · 20 comments
Assignees
Labels

Comments

@Ickaser
Copy link
Contributor

Ickaser commented Feb 10, 2025

Describe the bug 🐞

DAE solutions with callbacks work, but they are apparently type unstable, according to @code_warntype. ODE solutions with callbacks and DAE solutions without callbacks without are both type stable.

See also #2530 , #2558 .

Minimal Reproducible Example 👇

using OrdinaryDiffEqRosenbrock
using LinearAlgebra: Diagonal

function dae!(du, u, p, t)
    du[1] = -u[1]*p[1]
    du[2] = u[2] + u[1]
    nothing
end
dae_f = ODEFunction(dae!, mass_matrix=Diagonal([1.0, 0.0]))

callback = ContinuousCallback((u,_,__)->u[1]-1, terminate!)

prob_mwe = ODEProblem{true}(dae!, [2.0, -2.0], (0.0, 1.0), (1.0,))

evalsol(sol) = sum(abs2, sol[1,:] .- 1.0)

function eval_prm_nocb(pr)
    newprob = ODEProblem{true}(dae!, [2.0, -2.0], (0.0, 1.0), (pr,))
    sol = solve(newprob, Rosenbrock23())
    evalsol(sol)
end
function eval_prm_cb(pr)
    newprob = ODEProblem{true}(dae!, [2.0, -2.0], (0.0, 1.0), (pr,))
    sol = solve(newprob, Rosenbrock23(); callback=callback)
    evalsol(sol)
end

Error & Stacktrace ⚠️
Without callback, is type stable:

julia> @code_warntype eval_prm_nocb(2.0)
MethodInstance for eval_prm_nocb(::Float64)
  from eval_prm_nocb(pr) @ Main c:\Users\iwheeler\OneDrive - purdue.edu\Documents\LyoResearch\LyoPronto.jl_NIIMBL\scripts\mwe.jl:15
Arguments
  #self#::Core.Const(Main.eval_prm_nocb)
  pr::Float64
Locals
  sol::ODESolution{Float64, 2, Vector{Vector{Float64}}, Nothing, Nothing, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}, Rosenbrock23{0, ADTypes.AutoForwardDiff{1, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, OrdinaryDiffEqCore.InterpolationData{ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Vector{Float64}}, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, OrdinaryDiffEqRosenbrock.Rosenbrock23Cache{Vector{Float64}, Vector{Float64}, Vector{Float64}, Matrix{Float64}, Matrix{Float64}, OrdinaryDiffEqRosenbrock.Rosenbrock23Tableau{Float64}, SciMLBase.TimeGradientWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, Tuple{Float64}}, SciMLBase.UJacobianWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Float64, Tuple{Float64}}, LinearSolve.LinearCache{Matrix{Float64}, Vector{Float64}, Vector{Float64}, SciMLBase.NullParameters, LinearSolve.DefaultLinearSolver, LinearSolve.DefaultLinearSolverInit{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Vector{Int64}}, Nothing, Nothing, Nothing, LinearAlgebra.SVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int32}}, Base.RefValue{Int32}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Base.RefValue{Int64}}, LinearAlgebra.QRPivoted{Float64, Matrix{Float64}, Vector{Float64}, Vector{Int64}}, Nothing, Nothing}, LinearSolve.InvPreconditioner{Diagonal{Float64, Vector{Float64}}}, Diagonal{Float64, Vector{Float64}}, Float64, Bool, LinearSolve.LinearSolveAdjoint{Missing}}, SparseDiffTools.ForwardColorJacCache{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Vector{Vector{Tuple{Float64}}}, UnitRange{Int64}, Nothing}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Float64, Rosenbrock23{0, ADTypes.AutoForwardDiff{1, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing}, SciMLBase.DEStats, Nothing, Nothing, Nothing, Nothing}
  newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}
Body::Float64
1%1  = Core.apply_type(Main.ODEProblem, true)::Core.Const(ODEProblem{true})
│   %2  = Main.dae!::Core.Const(Main.dae!)
│   %3  = Base.vect(2.0, -2.0)::Vector{Float64}%4  = Core.tuple(0.0, 1.0)::Core.Const((0.0, 1.0))
│   %5  = Core.tuple(pr)::Tuple{Float64}
│         (newprob = (%1)(%2, %3, %4, %5))
│   %7  = Main.solve::Core.Const(CommonSolve.solve)
│   %8  = newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}%9  = Main.Rosenbrock23()::Core.Const(Rosenbrock23{0, ADTypes.AutoForwardDiff{nothing, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}(nothing, OrdinaryDiffEqCore.DEFAULT_PRECS, OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, ADTypes.AutoForwardDiff()))
│         (sol = (%7)(%8, %9))
│   %11 = sol::ODESolution{Float64, 2, Vector{Vector{Float64}}, Nothing, Nothing, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}, Rosenbrock23{0, ADTypes.AutoForwardDiff{1, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, OrdinaryDiffEqCore.InterpolationData{ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Vector{Float64}}, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, OrdinaryDiffEqRosenbrock.Rosenbrock23Cache{Vector{Float64}, Vector{Float64}, Vector{Float64}, Matrix{Float64}, Matrix{Float64}, OrdinaryDiffEqRosenbrock.Rosenbrock23Tableau{Float64}, SciMLBase.TimeGradientWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, Tuple{Float64}}, SciMLBase.UJacobianWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Float64, Tuple{Float64}}, LinearSolve.LinearCache{Matrix{Float64}, Vector{Float64}, Vector{Float64}, SciMLBase.NullParameters, LinearSolve.DefaultLinearSolver, LinearSolve.DefaultLinearSolverInit{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Vector{Int64}}, Nothing, Nothing, Nothing, LinearAlgebra.SVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int32}}, Base.RefValue{Int32}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Base.RefValue{Int64}}, LinearAlgebra.QRPivoted{Float64, Matrix{Float64}, Vector{Float64}, Vector{Int64}}, Nothing, Nothing}, LinearSolve.InvPreconditioner{Diagonal{Float64, Vector{Float64}}}, Diagonal{Float64, Vector{Float64}}, Float64, Bool, LinearSolve.LinearSolveAdjoint{Missing}}, SparseDiffTools.ForwardColorJacCache{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Vector{Vector{Tuple{Float64}}}, UnitRange{Int64}, Nothing}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Float64, Rosenbrock23{0, ADTypes.AutoForwardDiff{1, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing}, SciMLBase.DEStats, Nothing, Nothing, Nothing, Nothing}
│   %12 = Main.evalsol(%11)::Float64
└──       return %12

With callback, is unstable:

julia> @code_warntype eval_prm_cb(2.0)
MethodInstance for eval_prm_cb(::Float64)
  from eval_prm_cb(pr) @ Main c:\Users\iwheeler\OneDrive - purdue.edu\Documents\LyoResearch\LyoPronto.jl_NIIMBL\scripts\mwe.jl:20
Arguments
  #self#::Core.Const(Main.eval_prm_cb)
  pr::Float64
Locals
  sol::Any
  newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}
Body::Any
1%1  = Core.apply_type(Main.ODEProblem, true)::Core.Const(ODEProblem{true})
│   %2  = Main.dae!::Core.Const(Main.dae!)
│   %3  = Base.vect(2.0, -2.0)::Vector{Float64}%4  = Core.tuple(0.0, 1.0)::Core.Const((0.0, 1.0))
│   %5  = Core.tuple(pr)::Tuple{Float64}
│         (newprob = (%1)(%2, %3, %4, %5))
│   %7  = Main.Rosenbrock23()::Core.Const(Rosenbrock23{0, ADTypes.AutoForwardDiff{nothing, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}(nothing, OrdinaryDiffEqCore.DEFAULT_PRECS, OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, ADTypes.AutoForwardDiff()))
│   %8  = (:callback,)::Core.Const((:callback,))
│   %9  = Core.apply_type(Core.NamedTuple, %8)::Core.Const(NamedTuple{(:callback,)})
│   %10 = Core.tuple(Main.callback)::Tuple{Any}%11 = (%9)(%10)::NamedTuple{(:callback,), <:Tuple{Any}}%12 = newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}
│         (sol = Core.kwcall(%11, Main.solve, %12, %7))
│   %14 = sol::Any%15 = Main.evalsol(%14)::Any
└──       return %15

Environment (please complete the following information):

  • Output of using Pkg; Pkg.status()
  • Output of using Pkg; Pkg.status(; mode = PKGMODE_MANIFEST)
    Updated today. The SciML and OrdinaryDiffEq packages:
  [0bca4576] SciMLBase v2.72.2
  [19f34311] SciMLJacobianOperators v0.1.1
  [c0aeaf25] SciMLOperators v0.3.12
  [53ae85a6] SciMLStructures v1.6.1
  [bbf590c4] OrdinaryDiffEqCore v1.16.0
  [4302a76b] OrdinaryDiffEqDifferentiation v1.3.0
  [127b3ac7] OrdinaryDiffEqNonlinearSolve v1.3.0
  [43230ef6] OrdinaryDiffEqRosenbrock v1.4.0
@Ickaser
Copy link
Contributor Author

Ickaser commented Feb 21, 2025

Turns out that, on master at least, making the callback a const resolves this type instability. That is, augmenting the above MWE:

const constcallback = ContinuousCallback((u,_,__)->u[1]-1, terminate!)
function eval_prm_ccb(pr)
    newprob = ODEProblem{true}(dae!, [2.0, -2.0], (0.0, 1.0), (pr,))
    sol = solve(newprob, Rosenbrock23(); callback=constcallback)
    evalsol(sol)
end

@code_warntype eval_prm_cb(1.0) yields

MethodInstance for eval_prm_cb(::Float64)
  from eval_prm_cb(pr) @ Main c:\Users\iwheeler\OneDrive - purdue.edu\Documents\01_Projects\LyoPronto.jl_NIIMBL\scripts\mwe.jl:24
Arguments
  #self#::Core.Const(Main.eval_prm_cb)
  pr::Float64
Locals
  sol::Any
  newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}
Body::Any
1 ─ %1  = Core.apply_type(Main.ODEProblem, true)::Core.Const(ODEProblem{true})
│   %2  = Main.dae!::Core.Const(Main.dae!)
│   %3  = Base.vect(2.0, -2.0)::Vector{Float64}
│   %4  = Core.tuple(0.0, 1.0)::Core.Const((0.0, 1.0))
│   %5  = Core.tuple(pr)::Tuple{Float64}
│         (newprob = (%1)(%2, %3, %4, %5))
│   %7  = Main.Rosenbrock23()::Core.Const(Rosenbrock23{0, true, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}, true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}(nothing, OrdinaryDiffEqCore.DEFAULT_PRECS, OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!))
│   %8  = (:callback,)::Core.Const((:callback,))
│   %9  = Core.apply_type(Core.NamedTuple, %8)::Core.Const(NamedTuple{(:callback,)})
│   %10 = Core.tuple(Main.callback)::Tuple{Any}
│   %11 = (%9)(%10)::NamedTuple{(:callback,), <:Tuple{Any}}
│   %12 = newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}
│         (sol = Core.kwcall(%11, Main.solve, %12, %7))
│   %14 = sol::Any
│   %15 = Main.evalsol(%14)::Any
└──       return %15

while @code_warntype eval_prm_ccb(1.0) yields

MethodInstance for eval_prm_ccb(::Float64)
  from eval_prm_ccb(pr) @ Main c:\Users\iwheeler\OneDrive - purdue.edu\Documents\01_Projects\LyoPronto.jl_NIIMBL\scripts\mwe.jl:29
Arguments
  #self#::Core.Const(Main.eval_prm_ccb)
  pr::Float64
Locals
  sol::ODESolution{Float64, 2, Vector{Vector{Float64}}, Nothing, Nothing, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}, Rosenbrock23{1, true, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}, true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, OrdinaryDiffEqCore.InterpolationData{ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Vector{Float64}}, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, OrdinaryDiffEqRosenbrock.Rosenbrock23Cache{Vector{Float64}, Vector{Float64}, Vector{Float64}, Matrix{Float64}, Matrix{Float64}, OrdinaryDiffEqRosenbrock.Rosenbrock23Tableau{Float64}, SciMLBase.TimeGradientWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, Tuple{Float64}}, SciMLBase.UJacobianWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Float64, Tuple{Float64}}, LinearSolve.LinearCache{Matrix{Float64}, Vector{Float64}, Vector{Float64}, SciMLBase.NullParameters, LinearSolve.DefaultLinearSolver, LinearSolve.DefaultLinearSolverInit{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Vector{Int64}}, Nothing, Nothing, Nothing, LinearAlgebra.SVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int32}}, Base.RefValue{Int32}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Base.RefValue{Int64}}, LinearAlgebra.QRPivoted{Float64, Matrix{Float64}, Vector{Float64}, Vector{Int64}}, Nothing, Nothing}, LinearSolve.InvPreconditioner{Diagonal{Float64, Vector{Float64}}}, Diagonal{Float64, Vector{Float64}}, Float64, Bool, LinearSolve.LinearSolveAdjoint{Missing}}, SparseDiffTools.ForwardColorJacCache{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Vector{Vector{Tuple{Float64}}}, UnitRange{Int64}, Nothing}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Float64, Rosenbrock23{1, true, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}, true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing}, SciMLBase.DEStats, Nothing, Nothing, Nothing, Nothing}
  newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}
Body::Float64
1 ─ %1  = Core.apply_type(Main.ODEProblem, true)::Core.Const(ODEProblem{true})
│   %2  = Main.dae!::Core.Const(Main.dae!)
│   %3  = Base.vect(2.0, -2.0)::Vector{Float64}
│   %4  = Core.tuple(0.0, 1.0)::Core.Const((0.0, 1.0))
│   %5  = Core.tuple(pr)::Tuple{Float64}
│         (newprob = (%1)(%2, %3, %4, %5))
│   %7  = Main.Rosenbrock23()::Core.Const(Rosenbrock23{0, true, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}, true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}(nothing, OrdinaryDiffEqCore.DEFAULT_PRECS, OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!))
│   %8  = (:callback,)::Core.Const((:callback,))
│   %9  = Core.apply_type(Core.NamedTuple, %8)::Core.Const(NamedTuple{(:callback,)})
│   %10 = Core.tuple(Main.constcallback)::Core.Const((ContinuousCallback{var"#9#10", typeof(terminate!), typeof(terminate!), typeof(SciMLBase.INITIALIZE_DEFAULT), typeof(SciMLBase.FINALIZE_DEFAULT), Float64, Int64, Rational{Int64}, Nothing, Nothing, Int64}(var"#9#10"(), SciMLBase.terminate!, SciMLBase.terminate!, SciMLBase.INITIALIZE_DEFAULT, SciMLBase.FINALIZE_DEFAULT, nothing, SciMLBase.LeftRootFind, 10, Bool[1, 1], 1, 2.220446049250313e-15, 0, 1//100, nothing),))
│   %11 = (%9)(%10)::Core.Const((callback = ContinuousCallback{var"#9#10", typeof(terminate!), typeof(terminate!), typeof(SciMLBase.INITIALIZE_DEFAULT), typeof(SciMLBase.FINALIZE_DEFAULT), Float64, Int64, Rational{Int64}, Nothing, Nothing, Int64}(var"#9#10"(), SciMLBase.terminate!, SciMLBase.terminate!, SciMLBase.INITIALIZE_DEFAULT, SciMLBase.FINALIZE_DEFAULT, nothing, SciMLBase.LeftRootFind, 10, Bool[1, 1], 1, 2.220446049250313e-15, 0, 1//100, nothing),))
│   %12 = newprob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, typeof(dae!), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}
│         (sol = Core.kwcall(%11, Main.solve, %12, %7))
│   %14 = sol::ODESolution{Float64, 2, Vector{Vector{Float64}}, Nothing, Nothing, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Tuple{Float64}, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardODEProblem}, Rosenbrock23{1, true, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}, true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, OrdinaryDiffEqCore.InterpolationData{ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Vector{Float64}}, Vector{Float64}, Vector{Vector{Vector{Float64}}}, Nothing, OrdinaryDiffEqRosenbrock.Rosenbrock23Cache{Vector{Float64}, Vector{Float64}, Vector{Float64}, Matrix{Float64}, Matrix{Float64}, OrdinaryDiffEqRosenbrock.Rosenbrock23Tableau{Float64}, SciMLBase.TimeGradientWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, Tuple{Float64}}, SciMLBase.UJacobianWrapper{true, ODEFunction{true, SciMLBase.AutoSpecialize, FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Tuple{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Float64, Tuple{Float64}}, LinearSolve.LinearCache{Matrix{Float64}, Vector{Float64}, Vector{Float64}, SciMLBase.NullParameters, LinearSolve.DefaultLinearSolver, LinearSolve.DefaultLinearSolverInit{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Vector{Int64}}, Nothing, Nothing, Nothing, LinearAlgebra.SVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, LinearAlgebra.Cholesky{Float64, Matrix{Float64}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int32}}, Base.RefValue{Int32}}, Tuple{LinearAlgebra.LU{Float64, Matrix{Float64}, Vector{Int64}}, Base.RefValue{Int64}}, LinearAlgebra.QRPivoted{Float64, Matrix{Float64}, Vector{Float64}, Vector{Int64}}, Nothing, Nothing}, LinearSolve.InvPreconditioner{Diagonal{Float64, Vector{Float64}}}, Diagonal{Float64, Vector{Float64}}, Float64, Bool, LinearSolve.LinearSolveAdjoint{Missing}}, SparseDiffTools.ForwardColorJacCache{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Vector{Vector{Tuple{Float64}}}, UnitRange{Int64}, Nothing}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Float64, Rosenbrock23{1, true, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}, true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}, Nothing}, SciMLBase.DEStats, Nothing, Nothing, Nothing, Nothing}
│   %15 = Main.evalsol(%14)::Float64
└──       return %15

@oscardssmith
Copy link
Member

Oh right. That is expected. Otherwise this is just normal global variable type instability.

@Ickaser
Copy link
Contributor Author

Ickaser commented Feb 21, 2025

In my code base (which has some more intricacies), I'm still seeing something that isn't type inferrable. I'll make another issue later if I manage to identify where the problem actually is, but in the meantime I can probably get away with a type assertion in my squared error calculation.

@ChrisRackauckas
Copy link
Member

Are you using save_idxs?

@Ickaser
Copy link
Contributor Author

Ickaser commented Feb 22, 2025

No, not currently (didn't know that was an option). My problem only has two equations, so I haven't been worried on that front, but I have a parameter struct full of Unitful types and the endpoint in time is dependent on the system dynamics (hence a callback that terminates intrgration when one of my two variables approaches zero)

@ChrisRackauckas
Copy link
Member

Oh Unitful 😅 If you don't use unitful do you still have issues?

@Ickaser
Copy link
Contributor Author

Ickaser commented Feb 25, 2025

I can replicate my problem without Unitful; here is an example which resembles my code base, without using Unitful:

using OrdinaryDiffEqRosenbrock
using LinearAlgebra: Diagonal
using Accessors
# using OrdinaryDiffEqNonlinearSolve

struct Coeffs{T1, T2}
    p1::T1
    p2::T2
end
function Base.getindex(c::Coeffs, i::Int)
    if i == 1 
        return c.p1 
    elseif i == 2
        return c.p2
    else
        throw(ArgumentError("Index out of bounds"))
    end
end

function dae!(du, u, p, t)
    du[1] = -u[1]*p[1]
    du[2] = u[2] + u[1]
    nothing
end
const dae_fc = ODEFunction(dae!, mass_matrix=Diagonal([1.0, 0.0]))

calc_u0(c::Coeffs) = [2.0, -2.0]
function OrdinaryDiffEqRosenbrock.ODEProblem(c::Coeffs)
    u0 = calc_u0(c)
    return ODEProblem{true}(dae_fc, u0, (0.0, 1.0), c; initializealg=CheckInit())
    # return ODEProblem{true}(dae_fc, u0, (0.0, 1.0), c;)
end

With this example, @code_warntype ODEProblem(Coeffs(-1.0, 1.0)) tells me that the problem construction is type stable; so far so good. But when I move on to

@code_warntype solve(ODEProblem(Coeffs(-1.0, 1.0)), Rosenbrock23())

I get this, where it's a little hard to tell where the instability happens:

MethodInstance for CommonSolve.solve(::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Coeffs{Float64, Float64}, ODEFunction{true, SciMLBase.FullSpecialize, typeof(dae!), Diagonal{Float64, Vector{Float64}}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, CheckInit, Tuple{Symbol}, @NamedTuple{initializealg::CheckInit}}, SciMLBase.StandardODEProblem}, ::Rosenbrock23{0, ADTypes.AutoForwardDiff{nothing, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)})
  from solve(prob::SciMLBase.AbstractDEProblem, args...; sensealg, u0, p, wrap, kwargs...) @ DiffEqBase C:\Users\iwheeler\.julia\packages\DiffEqBase\HGITF\src\solve.jl:1033
Arguments
  #self#::Core.Const(CommonSolve.solve)
  prob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Coeffs{Float64, Float64}, ODEFunction{true, SciMLBase.FullSpecialize, typeof(dae!), Diagonal{Float64, Vector{Float64}}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, CheckInit, Tuple{Symbol}, @NamedTuple{initializealg::CheckInit}}, SciMLBase.StandardODEProblem}
  args::Core.Const((Rosenbrock23{0, ADTypes.AutoForwardDiff{nothing, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}(nothing, OrdinaryDiffEqCore.DEFAULT_PRECS, OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, ADTypes.AutoForwardDiff()),))
Body::Any
1 ─ %1  = DiffEqBase.:(var"#solve#42")::Core.Const(DiffEqBase.var"#solve#42")
│   %2  = DiffEqBase.nothing::Core.Const(nothing)
│   %3  = DiffEqBase.nothing::Core.Const(nothing)
│   %4  = DiffEqBase.nothing::Core.Const(nothing)
│   %5  = DiffEqBase.Val::Core.Const(Val)
│   %6  = (%5)(true)::Core.Const(Val{true}())
│   %7  = Core.NamedTuple()::Core.Const(NamedTuple())
│   %8  = Base.pairs(%7)::Core.Const(Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}())
│   %9  = Core.tuple(%2, %3, %4, %6, %8, #self#, prob)::Tuple{Nothing, Nothing, Nothing, Val{true}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, typeof(solve), ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Coeffs{Float64, Float64}, ODEFunction{true, SciMLBase.FullSpecialize, typeof(dae!), Diagonal{Float64, Vector{Float64}}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, Base.Pairs{Symbol, CheckInit, Tuple{Symbol}, @NamedTuple{initializealg::CheckInit}}, SciMLBase.StandardODEProblem}}
│   %10 = Core._apply_iterate(Base.iterate, %1, %9, args)::Any
└──       return %10

Dropping the kwarg for CheckInit and loading ODENonlinearSolve so that I don't need any kwargs doesn't change this in any way I can discern.

@Ickaser
Copy link
Contributor Author

Ickaser commented Feb 25, 2025

Using JET.@report_opt, the problem construction still doesn't have instabilities, but solving does:

prob = ODEProblem(cbase)
@report_opt solve(prob)
┌ Warning: Tuple{DiffEqBase.var"##solve#42", Any, Any, Any, Any, Base.Pairs{Symbol, V, NTuple{N, Symbol}, NamedTuple{names, T}} where {V, N, names, T<:NTuple{N, Any}}, typeof(solve), SciMLBase.AbstractDEProblem, Vararg{Any}} was not found
└ @ Revise C:\Users\iwheeler\.julia\packages\Revise\tTIBp\src\packagedef.jl:1181
┌ Warning: Tuple{DiffEqBase.var"##solve_up#44", Base.Pairs{Symbol, V, NTuple{N, Symbol}, NamedTuple{names, T}} where {V, N, names, T<:NTuple{N, Any}}, typeof(DiffEqBase.solve_up), SciMLBase.AbstractDEProblem, Any, Any, Any, Vararg{Any}} was not found
└ @ Revise C:\Users\iwheeler\.julia\packages\Revise\tTIBp\src\packagedef.jl:1181
[ Info: tracking Base
═════ 3 possible errors found ═════
┌ solve(::ODEProblem{Vector{…}, Tuple{…}, true, Coeffs{…}, ODEFunction{…}, @Kwargs{…}, SciMLBase.StandardODEProblem}) @ DiffEqBase C:\Users\iwheeler\.julia\packages\DiffEqBase\HGITF\src\solve.jl:1033
│┌ solve(::ODEProblem{…}; sensealg::Nothing, u0::Nothing, p::Nothing, wrap::Val{…}, kwargs::@Kwargs{}) @ DiffEqBase C:\Users\iwheeler\.julia\packages\DiffEqBase\HGITF\src\solve.jl:1043
││┌ solve_up(::ODEProblem{…}, ::Nothing, ::Vector{…}, ::Coeffs{…}) @ DiffEqBase C:\Users\iwheeler\.julia\packages\DiffEqBase\HGITF\src\solve.jl:1106
│││┌ solve_up(::ODEProblem{…}, ::Nothing, ::Vector{…}, ::Coeffs{…}; kwargs::@Kwargs{}) @ DiffEqBase C:\Users\iwheeler\.julia\packages\DiffEqBase\HGITF\src\solve.jl:1110
││││┌ kwcall(::@NamedTuple{…}, ::typeof(DiffEqBase.get_concrete_problem), prob::ODEProblem{…}, isadapt::Bool) @ DiffEqBase C:\Users\iwheeler\.julia\packages\DiffEqBase\HGITF\src\solve.jl:1215
│││││┌ get_concrete_problem(prob::ODEProblem{…}, isadapt::Bool; kwargs::@Kwargs{…}) @ DiffEqBase C:\Users\iwheeler\.julia\packages\DiffEqBase\HGITF\src\solve.jl:1229
││││││┌ kwcall(::@NamedTuple{…}, ::typeof(remake), prob::ODEProblem{…}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:204
│││││││┌ remake(prob::ODEProblem{…}; f::ODEFunction{…}, u0::Vector{…}, tspan::Tuple{…}, p::Coeffs{…}, kwargs::Missing, interpret_symbolicmap::Bool, build_initializeprob::Bool, use_defaults::Bool, lazy_initialization::Nothing, _kwargs::@Kwargs{}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:218
││││││││┌ kwcall(::@NamedTuple{…}, ::typeof(SciMLBase.updated_u0_p), prob::ODEProblem{…}, u0::Vector{…}, p::Coeffs{…}, t0::Float64) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1051
│││││││││┌ updated_u0_p(prob::ODEProblem{…}, u0::Vector{…}, p::Coeffs{…}, t0::Float64; interpret_symbolicmap::Bool,
 use_defaults::Bool) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1074
││││││││││┌ late_binding_update_u0_p(prob::ODEProblem{…}, u0::Vector{…}, p::Coeffs{…}, t0::Float64, newu0::Vector{…}, newp::Coeffs{…}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1101
│││││││││││┌ late_binding_update_u0_p(prob::ODEProblem{…}, root_indp::ODEProblem{…}, u0::Vector{…}, p::Coeffs{…}, t0::Float64, newu0::Vector{…}, newp::Coeffs{…}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1088
││││││││││││┌ late_binding_update_u0_p(prob::ODEProblem{…}, root_indp::ODEFunction{…}, u0::Vector{…}, p::Coeffs{…}, t0::Float64, newu0::Vector{…}, newp::Coeffs{…}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1088
│││││││││││││┌ late_binding_update_u0_p(prob::ODEProblem{…}, root_indp::SymbolicIndexingInterface.SymbolCache, u0::Vector{…}, p::Coeffs{…}, t0::Float64, newu0::Vector{…}, newp::Coeffs{…}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1086
││││││││││││││┌ hasmethod(f::typeof(SymbolicIndexingInterface.symbolic_container), t::Type{<:Tuple{…}}) @ Base ./reflection.jl:2347
│││││││││││││││ runtime dispatch detected: Core._hasmethod(f::typeof(SymbolicIndexingInterface.symbolic_container), t::Type{<:Tuple{SymbolicIndexingInterface.SymbolCache}})::Bool
││││││││││││││└────────────────────
│││││││││││││┌ late_binding_update_u0_p(prob::ODEProblem{…}, root_indp::SymbolicIndexingInterface.SymbolCache, u0::Vector{…}, p::Coeffs{…}, t0::Float64, newu0::Vector{…}, newp::Coeffs{…}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1086
││││││││││││││ runtime dispatch detected: SciMLBase.symbolic_container(root_indp::SymbolicIndexingInterface.SymbolCache)
│││││││││││││└────────────────────
││││││││││││┌ late_binding_update_u0_p(prob::ODEProblem{…}, root_indp::ODEFunction{…}, u0::Vector{…}, p::Coeffs{…}, t0::Float64, newu0::Vector{…}, newp::Coeffs{…}) @ SciMLBase C:\Users\iwheeler\.julia\packages\SciMLBase\dJpGC\src\remake.jl:1085
│││││││││││││ failed to optimize due to recursion: SciMLBase.late_binding_update_u0_p(::ODEProblem{…}, ::ODEFunction{…}, ::Vector{…}, ::Coeffs{…}, ::Float64, ::Vector{…}, ::Coeffs{…})
││││││││││││└────────────────────

And if I load ODENonlinearSolve and drop CheckInit as kwarg, then JET reports many more possible errors (321).

If it matters, these solves get put inside a call like below, but the type stability happens already at the solve step. In this case I can annotate the return type to match the input type, but it would be nice for that to be inferrable

function eval_prm_ccb(pr, c::Coeffs)
    # rtype == typeof(pr)
    newc = @set c.p1 = pr
    newprob = ODEProblem(newc)
    sol = solve(newprob, Rosenbrock23(); callback=ccallback)
    evalsol(sol)#::rtype
end

@oscardssmith oscardssmith reopened this Feb 25, 2025
@Ickaser
Copy link
Contributor Author

Ickaser commented Mar 3, 2025

Exploring this MWE with Cthulhu, it looks like maybe this is related to #2613 ? Inside of solve_up, it fails to infer the full type of the alg:

Image

which (if I am exploring this correctly, which I might not be) eventually leads to a culprit here:

L = StaticArrayInterface.known_length(typeof(u0))
if L === nothing # dynamic sized
# If chunksize is zero, pick chunksize right at the start of solve and
# then do function barrier to infer the full solve
x = if prob.f.colorvec === nothing
length(u0)
else
maximum(prob.f.colorvec)
end
cs = ForwardDiff.pickchunksize(x)
return remake(alg,
autodiff = AutoForwardDiff(
chunksize = cs))

@ChrisRackauckas
Copy link
Member

@oscardssmith did you ever look into this?

@Ickaser
Copy link
Contributor Author

Ickaser commented Mar 18, 2025

I checked this MWE again after #2617 merged, and this still occurs, so something else seems to be in play here.

@oscardssmith
Copy link
Member

@jClugstor this appears to be due to the remake that happens in prepare_alg to set the chunksize. Looking at the Cthulhu output:

return remake(alg::Core.Const(Rosenbrock23{0, ADTypes.AutoForwardDiff{nothing, Nothing}, Nothing, typeof(OrdinaryDiffEqCore.DEFAULT_PRECS), Val{:forward}(), true, nothing, typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!)}(nothing, OrdinaryDiffEqCore.DEFAULT_PRECS, OrdinaryDiffEqCore.trivial_limiter!, OrdinaryDiffEqCore.trivial_limiter!, ADTypes.AutoForwardDiff())),
86             autodiff = AutoForwardDiff(
87                 chunksize = cs::Int64::Tuple{Int64})::@NamedTuple{chunksize::Int64})::Rosenbrock23 # note that this is type unstable

@jClugstor
Copy link
Member

If I remember right using the AutoForwardDiff{cs}(tag) form of the constructor is type stable. It's just not ADTypes API technically.

@oscardssmith
Copy link
Member

so the problem is actually slightly earlier. The actual problem is that

        # If chunksize is zero, pick chunksize right at the start of solve and
        # then do function barrier to infer the full solve
        x = if prob.f.colorvec === nothing
            length(u0)
        else
            maximum(prob.f.colorvec)
        end

        cs = ForwardDiff.pickchunksize(x)
        remake(alg, autodiff = AutoForwardDiff(chunksize=cs))

means that the type of the alg dynamically depends on information that can't be computed at runtime. Is this branch really necessary?

@jClugstor
Copy link
Member

This was the behavior before the ADTypes change, it's only unnecessary if we don't care about picking the chunksize based on the colorvec I guess?

I was having a similar problem with the types not being inferred in #2567, changing to the other constructor type fixed it, but yeah this might not be the same thing. Let me check it out.

It's also possible that this is not a problem in #2567

@jClugstor
Copy link
Member

Nope, it's still an issue, so yeah something else is going on.

This is the previous code, which would still have that same issue, no? The type of the alg would change, especially since before chunksize was a type parameter. Hmm.

 L = StaticArrayInterface.known_length(typeof(u0))
    if L === nothing # dynamic sized
        # If chunksize is zero, pick chunksize right at the start of solve and
        # then do function barrier to infer the full solve
        x = if prob.f.colorvec === nothing
            length(u0)
        else
            maximum(prob.f.colorvec)
        end

        cs = ForwardDiff.pickchunksize(x)
        return remake(alg, chunk_size = Val{cs}())
    else # statically sized
        cs = pick_static_chunksize(Val{L}())
        return remake(alg, chunk_size = cs)
    end

@oscardssmith
Copy link
Member

I think the problem is that the "# then do function barrier to infer the full solve" must have disappeared.

@jClugstor
Copy link
Member

Yeah, I'm not sure what was supposed to be there before.

btw, on my branch with DI I get the exact same output from @code_warntype when running the MWE.

There are tests that go through this exact code and check that everything is inferred I believe, so I'm not sure why this is happening in this case.

@gdalle
Copy link
Contributor

gdalle commented Mar 28, 2025

I don't think we can get around the fact that the chunk size depends on the number of colors (see also JuliaDiff/DifferentiationInterface.jl#593), for the same reason that in the dense case it depends on the array length.
DI's preparation mechanism acts as a function barrier in both scenarios. And even inside preparation, I use a function barrier right after picking the chunk size to make the rest of preparation (storage allocation in particular) type-stable: see here for an example with the Hessian.

@jClugstor
Copy link
Member

Yes, I was testing this yesterday, and on the DI branch the type instability didn't seem to come from prepare_alg. I think something else is causing the output of __init to be type unstable, i.e. the integrator is type unstable. I'm not super experienced with finding type instabilities so I could be looking at something wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants