redback 1.0.1__py3-none-any.whl → 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- redback/__init__.py +4 -0
- redback/constraints.py +46 -25
- redback/eos.py +1 -0
- redback/get_data/fink.py +1 -1
- redback/get_data/lasair.py +3 -4
- redback/get_data/swift.py +7 -7
- redback/interaction_processes.py +1 -4
- redback/likelihoods.py +207 -21
- redback/model_library.py +2 -2
- redback/plotting.py +10 -10
- redback/priors/bazin_sne.prior +5 -0
- redback/priors/csm_interaction.prior +6 -7
- redback/priors/csm_nickel.prior +3 -3
- redback/priors/csm_shock_and_arnett.prior +11 -0
- redback/priors/csm_shock_and_arnett_bolometric.prior +10 -0
- redback/priors/csm_shock_breakout.prior +7 -0
- redback/priors/nicholl_bns.prior +2 -1
- redback/priors/one_comp_kne_rosswog_heatingrate.prior +5 -0
- redback/priors/pwn.prior +7 -0
- redback/priors/shocked_cocoon.prior +6 -6
- redback/priors/sn_fallback.prior +8 -0
- redback/priors/stream_stream_tde.prior +10 -0
- redback/priors/stream_stream_tde_bolometric.prior +9 -0
- redback/priors/tde_analytical.prior +5 -5
- redback/priors/tde_analytical_bolometric.prior +6 -4
- redback/priors/tde_fallback.prior +9 -0
- redback/priors/tde_fallback_bolometric.prior +6 -0
- redback/priors/tde_synchrotron.prior +6 -0
- redback/priors/tophat_from_emulator.prior +9 -0
- redback/priors/two_comp_kne_rosswog_heatingrate.prior +9 -0
- redback/priors/two_layer_stratified_kilonova.prior +1 -1
- redback/priors/villar_sne.prior +7 -0
- redback/priors.py +12 -1
- redback/sed.py +194 -2
- redback/simulate_transients.py +71 -35
- redback/tables/GRBs_w_redshift.txt +430 -413
- redback/tables/LGRB_table.txt +70 -6
- redback/tables/SGRB_table.txt +139 -135
- redback/tables/filters.csv +14 -0
- redback/tables/qdot_rosswogkorobkin24.pck +0 -0
- redback/tables/ztf.tar.gz +0 -0
- redback/transient/afterglow.py +17 -7
- redback/transient/kilonova.py +6 -3
- redback/transient/prompt.py +14 -4
- redback/transient/supernova.py +7 -3
- redback/transient/tde.py +6 -3
- redback/transient/transient.py +29 -12
- redback/transient_models/afterglow_models.py +152 -146
- redback/transient_models/combined_models.py +69 -48
- redback/transient_models/extinction_models.py +6 -6
- redback/transient_models/general_synchrotron_models.py +518 -0
- redback/transient_models/integrated_flux_afterglow_models.py +2 -2
- redback/transient_models/kilonova_models.py +310 -61
- redback/transient_models/magnetar_driven_ejecta_models.py +2 -2
- redback/transient_models/magnetar_models.py +1 -1
- redback/transient_models/phenomenological_models.py +69 -1
- redback/transient_models/shock_powered_models.py +159 -110
- redback/transient_models/supernova_models.py +211 -43
- redback/transient_models/tde_models.py +975 -5
- redback/utils.py +309 -16
- {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/METADATA +46 -6
- {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/RECORD +65 -49
- {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/WHEEL +1 -1
- redback/tables/ztf_obslog.csv +0 -106649
- {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/LICENCE.md +0 -0
- {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from redback.transient_models.magnetar_models import magnetar_only, basic_magnetar
|
|
3
|
+
from redback.transient_models.magnetar_driven_ejecta_models import _ejecta_dynamics_and_interaction
|
|
4
|
+
from redback.transient_models.shock_powered_models import _emissivity_pl, _emissivity_thermal, _tau_nu
|
|
5
|
+
from redback.transient_models.afterglow_models import _get_kn_dynamics, _pnu_synchrotron
|
|
6
|
+
from astropy.cosmology import Planck18 as cosmo
|
|
7
|
+
from redback.utils import calc_kcorrected_properties, citation_wrapper, logger, get_csm_properties, nu_to_lambda, lambda_to_nu, velocity_from_lorentz_factor, calc_ABmag_from_flux_density
|
|
8
|
+
from redback.constants import day_to_s, solar_mass, km_cgs, au_cgs, speed_of_light, qe, electron_mass, proton_mass, sigma_T
|
|
9
|
+
from scipy import integrate
|
|
10
|
+
from scipy.interpolate import interp1d
|
|
11
|
+
import astropy.units as uu
|
|
12
|
+
from collections import namedtuple
|
|
13
|
+
|
|
14
|
+
def _calc_free_free_abs(frequency, Y_fe, Zbar, mej, radius_2darray, F_nu_2darray):
|
|
15
|
+
"""
|
|
16
|
+
:param frequency: frequency to calculate
|
|
17
|
+
:param Y_fe: free electron fraction
|
|
18
|
+
:param Zbar: average proton number
|
|
19
|
+
:param mej: ejecta mass in solar units
|
|
20
|
+
:param radius_2darray: radius of the ejecta at each time
|
|
21
|
+
:param F_nu_2darray: unabsorbed flux density
|
|
22
|
+
:return: absorbed flux density
|
|
23
|
+
"""
|
|
24
|
+
n_e = mej * solar_mass * 3 / (4 * np.pi * radius_2darray**3) * Y_fe / proton_mass
|
|
25
|
+
tau_ff = 8.4e-28 * n_e**2 * radius_2darray * Zbar**2 * (frequency / 1.0e10) ** -2.1
|
|
26
|
+
F_nu_2darray = F_nu_2darray * np.exp(-tau_ff)
|
|
27
|
+
|
|
28
|
+
return F_nu_2darray
|
|
29
|
+
|
|
30
|
+
def _calc_compton_scat(frequency, Y_e, mej, radius_2darray, F_nu_2darray):
|
|
31
|
+
"""
|
|
32
|
+
:param frequency: frequency to calculate
|
|
33
|
+
:param Y_e: electron fraction
|
|
34
|
+
:param mej: ejecta mass in solar units
|
|
35
|
+
:param radius_2darray: radius of the ejecta at each time
|
|
36
|
+
:param F_nu_2darray: unabsorbed flux density
|
|
37
|
+
:return: absorbed flux density
|
|
38
|
+
"""
|
|
39
|
+
nu_e = 1.24e20
|
|
40
|
+
x = frequency/nu_e
|
|
41
|
+
msk = (x < 1e-3)
|
|
42
|
+
sigknpre = (1.0 + x)/x**3
|
|
43
|
+
sigkn1 = 2.0 * x * (1.0 + x)/(1.0 + 2.0*x) - np.log(1.0 + 2*x)
|
|
44
|
+
sigkn2 = np.log(1.0 + 2.0*x)/(2.0*x)
|
|
45
|
+
sigkn3 = (1.0 + 3.0*x)/(1.0 + 2.0*x)**2
|
|
46
|
+
sig_kn = (3.0/4.0) * sigma_T * (sigknpre*sigkn1 + sigkn2 - sigkn3)
|
|
47
|
+
if (np.size(sig_kn) > 1):
|
|
48
|
+
sig_kn[msk] = sigma_T
|
|
49
|
+
elif ((np.size(sig_kn) == 1) and (msk == True)):
|
|
50
|
+
sig_kn = sigma_T
|
|
51
|
+
kappa_comp = sig_kn * Y_e / proton_mass
|
|
52
|
+
tau_comp = 3.0 * kappa_comp * mej * solar_mass / (4.0 * np.pi * radius_2darray**2)
|
|
53
|
+
F_nu_2darray = F_nu_2darray * np.exp(-tau_comp)
|
|
54
|
+
|
|
55
|
+
return F_nu_2darray
|
|
56
|
+
|
|
57
|
+
def _calc_photoelectric_abs(frequency, Zbar, mej, radius_2darray, F_nu_2darray):
|
|
58
|
+
"""
|
|
59
|
+
:param frequency: frequency to calculate
|
|
60
|
+
:param Zbar: average proton number
|
|
61
|
+
:param mej: ejecta mass in solar units
|
|
62
|
+
:param radius_2darray: radius of the ejecta at each time
|
|
63
|
+
:param F_nu_2darray: unabsorbed flux density
|
|
64
|
+
:return: absorbed flux density
|
|
65
|
+
"""
|
|
66
|
+
msk = (frequency > 2.42e15)
|
|
67
|
+
kappa_pe = 2.37 * (Zbar/6.0)**3 * (frequency/2.42e18)**-3
|
|
68
|
+
tau_pe = 3.0 * kappa_pe * mej * solar_mass / (4.0 * np.pi * radius_2darray**2)
|
|
69
|
+
F_nu_2darray[:,msk] = F_nu_2darray[:,msk] * np.exp(-tau_pe[:,msk])
|
|
70
|
+
|
|
71
|
+
return F_nu_2darray
|
|
72
|
+
|
|
73
|
+
def _calc_optical_abs(frequency, kappa, mej, radius_2darray, F_nu_2darray):
|
|
74
|
+
"""
|
|
75
|
+
:param frequency: frequency to calculate
|
|
76
|
+
:param kappa: thermalization opacity
|
|
77
|
+
:param mej: ejecta mass in solar units
|
|
78
|
+
:param radius_2darray: radius of the ejecta at each time
|
|
79
|
+
:param F_nu_2darray: unabsorbed flux density
|
|
80
|
+
:return: absorbed flux density
|
|
81
|
+
"""
|
|
82
|
+
msk = np.logical_and((frequency < 2.42e15),(frequency > 2.42e13))
|
|
83
|
+
tau_opt = 3.0 * kappa * mej * solar_mass / (4.0 * np.pi * radius_2darray**2)
|
|
84
|
+
F_nu_2darray[:,msk] = F_nu_2darray[:,msk] * np.exp(-tau_opt[:,msk])
|
|
85
|
+
|
|
86
|
+
return F_nu_2darray
|
|
87
|
+
|
|
88
|
+
@citation_wrapper('Omand et al. (2024)')
|
|
89
|
+
def pwn(time, redshift, mej, l0, tau_sd, nn, eps_b, gamma_b, **kwargs):
|
|
90
|
+
"""
|
|
91
|
+
:param time: time in observer frame in days
|
|
92
|
+
:param redshift: redshift
|
|
93
|
+
:param mej: ejecta mass in solar units
|
|
94
|
+
:param l0: initial magnetar spin-down luminosity (in erg/s)
|
|
95
|
+
:param tau_sd: magnetar spin down damping timescale (in seconds)
|
|
96
|
+
:param nn: braking index
|
|
97
|
+
:param eps_b: magnetization of the PWN
|
|
98
|
+
:param gamma_b: Lorentz factor of electrons at synchrotron break
|
|
99
|
+
:param kwargs: Additional parameters -
|
|
100
|
+
:param E_sn: supernova explosion energy
|
|
101
|
+
:param kappa: opacity (used only in dynamics and optical absorption)
|
|
102
|
+
:param kappa_gamma: gamma-ray opacity used to calculate magnetar thermalisation efficiency (used only in dynamics)
|
|
103
|
+
:param q1: low energy spectral index (must be < 2)
|
|
104
|
+
:param q2: high energy spectral index (must be > 2)
|
|
105
|
+
:param Zbar: average proton number (used for free-free and photoelectric absorption)
|
|
106
|
+
:param Y_e: electron fraction (used for Compton scattering)
|
|
107
|
+
:param Y_fe: free electron fraction (used for free-free absorption)
|
|
108
|
+
:param pair_cascade_switch: whether to account for pair cascade losses, default is False
|
|
109
|
+
:param ejecta albedo: ejecta albedo; default is 0.5
|
|
110
|
+
:param pair_cascade_fraction: fraction of magnetar luminosity lost to pair cascades; default is 0.05
|
|
111
|
+
:param use_r_process: determine whether the ejecta is composed of r-process material; default is no
|
|
112
|
+
:param frequency: (frequency to calculate - Must be same length as time array or a single number)
|
|
113
|
+
:param f_nickel: Ni^56 mass as a fraction of ejecta mass
|
|
114
|
+
:return: flux density or AB magnitude or dynamics output
|
|
115
|
+
"""
|
|
116
|
+
#get parameter values or use defaults
|
|
117
|
+
E_sn = kwargs.get('E_sn', 1.0e51)
|
|
118
|
+
kappa = kwargs.get('kappa', 0.1)
|
|
119
|
+
if 'kappa' in kwargs:
|
|
120
|
+
del kwargs['kappa']
|
|
121
|
+
kappa_gamma = kwargs.get('kappa_gamma', 0.01)
|
|
122
|
+
kwargs['kappa_gamma'] = kappa_gamma
|
|
123
|
+
q1 = kwargs.get('q1',1.5)
|
|
124
|
+
q2 = kwargs.get('q2',2.5)
|
|
125
|
+
Zbar = kwargs.get('Zbar',8.0)
|
|
126
|
+
Y_e = kwargs.get('Y_e',0.5)
|
|
127
|
+
Y_fe = kwargs.get('Y_fe',0.0625)
|
|
128
|
+
|
|
129
|
+
ejecta_radius = 1.0e11
|
|
130
|
+
epse=1.0-eps_b
|
|
131
|
+
n_ism = 1.0e-5
|
|
132
|
+
dl = cosmo.luminosity_distance(redshift).cgs.value
|
|
133
|
+
pair_cascade_switch = kwargs.get('pair_cascade_switch', False)
|
|
134
|
+
use_r_process = kwargs.get('use_r_process', False)
|
|
135
|
+
nu_M=3.8e22*np.ones(2500)
|
|
136
|
+
|
|
137
|
+
#initial values and dynamics
|
|
138
|
+
time_temp = np.geomspace(1e0, 1e10, 2500)
|
|
139
|
+
frequency = kwargs['frequency']
|
|
140
|
+
if (np.size(frequency) == 1):
|
|
141
|
+
frequency = np.ones(len(time))*frequency
|
|
142
|
+
frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
|
|
143
|
+
magnetar_luminosity = magnetar_only(time=time_temp, l0=l0, tau=tau_sd, nn=nn)
|
|
144
|
+
v_init = np.sqrt(E_sn / (0.5 * mej * solar_mass)) / speed_of_light
|
|
145
|
+
output = _ejecta_dynamics_and_interaction(time=time_temp, mej=mej,
|
|
146
|
+
beta=v_init, ejecta_radius=ejecta_radius,
|
|
147
|
+
kappa=kappa, n_ism=n_ism, magnetar_luminosity=magnetar_luminosity,
|
|
148
|
+
pair_cascade_switch=pair_cascade_switch,
|
|
149
|
+
use_gamma_ray_opacity=True, **kwargs)
|
|
150
|
+
vej = velocity_from_lorentz_factor(output.lorentz_factor)/km_cgs
|
|
151
|
+
|
|
152
|
+
#calculating synchrotron quantites
|
|
153
|
+
int_lsd = integrate.cumulative_trapezoid(magnetar_luminosity, time_temp,initial=0)
|
|
154
|
+
B_nb = np.sqrt(6.0 * eps_b * int_lsd / output.radius**3)
|
|
155
|
+
B_nb[0] = B_nb[1]
|
|
156
|
+
nu_b = 3.0 / 4.0 / np.pi * gamma_b**2 * qe * B_nb / electron_mass / speed_of_light
|
|
157
|
+
nu_0 = np.minimum(nu_M, nu_b)
|
|
158
|
+
beta1 = np.maximum(1.5, ((2.0 + q1) / 2.0))
|
|
159
|
+
beta2 = (2.0 + q2) / 2.0
|
|
160
|
+
Rb = ((1.0 / (2.0 - q1)) - (1.0 / (2.0 - q2))) #bolometric correction
|
|
161
|
+
F_nu_0 = epse * magnetar_luminosity / (8.0 * np.pi * dl**2 * nu_0 * Rb)
|
|
162
|
+
nu_ssa = (dl**2 * 3.0**1.5 * qe**0.5 * B_nb**0.5 * F_nu_0 * nu_0**(beta1 - 1.0) / (4.0 * np.pi**1.5 * output.radius**2 * speed_of_light**0.5 * electron_mass**1.5))**(2.0 / (2 * beta1 + 3))
|
|
163
|
+
F_nu_ssa = F_nu_0 * (nu_ssa / nu_0) ** (1-beta1)
|
|
164
|
+
|
|
165
|
+
#making arrays to vectorize properly
|
|
166
|
+
freq_arr = np.tile(frequency, (2500,1))
|
|
167
|
+
F_nu_0_arr = np.tile(F_nu_0, (np.size(frequency),1))
|
|
168
|
+
nu_0_arr = np.tile(nu_0, (np.size(frequency),1))
|
|
169
|
+
F_nu_ssa_arr = np.tile(F_nu_ssa, (np.size(frequency),1))
|
|
170
|
+
nu_ssa_arr = np.tile(nu_ssa, (np.size(frequency),1))
|
|
171
|
+
r_arr = np.tile(output.radius, (np.size(frequency),1))
|
|
172
|
+
nu_b_arr = np.tile(nu_b, (np.size(frequency),1))
|
|
173
|
+
|
|
174
|
+
#calculate synchtron light curves for each desired frequency
|
|
175
|
+
F_nu = F_nu_0_arr.T * (frequency / nu_0_arr.T) ** (1-beta1)
|
|
176
|
+
|
|
177
|
+
if (np.max(frequency) > np.min(nu_b)):
|
|
178
|
+
msk = (freq_arr >= nu_b_arr.T)
|
|
179
|
+
F_nu[msk] = F_nu_0_arr.T[msk] * (freq_arr[msk] / nu_0_arr.T[msk]) ** (1-beta2)
|
|
180
|
+
|
|
181
|
+
if (np.min(frequency) < np.max(nu_ssa)):
|
|
182
|
+
msk = (freq_arr < nu_ssa_arr.T)
|
|
183
|
+
F_nu[msk] = F_nu_ssa_arr.T[msk] * (freq_arr[msk] / nu_ssa_arr.T[msk]) ** 2.5
|
|
184
|
+
|
|
185
|
+
F_nu = _calc_free_free_abs(frequency, Y_fe, Zbar, mej, r_arr.T, F_nu)
|
|
186
|
+
F_nu = _calc_compton_scat(frequency, Y_e, mej, r_arr.T, F_nu)
|
|
187
|
+
F_nu = _calc_optical_abs(frequency, kappa, mej, r_arr.T, F_nu)
|
|
188
|
+
if (np.max(frequency) > 2.42e15):
|
|
189
|
+
F_nu = _calc_photoelectric_abs(frequency, Zbar, mej, r_arr.T, F_nu)
|
|
190
|
+
|
|
191
|
+
#interpolate for each time
|
|
192
|
+
fnu_func = {}
|
|
193
|
+
fnu_func = interp1d(time_temp/day_to_s, y=F_nu.T)
|
|
194
|
+
fnu = np.diag(fnu_func(time))
|
|
195
|
+
fmjy = np.array(fnu) / 1.0e-26
|
|
196
|
+
|
|
197
|
+
return fmjy
|
|
198
|
+
|
|
199
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2022MNRAS.516.4949S/abstract')
|
|
200
|
+
def kilonova_afterglow_redback(time, redshift, loge0, mej, logn0, logepse, logepsb, p,
|
|
201
|
+
**kwargs):
|
|
202
|
+
"""
|
|
203
|
+
Calculate the afterglow emission from a kilonova remnant, following the model of Sarin et al. 2022.
|
|
204
|
+
This model was modified by Nikhil Sarin following code provided by Ben Margalit.
|
|
205
|
+
|
|
206
|
+
:param time: time in observer frame (days) in observer frame
|
|
207
|
+
:param redshift: source redshift
|
|
208
|
+
:param loge0: log10 of the initial kinetic energy of the ejecta (erg)
|
|
209
|
+
:param mej: ejecta mass (solar masses)
|
|
210
|
+
:param logn0: log10 of the circumburst density (cm^-3)
|
|
211
|
+
:param logepse: log10 of the fraction of shock energy given to electrons
|
|
212
|
+
:param logepsb: log10 of the fraction of shock energy given to magnetic field
|
|
213
|
+
:param p: power-law index of the electron energy distribution
|
|
214
|
+
:param kwargs: Additional keyword arguments
|
|
215
|
+
:param zeta_e: fraction of electrons participating in diffusive shock acceleration. Default is 1.
|
|
216
|
+
:param output_format: Whether to output flux density or AB mag
|
|
217
|
+
:param frequency: frequency in Hz for the flux density calculation
|
|
218
|
+
:param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
|
|
219
|
+
:return: flux density or AB mag. Note this is going to give the monochromatic magnitude at the effective frequency for the band.
|
|
220
|
+
For a proper calculation of the magntitude use the sed variant models.
|
|
221
|
+
"""
|
|
222
|
+
Eej = 10 ** loge0
|
|
223
|
+
Mej = mej * solar_mass
|
|
224
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
225
|
+
epsilon_e = 10 ** logepse
|
|
226
|
+
epsilon_B = 10 ** logepsb
|
|
227
|
+
n0 = 10 ** logn0
|
|
228
|
+
zeta_e = kwargs.get('zeta_e', 1.0)
|
|
229
|
+
qe = 4.803e-10
|
|
230
|
+
|
|
231
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
232
|
+
# calculate blast-wave dynamics
|
|
233
|
+
t, R, beta, Gamma, eden, tobs, beta_sh, Gamma_sh = _get_kn_dynamics(n0=n0, Eej=Eej, Mej=Mej)
|
|
234
|
+
|
|
235
|
+
# shock-amplified magnetic field, minimum & cooling Lorentz factors
|
|
236
|
+
B = (8.0 * np.pi * epsilon_B * eden) ** 0.5
|
|
237
|
+
gamma_m = 1.0 + (epsilon_e / zeta_e) * ((p - 2.0) / (p - 1.0)) * (proton_mass / electron_mass) * (Gamma - 1.0)
|
|
238
|
+
gamma_c = 6.0 * np.pi * electron_mass * speed_of_light / (sigma_T * Gamma * t * B ** 2)
|
|
239
|
+
|
|
240
|
+
# number of emitting electrons, where zeta_DN is an approximate smooth interpolation between the "standard"
|
|
241
|
+
# and deep-Newtonian regime discussed by Sironi & Giannios (2013)
|
|
242
|
+
zeta_DN = (gamma_m - 1.0) / gamma_m
|
|
243
|
+
Ne = zeta_DN * zeta_e * (4.0 * np.pi / 3.0) * R ** 3 * n0
|
|
244
|
+
|
|
245
|
+
# LOS approximation
|
|
246
|
+
mu = 1.0
|
|
247
|
+
blueshift = Gamma * (1.0 - beta * mu)
|
|
248
|
+
|
|
249
|
+
frequency = kwargs['frequency']
|
|
250
|
+
if isinstance(frequency, float):
|
|
251
|
+
frequency = np.ones(len(time)) * frequency
|
|
252
|
+
fnu_func = {}
|
|
253
|
+
for nu in frequency:
|
|
254
|
+
Fnu_opt_thin = _pnu_synchrotron(nu * blueshift * (1.0 + redshift), B, gamma_m, gamma_c, Ne, p) * (1.0 + redshift) / (
|
|
255
|
+
4.0 * np.pi * dl ** 2 * blueshift)
|
|
256
|
+
|
|
257
|
+
# correct for synchrotron self-absorption (approximate treatment, correct up to factors of order unity)
|
|
258
|
+
Fnu_opt_thick = Gamma * (8 * np.pi ** 2 * (nu * blueshift * (1.0 + redshift)) ** 2 / speed_of_light ** 2) * R ** 2 * (
|
|
259
|
+
1.0 / 3.0) * electron_mass * speed_of_light ** 2 * np.maximum(gamma_m, (
|
|
260
|
+
2 * np.pi * electron_mass * speed_of_light * nu * blueshift * (1.0 + redshift) / (qe * B)) ** 0.5) * (1.0 + redshift) / (
|
|
261
|
+
4.0 * np.pi * dl ** 2 * blueshift)
|
|
262
|
+
# new prescription:
|
|
263
|
+
Fnu = Fnu_opt_thick * (1e0 - np.exp(-Fnu_opt_thin / Fnu_opt_thick))
|
|
264
|
+
# add brute-force optically-thin case to avoid roundoff error in 1e0-np.exp(-x) term (above) when x->0
|
|
265
|
+
Fnu[Fnu == 0.0] = Fnu_opt_thin[Fnu == 0.0]
|
|
266
|
+
|
|
267
|
+
fnu_func[nu] = interp1d(tobs/day_to_s, Fnu, bounds_error=False, fill_value='extrapolate')
|
|
268
|
+
|
|
269
|
+
# interpolate onto actual observed frequency and time values
|
|
270
|
+
flux_density = []
|
|
271
|
+
for freq, tt in zip(frequency, time):
|
|
272
|
+
flux_density.append(fnu_func[freq](tt))
|
|
273
|
+
|
|
274
|
+
fmjy = np.array(flux_density) / 1e-26
|
|
275
|
+
if kwargs['output_format'] == 'flux_density':
|
|
276
|
+
return fmjy
|
|
277
|
+
elif kwargs['output_format'] == 'magnitude':
|
|
278
|
+
return calc_ABmag_from_flux_density(fmjy).value
|
|
279
|
+
|
|
280
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2011Natur.478...82N/abstract')
|
|
281
|
+
def kilonova_afterglow_nakarpiran(time, redshift, loge0, mej, logn0, logepse, logepsb, p, **kwargs):
|
|
282
|
+
"""
|
|
283
|
+
A kilonova afterglow model based on Nakar & Piran 2011
|
|
284
|
+
|
|
285
|
+
:param time: time in days in the observer frame
|
|
286
|
+
:param redshift: source redshift
|
|
287
|
+
:param loge0: initial kinetic energy in erg of ejecta
|
|
288
|
+
:param mej: mass of ejecta in solar masses
|
|
289
|
+
:param logn0: log10 of the number density of the circumburst medium in cm^-3
|
|
290
|
+
:param logepse: log10 of the fraction of energy given to electrons
|
|
291
|
+
:param logepsb: log10 of the fraction of energy given to the magnetic field
|
|
292
|
+
:param p: electron power law index
|
|
293
|
+
:param kwargs: Additional keyword arguments
|
|
294
|
+
:param output_format: Whether to output flux density or AB mag
|
|
295
|
+
:param frequency: frequency in Hz for the flux density calculation
|
|
296
|
+
:param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
|
|
297
|
+
:return: flux density or AB mag. Note this is going to give the monochromatic magnitude at the effective frequency for the band.
|
|
298
|
+
For a proper calculation of the magntitude use the sed variant models.
|
|
299
|
+
:return:
|
|
300
|
+
"""
|
|
301
|
+
Eej = 10 ** loge0
|
|
302
|
+
Mej = mej * solar_mass
|
|
303
|
+
Gamma0 = 1.0 + Eej / (Mej * speed_of_light ** 2)
|
|
304
|
+
vej = speed_of_light * (1.0 - Gamma0 ** (-2)) ** 0.5
|
|
305
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
306
|
+
epsilon_e = 10 ** logepse
|
|
307
|
+
epsilon_B = 10 ** logepsb
|
|
308
|
+
n0 = 10 ** logn0
|
|
309
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
310
|
+
|
|
311
|
+
# in days
|
|
312
|
+
t_dec = 30 * (Eej / 1e49) ** (1.0 / 3.0) * (n0 / 1e0) ** (-1.0 / 3.0) * (vej / speed_of_light) ** (-5.0 / 3.0)
|
|
313
|
+
|
|
314
|
+
fnu_dec_dict = {}
|
|
315
|
+
fnu_func = {}
|
|
316
|
+
temp_time = np.linspace(0.1, 100, 200) * t_dec
|
|
317
|
+
frequency = kwargs['frequency']
|
|
318
|
+
if isinstance(frequency, float):
|
|
319
|
+
frequency = np.ones(len(time)) * frequency
|
|
320
|
+
for freq in frequency:
|
|
321
|
+
# Eq. 11 in Nakar & Piran 2011 (in Mjy)
|
|
322
|
+
fnu_dec_dict[freq] = 0.3 * (Eej / 1e49) * n0 ** (0.25 * (p + 1)) * (epsilon_B / 1e-1) ** (0.25 * (p + 1)) * (
|
|
323
|
+
epsilon_e / 1e-1) ** (p - 1) * (vej / speed_of_light) ** (0.5 * (5 * p - 7)) * (freq / 1.4e9) ** (
|
|
324
|
+
-0.5 * (p - 1)) * (dl / 1e27) ** (-2)
|
|
325
|
+
fnu = fnu_dec_dict[freq] * (temp_time / t_dec) ** 3
|
|
326
|
+
fnu[temp_time > t_dec] = fnu_dec_dict[freq] * (temp_time[temp_time > t_dec] / t_dec) ** (-0.3 * (5 * p - 7))
|
|
327
|
+
fnu_func[freq] = interp1d(temp_time, fnu, bounds_error=False, fill_value='extrapolate')
|
|
328
|
+
|
|
329
|
+
# interpolate onto actual observed frequency and time values
|
|
330
|
+
flux_density = []
|
|
331
|
+
for freq, tt in zip(frequency, time):
|
|
332
|
+
flux_density.append(fnu_func[freq](tt))
|
|
333
|
+
fmjy = flux_density * uu.mJy
|
|
334
|
+
if kwargs['output_format'] == 'flux_density':
|
|
335
|
+
return fmjy.value
|
|
336
|
+
elif kwargs['output_format'] == 'magnitude':
|
|
337
|
+
return calc_ABmag_from_flux_density(fmjy.value).value
|
|
338
|
+
|
|
339
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2021ApJ...923L..14M/abstract')
|
|
340
|
+
def thermal_synchrotron_lnu(time, logn0, v0, logr0, eta, logepse, logepsb, xi, p, **kwargs):
|
|
341
|
+
"""
|
|
342
|
+
:param time: time in source frame in seconds
|
|
343
|
+
:param logn0: log10 initial ambient ism density
|
|
344
|
+
:param v0: initial velocity in c
|
|
345
|
+
:param logr0: log10 initial radius
|
|
346
|
+
:param eta: deceleration slope (r = r0 * (time/t0)**eta; v = v0*(time/t0)**(eta-1))
|
|
347
|
+
:param logepse: log10 epsilon_e; electron thermalisation efficiency
|
|
348
|
+
:param logepsb: log10 epsilon_b; magnetic field amplification efficiency
|
|
349
|
+
:param xi: fraction of energy carried by power law electrons
|
|
350
|
+
:param p: electron power law slope
|
|
351
|
+
:param kwargs: extra parameters to change physics/settings
|
|
352
|
+
:param frequency: frequency to calculate model on - Must be same length as time array or a single number)
|
|
353
|
+
:param wind_slope: slope for ism density scaling (nism = n0 * (r/r0)**(-wind_slope)). Default is 2
|
|
354
|
+
:param mu: mean molecular weight, default is 0.62
|
|
355
|
+
:param mu_e: mean molecular weight per electron, default is 1.18
|
|
356
|
+
:return: lnu
|
|
357
|
+
"""
|
|
358
|
+
v0 = v0 * speed_of_light
|
|
359
|
+
r0 = 10**logr0
|
|
360
|
+
t0 = eta * r0 / v0
|
|
361
|
+
radius = r0 * (time / t0) ** eta
|
|
362
|
+
velocity = v0 * (time/t0)**(eta - 1)
|
|
363
|
+
wind_slope = kwargs.get('wind_slope',2)
|
|
364
|
+
mu = kwargs.get('mu', 0.62)
|
|
365
|
+
mu_e = kwargs.get('mu_e', 1.18)
|
|
366
|
+
n0 = 10 ** logn0
|
|
367
|
+
nism = n0 * (radius / r0) ** (-wind_slope)
|
|
368
|
+
|
|
369
|
+
epsilon_T = 10**logepse
|
|
370
|
+
epsilon_B = 10**logepsb
|
|
371
|
+
|
|
372
|
+
frequency = kwargs['frequency']
|
|
373
|
+
|
|
374
|
+
ne = 4.0*mu_e*nism
|
|
375
|
+
beta = velocity/speed_of_light
|
|
376
|
+
|
|
377
|
+
theta0 = epsilon_T * (9.0 * mu * proton_mass / (32.0 * mu_e * electron_mass)) * beta ** 2
|
|
378
|
+
theta = (5.0*theta0-6.0+(25.0*theta0**2+180.0*theta0+36.0)**0.5)/30.0
|
|
379
|
+
|
|
380
|
+
bfield = (9.0*np.pi*epsilon_B*nism*mu*proton_mass)**0.5*velocity
|
|
381
|
+
# mean dynamical time:
|
|
382
|
+
td = radius/velocity
|
|
383
|
+
|
|
384
|
+
z_cool = (6.0 * np.pi * electron_mass * speed_of_light / (sigma_T * bfield ** 2 * td)) / theta
|
|
385
|
+
normalised_frequency_denom = 3.0*theta**2*qe*bfield/(4.0*np.pi*electron_mass*speed_of_light)
|
|
386
|
+
x = frequency / normalised_frequency_denom
|
|
387
|
+
|
|
388
|
+
emissivity_pl = _emissivity_pl(x=x, nism=ne, bfield=bfield, theta=theta, xi=xi, p=p, z_cool=z_cool)
|
|
389
|
+
|
|
390
|
+
emissivity_thermal = _emissivity_thermal(x=x, nism=ne, bfield=bfield, theta=theta, z_cool=z_cool)
|
|
391
|
+
|
|
392
|
+
emissivity = emissivity_thermal + emissivity_pl
|
|
393
|
+
|
|
394
|
+
tau = _tau_nu(x=x, nism=ne, radius=radius, bfield=bfield, theta=theta, xi=xi, p=p, z_cool=z_cool)
|
|
395
|
+
|
|
396
|
+
lnu = 4.0 * np.pi ** 2 * radius ** 3 * emissivity * (1e0 - np.exp(-tau)) / tau
|
|
397
|
+
if np.size(x) > 1:
|
|
398
|
+
lnu[tau < 1e-10] = (4.0 * np.pi ** 2 * radius ** 3 * emissivity)[tau < 1e-10]
|
|
399
|
+
elif tau < 1e-10:
|
|
400
|
+
lnu = 4.0 * np.pi ** 2 * radius ** 3 * emissivity
|
|
401
|
+
return lnu
|
|
402
|
+
|
|
403
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2021ApJ...923L..14M/abstract')
|
|
404
|
+
def thermal_synchrotron_fluxdensity(time, redshift, logn0, v0, logr0, eta, logepse, logepsb,
|
|
405
|
+
xi, p, **kwargs):
|
|
406
|
+
"""
|
|
407
|
+
:param time: time in observer frame in days
|
|
408
|
+
:param redshift: redshift
|
|
409
|
+
:param logn0: log10 initial ambient ism density
|
|
410
|
+
:param v0: initial velocity in c
|
|
411
|
+
:param logr0: log10 initial radius
|
|
412
|
+
:param eta: deceleration slope (r = r0 * (time/t0)**eta; v = v0*(time/t0)**(eta-1))
|
|
413
|
+
:param logepse: log10 epsilon_e; electron thermalisation efficiency
|
|
414
|
+
:param logepsb: log10 epsilon_b; magnetic field amplification efficiency
|
|
415
|
+
:param xi: fraction of energy carried by power law electrons
|
|
416
|
+
:param p: electron power law slope
|
|
417
|
+
:param kwargs: extra parameters to change physics/settings
|
|
418
|
+
:param frequency: frequency to calculate model on - Must be same length as time array or a single number)
|
|
419
|
+
:param wind_slope: slope for ism density scaling (nism = n0 * (r/r0)**(-wind_slope)). Default is 2
|
|
420
|
+
:param mu: mean molecular weight, default is 0.62
|
|
421
|
+
:param mu_e: mean molecular weight per electron, default is 1.18
|
|
422
|
+
:param kwargs: extra parameters to change physics and other settings
|
|
423
|
+
:param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
|
|
424
|
+
:return: flux density
|
|
425
|
+
"""
|
|
426
|
+
frequency = kwargs['frequency']
|
|
427
|
+
frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
|
|
428
|
+
new_kwargs = kwargs.copy()
|
|
429
|
+
new_kwargs['frequency'] = frequency
|
|
430
|
+
time = time * day_to_s
|
|
431
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
432
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
433
|
+
lnu = thermal_synchrotron_lnu(time,logn0, v0, logr0, eta, logepse, logepsb, xi, p,**new_kwargs)
|
|
434
|
+
flux_density = lnu / (4.0 * np.pi * dl**2)
|
|
435
|
+
return flux_density
|
|
436
|
+
|
|
437
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2022MNRAS.511.5328G/abstract')
|
|
438
|
+
def tde_synchrotron(time, redshift, Mej, vej, logepse, logepsb, p, **kwargs):
|
|
439
|
+
"""
|
|
440
|
+
:param time: time in observer frame in days
|
|
441
|
+
:param redshift: redshift
|
|
442
|
+
:param Mej: mass of the emitting region (solar masses)
|
|
443
|
+
:param vej: initial velocity of the outflow (km/s)
|
|
444
|
+
:param logepse: log10 epsilon_e; electron thermalisation efficiency
|
|
445
|
+
:param logepsb: log10 epsilon_b; magnetic field amplification efficiency
|
|
446
|
+
:param p: electron power law slope
|
|
447
|
+
:param kwargs: extra parameters to change physics/settings
|
|
448
|
+
:param frequency: frequency to calculate model on - Must be same length as time array or a single number)
|
|
449
|
+
:param geometry: geometry of the outflow. Either "sphere" or "cone" is supported.
|
|
450
|
+
:param output_format: Whether to output light curves or physical parameters.
|
|
451
|
+
:param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
|
|
452
|
+
:return: flux density
|
|
453
|
+
"""
|
|
454
|
+
frequency = kwargs['frequency']
|
|
455
|
+
geometry = kwargs.get('geometry', 'sphere')
|
|
456
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
457
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
458
|
+
beta1 = 5.0 / 2.0
|
|
459
|
+
beta2 = (1.0 - p) / 2.0
|
|
460
|
+
s = 1.47 - (0.21 * p)
|
|
461
|
+
eps_e = 10.0 ** logepse
|
|
462
|
+
eps_b = 10.0 ** logepsb
|
|
463
|
+
if geometry == 'cone':
|
|
464
|
+
F_A = 0.13
|
|
465
|
+
F_V = 1.15
|
|
466
|
+
else:
|
|
467
|
+
F_A = 1.0
|
|
468
|
+
F_V = 4.0/3.0
|
|
469
|
+
|
|
470
|
+
beta = vej * km_cgs / speed_of_light
|
|
471
|
+
E = Mej * solar_mass * (beta * speed_of_light) ** 2.0 / 2.0
|
|
472
|
+
R = time * day_to_s * beta * speed_of_light / ((1 - beta) * (1 + redshift))
|
|
473
|
+
eps = 11.0 * eps_b / (6.0 * eps_e)
|
|
474
|
+
R_eq = R / eps ** (1.0 / 17.0)
|
|
475
|
+
E_eq = E / ((11.0 / 17.0) * eps ** (-6.0 / 17.0) + (6.0 / 17.0) * eps ** (11.0 / 17.0))
|
|
476
|
+
chi_e = 2.0
|
|
477
|
+
xi = 1.0 + (1.0 / eps_e)
|
|
478
|
+
|
|
479
|
+
R_prefac = (1e17 * (21.8 * 525.0 ** (p - 1.0)) ** (1.0 / (13.0 + 2.0 * p))
|
|
480
|
+
* chi_e ** ((2.0 - p) / (13.0 + 2.0 * p))
|
|
481
|
+
* xi ** (1.0 / (13.0 + 2.0 * p))
|
|
482
|
+
* (dl / 1.0e28) ** (2.0 * (p + 6.0) / (13.0 + 2.0 * p))
|
|
483
|
+
* (1.0 + redshift) ** (-(19.0 + 3.0 * p) / (13.0 + 2.0 * p))
|
|
484
|
+
* F_A ** (-(5.0 + p) / (13.0 + 2.0 * p))
|
|
485
|
+
* F_V ** (-1.0 / (13.0 + 2.0 * p))
|
|
486
|
+
* 4.0 ** (1.0 / (13.0 + 2.0 * p)))
|
|
487
|
+
E_prefac = (1.3e48 * 21.8 ** ((-2.0 * (p + 1.0)) / (13.0 + 2.0 * p))
|
|
488
|
+
* (525 ** (p - 1.0) * chi_e ** (2.0 - p)) ** (11.0 / (13.0 + 2.0 * p))
|
|
489
|
+
* xi ** (11.0 / (13.0 + 2.0 * p))
|
|
490
|
+
* (dl / 1.0e28) ** (2.0 * (3.0 * p + 14.0) / (13.0 + 2.0 * p))
|
|
491
|
+
* (1.0 + redshift) ** ((-27.0 + 5.0 * p) / (13.0 + 2.0 * p))
|
|
492
|
+
* F_A ** (-(3.0 * (p + 1.0)) / (13.0 + 2.0 * p))
|
|
493
|
+
* F_V ** ((2.0 * (p + 1.0)) / (13.0 + 2.0 * p))
|
|
494
|
+
* 4.0 ** (11.0 / (13.0 + 2.0 * p)))
|
|
495
|
+
|
|
496
|
+
Fvb = (E_prefac * R_eq / (R_prefac * E_eq)) ** ((2.0 * (p + 4.0)) / (13.0 + 2.0 * p))
|
|
497
|
+
vb = (R_prefac * Fvb ** ((p + 6.0) / (13.0 + 2.0 * p)) / R_eq) * 1.0e10
|
|
498
|
+
|
|
499
|
+
if kwargs['output_format'] == 'physical_parameters':
|
|
500
|
+
physical_parameters = namedtuple('physical_parameters', ['E', 'R', 'N_e', 'n_e', 'B'])
|
|
501
|
+
gamma_m = 2.0
|
|
502
|
+
gamma_a = (525.0 * Fvb * (dl / 1.0e28) ** 2.0 * (1.0 + redshift) ** -3.0
|
|
503
|
+
* (vb / 1.0e10) ** -2.0 / (F_A * (R / 1.0e17) ** 2.0))
|
|
504
|
+
N_e = (4.0e54 * Fvb ** 3.0 * (dl / 1.0e28) ** 6.0 * (vb / 1.0e10) ** -5.0
|
|
505
|
+
* (1.0 + redshift) ** -8.0 * F_A ** -2.0 * (R / 1.0e17) ** -4.0
|
|
506
|
+
* (gamma_m / gamma_a) ** (1.0 - p))
|
|
507
|
+
n_e = N_e / (4.0 /3.0 * np.pi * R ** 3.0)
|
|
508
|
+
B = (1.3e-2 * Fvb ** -2.0 * (dl / 1.0e28) ** -4.0 * (vb / 1.0e10) ** 5.0
|
|
509
|
+
* (1.0 + redshift) ** 7.0 * F_A ** 2.0 * (R / 1.0e17) ** 4.0)
|
|
510
|
+
physical_parameters.E = E
|
|
511
|
+
physical_parameters.R = R
|
|
512
|
+
physical_parameters.N_e = N_e
|
|
513
|
+
physical_parameters.n_e = n_e
|
|
514
|
+
physical_parameters.B = B
|
|
515
|
+
return physical_parameters
|
|
516
|
+
else:
|
|
517
|
+
flux_density = Fvb * ((frequency / vb) ** (-beta1 * s) + (frequency / vb) ** (-beta2 * s)) ** (-1.0 / s)
|
|
518
|
+
return flux_density
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from inspect import isfunction
|
|
2
2
|
import numpy as np
|
|
3
3
|
|
|
4
|
-
from scipy.integrate import
|
|
4
|
+
from scipy.integrate import simpson
|
|
5
5
|
|
|
6
6
|
from redback.utils import logger, citation_wrapper
|
|
7
7
|
|
|
@@ -45,7 +45,7 @@ def integrated_flux_afterglowpy_base_model(time, **kwargs):
|
|
|
45
45
|
lightcurve_at_nu = flux_density.reshape(len(nu_1d), len(time))
|
|
46
46
|
prefactor = 1e-26
|
|
47
47
|
lightcurve_at_nu = prefactor * lightcurve_at_nu
|
|
48
|
-
integrated_flux =
|
|
48
|
+
integrated_flux = simpson(np.array(lightcurve_at_nu), axis=0, x=nu_1d)
|
|
49
49
|
return integrated_flux
|
|
50
50
|
|
|
51
51
|
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2021arXiv210510108S/abstract')
|