None Note: This tutorial was generated from an IPython notebook that can be downloaded here.
Particle Sampling¶
The TigressWindSampler
class is a child class of the
TigressWindModel
class. For sampling, it won’t build pdf
models, but use the scaling relations and parameters of the model.
import twind
sampler=twind.TigressWindSampler()
Sampling at a single epoch¶
For this example, we use
- \(\Sigma_{\rm SFR} = 10^{-2} M_\odot{\rm kpc^{-2} yr^{-1}}\),
- area = \(1 {\rm kpc}^2\)
- dt = 1 Myr
and
- \(m^{\rm cool} = m^{\rm hot} \in (10^2, 10^3)M_\odot\)
def draw_particle_dist(sfr0,area,dt,masses=[1.e2,1.e3,1.e4]):
Nm=len(masses)
fig, axes = plt.subplots(1,Nm,figsize=(3*Nm,3))
for ax, m in zip(axes,masses):
cool,hot=sampler.draw_mass(sfr0,m,m,area=area,dt=dt)
plt.sca(ax)
plt.plot(cool['vz'],cool['cs'],marker='o',ls='',ms=5,alpha=0.5,mew=0)
plt.plot(hot['vz'],hot['cs'],marker='o',ls='',ms=5,alpha=0.5,mew=0)
plt.xscale('log')
plt.yscale('log')
plt.title(r'$m = 10^{:.0f} M_\odot$'.format(np.log10(m)))
ax.grid('on')
ax.set_aspect('equal')
plt.xlim(1.,5.e3)
plt.ylim(1.,5.e3)
plt.xlabel(r'$u=\log v_{\rm out}$')
plt.ylabel(r'$w=\log c_s$')
plt.tight_layout()
return fig
sfr0 = 1.e-2
area = 1
dt = 1.e6
f = draw_particle_dist(sfr0,area,dt,masses=[1.e2,1.e3])

The mass in the outflow can be obatined by
For a chosen \(\Sigma_{\rm SFR}\), the total, cool, and hot mass loading factors are
etaM=sampler._eta_sfr_scaling(sfr0,'M_total')
etaMc=sampler._eta_sfr_scaling(sfr0,'M_cool')
etaMh=sampler._eta_sfr_scaling(sfr0,'M_hot')
print('eta_M={:.2f} eta_M^cool={:.2f} eta_M^hot={:.2f}'.format(etaM, etaMc, etaMh))
eta_M=7.07 eta_M^cool=6.54 eta_M^hot=0.19
which give the outflowing mass in each phase
print('M_out={:.3g} M_out^cool={:.3g} M_out^hot={:.3g}'.format(etaM*sfr0*area*dt,etaMc*sfr0*area*dt,etaMh*sfr0*area*dt))
M_out=7.07e+04 M_out^cool=6.54e+04 M_out^hot=1.93e+03
Therefore, even for \(m^{\rm hot}=10^3 M_\odot\), we expect to sample a few particles as shown in the right panel of the above figure.
Sampling from a time series¶
For this example, we use a sinusoidal function for SFR surface density time series for 200 Myr with
- mean \(\Sigma_{\rm SFR} = 10^{-3} M_\odot{\rm kpc^{-2} yr^{-1}}\),
- period of 50 Myr
tmax = 2.e8
dt = 1.e6
time = np.arange(0,tmax,dt)
tp = 5.e7
sfr0 = 2.e-3
area = 1
sfr=sfr0*0.5*(np.sin(2*np.pi/tp*time)+2)
For a given time series of \(\Sigma_{\rm SFR}\), we get reference values of outflow rates using the scaling relations of outflow loading factors (of each outflow phase) presented in Kim et al. (2020a).
The TigressWindSampler.get_refs()
method returns four lists
containing time series of reference outflow rates and loading factors
for total, cool, and hot outflows. Each list contains mass
,
momemtum
, energy
, and metal
in order.
refs,eta,etac,etah = sampler.get_refs(sfr)
mout = [eta[0]*refs[0]*area*dt, etac[0]*refs[0]*area*dt, etah[0]*refs[0]*area*dt]
Eout = [eta[2]*refs[2]*area*dt, etac[2]*refs[2]*area*dt, etah[2]*refs[2]*area*dt]
print('mean outflowing mass = {:.3g} (total) {:.3g} (cool) {:.3g} (hot) Msun'.format(mout[0].mean(),mout[1].mean(),mout[2].mean()))
print('mean outflowing energy = {:.3g} (total) {:.3g} (cool) {:.3g} (hot) erg'.format(Eout[0].mean(),Eout[1].mean(),Eout[2].mean()))
mean outflowing mass = 2.73e+04 (total) 2.62e+04 (cool) 429 (hot) Msun
mean outflowing energy = 2.16e+51 (total) 4.3e+50 (cool) 1.82e+51 (hot) erg
For the area of 1 kpc\(^2\) and time interval 1 Myr considered here, we expect the mean mass and energy in outflow are \(2.7\times10^4 M_\odot\) and \(2.2\times10^{51}\) erg, respectively. The mass ratio between cool and hot outflows is about 50, therefore, for a fair sampling, we might need \(m^{\rm cool}/m^{\rm hot}\sim50\) with \(m^{\rm cool}<10^4 M_\odot\).
Frist, as a well sampled example, we use
- \(m^{\rm cool} = 10^3 M_\odot\)
- \(m^{\rm hot} = 10^1 M_\odot\)
def draw_particle_time_series(time, sfr, mc, mh, area, dt):
refs,eta,etac,etah = sampler.get_refs(sfr)
cool,hot=sampler.draw_mass(sfr,mc,mh,area=area,dt=dt)
fig,axes = plt.subplots(4,1,sharex=True,figsize=(5,8))
for p, etas_ in zip([cool,hot],[etac,etah]):
outs=twind.to_time_series(p,time)
for ax, q, qref, eta in zip(axes,outs,refs,etas_):
plt.sca(ax)
l,=plt.plot(time,q)
plt.plot(time,eta*qref*area*dt,color=l.get_color(),ls='--')
plt.yscale('log')
axes[0].set_title(r'$m^{{\rm cool}} = 10^{}, m^{{\rm hot}} = 10^{}$'.format(int(np.log10(mc)),int(np.log10(mh))))
axes[0].set_ylabel(r'Mass $[M_\odot/{\rm yr}]$')
axes[1].set_ylabel(r'Momentum $[(M_\odot {\rm km/s})/{\rm yr}]$')
axes[2].set_ylabel(r'Energy $[{\rm erg/yr}]$')
axes[3].set_ylabel(r'Metal Mass $[M_\odot/{\rm yr}]$')
return fig
Here, a utility function to_time_series()
is used to convert
particle data into time series of rates.
f = draw_particle_time_series(time, sfr, 1.e3, 1.e1, area, dt)

The second example is for well sampled cool phase but poorly sampled hot phase.
- \(m^{\rm cool} = 10^3 M_\odot\)
- \(m^{\rm hot} = 10^3 M_\odot\)
f = draw_particle_time_series(time, sfr, 1.e3, 1.e3, area, dt)
