Skip to content

orbit: make Orbit.L() cross-product namespace-consistent#985

Merged
jobovy merged 2 commits into
feat/backendsfrom
backend/orbits-L-namespace
Jun 20, 2026
Merged

orbit: make Orbit.L() cross-product namespace-consistent#985
jobovy merged 2 commits into
feat/backendsfrom
backend/orbits-L-namespace

Conversation

@jobovy

@jobovy jobovy commented Jun 20, 2026

Copy link
Copy Markdown
Owner

What

Burndown PR-6 (Orbits.py only). Under a forced jax/torch backend, L()'s position/velocity accessors were inconsistent (some returned a backend Tensor, some stayed numpy), so out=numpy.zeros(...); out[...,0]=y*vz-z*vy hit numpy.ndarray * Tensor → TypeError. Resolve one namespace from all six components, coerce onto it only when non-numpy, and assemble via xp.stack(..., axis=-1) (also avoids jax's immutable-array in-place assign).

Byte-identity + review

numpy path byte-identical in data and flags: get_namespace(<all numpy>) is numpy, coercion skipped, and the result is passed through numpy.ascontiguousarray to restore the historical numpy.zeros()+assign C-contiguous layout (xp.stack(axis=-1) of the F-contiguous accessor outputs is otherwise non-C-contiguous for ensemble shapes — caught by adversarial review). Verified SHA-256 identical + C_CONTIGUOUS for single/ensemble/init-time L(). Fixes the torch Orbit.L() TypeError; the other L() code paths (1D/2D/phasedim-5) are untouched.

🤖 Generated with Claude Code

jobovy and others added 2 commits June 20, 2026 01:33
Under a forced jax/torch backend, L()'s position/velocity accessors were
inconsistent (some returned a backend Tensor, some stayed numpy), so
`out = numpy.zeros(...); out[...,0] = y*vz - z*vy` hit
`numpy.ndarray * Tensor -> TypeError`. Resolve a single namespace from all six
components (`xp = get_namespace(x,y,z,vx,vy,vz)`), coerce them onto xp only when
xp is not numpy, and assemble the cross product with `xp.stack(..., axis=-1)`
(also avoids jax's immutable-array in-place-assign).

numpy path byte-identical: get_namespace(<all numpy>) is numpy and the coercion
block is skipped. xp.stack(axis=-1) of the F-contiguous accessor outputs is not
C-contiguous for ensemble shapes, so on the numpy branch the result is passed
through numpy.ascontiguousarray to restore the historical numpy.zeros()+assign
C-contiguous layout -> byte-identical in BOTH data and flags (verified SHA-256
identical + C_CONTIGUOUS for single/ensemble/init-time L()). Fixes the torch
`numpy.ndarray * Tensor` failure in Orbit.L().

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was no backend test for Orbit.L(). PR-6 made its phasedim==6 cross-product
namespace-consistent; add jax + torch tests that integrate a backend orbit and
call o.L(ts), asserting it returns a backend array matching the numpy/C
reference (and a numpy-path no-change check) -- covering the new
get_namespace+asarray+xp.stack coercion branch in the coverage shard.

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 (fcad3f7) to head (07754ee).

Additional details and impacted files
@@              Coverage Diff               @@
##           feat/backends     #985   +/-   ##
==============================================
  Coverage          99.93%   99.93%           
==============================================
  Files                253      253           
  Lines              39803    39806    +3     
  Branches             839      836    -3     
==============================================
+ Hits               39778    39781    +3     
  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

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

All-backend test status (jax / torch)

Commit 8b3429169ce7204aa198a911ae7c42b0aef0d1a0

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: 1051 passed · 271 xfail · 725 deferred | torch: 766 passed · 1277 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 ✅ 281 pass · 55 xfail ✅ 189 pass · 147 xfail
orbit (energy/Jacobi + from_name) ✅ 0 pass · 0 xfail · 115 deferred ✅ 54 pass · 61 xfail
orbit + orbits (main) ✅ 0 pass · 0 xfail · 578 deferred ✅ 190 pass · 385 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 281 55 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 54 61 0 0 0 0
orbit + orbits (main) jax 0 0 578 0 0 0
orbit + orbits (main) torch 190 385 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 0ddb1ee into feat/backends Jun 20, 2026
146 checks passed
@jobovy jobovy deleted the backend/orbits-L-namespace branch June 20, 2026 12: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