orbit/coords: pin the 3D variational dxdv driver's host-side coords to numpy#988
Conversation
…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 Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
All-backend test status (jax / torch)Commit Green is achieved via the checked-in xfail-ledger ( Overall: jax: 1057 passed · 265 xfail · 725 deferred | torch: 833 passed · 1210 xfail · 1 deferred Ledger size: 2357 entries (jax=284, torch=2073).
Per-shard counts
|
What
Burndown PR-7.
integrateFullOrbit_dxdv(the 3D variational/STM driver) builds a pure-numpy base state and converts it viacoords.cyl_to_rect/rect_to_cyl/rect_to_cyl_vecaround the C integrator. Each doesxp = 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 literalnumpy.cos/sin).xp=Nonekeyword tocoords.cyl_to_rect/rect_to_cyl/rect_to_cyl_vec(forwarded toget_namespace, which already takes an explicitxp=override;rect_to_cyl_vecforwards to its internalrect_to_cyl).xp=numpyat the 3 dxdv-driver call sites inintegrateFullOrbit.py.Impact
Flips 37/41
test_liouville_3d_2d_bridgetorch entries (thedop853_cC path). The remaining 4 +test_liouville_3d/test_dxdv_3d_c_vs_pythonneed the central scalar-coercion (#987) for their pure-Python_EOM_dxdvforce eval (and one test-side coords call) — they flip once #987 lands.Byte-identity + review
The
xp=Nonedefault 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.py97/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