fix: handle r=0 in NFWSph deflections#430
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
NFWSph.deflections_2d_via_analytic_fromproduced NaN at the profile centre. The analytic form divides byeta = r/scale_radiusand evaluatesarccosh(1/r)insidecoord_func_h, both of which blow up at r=0.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 ellipticalNFWpath (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 theTracer's total. Both sides got NaN at the origin pixel, andnp.allclose(NaN, NaN) == Falsemade 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 passedNaN in dark/sum/lens == 0,allclose(sum, lens) == True,allclose(grid_manual, grid_tracer) == True, origin deflection now[-0., 0.]mass_stellar_darkworkspace scripts run end-to-end with noRuntimeWarning: divide by zeroand noAssertionError🤖 Generated with Claude Code