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", "Hz", "erg cm-2 s-1", ) # agnpy # change the gamma_max in the blob pwl_dict_test["parameters"]["gamma_max"] = float(gamma_max) pwl_blob_test.set_spectrum(pwl_spectrum_norm_test, pwl_dict_test, "integral") # recompute the SED at the same ordinates where the figure was sampled ssc = SynchrotronSelfCompton(pwl_blob_test) sed_agnpy = ssc.sed_flux(nu_ref) # sed comparison plot nu_range = [1e14, nu_range_max] * u.Hz make_comparison_plot( nu_ref, sed_agnpy, sed_ref, "agnpy", "Figure 7.4, Dermer and Menon (2009)", "Synchrotron Self Compton, " + r"$\gamma_{max} = $" + gamma_max, f"{figures_dir}/ssc/comparison_gamma_max_{gamma_max}_figure_7_4_dermer_menon_2009.png", "sed", y_range=[1e-13, 1e-9], comparison_range=nu_range.to_value("Hz"), ) # requires that the SED points deviate less than 20% from the figure assert check_deviation(nu_ref, sed_agnpy, sed_ref, 0.2, nu_range)
def test_ssc_reference_sed(self): """test agnpy SSC SED against the one in Figure 7.4 of Dermer Menon""" sampled_ssc_table = np.loadtxt( f"{tests_dir}/sampled_seds/ssc_figure_7_4_dermer_menon_2009.txt", delimiter=",", comments="#", ) sampled_ssc_nu = sampled_ssc_table[:, 0] * u.Hz sampled_ssc_sed = sampled_ssc_table[:, 1] * u.Unit("erg cm-2 s-1") # agnpy synch = Synchrotron(PWL_BLOB) ssc = SynchrotronSelfCompton(PWL_BLOB, synch) # recompute the SED at the same ordinates where the figure was sampled agnpy_ssc_sed = ssc.sed_flux(sampled_ssc_nu) # sed comparison plot make_sed_comparison_plot( sampled_ssc_nu, sampled_ssc_sed, agnpy_ssc_sed, "Synchrotron Self Compton", "ssc_comparison_figure_7_4_dermer_menon_2009", ) # requires that the SED points deviate less than 15% from the figure assert u.allclose( agnpy_ssc_sed, sampled_ssc_sed, atol=0 * u.Unit("erg cm-2 s-1"), rtol=0.15 )
def test_ssc_integration_methods(self): """test SSC SED for different integration methods against each other """ nu = np.logspace(15, 28) * u.Hz ssc_trapz = SynchrotronSelfCompton(pwl_blob_test, integrator=np.trapz) ssc_trapz_loglog = SynchrotronSelfCompton(pwl_blob_test, integrator=trapz_loglog) sed_ssc_trapz = ssc_trapz.sed_flux(nu) sed_ssc_trapz_loglog = ssc_trapz_loglog.sed_flux(nu) # compare in a restricted energy range nu_range = [1e15, 1e27] * u.Hz make_comparison_plot( nu, sed_ssc_trapz_loglog, sed_ssc_trapz, "trapezoidal log-log integration", "trapezoidal integration", "Synchrotron Self Compton", f"{figures_dir}/ssc/comparison_integration_methods.png", "sed", comparison_range=nu_range.to_value("Hz"), ) # requires that the SED points deviate less than 15% assert check_deviation(nu, sed_ssc_trapz_loglog, sed_ssc_trapz, 0.15, nu_range)
import numpy as np import astropy.units as u from agnpy.emission_regions import Blob from agnpy.compton import SynchrotronSelfCompton from agnpy.utils.plot import plot_sed import matplotlib.pyplot as plt from agnpy.utils.plot import load_mpl_rc # matplotlib adjustments load_mpl_rc() # define the emission region and the radiative process blob = Blob() ssc = SynchrotronSelfCompton(blob) # compute the SED over an array of frequencies nu = np.logspace(15, 28) * u.Hz sed = ssc.sed_flux(nu) # plot it plot_sed(nu, sed, label="Synchrotron Self Compton") plt.show()
# total energy in blob / (average time * 4 pi dist^2) energy_flux_predicted = (blob.u_ph_synch * blob1.V_b / (0.75 * blob1.R_b / const.c.cgs) * np.power(blob1.d_L, -2) / (4 * np.pi)).to("erg cm-2 s-1") synch1 = Synchrotron(blob1, ssa=False) synch1_sed = synch1.sed_flux(nu) energy_flux_sim = np.trapz(synch1_sed / (nu * const.h.cgs), nu * const.h.cgs) print( f"predicted energy flux: {energy_flux_predicted:.5e}, simulated energy flux: {energy_flux_sim:.5e}" ) # nice agreement ssc1 = SynchrotronSelfCompton(blob1, synch1) ssc1_sed = ssc1.sed_flux(nu) print("UB/Usynch = ", blob1.U_B / u_ph_synch) print( "SED_synch/SED_SSC=", energy_flux_sim / np.trapz(ssc1_sed / (nu * const.h.cgs), nu * const.h.cgs), ) # same energy densities mean in Thomson regime the same energy losses ==> the same energy flux print("break_synchr/break_SSC = ", blob1.gamma_break_synch / blob1.gamma_break_SSC) print("gmax_synchr/gmax_SSC = ", blob1.gamma_max_synch / blob1.gamma_max_SSC) # SSC is at the same level as Synchr. so the cooling breaks and maximum energies are also same
"parameters": { "p": 2.8, "gamma_min": 1e2, "gamma_max": 1e7 }, } R_b = 1e16 * u.cm B = 1 * u.G z = Distance(1e27, unit=u.cm).z delta_D = 10 Gamma = 10 blob = Blob(R_b, z, delta_D, Gamma, B, spectrum_norm, spectrum_dict) print("blob definition:") print(blob) synch = Synchrotron(blob) ssc = SynchrotronSelfCompton(blob, synch) nu_syn = np.logspace(8, 23) * u.Hz nu_ssc = np.logspace(15, 30) * u.Hz # commands to profile syn_sed_command = "synch.sed_flux(nu_syn)" syn_sed_SSA_command = "synch.sed_flux(nu_syn, SSA=True)" ssc_sed_command = "ssc.sed_flux(nu_ssc)" n = 100 print("\nprofiling synchrotron sed computation:") profile(syn_sed_command, "syn_sed") time_syn = timing(syn_sed_command, n) time_syn /= n print(f"time: {time_syn:.2e} s")
"p": 2.8, "gamma_min": 1e2, "gamma_max": 1e7 }, } R_b = 1e16 * u.cm B = 1 * u.G z = Distance(1e27, unit=u.cm).z delta_D = 10 Gamma = 10 blob = Blob(R_b, z, delta_D, Gamma, B, spectrum_norm, spectrum_dict) print("blob definition:") print(blob) synch = Synchrotron(blob) synch_ssa = Synchrotron(blob, ssa=True) ssc = SynchrotronSelfCompton(blob, synch) ssc_ssa = SynchrotronSelfCompton(blob, synch_ssa) nu_syn = np.logspace(8, 23) * u.Hz nu_ssc = np.logspace(15, 30) * u.Hz # commands to profile syn_sed_command = "synch.sed_flux(nu_syn)" syn_sed_ssa_command = "synch_ssa.sed_flux(nu_syn)" ssc_sed_command = "ssc.sed_flux(nu_ssc)" ssc_ssa_sed_command = "ssc_ssa.sed_flux(nu_ssc)" n = 100 print("\nprofiling synchrotron sed computation:") profile(syn_sed_command, "syn_sed") time_syn = timing(syn_sed_command, n) time_syn /= n