Ejemplo n.º 1
0
 def test_bb_sed_luminosity(self, T_dt):
     """test that the luminosity of the DT BB SED is the same as xi_dt * L_disk,
     create DTs with different temperatrues (and radii)"""
     xi_dt = 0.5
     L_dt = xi_dt * L_disk_test
     dt = RingDustTorus(L_disk_test, xi_dt, T_dt)
     # compute the SEDs, assume a random redshift
     z = 0.23
     nu = np.logspace(10, 20, 100) * u.Hz
     sed = dt.sed_flux(nu, z)
     # compute back the luminosity
     d_L = Distance(z=z).to("cm")
     F_nu = sed / nu
     L = 4 * np.pi * np.power(d_L, 2) * np.trapz(F_nu, nu, axis=0)
     assert u.isclose(L, L_dt, atol=0 * u.Unit("erg s-1"), rtol=1e-2)
Ejemplo n.º 2
0
 def test_abs_dt_vs_point_source(self):
     """check if in the limit of large distances the gamma-gamma optical depth 
     on the DT tends to the one of a point-like source approximating it"""
     # dust torus
     L_disk = 2e46 * u.Unit("erg s-1")
     T_dt = 1e3 * u.K
     csi_dt = 0.1
     dt = RingDustTorus(L_disk, csi_dt, T_dt)
     r = 1e22 * u.cm
     # point like source approximating the dt
     ps_dt = PointSourceBehindJet(dt.xi_dt * L_disk, dt.epsilon_dt)
     # absorption
     z = 0.859
     theta_s = np.deg2rad(10)
     abs_dt = Absorption(dt, r, z, mu_s=np.cos(theta_s))
     abs_ps_dt = Absorption(ps_dt, r, z, mu_s=np.cos(theta_s))
     # taus
     E = np.logspace(2, 6) * u.GeV
     nu = E.to("Hz", equivalencies=u.spectral())
     tau_dt = abs_dt.tau(nu)
     tau_ps_dt = abs_ps_dt.tau(nu)
     make_comparison_plot(
         nu,
         tau_ps_dt,
         tau_dt,
         "point source approximating the DT",
         "ring dust torus",
         "Absorption on Ring Dust Torus, " +
         r"$r = 10^{22}\,{\rm cm} \gg R_{\rm dt},\,\theta_s=10^{\circ}$",
         f"{figures_dir}/dt/tau_dt_point_source_comparison.png",
         "tau",
     )
     # requires a 10% deviation from the two SED points
     assert check_deviation(nu, tau_dt, tau_ps_dt, 0.1)
Ejemplo n.º 3
0
 def test_absorption_dt_reference_tau(self, r):
     """test agnpy gamma-gamma optical depth for DT against the one in 
     Figure 14 of Finke 2016"""
     # reference tau
     E_ref, tau_ref = extract_columns_sample_file(
         f"{data_dir}/reference_taus/finke_2016/figure_14_left/tau_DT_r_{r}_R_Ly_alpha.txt",
         "GeV",
     )
     nu_ref = E_ref.to("Hz", equivalencies=u.spectral())
     # target
     L_disk = 2e46 * u.Unit("erg s-1")
     T_dt = 1e3 * u.K
     csi_dt = 0.1
     dt = RingDustTorus(L_disk, csi_dt, T_dt)
     R_Ly_alpha = 1.1e17 * u.cm
     _r = float(r) * R_Ly_alpha
     # recompute the tau, use the full energy range of figure 14
     z = 0.859
     ec_dt = Absorption(dt, _r, z)
     tau_agnpy = ec_dt.tau(nu_ref)
     # comparison plot
     make_comparison_plot(
         nu_ref,
         tau_agnpy,
         2 * tau_ref,
         "agnpy",
         "Figure 14, Finke (2016)",
         f"Absorption on Dust Torus, r = {r} R(Ly alpha)",
         f"{figures_dir}/dt/tau_dt_comprison_r_{r}_R_Ly_alpha_figure_14_finke_2016.png",
         "tau",
         y_range=[1e-5, 1e5],
     )
     assert True
Ejemplo n.º 4
0
 def test_ec_dt_reference_sed(self):
     """test agnpy SED for EC on DT against the one in Figure 11 of Finke 2016"""
     # reference SED
     sampled_ec_dt_table = np.loadtxt(
         f"{tests_dir}/sampled_seds/ec_dt_figure_11_finke_2016.txt",
         delimiter=",",
         comments="#",
     )
     sampled_ec_dt_nu = sampled_ec_dt_table[:, 0] * u.Hz
     # multiply the reference SED for 2 as this is the missing factor
     # in the emissivity expression in Eq. 90 of Finke 2016
     sampled_ec_dt_sed = 2 * sampled_ec_dt_table[:, 1] * u.Unit("erg cm-2 s-1")
     # agnpy SED
     L_disk = 2 * 1e46 * u.Unit("erg s-1")
     T_dt = 1e3 * u.K
     csi_dt = 0.1
     dt = RingDustTorus(L_disk, csi_dt, T_dt)
     # recompute the SED at the same ordinates where the figure was sampled
     ec_dt = ExternalCompton(BPL_BLOB, dt, r=1e20 * u.cm)
     agnpy_ec_dt_sed = ec_dt.sed_flux(sampled_ec_dt_nu)
     # sed comparison plot
     make_sed_comparison_plot(
         sampled_ec_dt_nu,
         sampled_ec_dt_sed,
         agnpy_ec_dt_sed,
         "External Compton on Ring Dust Torus",
         "ec_dt_comparison_figure_11_finke_2016",
     )
     # requires that the SED points deviate less than 30% from the figure
     assert u.allclose(
         agnpy_ec_dt_sed,
         sampled_ec_dt_sed,
         atol=0 * u.Unit("erg cm-2 s-1"),
         rtol=0.3,
     )
Ejemplo n.º 5
0
    def test_tau_dt_mu_s_far(self, mu_s):
        """
        comparing the DT absorption for mu_s !=1 with point source simplification
        """
        L_disk = 2e46 * u.Unit("erg s-1")
        xi_DT = 0.1
        temp = 1000 * u.K
        R_DT = 1.0e17 * u.cm  # radius of DT
        dt = RingDustTorus(L_disk, xi_DT, temp, R_dt=R_DT)

        r = 10 * R_DT  # distance at which the photon starts

        nu_ref = np.logspace(26, 32, 60) * u.Hz

        # absorption at mu_s
        abs_dt_mu_s = Absorption(dt, r, z=0, mu_s=mu_s)
        tau_dt_mu_s = abs_dt_mu_s.tau(nu_ref)

        uu = np.logspace(-5, 5, 100) * r
        _u, _nu_ref = axes_reshaper(uu, nu_ref)

        eps = (2.7 * temp * k_B).to("eV")  # energy of soft photons
        # distance from the DT
        _x = np.sqrt(r * r + _u * _u + 2 * mu_s * _u * r)

        # soft photon density
        _nph = (L_disk * xi_DT / (4 * np.pi * _x**2) / c / eps).to("cm-3")

        _E = _nu_ref.to("eV", equivalencies=u.spectral())
        _cospsi = (_u**2 + _x**2 - r**2) / (2 * _u * _x)

        _beta2 = 1 - 2 * mec2**2 / (_E * eps * (1 - _cospsi))
        _beta2[_beta2 < 0] = 0

        integrand = sigma_pp(np.sqrt(_beta2)) * _nph * (1 - _cospsi)
        tau_my = (np.trapz(integrand, uu, axis=0)).to("")

        print(tau_my / tau_dt_mu_s)

        max_agnpy = max(tau_dt_mu_s)
        max_my = max(tau_my)
        max_pos_agnpy = nu_ref[np.argmax(tau_dt_mu_s)]
        max_pos_my = nu_ref[np.argmax(tau_my)]

        # if r>>R_re this should be pretty precise, allowing for 10% accuracy
        assert np.isclose(max_agnpy, max_my, atol=0, rtol=0.1)
        assert np.isclose(max_pos_agnpy, max_pos_my, atol=0, rtol=0.1)
Ejemplo n.º 6
0
    def test_tau_dt_mu_s_simple(self):
        """
        order of magnitude test comparing with simplified calculations
        the case of a perpendicularly moving photon starting at r~0.5 * R_re
        """
        r = 1.0e17 * u.cm  # distance at which the photon starts
        mu_s = 0.0  # angle of propagation

        L_disk = 2e46 * u.Unit("erg s-1")
        xi_DT = 0.1
        temp = 1000 * u.K
        R_DT = 2 * r  # radius of DT: assume the same as the distance r
        dt = RingDustTorus(L_disk, xi_DT, temp, R_dt=R_DT)

        nu_ref = np.logspace(26, 32, 120) * u.Hz

        # absorption at mu_s
        abs_dt_mu_s = Absorption(dt, r, z=0, mu_s=mu_s)
        tau_dt_mu_s = abs_dt_mu_s.tau(nu_ref)

        eps = (2.7 * temp * k_B).to("eV")  # energy of soft photons
        # soft photon density
        nph = (L_disk * xi_DT / (4 * np.pi * (r**2 + R_DT**2)) / c /
               eps).to("cm-3")

        E = nu_ref.to("eV", equivalencies=u.spectral())
        cospsi = 0  # assume perpendicular scattering
        beta2 = 1 - 2 * mec2**2 / (E * eps * (1 - cospsi))
        beta2[beta2 < 0] = 0  # below the threshold
        # for tau calculations we assume that gamma ray moves
        # roughtly the characteristic distance of ~R_DT
        tau_my = (sigma_pp(np.sqrt(beta2)) * nph * R_DT * (1 - cospsi)).to("")

        max_agnpy = max(tau_dt_mu_s)
        max_my = max(tau_my)
        max_pos_agnpy = nu_ref[np.argmax(tau_dt_mu_s)]
        max_pos_my = nu_ref[np.argmax(tau_my)]
        # very rough calculations so allowing for
        # 15% accuracy in peak maximum and 30% in peak position
        assert np.isclose(max_agnpy, max_my, atol=0, rtol=0.15)
        assert np.isclose(max_pos_agnpy, max_pos_my, atol=0, rtol=0.3)
Ejemplo n.º 7
0
 def test_ec_dt_vs_point_source(self):
     """check if in the limit of large distances the EC on the DT tends to
     the one of a point-like source approximating it"""
     # dust torus
     L_disk = 2 * 1e46 * u.Unit("erg s-1")
     T_dt = 1e3 * u.K
     csi_dt = 0.1
     dt = RingDustTorus(L_disk, csi_dt, T_dt)
     # point like source approximating the dt
     ps_dt = PointSourceBehindJet(dt.xi_dt * L_disk, dt.epsilon_dt)
     # external Compton
     ec_dt = ExternalCompton(BPL_BLOB, dt, r=1e22 * u.cm)
     ec_ps_dt = ExternalCompton(BPL_BLOB, ps_dt, r=1e22 * u.cm)
     # seds
     nu = np.logspace(15, 28) * u.Hz
     ec_dt_sed = ec_dt.sed_flux(nu)
     ec_ps_dt_sed = ec_ps_dt.sed_flux(nu)
     # requires a 20% deviation from the two SED points
     assert u.allclose(
         ec_dt_sed, ec_ps_dt_sed, atol=0 * u.Unit("erg cm-2 s-1"), rtol=0.2
     )
Ejemplo n.º 8
0
 def test_absorption_dt_reference_tau(self, r, nu_min):
     """test agnpy gamma-gamma optical depth for DT against the one in 
     Figure 14 of Finke 2016"""
     # reference tau
     E_ref, tau_ref = extract_columns_sample_file(
         f"{data_dir}/reference_taus/finke_2016/figure_14_left/tau_DT_r_{r}_R_Ly_alpha.txt",
         "GeV",
     )
     nu_ref = E_ref.to("Hz", equivalencies=u.spectral())
     # target
     L_disk = 2 * 1e46 * u.Unit("erg s-1")
     T_dt = 1e3 * u.K
     csi_dt = 0.1
     dt = RingDustTorus(L_disk, csi_dt, T_dt)
     R_Ly_alpha = 1.1 * 1e17 * u.cm
     # parse the string providing the distance in units of R_Ly_alpha
     # numbers as 1e1.5 cannot be directly converted to float
     num = r.split("e")
     Ly_alpha_units = (float(num[0]) * 10)**(float(num[-1]))
     _r = Ly_alpha_units * R_Ly_alpha
     # recompute the tau, use the full energy range of figure 14
     z = 0.859
     abs_dt = Absorption(dt, _r, z)
     tau_agnpy = abs_dt.tau(nu_ref)
     # check in a restricted energy range
     nu_range = [nu_min, 3e28] * u.Hz
     make_comparison_plot(
         nu_ref,
         tau_agnpy,
         2 * tau_ref,
         "agnpy",
         "Figure 14, Finke (2016)",
         f"Absorption on Dust Torus, r = {Ly_alpha_units:.2e} R(Ly alpha)",
         f"{figures_dir}/dt/tau_dt_comprison_r_{r}_R_Ly_alpha_figure_14_finke_2016.png",
         "tau",
         comparison_range=nu_range.to_value("Hz"),
         y_range=[1e-6, 1e3],
     )
     # requires that the SED points deviate less than 20 % from those of the reference figure
     assert check_deviation(nu_ref, tau_agnpy, 2 * tau_ref, 0.20, nu_range)
Ejemplo n.º 9
0
print("\ndisk definition:")
print(disk)

# blr definition
epsilon_line = 2e-5
csi_line = 0.024
R_line = 1e17 * u.cm
blr = SphericalShellBLR(disk, csi_line, epsilon_line, R_line)
print("\nblr definition:")
print(blr)

# dust torus definition
T_dt = 1e3 * u.K
epsilon_dt = 2.7 * ((const.k_B * T_dt) / (const.m_e * const.c * const.c)).decompose()
csi_dt = 0.1
dt = RingDustTorus(disk, csi_dt, epsilon_dt)
print("\ntorus definition:")
print(dt)

# define the External Compton
ec_disk = ExternalCompton(blob, disk, r=1e17 * u.cm)
ec_blr = ExternalCompton(blob, blr, r=1e17 * u.cm)
ec_dt = ExternalCompton(blob, dt, r=1e17 * u.cm)
nu = np.logspace(15, 30) * u.Hz

# commands to profile
ec_disk_sed_command = "ec_disk.sed_flux(nu)"
ec_blr_sed_command = "ec_blr.sed_flux(nu)"
ec_dt_sed_command = "ec_dt.sed_flux(nu)"

n = 100
Ejemplo n.º 10
0
import sys
import numpy as np
import astropy.units as u
import matplotlib.pyplot as plt

sys.path.append("../../")
from agnpy.targets import SphericalShellBLR, RingDustTorus

blr = SphericalShellBLR(1e46 * u.Unit("erg s-1"), 0.1, "Lyalpha", 1e17 * u.cm)
dt = RingDustTorus(1e46 * u.Unit("erg s-1"), 0.6, 1000 * u.K)
print(blr)
print(dt)

r = np.logspace(14, 21, 200) * u.cm

plt.loglog(r, blr.u(r), label="BLR")
plt.loglog(r, dt.u(r), label="Torus")
plt.xlabel(r"$r\,/\,{\rm cm}$")
plt.ylabel(r"$u\,/\,({\rm erg}\,{\rm cm}^{-3})$")
plt.legend()
plt.show()
Ejemplo n.º 11
0
M_BH = 1.2 * 1e9 * const.M_sun.cgs
L_disk = 2 * 1e46 * u.Unit("erg s-1")
eta = 1 / 12
R_in = 6
R_out = 200
disk = SSDisk(M_BH, L_disk, eta, R_in, R_out, R_g_units=True)

# blr definition
csi_line = 0.024
R_line = 1e17 * u.cm
blr = SphericalShellBLR(L_disk, csi_line, "Lyalpha", R_line)

# dust torus definition
T_dt = 1e3 * u.K
csi_dt = 0.1
dt = RingDustTorus(L_disk, csi_dt, T_dt)

# consider a fixed distance of the blob from the target fields
r = 1.1e16 * u.cm
# let us consider 3C 454.3 as source
z = 0.859

absorption_disk = Absorption(disk, r=r, z=z)
absorption_blr = Absorption(blr, r=r, z=z)
absorption_dt = Absorption(dt, r=r, z=z)

# plot using the same energy range as in Finke 2016
E = np.logspace(0, 5) * u.GeV
nu = E.to("Hz", equivalencies=u.spectral())

tau_disk = absorption_disk.tau(nu)
Ejemplo n.º 12
0
#####################
# test one with emission region in the center of the DT
L_disk = 0.91e45 * u.Unit("erg s-1")
xi_dt = 0.6
T_dt = 100 * u.K
R_dt = 1.0e18 * u.cm
h = 0.01 * R_dt

## test with lower numbers, gives virtually the same
# B0/=10
# T_dt/=10
# L_disk/=100

blob1 = Blob(r0, z, delta_D, Gamma, B0, norm, spectrum_dict, xi=xi)
dt1 = RingDustTorus(L_disk, xi_dt, T_dt, R_dt=R_dt)

# energy density of DT radiation field in the blob
u_dt1 = dt1.u_ph(h, blob1)
u_synch1 = blob1.u_ph_synch
print(
    "energy density in the blob, DT radiation: ",
    u_dt1,
    "synchrotron photons: ",
    u_synch1,
)
dt1_sed = dt1.sed_flux(nu, z)
# energy density was set to be the same

synch1 = Synchrotron(blob1, ssa=False)
synch1_sed = synch1.sed_flux(nu)
Ejemplo n.º 13
0
 def test_setting_radius(self):
     """check that, when passed manually, the radius is correctly set"""
     dt = RingDustTorus(L_DISK, 0.1, 1e3 * u.K, 1e19 * u.cm)
     assert u.allclose(dt.R_dt, 1e19 * u.cm, atol=0 * u.cm)
Ejemplo n.º 14
0
ETA = 1 / 12
R_G = 1.77 * 1e14 * u.cm
R_IN_G_UNITS = 6
R_OUT_G_UNITS = 200
R_IN = R_IN_G_UNITS * R_G
R_OUT = R_OUT_G_UNITS * R_G
DISK = SSDisk(M_BH, L_DISK, ETA, R_IN, R_OUT)
# useful for checks
L_EDD = 15.12 * 1e46 * u.Unit("erg s-1")
M_DOT = 2.019 * 1e26 * u.Unit("g s-1")

# global SphericalShellBLR
BLR = SphericalShellBLR(L_DISK, 0.1, "Lyalpha", 1e17 * u.cm)

# dust torus definition
DT = RingDustTorus(L_DISK, 0.1, 1000 * u.K)


class TestCMB:
    """class grouping all the tests related to the CMB"""
    def test_u(self):
        """test u in the stationary reference frame"""
        assert u.isclose(
            6.67945605e-12 * u.Unit("erg / cm3"),
            CMB_Z_1.u(),
            atol=0 * u.Unit("erg / cm3"),
            rtol=1e-3,
        )

    def test_u_comoving(self):
        """test u in the reference frame comoving with the blob"""
Ejemplo n.º 15
0
eta_test = 1 / 12
R_g_test = 1.77 * 1e14 * u.cm
R_in_tilde_test = 6
R_out_tilde_test = 200
R_in_test = R_in_tilde_test * R_g_test
R_out_test = R_out_tilde_test * R_g_test
disk_test = SSDisk(M_BH_test, L_disk_test, eta_test, R_in_test, R_out_test)
# useful for checks
L_Edd_test = 15.12 * 1e46 * u.Unit("erg s-1")
m_dot_test = 2.019 * 1e26 * u.Unit("g s-1")

# SphericalShellBLR
blr_test = SphericalShellBLR(L_disk_test, 0.1, "Lyalpha", 1e17 * u.cm)

# dust torus definition
dt_test = RingDustTorus(L_disk_test, 0.1, 1000 * u.K)


class TestCMB:
    """class grouping all the tests related to the CMB"""
    def test_u(self):
        """test u in the stationary reference frame"""
        assert u.isclose(
            6.67945605e-12 * u.Unit("erg / cm3"),
            cmb_test.u(),
            atol=0 * u.Unit("erg / cm3"),
            rtol=1e-5,
        )

    def test_u_comoving(self):
        """test u in the reference frame comoving with the blob"""