Skip to content

fix: handle r=0 in NFWSph deflections#430

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/nfw-sph-deflection-origin-fix
May 20, 2026
Merged

fix: handle r=0 in NFWSph deflections#430
Jammy2211 merged 1 commit into
mainfrom
feature/nfw-sph-deflection-origin-fix

Conversation

@Jammy2211
Copy link
Copy Markdown
Collaborator

Summary

  • NFWSph.deflections_2d_via_analytic_from produced NaN at the profile centre. The analytic form divides by eta = r/scale_radius and evaluates arccosh(1/r) inside coord_func_h, both of which blow up at r=0.
  • Any grid that included the origin pixel (e.g. an odd-sized image-plane grid centred on a lens at (0, 0)) propagated NaNs through every subsequent ray-trace.
  • Added an xp.where(eta < 1e-6, ...) guard so r=0 returns 0 (the symmetry-required value), matching the existing 1e-6 / 1e-24 guards already used by the elliptical NFW path (convergence_2d_from, shear_yx_2d_from, deflections_2d_via_analytic_from). No public API change.

Why now

Surfaced by two scripts in autolens_workspace/scripts/imaging/features/advanced/mass_stellar_dark/ (fit.py, likelihood_function.py) where a manual stellar + dark + shear deflection sum is compared against the Tracer's total. Both sides got NaN at the origin pixel, and np.allclose(NaN, NaN) == False made the comparison fail despite the math being correct everywhere else.

API Changes

None. NFWSph.deflections_yx_2d_from(grid) signature and return type unchanged; only the behaviour at r=0 changes (NaN → 0).

Test plan

  • pytest test_autogalaxy/profiles/mass/dark/test_nfw.py — 25 passed
  • Reproduction snippet: NaN in dark/sum/lens == 0, allclose(sum, lens) == True, allclose(grid_manual, grid_tracer) == True, origin deflection now [-0., 0.]
  • Both mass_stellar_dark workspace scripts run end-to-end with no RuntimeWarning: divide by zero and no AssertionError

🤖 Generated with Claude Code

The analytic spherical NFW deflection divides by `eta = r/scale_radius`
and evaluates `arccosh(1/r)` inside `coord_func_h`, both of which blow
up to NaN at the profile centre. Any grid that included the origin
pixel (e.g. an odd-sized image-plane grid centred on a lens at (0, 0))
propagated those NaNs through every subsequent ray-trace.

Add a `xp.where(eta < 1e-6, ...)` guard so the centre pixel returns the
symmetry-required value of zero, matching the existing 1e-6 / 1e-24
guards already used by the elliptical NFW path
(`NFW.convergence_2d_from`, `NFW.shear_yx_2d_from`,
`NFW.deflections_2d_via_analytic_from`). No public API change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Jammy2211 Jammy2211 merged commit 398f741 into main May 20, 2026
6 checks passed
@Jammy2211 Jammy2211 deleted the feature/nfw-sph-deflection-origin-fix branch May 20, 2026 17:09
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