Пример #1
0
def plot_edd_rate_line(MBH1d, eddrate=1, **kwargs):
    L_AGN_edd = compute_eddington_luminosity(MBH1d)
    x, y = log_lum(L_AGN_edd * eddrate), log_bhm(MBH1d)
    plt.plot(x, y, "--", label='$\lambda=%s$' % eddrate, **kwargs)
    plt.text(x[4],
             y[4],
             '$\lambda=%s$' % eddrate,
             va='center',
             ha='center',
             rotation=60,
             bbox=dict(color='white', pad=0),
             size=8)
Пример #2
0
        # equation (9)
        R_in = 0.018 * u.pc * (L_opt_45)**0.5

        x = numpy.linspace(0, 0.05, 1000) * u.pc
        z = compute_blr_height(MBH, M_dot, Z, x)
        #HR = y / x
        #HRmax = 2**-0.5
        #y = numpy.where(HR > HRmax, 0, y)

        print("R_in:", R_in, M_dot)

        plt.plot(
            x,
            z,
            ls=ls,
            color=color,
            label=
            "$M_\mathrm{BH}=%d$ $\lambda=%.3f$ $L_{46}=%.2f$ $\dot{M}=%.1f M_\odot/yr$"
            % (log_bhm(MBH), eddrate, L_AGN_46, M_dot.to(u.Msun / u.yr).value))
        plt.vlines(R_in.value, 0, 0.004, linestyles=[ls], colors=['k'])
        plt.plot(x, compute_sub_height(L_AGN, 1, x), '--', color='k', lw=1)

plt.xlim(0, 0.05)
plt.ylim(0, 0.03)
plt.xlabel("R [pc]")
plt.ylabel("z [pc]")
plt.legend(loc="best", prop=dict(size=8))
plt.savefig("windyblr.pdf", bbox_inches="tight")
plt.close()
Пример #3
0
        r_d = compute_dust_sublimation_radius(L_AGN)
        r_0 = compute_heating_radius(L_AGN, rho_g=300 * u.Msun / u.pc**3)
        r_max = compute_rmax(MBH,
                             L_AGN,
                             theta,
                             r_0,
                             r_d,
                             dust_to_gas_ratio=dust_to_gas_ratio,
                             kappa=kappa)
        y, x = pol2cart(r_max, theta)
        plt.plot(x,
                 y,
                 ls=ls,
                 color=color,
                 label="$M_\mathrm{BH}=%d$ $\lambda=%s$" %
                 (log_bhm(MBH), eddrate))

r_max = max(max(plt.ylim()), max(plt.xlim()))
r_max = 20
plt.ylim(0.01, r_max)
plt.xlim(0.01, r_max)
plt.xlabel("x [pc]")
plt.ylabel("y [pc]")
plt.legend(loc="best", prop=dict(size=8))
#plt.xscale("log")
#plt.yscale("log")
plt.savefig("radfountain_2d-angle.pdf", bbox_inches="tight")
plt.close()

MBH_lo, MBH_hi = 6.5, 9.5
MBH1d = numpy.logspace(MBH_lo, MBH_hi, 100) * u.Msun
Пример #4
0
    CF = get_blr_covering_factor(z1, z2, R)
    Rpeak, Hpeak = get_peak(z2, z1, R)
    z1, z2, zmax_dyn_nodust = compute_blr_shape(MBH,
                                                M_dot,
                                                L_AGN,
                                                R,
                                                Z,
                                                variant='dustfree',
                                                dyn_factor=2)

    l, = plt.plot(
        R,
        zmax_dyn,
        label=
        "$M_\mathrm{BH}=%d$ $\lambda=%.3f$ $L_{46}=%.2f$ $\dot{M}=%.1f M_\odot/yr$ CF=%.0f%%"
        % (log_bhm(MBH), eddrate, L_AGN_46, M_dot.to(
            u.Msun / u.yr).value, CF * 100))
    color = l.get_color()
    #plt.plot(R.flatten(), zmax, ':', color=color)
    plt.plot(R.flatten(), zmax_dyn_nodust, '--', color=color)
    plt.plot(Rpeak, Hpeak, 'o', color=color)
    plt.fill_between(R.flatten(), 0, zmax_dyn, color=color, hatch='//')
    plt.vlines(R_in.to(u.pc).value,
               0,
               Hpeak.to(u.pc).value,
               linestyles=[':'],
               colors=[color])
    #break

#plt.xlim(0, 0.1)
#plt.xlim(0.001, R_in.value * 2)
Пример #5
0
def plot_log_agn_postcard(MBH, eddrate, 
	# from Baskin & Laor (2017)
	rad_efficiency = 0.1,
	Z = 5, # metallicity
	# Radiative Fountain system assumptions
	dust_to_gas_ratio = 1/20.,
	kappa = 1e3 * u.cm**2/u.g,
	rho_g = 300 * u.Msun / u.pc**3,
	show_BH = True,
	show_corona = True,
	show_disk = True,
	show_BLR = True,
	show_NLR = True,
	show_jet = True,
	show_TOR = True,
	show_SOI = True,
	show_viewing = True,
	colored_disk = True,
	show_flows = True,
):
	L_AGN_edd = compute_eddington_luminosity(MBH)

	L_AGN = eddrate * L_AGN_edd
	L_AGN_46 = (L_AGN / (1e46 * u.erg/u.s)).to(1)
	L_AGN_edd = compute_eddington_luminosity(MBH)
	r_grav = compute_grav_radius(MBH).to(u.pc)

	M_dot = (L_AGN / c.c**2 / rad_efficiency).to(u.Msun / u.yr)
	
	R_in = compute_sublimation_radius(MBH, M_dot)
	# from Kormendy & Ho+13, compute sigma from BH mass
	sigma = 200 * u.km / u.s * 10**((log10((MBH / (1e9 * u.Msun)).to(1)) + 0.510) / 4.377)
	r_infl = compute_sphere_of_influence(MBH, sigma).to(u.pc)

	R = numpy.logspace(log10(r_grav/R_in), 3, 1000) * R_in
	R = numpy.logspace(log10(r_grav/R_in), max(3, log10(r_infl/R_in)), 1000) * R_in

	title = "$M_\mathrm{BH}=%s$ $\lambda=%.3f$ $L_\mathrm{AGN}=%.1f$ $\dot{M}=%.1f M_\odot/yr$" % (log_bhm(MBH), eddrate, log_lum(L_AGN), M_dot.to(u.Msun / u.yr).value)
	#plt.title(title)
	
	colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
	textsize = 10
	
	xlo, xhi = 8e-8 * u.pc, 50*100 * u.pc
	ylo, yhi = xlo / 100,  200*100 * u.pc

	# Sphere of influence:
	theta = numpy.linspace(0, pi/2, 400)
	y, x = pol2cart(r_infl, theta)
	if show_SOI:
		plt.plot(x, y, ls='--', lw=0.5, color=colors[8], label='Sphere of influence')
		#plt.text(x.max().value*1.1, r_infl.value / 1000, 'Sphere of influence', 
		#	va='bottom', ha='left', rotation=90)
		plt.text(x.max().value * 1.2, ylo.value * 2, 'Sphere of influence', 
			va='bottom', ha='left', rotation=90)
		#plt.fill_between(x.value, y.value, y.value*0 + yhi.value, 
		#	color=colors[8], alpha=0.1)
		#plt.fill_between([x.max().value, xhi.value], [ylo.value]*2, [yhi.value]*2, 
		#	color=colors[8], alpha=0.1)
		#plt.fill_between(x.value, y.value, y.value*0 + ylo.value, 
		#	color=colors[8], alpha=0.06)

	# Accretion disk:
	R_disk = R
	z_disk = compute_alphadisk_height(MBH, M_dot, R_disk, alpha=1).to(u.pc)
	T_disk = compute_alphadisk_temperature(MBH, M_dot, R_disk, alpha=1).to(u.K)
	if show_disk:
		mask = R < r_infl
		if colored_disk:
			for color, R_part, z_disk_part in find_color_chunks(color_data_T, T_disk[mask], color_data_rgb, R_disk[mask], z_disk[mask]):
				plt.fill_between(R_part, z_disk_part, z_disk_part * 0 + ylo, color=color)
		else:
			plt.fill_between(R_disk[mask], z_disk[mask], z_disk[mask] * 0 + ylo, color='k', label="Accretion disk (SS)")
		
		#	'Accretion disk\n$\log \dot{M}=%.1f$' % rround(log10(M_dot.value)),
		plt.text(7 * r_grav.value, ylo.value * 2, 
			'Accretion disk\n$\log L_\mathrm{bol}=%.1f$' % log_lum(L_AGN),
			va='bottom', ha='left', color='k', size=textsize, bbox=dict(color='white'))
		#idx = numpy.where(R>20*r_grav)[0][0]
		#plt.text(R_disk[idx].value, z_disk[idx].value, 'Accretion disk', 
		#	va='top', ha='left', color='k', size=textsize)
		
		if show_flows:
			outflow = compute_outflow_rate(L_AGN, Mstar = 1e11 * u.Msun, SFR = 0*u.Msun/u.yr)
			inflow = M_dot # at accretion disk at least, or when considering steady-state
			# y = z_disk[mask][-1].value/10
			plt.text(r_infl.value*2, 1e-3, '$\\uparrow$ Outflow\n$%s M_\odot/\mathrm{yr} \cdot M_{\star,11}^{-0.4}$\n$\leftarrow$ BH Inflow\n$%s M_\odot/\mathrm{yr}$' % (rround(outflow.to(u.Msun/u.yr).value), rround(inflow.to(u.Msun/u.yr).value)), 
				va='top', ha='left', color='k', size=textsize)
		
	# Jet:
	R_fullrange = numpy.logspace(log10(r_grav.value), log10(R.value.max()*5), 400) * u.pc
	R_fullrange = numpy.logspace(log10(r_grav.value), log10(max(yhi, 1e8*r_grav).value), 400) * u.pc
	R_j = compute_jet_edge(MBH, R_fullrange)
	if show_jet:
		jetcolor = colors[4]
		plt.plot(R_j, R_fullrange, '--', color=jetcolor, label='Jet')
		plt.fill_betweenx(R_fullrange, R_j, color=jetcolor, label='Jet', alpha=0.05)
		plt.text(R_j.value[-1] / 5, R_fullrange.value[-1] / 2, 'Jet', color=jetcolor, 
			va='top', ha='right', size=textsize)

	# BH:
	theta = numpy.linspace(0, pi/2, 4000)
	y, x = pol2cart(r_grav, theta[::-1])
	if show_BH:
		plt.fill_between(x, 1e-10 + 0*y.value, y, color='k', label='Black hole')
		#plt.plot(x, y / 10, '-', color='k', label='Black hole 1')
		plt.text(r_grav.value * 0.8, r_grav.value / 3, 
			'Black Hole\n\n$\log M=%.1f$' % (log_bhm(MBH)) if MBH > 10**7.5 * u.Msun else 'BH\n\n$\log M=%.1f$' % (log_bhm(MBH)), 
			va='top', ha='right', color='white', fontweight='bold', size=textsize)

	# Corona:
	y, x = pol2cart(6*r_grav, theta)
	if show_corona:
		plt.plot(x, y, ls=':', color=colors[1], label='X-ray Corona')
		plt.text(xlo.value*1.2, 6*r_grav.value, 'Corona',
			va='bottom', ha='left', color=colors[1])

	# BLR:
	z1, z2, zmax            = compute_blr_shape(MBH, M_dot, L_AGN, R, Z, variant='static')
	z1, z2, zmax_dyn        = compute_blr_shape(MBH, M_dot, L_AGN, R, Z, variant='dynamic', dyn_factor=2)
	CF = get_blr_covering_factor(z1, z2, R)
	Rpeak, Hpeak = get_peak(z2, z1, R)
	z1, z2, zmax_dyn_nodust = compute_blr_shape(MBH, M_dot, L_AGN, R, Z, variant='dustfree', dyn_factor=2)

	idx, = numpy.where(numpy.logical_or(zmax_dyn_nodust > z_disk, zmax_dyn > z_disk))
	if idx.any():
		lo, hi = idx.min() - 1, idx.max() + 1
		zmax_dyn_disk = numpy.where(zmax_dyn > z_disk, zmax_dyn, z_disk)
		zmax_dyn_nodust_disk = numpy.where(zmax_dyn_nodust > z_disk, zmax_dyn_nodust, z_disk)
	else:
		lo, hi = 0, -1
		zmax_dyn_disk = zmax_dyn
		zmax_dyn_nodust_disk = zmax_dyn_nodust
	
	if show_BLR:
		color = colors[0]
		l, = plt.plot(R[lo:hi], zmax_dyn_nodust_disk[lo:hi], '--',
			label="Broad Line Region (BLCH, CF=%.0f%%)" % (CF*100),
			color=color,
		)
		
		plt.plot(R[lo:hi], zmax_dyn_disk[lo:hi], '-', color=color, label='Dusty BLR')
		plt.fill_between(R[lo:hi], z_disk[lo:hi], zmax_dyn_disk[lo:hi], color=color)
		#plt.plot(Rpeak, Hpeak, 'o', color=color)
		plt.text(Rpeak.value, Hpeak.value, 'BLCH BLR\nCF=%.2f' % (CF),
			va='bottom', ha='center', color=color)
		#plt.fill_between(R.flatten(), 0, zmax_dyn, color=color, hatch='//')
		#plt.vlines(R_in.to(u.pc).value, 0, Hpeak.to(u.pc).value, linestyles=[':'], colors=[color])

	# Radiative fountain
	r_d = compute_dust_sublimation_radius(L_AGN)
	r_0 = compute_heating_radius(L_AGN, rho_g = 300 * u.Msun / u.pc**3)
	r_max = compute_rmax(MBH, L_AGN, theta, r_0, r_d, 
		dust_to_gas_ratio = dust_to_gas_ratio,
		kappa = kappa).to(u.pc)
	theta_crit = compute_critical_angle(MBH, L_AGN, r_0, r_d, 
		dust_to_gas_ratio, kappa = kappa)
	CF = cos(theta_crit)
	
	color = colors[3]
	r_max[r_max > 1000 * u.pc] = numpy.nan
	z_min = numpy.interp(r_d.value, R.value, z_disk.value)
	theta_min = arctan2(z_min, r_d.value)
	y, x = pol2cart(r_max, theta)
	
	if show_TOR:
		#plt.plot(x, y, ls='-.', color=color, label="Radiative Fountain TOR")
		
		## structure:
		rng = numpy.random.RandomState(1)
		Nrad = 100
		# 100 pixels in radial direction
		rho = 10**rng.normal(size=(Nrad, Nrad))
		rho[rho > 1000] = 1000
		from scipy.signal import sepfir2d, convolve2d
		# we need 5 degree smoothing in theta according to Wada+ sims
		# but this could be partly due to resolution issues, 
		# so I take twice that here
		correlation_degrees = 5 / 2
		# same scale in radial direction as in vertical direction
		sigma_rad_pixels = len(rho) * sin(correlation_degrees * pi / 180)
		H_r = numpy.exp(-0.5 * numpy.linspace(-5, 5, int(sigma_rad_pixels)*10)**2)
		H_r /= H_r.sum()
		H_c = H_r
		kernel = H_r.reshape((-1, 1)) * H_c.reshape((1, -1))
		kernel /= kernel.sum()
		
		rad = numpy.linspace(0, r_infl.to(u.pc).value, Nrad)
		X, Y = numpy.meshgrid(rad, rad)
		R, THETA = cart2pol(X, Y)
		low_density = 0
		# use high values close to disk
		rho[THETA <= theta_min] = 10
		# now erase disallowed regions:
		# empty jet
		X_jet = compute_jet_edge(MBH, Y * u.pc).to(u.pc).value
		rho[X < X_jet] = low_density
		RMAX = numpy.interp(pi/2 - THETA, xp=theta, fp=r_max.value)
		RMAX[~numpy.isfinite(RMAX)] = numpy.inf
		# only fill below r_max
		rho[R <= RMAX] = low_density
		# only fill within SOI
		rho[R > r_infl.to(u.pc).value] = low_density
		
		# do convolution
		convolved = sepfir2d(rho, H_r, H_c)
		#convolved = convolve2d(rho, kernel, mode='same', fillvalue=low_density)
		convolved[R <= RMAX] = low_density
		convolved[R > r_infl.to(u.pc).value] = low_density
		convolved[X < X_jet] = low_density
		#convolved[THETA <= theta_min] = 3
		#plt.contourf(rad, rad, convolved/convolved[convolved>low_density].std(), 
		#	levels=numpy.linspace(-3, 3, 10), cmap='Reds', zorder=-10)
		#convolved[convolved > 3] = 3
		#convolved[convolved < -3] = numpy.nan
		C = plt.contourf(rad, rad, convolved, 
			levels=10, cmap='Reds', zorder=-10)
		C.collections[0].set_facecolor('white')
		## end structure


	mask = theta > 89.7/180*pi
	if show_TOR and mask.any() and numpy.isfinite(x[mask][0].value):
		plt.text(x[mask][0].value, y[mask][0].value, 'RF TOR \nCF=%.2f ' % CF, 
			va='bottom', ha='right', color=color)
	
	# NLR
	R_NLR_hi = get_nlr_size().to(u.pc)
	# these are chosen arbitrarily: the inner edge of the NLR and the maximum angle
	# in practice they are observationally and host galaxy limited, respectively
	R_NLR_lo = r_infl
	R_NLR = numpy.array([R_NLR_lo.value, R_NLR_hi.value]) * u.pc
	thetai = numpy.linspace(pi/400, pi/4, 10)
	for i, (thetalo, thetahi) in enumerate(zip(thetai[:-1], thetai[1:])):
		if not show_NLR: break
		ylo1, ylo2 = R_NLR.value
		xlo1, xlo2 = compute_jet_edge(MBH, R_NLR).value
		(yhi1, yhi2), (xhi1, xhi2) = pol2cart(R_NLR.value, thetahi)
		
		#(ylo1, ylo2), (xlo1, xlo2) = pol2cart(R_NLR_lo.value, numpy.array([thetalo, thetahi]))
		#(yhi1, yhi2), (xhi1, xhi2) = pol2cart(R_NLR_hi.value, numpy.array([thetalo, thetahi]))
		label = 'NLR' if i == 0 else None
		alpha = (1. - (i*1./len(thetai))**0.8)*0.5
		
		plt.fill([xlo1, xhi1, xhi2, xlo2], [ylo1, yhi1, yhi2, ylo2], 
			color=colors[2], 
			alpha=alpha, lw=0,
			label=label)
		plt.text(xlo2, ylo2*0.9, 'NLR',
			color='white', va='top', ha='left', size=textsize)
	
	
	# sight-lines
	theta = numpy.array([1, 5, 15, 30, 60, 85])
	theta[theta == 0] = 5
	theta[theta == 90] = 85
	for thetai in theta:
		if not show_viewing: break
		Rline = numpy.array([5 * r_grav.to(u.pc).value, 4])
		#Rline = numpy.linspace(5 * r_grav.to(u.pc).value, 10, 1000)
		y, x = pol2cart(Rline, thetai / 180 * pi)
		#x = R_fullrange.value
		#y = x * sin(thetai / 180 * pi)
		#mask = y > 1
		#y, x = y[mask], x[mask]
		plt.plot(x, y, ':', color='k', alpha=0.1)
		plt.text(x[-1], y[-1], '$%d^\circ$' % (thetai))
	
	plt.xlabel("R [pc]")
	plt.ylabel("z [pc]")
	plt.xticks()
	#plt.legend(loc="lower right", prop=dict(size=12))
	#plt.ylim(r_grav.value / 100, 200*100)
	#plt.xlim(r_grav.value / 2, 50*100)
	plt.ylim(8e-8 / 100, 200*100)
	plt.xlim(8e-8, 50*100)
	plt.xscale('log')
	plt.yscale('log')