Fix type instability in solve pathway (#454) - #455
Conversation
Implementation notesWhat this PR fixes:
Function barriers at these points ensure each branch compiles to type-stable code. With Upstream SciMLBase changes (not included): Workaround for users (no code changes needed): prob = BVProblem{true}(f!, bc!, u0, tspan; nlls=Val(false))
sol = solve(prob, MIRK5(; jac_alg=BVPJacobianAlgorithm(AutoForwardDiff(; chunksize=N))); dt=h) |
Benchmark ResultsClick to check benchmark results
|
Updated approach — fixing the true instabilityAfter further investigation, the function barrier approach was a band-aid. The true root cause is a one-line bug in SciMLBase. Root causeIn _nlls = Nothing # Cannot reliably inferThis is hit for This FixSciMLBase one-liner: - _nlls = Nothing # Cannot reliably infer
+ _nlls = false # Without bcresid_prototype, residual matches u0 sizeWith this fix, I've updated this PR to just update the tests (removing the now-unnecessary |
SciMLBase v2.152.1 fixes the root cause of SciML#454: the BVProblem constructor set `_nlls = Nothing` for StandardBVProblem without bcresid_prototype, but the solver always creates a residual matching u0 size, so nlls is definitionally false. The `Nothing` type parameter caused __internal_nlsolve_problem to return Union{NonlinearProblem, NonlinearLeastSquaresProblem}, propagating type instability through the entire solve chain. Test changes: - Remove nlls=Val(false) workaround from StandardBVProblem tests - Add BVProblem{true/false} constructor @inferred tests - Add __init type stability test Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
eb6de83 to
a893ce8
Compare
Summary
Addresses #454 by adding function barriers at key points in the solve chain where type instability propagates.
Changes
BoundaryValueDiffEqCore:
Val-dispatched function barrier in__internal_nlsolve_problemfor thenlls=Nothingcase, preventingUnion{NonlinearProblem, NonlinearLeastSquaresProblem}from propagatingMIRK/FIRK/MIRKN/Ascher/Shooting solvers:
__solve_internal_problembarrier functions, ensuring the algorithm selection and solve happens in a type-stable contextTests:
BVProblem Constructortest section verifyingBVProblem{true}(...),BVProblem{false}(...),TwoPointBVProblem{true/false}(...)are@inferred-clean__inittype stability testType stability status
BVProblem{true}(f!, bc!, u0, tspan)iipavoids runtimeisinplacecheckBVProblem(f!, bc!, u0, tspan)ODEProblem—isinplaceis runtime. Needs upstream SciMLBase fixsolve(prob, MIRK5(; jac_alg=...); nlls=Val(false))jac_algandnllssolve(prob, MIRK5(); dt=...)AutoSparsejac_alg has complex inferenceUpstream work needed
The convenience constructor
BVProblem(f, bc, u0, tspan)type instability lives in SciMLBase (same pattern asODEProblem). A companion PR to SciMLBase with function barriers for the BVP convenience constructors would complete the fix. The BoundaryValueDiffEq changes in this PR are independent and beneficial regardless.Test plan
@inferred solve(...)with explicitjac_algandnlls=Val(false))BVP.BVProblem()andBVP.solve()#454 reproducer works correctly🤖 Generated with Claude Code