Skip to content

Commit edbb21b

Browse files
Jammy2211claude
authored andcommitted
Remove integral-based deflection and potential methods from mass profiles
Move slow scipy.integrate.quad-based methods to standalone reference scripts in autolens_workspace_test. The actual deflection calculations already use MGE or CSE decompositions; the integrals were only used for testing. Removed: deflections_2d_via_integral_from, deflection_func from Gaussian, Sersic, SersicGradient, NFW, gNFW, gNFWSph. Removed integral-based potential_2d_from and potential_func from elliptical NFW and gNFW. Removed dead tabulate_integral from AbstractgNFW. Kept gNFW.convergence_func (essential for convergence_2d_from and MGE). Updated comparison tests to use hardcoded expected values instead of calling integral methods. Closes #323 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 07374f0 commit edbb21b

15 files changed

Lines changed: 2245 additions & 3280 deletions

File tree

autogalaxy/profiles/mass/dark/abstract.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,6 @@ def convergence_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
6767

6868
return self.convergence_func(grid_radius=grid_eta, xp=xp)
6969

70-
def tabulate_integral(self, grid, tabulate_bins, **kwargs):
71-
"""Tabulate an integral over the convergence of deflection potential of a mass profile. This is used in \
72-
the gNFW profile classes to speed up the integration procedure.
73-
74-
Parameters
75-
----------
76-
grid
77-
The grid of (y,x) arc-second coordinates the potential / deflection_stacks are computed on.
78-
tabulate_bins
79-
The number of bins to tabulate the inner integral of this profile.
80-
"""
81-
eta_min = 1.0e-4
82-
eta_max = 1.05 * np.max(self.elliptical_radii_grid_from(grid=grid, **kwargs))
83-
84-
minimum_log_eta = np.log10(eta_min)
85-
maximum_log_eta = np.log10(eta_max)
86-
bin_size = (maximum_log_eta - minimum_log_eta) / (tabulate_bins - 1)
87-
88-
return eta_min, eta_max, minimum_log_eta, maximum_log_eta, bin_size
89-
9070
def density_3d_func(self, r, xp=np):
9171
x = r.array / self.scale_radius
9272

autogalaxy/profiles/mass/dark/gnfw.py

Lines changed: 1 addition & 266 deletions
Original file line numberDiff line numberDiff line change
@@ -28,118 +28,6 @@ def deflections_2d_via_mge_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs)
2828
)
2929
return deflections_via_mge
3030

31-
@aa.grid_dec.to_vector_yx
32-
@aa.grid_dec.transform
33-
def deflections_2d_via_integral_from(
34-
self, grid: aa.type.Grid2DLike, xp=np, tabulate_bins=1000, **kwargs
35-
):
36-
"""
37-
Calculate the deflection angles at a given set of arc-second gridded coordinates.
38-
39-
Parameters
40-
----------
41-
grid
42-
The grid of (y,x) arc-second coordinates the deflection angles are computed on.
43-
tabulate_bins
44-
The number of bins to tabulate the inner integral of this profile.
45-
46-
"""
47-
48-
def surface_density_integrand(x, kappa_radius, scale_radius, inner_slope):
49-
return (
50-
(3 - inner_slope)
51-
* (x + kappa_radius / scale_radius) ** (inner_slope - 4)
52-
* (1 - np.sqrt(1 - x * x))
53-
)
54-
55-
def calculate_deflection_component(npow, yx_index):
56-
57-
from scipy.integrate import quad
58-
59-
deflection_grid = np.zeros(grid.shape[0])
60-
61-
for i in range(grid.shape[0]):
62-
deflection_grid[i] = (
63-
2.0
64-
* self.kappa_s
65-
* self.axis_ratio(xp)
66-
* grid[i, yx_index]
67-
* quad(
68-
self.deflection_func,
69-
a=0.0,
70-
b=1.0,
71-
args=(
72-
grid.array[i, 0],
73-
grid.array[i, 1],
74-
npow,
75-
self.axis_ratio(xp),
76-
minimum_log_eta,
77-
maximum_log_eta,
78-
tabulate_bins,
79-
surface_density_integral,
80-
),
81-
epsrel=gNFW.epsrel,
82-
)[0]
83-
)
84-
85-
return deflection_grid
86-
87-
(
88-
eta_min,
89-
eta_max,
90-
minimum_log_eta,
91-
maximum_log_eta,
92-
bin_size,
93-
) = self.tabulate_integral(grid, tabulate_bins)
94-
95-
surface_density_integral = np.zeros((tabulate_bins,))
96-
97-
for i in range(tabulate_bins):
98-
from scipy.integrate import quad
99-
100-
eta = 10.0 ** (minimum_log_eta + (i - 1) * bin_size)
101-
102-
integral = quad(
103-
surface_density_integrand,
104-
a=0.0,
105-
b=1.0,
106-
args=(eta, self.scale_radius, self.inner_slope),
107-
epsrel=gNFW.epsrel,
108-
)[0]
109-
110-
surface_density_integral[i] = (
111-
(eta / self.scale_radius) ** (1 - self.inner_slope)
112-
) * (((1 + eta / self.scale_radius) ** (self.inner_slope - 3)) + integral)
113-
114-
deflection_y = calculate_deflection_component(npow=1.0, yx_index=0)
115-
deflection_x = calculate_deflection_component(npow=0.0, yx_index=1)
116-
117-
return self.rotated_grid_from_reference_frame_from(
118-
np.multiply(1.0, np.vstack((deflection_y, deflection_x)).T),
119-
)
120-
121-
@staticmethod
122-
def deflection_func(
123-
u,
124-
y,
125-
x,
126-
npow,
127-
axis_ratio,
128-
minimum_log_eta,
129-
maximum_log_eta,
130-
tabulate_bins,
131-
surface_density_integral,
132-
):
133-
_eta_u = np.sqrt((u * ((x**2) + (y**2 / (1 - (1 - axis_ratio**2) * u)))))
134-
bin_size = (maximum_log_eta - minimum_log_eta) / (tabulate_bins - 1)
135-
i = 1 + int((np.log10(_eta_u) - minimum_log_eta) / bin_size)
136-
r1 = 10.0 ** (minimum_log_eta + (i - 1) * bin_size)
137-
r2 = r1 * 10.0**bin_size
138-
kap = surface_density_integral[i] + (
139-
surface_density_integral[i + 1] - surface_density_integral[i]
140-
) * (_eta_u - r1) / (r2 - r1)
141-
return kap / (1.0 - (1.0 - axis_ratio**2) * u) ** (npow + 0.5)
142-
14331
def convergence_func(self, grid_radius: float, xp=np) -> float:
14432

14533
from scipy.integrate import quad
@@ -170,108 +58,6 @@ def integral_y(y, eta):
17058

17159
return grid_radius
17260

173-
@aa.over_sample
174-
@aa.grid_dec.to_array
175-
@aa.grid_dec.transform
176-
def potential_2d_from(
177-
self, grid: aa.type.Grid2DLike, xp=np, tabulate_bins=1000, **kwargs
178-
):
179-
"""
180-
Calculate the potential at a given set of arc-second gridded coordinates.
181-
182-
Parameters
183-
----------
184-
grid
185-
The grid of (y,x) arc-second coordinates the deflection angles are computed on.
186-
tabulate_bins
187-
The number of bins to tabulate the inner integral of this profile.
188-
189-
"""
190-
191-
from scipy import special
192-
from scipy.integrate import quad
193-
194-
def deflection_integrand(x, kappa_radius, scale_radius, inner_slope):
195-
return (x + kappa_radius / scale_radius) ** (inner_slope - 3) * (
196-
(1 - np.sqrt(1 - x**2)) / x
197-
)
198-
199-
(
200-
eta_min,
201-
eta_max,
202-
minimum_log_eta,
203-
maximum_log_eta,
204-
bin_size,
205-
) = self.tabulate_integral(grid, tabulate_bins)
206-
207-
potential_grid = np.zeros(grid.shape[0])
208-
209-
deflection_integral = np.zeros((tabulate_bins,))
210-
211-
for i in range(tabulate_bins):
212-
eta = 10.0 ** (minimum_log_eta + (i - 1) * bin_size)
213-
214-
integral = quad(
215-
deflection_integrand,
216-
a=0.0,
217-
b=1.0,
218-
args=(eta, self.scale_radius, self.inner_slope),
219-
epsrel=gNFW.epsrel,
220-
)[0]
221-
222-
deflection_integral[i] = (
223-
(eta / self.scale_radius) ** (2 - self.inner_slope)
224-
) * (
225-
(1.0 / (3 - self.inner_slope))
226-
* special.hyp2f1(
227-
3 - self.inner_slope,
228-
3 - self.inner_slope,
229-
4 - self.inner_slope,
230-
-(eta / self.scale_radius),
231-
)
232-
+ integral
233-
)
234-
235-
for i in range(grid.shape[0]):
236-
potential_grid[i] = (2.0 * self.kappa_s * self.axis_ratio(xp)) * quad(
237-
self.potential_func,
238-
a=0.0,
239-
b=1.0,
240-
args=(
241-
grid.array[i, 0],
242-
grid.array[i, 1],
243-
self.axis_ratio(xp),
244-
minimum_log_eta,
245-
maximum_log_eta,
246-
tabulate_bins,
247-
deflection_integral,
248-
),
249-
epsrel=gNFW.epsrel,
250-
)[0]
251-
252-
return potential_grid
253-
254-
@staticmethod
255-
def potential_func(
256-
u,
257-
y,
258-
x,
259-
axis_ratio,
260-
minimum_log_eta,
261-
maximum_log_eta,
262-
tabulate_bins,
263-
potential_integral,
264-
):
265-
_eta_u = np.sqrt((u * ((x**2) + (y**2 / (1 - (1 - axis_ratio**2) * u)))))
266-
bin_size = (maximum_log_eta - minimum_log_eta) / (tabulate_bins - 1)
267-
i = 1 + int((np.log10(_eta_u) - minimum_log_eta) / bin_size)
268-
r1 = 10.0 ** (minimum_log_eta + (i - 1) * bin_size)
269-
r2 = r1 * 10.0**bin_size
270-
angle = potential_integral[i] + (
271-
potential_integral[i + 1] - potential_integral[i]
272-
) * (_eta_u - r1) / (r2 - r1)
273-
return _eta_u * (angle / u) / (1.0 - (1.0 - axis_ratio**2) * u) ** 0.5
274-
27561

27662
class gNFWSph(gNFW):
27763
def __init__(
@@ -306,55 +92,4 @@ def __init__(
30692
scale_radius=scale_radius,
30793
)
30894

309-
@aa.grid_dec.to_vector_yx
310-
@aa.grid_dec.transform
311-
def deflections_2d_via_integral_from(
312-
self, grid: aa.type.Grid2DLike, xp=np, **kwargs
313-
):
314-
"""
315-
Calculate the deflection angles at a given set of arc-second gridded coordinates.
316-
317-
Parameters
318-
----------
319-
grid
320-
The grid of (y,x) arc-second coordinates the deflection angles are computed on.
321-
"""
322-
323-
eta = np.multiply(
324-
1.0 / self.scale_radius, self.radial_grid_from(grid, **kwargs).array
325-
)
326-
327-
deflection_grid = np.zeros(grid.shape[0])
328-
329-
for i in range(grid.shape[0]):
330-
deflection_grid[i] = np.multiply(
331-
4.0 * self.kappa_s * self.scale_radius, self.deflection_func_sph(eta[i])
332-
)
333-
334-
return self._cartesian_grid_via_radial_from(
335-
grid=grid, radius=deflection_grid, xp=xp
336-
)
337-
338-
@staticmethod
339-
def deflection_integrand(y, eta, inner_slope):
340-
return (y + eta) ** (inner_slope - 3) * ((1 - np.sqrt(1 - y**2)) / y)
341-
342-
def deflection_func_sph(self, eta):
343-
344-
from scipy import special
345-
from scipy.integrate import quad
346-
347-
integral_y_2 = quad(
348-
self.deflection_integrand,
349-
a=0.0,
350-
b=1.0,
351-
args=(eta, self.inner_slope),
352-
epsrel=1.49e-6,
353-
)[0]
354-
return eta ** (2 - self.inner_slope) * (
355-
(1.0 / (3 - self.inner_slope))
356-
* special.hyp2f1(
357-
3 - self.inner_slope, 3 - self.inner_slope, 4 - self.inner_slope, -eta
358-
)
359-
+ integral_y_2
360-
)
95+
pass

0 commit comments

Comments
 (0)