Skip to content

feat: solve_bvp collocation solver with implicit differentiation - #11

Merged
jlperla merged 5 commits into
mainfrom
bvp-solver
Aug 20, 2026
Merged

feat: solve_bvp collocation solver with implicit differentiation#11
jlperla merged 5 commits into
mainfrom
bvp-solver

Conversation

@jlperla

@jlperla jlperla commented Aug 20, 2026

Copy link
Copy Markdown
Member

Ports scipy v1.18's solve_bvp to JAX as tinydiffeq.solve_bvp: the same 4th-order Lobatto IIIA collocation, damped Newton method, 5-point Lobatto residual control, mesh refinement, constants, and status semantics, validated node-for-node against scipy to machine epsilon (including failure paths).

Beyond the port: fully jit-compiled with static max_nodes padding and zero recompiles across changed meshes/guesses/p/tolerances; local Jacobians from AD instead of finite differences; one custom_jvp implementing the implicit function theorem on the frozen final mesh (reverse mode via transposition through lax.custom_linear_solve, exact higher order); vmap with per-lane statuses; float32/GPU support; and a structured orthogonal factorization of the bordered almost-block-diagonal collocation system (tinydiffeq.babd, level-batched cyclic reduction). Unknown parameters are z (solved jointly); p is the only AD input; the singular term S is supported.

Warm jitted calls beat scipy on every benchmark case (shock layer 2.1 ms vs 6.3 ms; 5-node problem 0.25 ms vs 0.60 ms); the kernels neoclassical-growth baseline (1489 nodes, tol=1e-10) matches scipy's meshes node-for-node at runtime parity. Also removes the flaky _cache_size() tests in favor of the AGENTS.md audit protocol, adds the repo disclaimer, and trims the README.

Reviewed pre-merge by Codex and an Opus JAX reviewer; all confirmed findings fixed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UwxGiVZSEDw3pzMA7Zzb1g

jlperla and others added 5 commits August 19, 2026 21:25
Level-batched cyclic reduction with orthogonal eliminations for
bordered almost-block-diagonal systems: one batched complete QR per
level, a final dense boundary LU, forward and transpose solves from
the same factors, and a dense scatter/matvec reference.

Co-Authored-By: Mecha Perla (Claude) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwxGiVZSEDw3pzMA7Zzb1g
Faithful port of scipy.integrate.solve_bvp: 4th-order Lobatto IIIA
collocation, damped Newton with the affine-invariant criterion, 5-point
Lobatto residual control, and insert-1/insert-2 mesh refinement, with
scipy's constants and status semantics. Local Jacobians come from AD
instead of finite differences; the collocation system is factored by
the structured BABD cyclic reduction each Newton refresh.

The whole solve is jit-compiled with lax.while_loop loops and padded
to a static max_nodes, vmaps with per-lane statuses, and carries one
custom_jvp: the implicit function theorem at the solution on the
frozen final mesh, transposing to reverse mode through
lax.custom_linear_solve and recursing for higher order. Failures are
data (statuses 0-3, never raises in traced code); failed lanes have
exact-zero tangents and a converged solve whose Jacobian cannot be
refactored reports NaN tangents in both AD modes. Unknown parameters
are z (guess z_0, solved jointly); p is the only AD input; args is
inert. Adds BVPSolution, hermite_derivative, docs, and tests
cross-checked against scipy.

Co-Authored-By: Mecha Perla (Claude) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwxGiVZSEDw3pzMA7Zzb1g
fn._cache_size() reads JAX's globally shared C++ executable cache
(capacity 8192, LRU), so absolute entry-count assertions turn flaky as
the suite grows. Recompilation hygiene is instead audited manually with
the environment-variable protocol recorded in AGENTS.md.

Co-Authored-By: Mecha Perla (Claude) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwxGiVZSEDw3pzMA7Zzb1g
Cold-compile and warm timings of jitted-wrapper solves against scipy
references, plus a cache-audit mode for the AGENTS.md recompilation
protocol. Warm jitted calls beat scipy on every recorded case.

Co-Authored-By: Mecha Perla (Claude) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwxGiVZSEDw3pzMA7Zzb1g
Lead the README and docs index with the unsupported-research-repo
disclaimer naming SciML, scipy, and diffrax as the reference
implementations, and trim the README to one example block with an SDE
ensemble snippet.

Co-Authored-By: Mecha Perla (Claude) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwxGiVZSEDw3pzMA7Zzb1g
@jlperla
jlperla merged commit 2f99b0f into main Aug 20, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant