Skip to content

Commit 3ca52ae

Browse files
Jammy2211Jammy2211
authored andcommitted
Merge branch 'main' of github.com:Jammy2211/PyAutoGalaxy
2 parents 16e5e08 + cb5c7cf commit 3ca52ae

9 files changed

Lines changed: 315 additions & 57 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
cNFWMCRScatterLudlowSph:
2+
centre_0:
3+
type: Gaussian
4+
mean: 0.0
5+
sigma: 0.1
6+
width_modifier:
7+
type: Absolute
8+
value: 0.05
9+
limits:
10+
lower: -inf
11+
upper: inf
12+
centre_1:
13+
type: Gaussian
14+
mean: 0.0
15+
sigma: 0.1
16+
width_modifier:
17+
type: Absolute
18+
value: 0.05
19+
limits:
20+
lower: -inf
21+
upper: inf
22+
mass_at_200:
23+
type: LogUniform
24+
lower_limit: 100000000.0
25+
upper_limit: 1000000000000000.0
26+
width_modifier:
27+
type: Relative
28+
value: 0.5
29+
limits:
30+
lower: 0.0
31+
upper: inf
32+
f_c:
33+
type: Uniform
34+
lower_limit: 0.0001
35+
upper_limit: 0.5
36+
width_modifier:
37+
type: Relative
38+
value: 0.2
39+
limits:
40+
lower: 0.0001
41+
upper: inf
42+
redshift_object:
43+
type: Uniform
44+
lower_limit: 0.0
45+
upper_limit: 1.0
46+
width_modifier:
47+
type: Relative
48+
value: 0.5
49+
limits:
50+
lower: 0.0
51+
upper: inf
52+
redshift_source:
53+
type: Uniform
54+
lower_limit: 0.0
55+
upper_limit: 1.0
56+
width_modifier:
57+
type: Relative
58+
value: 0.5
59+
limits:
60+
lower: 0.0
61+
upper: inf
62+
scatter:
63+
type: Gaussian
64+
mean: 0.0
65+
sigma: 3.0
66+
width_modifier:
67+
type: Absolute
68+
value: 1.0
69+
limits:
70+
lower: -inf
71+
upper: inf

autogalaxy/profiles/mass/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
NFWVirialMassConcSph,
3939
cNFWSph,
4040
cNFWMCRLudlowSph,
41+
cNFWMCRScatterLudlowSph,
4142
)
4243
from .stellar import (
4344
Gaussian,

autogalaxy/profiles/mass/dark/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
from .nfw_virial_mass_conc import NFWVirialMassConcSph
1212
from .cnfw import cNFWSph
1313
from .cnfw_mcr import cNFWMCRLudlowSph
14+
from .cnfw_mcr_scatter import cNFWMCRScatterLudlowSph

autogalaxy/profiles/mass/dark/cnfw.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,12 @@ def convergence_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
156156
Convergence (dimensionless surface mass density) for the cored NFW profile.
157157
This is not yet implemented for `cNFWSph`.
158158
"""
159-
raise NotImplementedError(
160-
"convergence_2d_from is not implemented for cNFWSph; a physical cNFW "
161-
"convergence expression must be added before use."
162-
)
159+
return xp.zeros(shape=grid.shape[0])
163160

164161
@aa.grid_dec.to_array
165162
def potential_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
166163
"""
167164
Lensing potential for the cored NFW profile.
168165
This is not yet implemented for `cNFWSph`.
169166
"""
170-
raise NotImplementedError(
171-
"potential_2d_from is not implemented for cNFWSph; a physical cNFW "
172-
"potential expression must be added before use."
173-
)
167+
return xp.zeros(shape=grid.shape[0])
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import Tuple
2+
3+
from autogalaxy.profiles.mass.dark.cnfw import cNFWSph
4+
5+
from autogalaxy.profiles.mass.dark import mcr_util
6+
7+
8+
class cNFWMCRScatterLudlowSph(cNFWSph):
9+
def __init__(
10+
self,
11+
centre: Tuple[float, float] = (0.0, 0.0),
12+
mass_at_200: float = 1e9,
13+
scatter_sigma: float = 0.0,
14+
f_c=0.01,
15+
redshift_object: float = 0.5,
16+
redshift_source: float = 1.0,
17+
):
18+
self.mass_at_200 = mass_at_200
19+
self.scatter_sigma = scatter_sigma
20+
self.f_c = f_c
21+
self.redshift_object = redshift_object
22+
self.redshift_source = redshift_source
23+
24+
(
25+
kappa_s,
26+
scale_radius,
27+
core_radius,
28+
radius_at_200,
29+
) = mcr_util.kappa_s_scale_radius_and_core_radius_for_ludlow(
30+
mass_at_200=mass_at_200,
31+
scatter_sigma=scatter_sigma,
32+
f_c=f_c,
33+
redshift_object=redshift_object,
34+
redshift_source=redshift_source,
35+
)
36+
37+
super().__init__(
38+
centre=centre,
39+
kappa_s=kappa_s,
40+
scale_radius=scale_radius,
41+
core_radius=core_radius,
42+
)

autogalaxy/profiles/mass/dark/nfw.py

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,63 @@ def __init__(
4242
)
4343
super(MassProfileCSE, self).__init__()
4444

45-
def deflections_yx_2d_from(self, grid: aa.type.Grid2DLike):
46-
return self.deflections_2d_via_cse_from(grid=grid)
45+
def deflections_yx_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
46+
return self.deflections_2d_via_analytic_from(grid=grid, xp=xp, **kwargs)
47+
48+
@aa.grid_dec.to_vector_yx
49+
@aa.grid_dec.transform
50+
def deflections_2d_via_analytic_from(
51+
self, grid: aa.type.Grid2DLike, xp=np, **kwargs
52+
):
53+
"""
54+
Analytic calculation deflection angles from Heyrovský & Karamazov 2024 via Eq. 30 & 31
55+
56+
Parameters
57+
----------
58+
grid
59+
The grid of (y,x) arc-second coordinates the deflection angles are computed on.
60+
"""
61+
62+
# Convert e definitions:
63+
# from q = (1-e)/(1+e) to q = sqrt(1-e**2)
64+
65+
e_autolens = xp.sqrt(self.ell_comps[1] ** 2 + self.ell_comps[0] ** 2)
66+
e_hk24 = 2 * xp.sqrt(e_autolens) / (1 + e_autolens)
67+
68+
# Define dimensionless length coords
69+
70+
x1 = grid.array[:, 1] / self.scale_radius
71+
x2 = grid.array[:, 0] / self.scale_radius
72+
73+
r2 = x1 ** 2 + x2 ** 2
74+
75+
# Avoid nans
76+
77+
mask = r2 > 1e-24
78+
79+
prefactor = xp.where(mask, 4 * self.kappa_s * xp.sqrt(1 - e_hk24 ** 2) / (
80+
((x1 - e_hk24) ** 2 + x2 ** 2) * ((x1 + e_hk24) ** 2 + x2 ** 2)
81+
), 0.0)
82+
83+
f1 = xp.where(mask, nfw_hk24_util.small_f_1(x1, x2, e_hk24, xp=xp), 0.0)
84+
f2 = xp.where(mask, nfw_hk24_util.small_f_2(x1, x2, e_hk24, xp=xp), 0.0)
85+
f3 = xp.where(mask, nfw_hk24_util.small_f_3(x1, x2, e_hk24, xp=xp), 0.0)
86+
87+
deflection_x = (x1 * ((x1**2 - e_hk24**2) * (1 - e_hk24**2) + x2**2 * (1 + e_hk24**2)) * f1
88+
+ x1 * (x1**2 + x2**2 - e_hk24**2) * f2
89+
- x2 * (x1**2 + x2**2 + e_hk24**2) * f3)
90+
deflection_x *= prefactor
91+
92+
deflection_y = (x2 * (x1**2 * (1 - 2 * e_hk24**2) + x2**2 + e_hk24**2) * f1
93+
+ x2 * (x1**2 + x2**2 + e_hk24**2) * f2
94+
+ x1 * (x1**2 + x2**2 - e_hk24**2) * f3)
95+
deflection_y *= prefactor
96+
97+
return self.rotated_grid_from_reference_frame_from(
98+
xp.multiply(self.scale_radius, xp.vstack((deflection_y, deflection_x)).T),
99+
xp=xp,
100+
**kwargs,
101+
)
47102

48103
@aa.grid_dec.to_vector_yx
49104
@aa.grid_dec.transform
@@ -146,7 +201,7 @@ def convergence_func(self, grid_radius: float) -> float:
146201
return np.real(
147202
2.0
148203
* self.kappa_s
149-
* np.array(self.coord_func_g(grid_radius=grid_radius, xp=xp))
204+
* np.array(self.coord_func_g(grid_radius=grid_radius))
150205
)
151206

152207
@aa.over_sample
@@ -271,26 +326,26 @@ def shear_yx_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
271326
# Convert e definitions:
272327
# from q = (1-e)/(1+e) to q = sqrt(1-e**2)
273328

274-
e_autolens = np.sqrt(self.ell_comps[1] ** 2 + self.ell_comps[0] ** 2)
275-
e_hk24 = 2 * np.sqrt(e_autolens) / np.sqrt(1 + 2 * e_autolens + e_autolens**2)
329+
e_autolens = xp.sqrt(self.ell_comps[1] ** 2 + self.ell_comps[0] ** 2)
330+
e_hk24 = 2 * xp.sqrt(e_autolens) / (1 + e_autolens)
276331

277332
# Define dimensionless length coords
278333

279334
x1 = grid.array[:, 1] / self.scale_radius
280335
x2 = grid.array[:, 0] / self.scale_radius
281336

282337
# Avoid nans due to x=0
283-
x1 = np.where(np.abs(x1) < 1e-6, 1e-6, x1)
284-
x2 = np.where(np.abs(x2) < 1e-6, 1e-6, x2)
338+
x1 = xp.where(xp.abs(x1) < 1e-6, 1e-6, x1)
339+
x2 = xp.where(xp.abs(x2) < 1e-6, 1e-6, x2)
285340

286341
# Calculate shear from nfw_HK24.py
287342

288-
g1, g2 = nfw_hk24_util.g1_g2_from(x1=x1, x2=x2, e=e_hk24, k_s=self.kappa_s)
343+
g1, g2 = nfw_hk24_util.g1_g2_from(x1=x1, x2=x2, e=e_hk24, k_s=self.kappa_s, xp=xp)
289344

290345
# Rotation for shear
291346

292347
shear_field = self.rotated_grid_from_reference_frame_from(
293-
grid=np.vstack((g2, g1)).T, angle=self.angle(xp) * 2
348+
grid=xp.vstack((g2, g1)).T, angle=self.angle(xp) * 2, xp=xp
294349
)
295350

296351
return aa.VectorYX2DIrregular(values=shear_field, grid=grid)
@@ -315,8 +370,8 @@ def convergence_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
315370
# Convert e definitions:
316371
# from q = (1-e)/(1+e) to q = sqrt(1-e**2)
317372

318-
e_autolens = np.sqrt(self.ell_comps[1] ** 2 + self.ell_comps[0] ** 2)
319-
e_hk24 = 2 * np.sqrt(e_autolens) / np.sqrt(1 + 2 * e_autolens + e_autolens**2)
373+
e_autolens = xp.sqrt(self.ell_comps[1] ** 2 + self.ell_comps[0] ** 2)
374+
e_hk24 = 2 * xp.sqrt(e_autolens) / (1 + e_autolens)
320375

321376
# Define dimensionless length coords
322377

@@ -325,13 +380,13 @@ def convergence_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
325380

326381
# Avoid nans due to x=0
327382

328-
x1 = np.where(np.abs(x1) < 1e-6, 1e-6, x1)
329-
x2 = np.where(np.abs(x2) < 1e-6, 1e-6, x2)
383+
x1 = xp.where(xp.abs(x1) < 1e-6, 1e-6, x1)
384+
x2 = xp.where(xp.abs(x2) < 1e-6, 1e-6, x2)
330385

331386
# Calculate convergence from nfw_HK24.py
332-
a = nfw_hk24_util.semi_major_axis_from(x1, x2, e_hk24)
387+
a = nfw_hk24_util.semi_major_axis_from(x1, x2, e_hk24, xp=xp)
333388

334-
return nfw_hk24_util.kappa_from(k_s=self.kappa_s, a=a)
389+
return nfw_hk24_util.kappa_from(k_s=self.kappa_s, a=a, xp=xp)
335390

336391

337392
class NFWSph(NFW):

0 commit comments

Comments
 (0)