Skip to content

orbit/coords: pin the 3D variational dxdv driver's host-side coords to numpy#988

Merged
jobovy merged 1 commit into
feat/backendsfrom
backend/variational-coords-pin
Jun 20, 2026
Merged

orbit/coords: pin the 3D variational dxdv driver's host-side coords to numpy#988
jobovy merged 1 commit into
feat/backendsfrom
backend/variational-coords-pin

Conversation

@jobovy

@jobovy jobovy commented Jun 20, 2026

Copy link
Copy Markdown
Owner

What

Burndown PR-7. integrateFullOrbit_dxdv (the 3D variational/STM driver) builds a pure-numpy base state and converts it via coords.cyl_to_rect/rect_to_cyl/rect_to_cyl_vec around the C integrator. Each does xp = get_namespace(...), which under the forced all-backend harness returns torch even for the numpy data → torch.cos(numpy_array) raises. This is host-side numpy bookkeeping, not a backend/autodiff path (the planar twin already uses literal numpy.cos/sin).

  • Add an inert xp=None keyword to coords.cyl_to_rect/rect_to_cyl/rect_to_cyl_vec (forwarded to get_namespace, which already takes an explicit xp= override; rect_to_cyl_vec forwards to its internal rect_to_cyl).
  • Pass xp=numpy at the 3 dxdv-driver call sites in integrateFullOrbit.py.

Impact

Flips 37/41 test_liouville_3d_2d_bridge torch entries (the dop853_c C path). The remaining 4 + test_liouville_3d/test_dxdv_3d_c_vs_python need the central scalar-coercion (#987) for their pure-Python _EOM_dxdv force eval (and one test-side coords call) — they flip once #987 lands.

Byte-identity + review

The xp=None default is inert for every existing caller, so numpy AND data-first jax/torch dispatch are unchanged. Verified byte-identical: coords + dxdv-driver output hashes identical parent vs branch; test_coords.py 97/97 and the orbit liouville/dxdv slice 288/3 identical. Adversarially reviewed (4 angles, all refuted) — including a full audit of every caller of these widely-used coords functions (no positional-arg collisions with the keyword-only boundary), the load-bearing-and-complete numpy-pin, and no decorator interaction.

🤖 Generated with Claude Code

…o numpy

integrateFullOrbit_dxdv builds a pure-numpy base state and converts it via
coords.cyl_to_rect / rect_to_cyl / rect_to_cyl_vec around the C integrator. Each
does `xp = get_namespace(...)`, which under the forced all-backend harness
returns torch even for the numpy data, so `torch.cos(numpy_array)` raises. This
is host-side numpy bookkeeping, not a backend/autodiff path (the planar twin
already uses literal numpy.cos/sin).

Add an inert `xp=None` keyword to coords.cyl_to_rect/rect_to_cyl/rect_to_cyl_vec
(forwarded to get_namespace, which already takes an explicit xp= override;
rect_to_cyl_vec forwards to its internal rect_to_cyl), and pass xp=numpy at the
3 dxdv-driver call sites in integrateFullOrbit.py. The xp=None default is inert
for every existing caller, so numpy AND data-first jax/torch dispatch are
unchanged (verified: test_orbit liouville_3d/dxdv_3d 150/150 identical parent vs
branch; cyl_to_rect/rect_to_cyl array_equal with/without xp=numpy).

Flips 37/41 test_liouville_3d_2d_bridge torch entries (the dop853_c C path). The
remaining 4 + test_liouville_3d/test_dxdv_3d_c_vs_python need the central
scalar-coercion (PR #987) for their pure-Python _EOM_dxdv force eval and a
test-side coords call.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.93%. Comparing base (69659c6) to head (9bf3ee6).

Additional details and impacted files
@@              Coverage Diff               @@
##           feat/backends     #988   +/-   ##
==============================================
  Coverage          99.93%   99.93%           
==============================================
  Files                254      254           
  Lines              39820    39820           
  Branches             837      839    +2     
==============================================
  Hits               39795    39795           
  Misses                25       25           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

All-backend test status (jax / torch)

Commit b4df5c81e8c887981413673ed2ec5f4d00ca45be

Green is achieved via the checked-in xfail-ledger (tests/backend_xfail.txt, applied xfail(strict=False)), so the metric to watch is the shrinking xfail count (burndown), not a raw pass count. A FAIL/ERR is an un-ledgered regression (reds the run). Because the ledger is non-strict, a now-passing ledgered test is a plain pass here (no per-push XPASS); burndown candidates -- in both directions -- are surfaced by the scheduled regen run, which rewrites the ledger from real outcomes. deferred is a separate burndown: tests skipped because they are unrunnable under the backend until the port is vectorized (see tests/backend_slow_skip.txt), e.g. the jax spherical-DF sampling/quadrature tests pending the Track F DF migration.

Overall: jax: 1057 passed · 265 xfail · 725 deferred | torch: 833 passed · 1210 xfail · 1 deferred

Ledger size: 2357 entries (jax=284, torch=2073).

Test shard jax torch
actionAngle ✅ 112 pass · 89 xfail ✅ 26 pass · 175 xfail
sphericaldf ✅ 164 pass · 26 xfail · 28 deferred ✅ 8 pass · 210 xfail
conversion + util + misc ✅ 86 pass · 5 xfail · 1 deferred ✅ 41 pass · 51 xfail
potential + scf + multipole — (no result) — (no result)
quantity + coords ✅ 287 pass · 49 xfail ✅ 189 pass · 147 xfail
orbit (energy/Jacobi + from_name) ✅ 0 pass · 0 xfail · 115 deferred ✅ 63 pass · 52 xfail
orbit + orbits (main) ✅ 0 pass · 0 xfail · 578 deferred ✅ 248 pass · 327 xfail
evolveddiskdf ✅ 35 pass · 0 xfail ✅ 32 pass · 3 xfail
jeans + dynamfric ✅ 17 pass · 2 xfail · 2 deferred ✅ 7 pass · 13 xfail · 1 deferred
qdf + pv2qdf + streamgapdf_impulse + noninertial ✅ 57 pass · 75 xfail · 1 deferred ✅ 14 pass · 119 xfail
streamgapdf ✅ 28 pass · 2 xfail ✅ 27 pass · 3 xfail
diskdf ✅ 129 pass · 0 xfail ✅ 112 pass · 17 xfail
streamdf + streamspraydf + streamTrack ✅ 142 pass · 17 xfail ✅ 66 pass · 93 xfail
Per-shard counts
Test shard backend pass xfail deferred XPASS fail error
actionAngle jax 112 89 0 0 0 0
actionAngle torch 26 175 0 0 0 0
sphericaldf jax 164 26 28 0 0 0
sphericaldf torch 8 210 0 0 0 0
conversion + util + misc jax 86 5 1 0 0 0
conversion + util + misc torch 41 51 0 0 0 0
potential + scf + multipole jax
potential + scf + multipole torch
quantity + coords jax 287 49 0 0 0 0
quantity + coords torch 189 147 0 0 0 0
orbit (energy/Jacobi + from_name) jax 0 0 115 0 0 0
orbit (energy/Jacobi + from_name) torch 63 52 0 0 0 0
orbit + orbits (main) jax 0 0 578 0 0 0
orbit + orbits (main) torch 248 327 0 0 0 0
evolveddiskdf jax 35 0 0 0 0 0
evolveddiskdf torch 32 3 0 0 0 0
jeans + dynamfric jax 17 2 2 0 0 0
jeans + dynamfric torch 7 13 1 0 0 0
qdf + pv2qdf + streamgapdf_impulse + noninertial jax 57 75 1 0 0 0
qdf + pv2qdf + streamgapdf_impulse + noninertial torch 14 119 0 0 0 0
streamgapdf jax 28 2 0 0 0 0
streamgapdf torch 27 3 0 0 0 0
diskdf jax 129 0 0 0 0 0
diskdf torch 112 17 0 0 0 0
streamdf + streamspraydf + streamTrack jax 142 17 0 0 0 0
streamdf + streamspraydf + streamTrack torch 66 93 0 0 0 0

@jobovy jobovy merged commit 76555cc into feat/backends Jun 20, 2026
146 checks passed
@jobovy jobovy deleted the backend/variational-coords-pin branch June 20, 2026 18:15
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