def test_abs_blr_vs_point_source(self): """check if in the limit of large distances the gamma-gamma optical depth on the BLR tends to the one of a point-like source approximating it""" # broad line region L_disk = 2e46 * u.Unit("erg s-1") xi_line = 0.024 R_line = 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) r = 1e20 * u.cm # point like source approximating the blr ps_blr = PointSourceBehindJet(blr.xi_line * L_disk, blr.epsilon_line) # absorption, consider a small viewing angle for this case z = 0.859 theta_s = np.deg2rad(10) abs_blr = Absorption(blr, r, z, mu_s=np.cos(theta_s)) abs_ps_blr = Absorption(ps_blr, r, z, mu_s=np.cos(theta_s)) # taus E = np.logspace(2, 6) * u.GeV nu = E.to("Hz", equivalencies=u.spectral()) tau_blr = abs_blr.tau(nu) tau_ps_blr = abs_ps_blr.tau(nu) # sed comparison plot make_comparison_plot( nu, tau_ps_blr, tau_blr, "point source approximating the BLR", "spherical shell BLR", "Absorption on Spherical Shell BLR, " + r"$r = 10^{20}\,{\rm cm} \gg R({\rm Ly\alpha}),\,\theta_s=10^{\circ}$", f"{figures_dir}/blr/tau_blr_point_source_comparison.png", "tau", ) # requires a 10% deviation from the two SED points assert check_deviation(nu, tau_blr, tau_ps_blr, 0.1)
def test_absorption_blr_reference_tau(self, r): """test agnpy gamma-gamma optical depth for a Lyman alpha BLR 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_BLR_Ly_alpha_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") xi_line = 0.024 R_line = 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) 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_blr = Absorption(blr, _r, z) tau_agnpy = ec_blr.tau(nu_ref) # comparison plot make_comparison_plot( nu_ref, tau_agnpy, tau_ref, "agnpy", "Figure 14, Finke (2016)", f"Absorption on Spherical Shell BLR, r = {r} R(Ly alpha)", f"{figures_dir}/blr/tau_blr_Ly_alpha_comprison_r_{r}_R_Ly_alpha_figure_14_finke_2016.png", "tau", y_range=[1e-5, 1e5], ) assert True
def test_ec_blr_reference_sed(self): """test agnpy SED for EC on BLR against the one in Figure 10 of Finke 2016""" # reference SED sampled_ec_blr_table = np.loadtxt( f"{tests_dir}/sampled_seds/ec_blr_figure_10_finke_2016.txt", delimiter=",", comments="#", ) sampled_ec_blr_nu = sampled_ec_blr_table[:, 0] * u.Hz sampled_ec_blr_sed = sampled_ec_blr_table[:, 1] * u.Unit("erg cm-2 s-1") # agnpy SED L_disk = 2 * 1e46 * u.Unit("erg s-1") xi_line = 0.024 R_line = 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) # recompute the SED at the same ordinates where the figure was sampled ec_blr = ExternalCompton(BPL_BLOB, blr, r=1e18 * u.cm) agnpy_ec_blr_sed = ec_blr.sed_flux(sampled_ec_blr_nu) # sed comparison plot make_sed_comparison_plot( sampled_ec_blr_nu, sampled_ec_blr_sed, agnpy_ec_blr_sed, "External Compton on Spherical Shell Broad Line Region", "ec_blr_comparison_figure_10_finke_2016", ) # requires that the SED points deviate less than 30% from the figure assert u.allclose( agnpy_ec_blr_sed, sampled_ec_blr_sed, atol=0 * u.Unit("erg cm-2 s-1"), rtol=0.3, )
def test_absorption_failing_without_r(self): """Tests that you cannot run absorption on "fixed" targets (like BLR, DT or the disk) without specifying distance""" L_disk = 2 * 1e46 * u.Unit("erg s-1") xi_line = 0.024 R_line = 1.1 * 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) # no distance specified, should fail with pytest.raises(ValueError): abs_blr = Absorption(blr)
def test_abs_blr_mu_s_vs_on_axis(self, r_to_R): """check if the codes computing absorption on BLR for mu_s = 1 and !=1 cases are consistent """ # broad line region L_disk = 2e46 * u.Unit("erg s-1") xi_line = 0.024 R_line = 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) r = r_to_R * R_line z = 0.859 abs_blr = Absorption(blr, r, z, mu_s=0.9999) abs_blr_on_axis = Absorption(blr, r, z) abs_blr.set_l(50) abs_blr_on_axis.set_l(50) # taus E = np.logspace(0, 6) * u.GeV nu = E.to("Hz", equivalencies=u.spectral()) tau_blr = abs_blr.tau(nu) tau_blr_on_axis = abs_blr_on_axis.tau(nu) # sed comparison plot make_comparison_plot( nu, tau_blr_on_axis, tau_blr, "on-axis calculations", "general", "Absorption on Spherical Shell BLR, " + r"$r/R_{\rm line}=$" + f"{r_to_R}", f"{figures_dir}/blr/tau_blr_on_axis_vs_general_r_{r_to_R}_R_line_comparison.png", "tau", ) # only check in there range with measurable absorption xmin = min(nu[tau_blr_on_axis > 1.0e-4]) xmax = max(nu[tau_blr_on_axis > 1.0e-4]) xrange = (xmin, xmax) print(xrange) # close to the threshold there are some differences up to ~25% # which are probably due to numerical uncertainties in the integrals assert check_deviation(nu, tau_blr, tau_blr_on_axis, 0.25, x_range=xrange)
def test_ec_blr_vs_point_source(self): """check if in the limit of large distances the EC on the BLR tends to the one of a point-like source approximating it""" # broad line region L_disk = 2 * 1e46 * u.Unit("erg s-1") xi_line = 0.024 R_line = 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) # point like source approximating the blr ps_blr = PointSourceBehindJet(blr.xi_line * L_disk, blr.epsilon_line) # external Compton ec_blr = ExternalCompton(BPL_BLOB, blr, r=1e22 * u.cm) ec_ps_blr = ExternalCompton(BPL_BLOB, ps_blr, r=1e22 * u.cm) # seds nu = np.logspace(15, 28) * u.Hz ec_blr_sed = ec_blr.sed_flux(nu) ec_ps_blr_sed = ec_ps_blr.sed_flux(nu) # requires a 20% deviation from the two SED points assert u.allclose( ec_blr_sed, ec_ps_blr_sed, atol=0 * u.Unit("erg cm-2 s-1"), rtol=0.2 )
def test_absorption_blr_reference_tau(self, r, nu_min): """test agnpy gamma-gamma optical depth for a Lyman alpha BLR 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_BLR_Ly_alpha_r_{r}_R_Ly_alpha.txt", "GeV", ) # Finke's frequencies are not corrected for the redshift z = 0.859 nu_ref = E_ref.to("Hz", equivalencies=u.spectral()) / (1 + z) # target L_disk = 2 * 1e46 * u.Unit("erg s-1") xi_line = 0.024 R_Ly_alpha = 1.1 * 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_Ly_alpha) # 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 abs_blr = Absorption(blr, _r, z) tau_agnpy = abs_blr.tau(nu_ref) # check in a restricted energy range nu_range = [nu_min, 3e28] * u.Hz make_comparison_plot( nu_ref, tau_agnpy, tau_ref, "agnpy", "Figure 14, Finke (2016)", f"Absorption on Spherical Shell BLR, r = {Ly_alpha_units:.2e} R(Ly alpha)", f"{figures_dir}/blr/tau_blr_Ly_alpha_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 35 % from those of the reference figure assert check_deviation(nu_ref, tau_agnpy, tau_ref, 0.35, nu_range)
def test_tau_blr_mus_Rline(self, r_R_line): """ Checks if absorption on BLR works also fine if one of the integration points falls on R_line """ L_disk = 2 * 1e46 * u.Unit("erg s-1") xi_line = 0.024 R_line = 1.1 * 1e17 * u.cm blr = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) abs_blr = Absorption(blr, r=r_R_line * R_line, mu_s=0.99) # reference (without problem) abs_blr0 = Absorption(blr, r=r_R_line * R_line * 1.001, mu_s=0.99) nu = np.logspace(22, 28) * u.Hz tau_blr = abs_blr.tau(nu) tau_blr0 = abs_blr0.tau(nu) # the current integrals are not very precise, and this includes # tricky part to integrate, so allowing for rather large error margin assert np.allclose(tau_blr, tau_blr0, atol=0.01, rtol=1.04)
M_sun = const.M_sun.cgs M_BH = 1.2 * 1e9 * M_sun R_g = ((const.G * M_BH) / (const.c * const.c)).cgs L_disk = 2 * 1e46 * u.Unit("erg s-1") eta = 1 / 12 R_in = 6 * R_g R_out = 200 * R_g disk = SSDisk(M_BH, L_disk, eta, R_in, R_out) 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)
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()
# matplotlib adjustments load_mpl_rc() # disk parameters 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)
0.56 * u.G, bpwl_spectrum_norm_test, bpwl_dict_test, ) bpwl_blob_test.set_gamma_size(400) # global disk M_BH = 1.2 * 1e9 * M_sun.cgs L_disk = 2e46 * u.Unit("erg s-1") eta = 1 / 12 R_in = 6 R_out = 200 disk_test = SSDisk(M_BH, L_disk, eta, R_in, R_out, R_g_units=True) # global blr xi_line = 0.024 R_line = 1e17 * u.cm blr_test = SphericalShellBLR(L_disk, xi_line, "Lyalpha", R_line) # global dt T_dt = 1e3 * u.K csi_dt = 0.1 dt_test = RingDustTorus(L_disk, csi_dt, T_dt) class TestSynchrotronSelfCompton: """class grouping all tests related to the Synchrotron Slef Compton class""" @pytest.mark.parametrize("gamma_max, nu_range_max", [("1e5", 1e25), ("1e7", 1e27)]) def test_ssc_reference_sed(self, gamma_max, nu_range_max): """test agnpy SSC SED against the ones in Figure 7.4 of Dermer Menon 2009""" # reference SED nu_ref, sed_ref = extract_columns_sample_file( f"{data_dir}/reference_seds/dermer_menon_2009/figure_7_4/ssc_gamma_max_{gamma_max}.txt",
def test_line_dict(self, line, lambda_line): """test correct loading of some of the emission line""" blr = SphericalShellBLR(1e46 * u.Unit("erg s-1"), 0.1, line, 1e17) assert u.isclose(blr.lambda_line, lambda_line, atol=0 * u.Angstrom)
# global disk M_BH = 1.2 * 1e9 * M_sun L_DISK = 1.512 * 1e46 * u.Unit("erg s-1") 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, )
# disk M_BH_test = 1.2 * 1e9 * M_sun L_disk_test = 1.512 * 1e46 * u.Unit("erg s-1") 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, )