Skip to content

Commit e23e6ed

Browse files
thjsalsguillot
andauthored
Reducing duplication in cellmesh integrators (#681)
* Polarization angle and disk blocking calculations separated to their own functions to decrease duplication. * Unit tests for cellmesh tools added. * Changelog and preliminary version update information added. * The preliminary version syntax changed to make the installation to work. * image_order_limit default fixed back to original * Switch using the same new version number as already in the main branch. * Debug print removed. * Fixing a bug in the example without disk blocking. * Likelihood check value updated to account for the fix in the Gaussian likelihood normalization sign done already in the past. --------- Co-authored-by: Sebastien Guillot <sebguillot60@gmail.com>
1 parent 1bba72a commit e23e6ed

17 files changed

Lines changed: 366 additions & 161 deletions

changelog.d/681.attribution.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Tuomo Salmi

changelog.d/681.changed.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Reduced repetitive codes in the cellmesh integrators by calculating polarization angle and accretion disk blocking in their own functions. Unit tests were also added to these.

examples/examples_modeling_tutorial/TestRun_PolNum_split_1spot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777

7878
bounds = dict(spin_axis_position_angle = (None, None))
7979
photosphere = CustomPhotosphere_NumA5(hot = hot, elsewhere = elsewhere, stokes=True, bounds=bounds,
80-
values=dict(mode_frequency = spacetime['frequency']))
80+
values=dict(mode_frequency = spacetime['frequency']),disk_blocking=False)
8181

8282
photosphere.hot_atmosphere = this_directory+'/model_data/Bobrikova_compton_slab_I.npz'
8383
photosphere.hot_atmosphere_Q = this_directory+'/model_data/Bobrikova_compton_slab_Q.npz'

examples/examples_modeling_tutorial/TestRun_PolNum_split_inference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ def transform(self, p, **kwargs):
714714
likelihood.reinitialise()
715715
likelihood.clear_cache()
716716

717-
true_logl = -1.5663833842e+06
717+
true_logl = -1.5663327873e+06
718718

719719
if __name__ == '__main__': # sample from the posterior
720720
# inform source code that parameter objects updated when inverse sampling

examples/examples_modeling_tutorial/modules/CustomPhotosphere.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ def integrate(self, energies, threads):
194194
except:
195195
else_atm_ext = None
196196

197-
R_in = self.disk['R_in'] * 1000
197+
if self.disk is not None:
198+
R_in = self.disk['R_in'] * 1000
198199
if self._stokes:
199200
if self._disk_blocking:
200201
self._signal, self._signalQ, self._signalU = self._hot.integrate_stokes(self._spacetime,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"
1212
# ---------------------------------------------------------
1313
[project]
1414
name = "xpsi"
15-
version = "3.2.1"
15+
version = "3.3.0"
1616
authors = [
1717
{ name = "The X-PSI Core Team", email = "A.L.Watts@uva.nl" },
1818
]

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@
235235
"xpsi.surface_radiation_field.elsewhere_user",
236236
"xpsi.surface_radiation_field.elsewhere_wrapper",
237237
"xpsi.cellmesh.integrator",
238+
"xpsi.cellmesh.common_functions",
238239
"xpsi.cellmesh.integratorIQU",
239240
"xpsi.cellmesh.integrator_for_azimuthal_invariance",
240241
"xpsi.cellmesh.integrator_for_azimuthal_invariance_split",

xpsi/HotRegion.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,9 @@ def integrate(self,
10781078
'smaller than 90 degrees. However, inclination > 90 degrees.'
10791079
' Formula for r_psi_d in the integrator is incorrect in this'
10801080
' case.')
1081+
1082+
if (not self.symmetry) and (R_in != 1e6):
1083+
print("WARNING: Inner disc radius was given, although the disk blocking model has not been implemented for the chosen integrator (symmetry=False).")
10811084

10821085
super_pulse = self._integrator(threads,
10831086
st.R,
@@ -1199,6 +1202,15 @@ def integrate_stokes(self,
11991202
raise AtmosError('The numerical atmosphere data were not preloaded, '
12001203
'even though that is required by the current atmosphere extension.')
12011204

1205+
if st.i > _np.pi/2 and R_in != 1e6:
1206+
print('WARNING: disk blocking assumes that the inclination is '
1207+
'smaller than 90 degrees. However, inclination > 90 degrees.'
1208+
' Formula for r_psi_d in the integrator is incorrect in this'
1209+
' case.')
1210+
1211+
if (not self.symmetry) and (R_in != 1e6):
1212+
print("WARNING: Inner disc radius was given, although the disk blocking model has not been implemented for the chosen integrator (symmetry=False).")
1213+
12021214
all_pulses = self._integratorIQU(threads,
12031215
st.R,
12041216
st.Omega,

xpsi/cellmesh/common_functions.pxd

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
cdef double compute_pol_ang(
2+
double leaves_kdx,
3+
double sin_psi,
4+
double cos_psi,
5+
double sin_alpha,
6+
double cos_alpha,
7+
double sin_theta_i,
8+
double cos_theta_i,
9+
double sin_i,
10+
double cos_i,
11+
double sin_gamma,
12+
double cos_gamma,
13+
double Grav_z,
14+
double mu,
15+
double eta,
16+
double beta,
17+
double Lorentz,
18+
double cos_xi) noexcept nogil
19+
20+
cdef int disk_block(
21+
double R_in,
22+
double cos_i,
23+
double cos_psi,
24+
double cos_theta_i,
25+
double r_s_over_r,
26+
double radius,
27+
double sin_alpha,
28+
double theta_i_over_pi
29+
) noexcept nogil

xpsi/cellmesh/common_functions.pyx

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
from libc.math cimport M_PI, sqrt, sin, cos, acos, log10, pow, exp, fabs, ceil, log, atan2
2+
from ..tools.core cimport are_equal
3+
from libc.stdio cimport printf
4+
5+
cdef double _2pi = 2.0 * M_PI
6+
7+
cdef double compute_pol_ang(
8+
double leaves_kdx,
9+
double sin_psi,
10+
double cos_psi,
11+
double sin_alpha,
12+
double cos_alpha,
13+
double sin_theta_i,
14+
double cos_theta_i,
15+
double sin_i,
16+
double cos_i,
17+
double sin_gamma,
18+
double cos_gamma,
19+
double Grav_z,
20+
double mu,
21+
double eta,
22+
double beta,
23+
double Lorentz,
24+
double cos_xi) noexcept nogil:
25+
"""
26+
Calculation of polarization angle using the polarized Oblate Schwarcshild approximation as in Loktev et al. (2020).
27+
"""
28+
29+
cdef:
30+
double sin_chi_0, cos_chi_0, chi_0, chi_1, chi_prime, chi
31+
double sin_chi_1, cos_chi_1, sin_chi_prime, cos_chi_prime
32+
double sin_lambda, cos_lambda, cos_eps
33+
double sin_alpha_over_sin_psi
34+
35+
sin_chi_0 = - sin_theta_i*sin(leaves_kdx)
36+
cos_chi_0 = sin_i*cos_theta_i - sin_theta_i*cos_i*cos(leaves_kdx)
37+
chi_0 = atan2(sin_chi_0,cos_chi_0)
38+
39+
if not are_equal(sin_psi, 0.0):
40+
sin_alpha_over_sin_psi = sin_alpha/sin_psi
41+
else: #using small-angle limit of the Beloborodov (2002) approximation
42+
sin_alpha_over_sin_psi = Grav_z
43+
44+
#Notes: mu = cos_sigma , Lorentz = 1/Gamma, mu0=eta*mu, cos_xi defined with no minus sign
45+
sin_chi_1 = sin_gamma*sin_i*sin(leaves_kdx)*sin_alpha_over_sin_psi #times sin alpha sin sigma
46+
cos_chi_1 = cos_gamma - cos_alpha*mu #times sin alpha sin sigma
47+
chi_1 = atan2(sin_chi_1,cos_chi_1)
48+
49+
sin_lambda = sin_theta_i*cos_gamma - sin_gamma*cos_theta_i
50+
cos_lambda = cos_theta_i*cos_gamma + sin_theta_i*sin_gamma
51+
cos_eps = sin_alpha_over_sin_psi*(cos_i*sin_lambda - sin_i*cos_lambda*cos(leaves_kdx) + cos_psi*sin_gamma) - cos_alpha*sin_gamma
52+
53+
sin_chi_prime = cos_eps*eta*mu*beta/Lorentz
54+
cos_chi_prime = (1. - mu**2 /(1. + beta*cos_xi))
55+
chi_prime = atan2(sin_chi_prime,cos_chi_prime)
56+
57+
chi = chi_0+chi_1+chi_prime
58+
59+
#printf("leaves[_kdx] = %.6e ",leaves_kdx/_2pi)
60+
#printf("chi_0 = %.6e ",chi_0)
61+
#printf("chi_1 = %.6e ",chi_1)
62+
#printf("chi_prime = %.6e ",chi_prime)
63+
#printf("PA_tot = %.6e\n",chi)
64+
65+
return chi
66+
67+
# Python wrapper for testing
68+
cpdef double compute_pol_ang_py(
69+
double leaves_kdx,
70+
double sin_psi,
71+
double cos_psi,
72+
double sin_alpha,
73+
double cos_alpha,
74+
double sin_theta_i,
75+
double cos_theta_i,
76+
double sin_i,
77+
double cos_i,
78+
double sin_gamma,
79+
double cos_gamma,
80+
double Grav_z,
81+
double mu,
82+
double eta,
83+
double beta,
84+
double Lorentz,
85+
double cos_xi):
86+
"""
87+
Python-callable wrapper for compute_pol_ang.
88+
Useful for unit testing.
89+
"""
90+
return compute_pol_ang(
91+
leaves_kdx,
92+
sin_psi,
93+
cos_psi,
94+
sin_alpha,
95+
cos_alpha,
96+
sin_theta_i,
97+
cos_theta_i,
98+
sin_i,
99+
cos_i,
100+
sin_gamma,
101+
cos_gamma,
102+
Grav_z,
103+
mu,
104+
eta,
105+
beta,
106+
Lorentz,
107+
cos_xi
108+
)
109+
110+
cdef int disk_block(
111+
double R_in,
112+
double cos_i,
113+
double cos_psi,
114+
double cos_theta_i,
115+
double r_s_over_r_i,
116+
double radius,
117+
double sin_alpha,
118+
double theta_i_over_pi
119+
) noexcept nogil:
120+
"""
121+
Checking whether an accretion disk blocks certain rays based on Ibragimov & Poutanen (2009). Returns 1 if the ray is not blocked.
122+
"""
123+
124+
cdef:
125+
double cos_psi_d, sin_psi_d # geometric quantities
126+
double impact_b, r_psi_d # impact parameter and radial coordinate
127+
double r_s_i # schwarzschild radius at the cell location
128+
129+
cos_psi_d = (cos_i * cos_psi - cos_theta_i) / sqrt(cos_i * cos_i + cos_theta_i * cos_theta_i - 2 * cos_i * cos_theta_i * cos_psi) #Ibragimov & Poutanen (2009), Equation (C2)
130+
sin_psi_d = sqrt(1 - cos_psi_d * cos_psi_d)
131+
r_s_i = r_s_over_r_i*radius
132+
impact_b = radius * sin_alpha / sqrt(1 - r_s_over_r_i) # impact parameter
133+
r_psi_d = sqrt((r_s_i * r_s_i * (1 - cos_psi_d) * (1 - cos_psi_d)) / (4 * (1 + cos_psi_d) * (1 + cos_psi_d)) + ((impact_b * impact_b) / (sin_psi_d * sin_psi_d))) - (r_s_i * (1 - cos_psi_d)) / (2 * (1 + cos_psi_d)) ##Ibragimov & Poutanen (2009), Equation (B9)
134+
135+
if theta_i_over_pi < 0.5 or (theta_i_over_pi > 0.5 and r_psi_d < R_in):
136+
return 1
137+
else: #theta > pi/2 and (theta < pi/2 or r_psi_d > R_in), don't calculate.
138+
return 0
139+
140+
# Python wrapper for testing
141+
cpdef int disk_block_py(
142+
double R_in,
143+
double cos_i,
144+
double cos_psi,
145+
double cos_theta_i,
146+
double r_s_over_r_i,
147+
double radius,
148+
double sin_alpha,
149+
double theta_i_over_pi
150+
):
151+
"""
152+
Python-callable wrapper for disk_ block.
153+
Useful for unit testing.
154+
"""
155+
return disk_block(
156+
R_in,
157+
cos_i,
158+
cos_psi,
159+
cos_theta_i,
160+
r_s_over_r_i,
161+
radius,
162+
sin_alpha,
163+
theta_i_over_pi
164+
)
165+

0 commit comments

Comments
 (0)