Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

21 cm part updated #128

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 84 additions & 4 deletions trident/absorption_spectrum/absorption_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
from yt.utilities.physical_constants import \
charge_proton_cgs, \
mass_electron_cgs, \
speed_of_light_cgs
speed_of_light_cgs, \
planck_constant_cgs, \
boltzmann_constant_cgs
from yt.utilities.on_demand_imports import _scipy, NotAModule
from yt.units.yt_array import YTArray, YTQuantity

special = _scipy.special
signal = _scipy.signal
tau_factor = None
_cs = None

Expand Down Expand Up @@ -143,7 +147,6 @@ def voigt_old(a, u):
k1 = k1.astype(np.float64).clip(0)
return k1


def tau_profile(lambda_0, f_value, gamma, v_doppler, column_density,
delta_v=None, delta_lambda=None,
lambda_bins=None, n_lambda=12000, dlambda=0.01):
Expand All @@ -159,7 +162,7 @@ def tau_profile(lambda_0, f_value, gamma, v_doppler, column_density,
f_value : float
absorption line f-value.
gamma : float
absorption line gamma value.
Anikbh11 marked this conversation as resolved.
Show resolved Hide resolved
absorption line gamma value
v_doppler : float in cm/s
doppler b-parameter.
column_density : float in cm^-2
Expand Down Expand Up @@ -213,7 +216,7 @@ def tau_profile(lambda_0, f_value, gamma, v_doppler, column_density,
# tau_0
tau_X = tau_factor * column_density * f_value / v_doppler
tau0 = tau_X * lambda_0 * 1e-8

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think whitespace changes like these will fail the flake tests. In general, try to leave whitespace alone.

# dimensionless frequency offset in units of doppler freq
x = _cs / v_doppler * (lam1 / lambda_bins - 1.0)
a = gamma / (4.0 * np.pi * nudop) # damping parameter
Expand All @@ -222,6 +225,83 @@ def tau_profile(lambda_0, f_value, gamma, v_doppler, column_density,

return (lambda_bins, tauphi)

def tau_profile_21cm(lambda_0, f_value, gamma, temperature, number_density,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need both a tau_profile_21cm function and a variable deposition method in the regular tau_profile function. I would say choose one or the other, perhaps whichever option has the least amount of duplicate code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I would say we could just do with tau_profile and have a keyword which triggers the 21 cm deposition to be different, and in turn, this would get triggered by using a line like: H I 21cm or something?

h_now, delta_v=None, delta_lambda=None,
lambda_bins=None, n_lambda=12000, dlambda=0.01):
r"""
Create an optical depth vs. wavelength profile for the
21 cm forest. The optical depth is calculated using eq. 1 in https://arxiv.org/abs/1510.02296. At this point in the implementation, we make a very reasonable assumption that (1+ 1/H(z) dv/dr) ~ 1.
Anikbh11 marked this conversation as resolved.
Show resolved Hide resolved

Parameters
----------

lambda_0 : float in angstroms
central wavelength.
f_value : float
absorption line f-value.
gamma : float
absorption line gamma value. For this case, represents the einstein coefficient A_10
temperature : Gas temperature in K
Anikbh11 marked this conversation as resolved.
Show resolved Hide resolved
Gas temperature. Assumption that T_K = T_S is made here.
number_density : float in cm^-2
neutral hydrogen number density.
h_now ; hubble constant at redshift z
H(z)
delta_v : float in cm/s
velocity offset from lambda_0.
Default: None (no shift).
delta_lambda : float in angstroms
wavelength offset.
Default: None (no shift).
lambda_bins : array in angstroms
wavelength array for line deposition. If None, one will be
created using n_lambda and dlambda.
Default: None.
n_lambda : int
size of lambda bins to create if lambda_bins is None.
Default: 12000.
dlambda : float in angstroms
lambda bin width in angstroms if lambda_bins is None.
Default: 0.01.

"""
global tau_factor
if tau_factor is None:
lam0 = YTQuantity(lambda_0,'angstrom')
gam = YTQuantity(gamma,'1/s')
tau_factor = ((3 / 32 / np.pi) * planck_constant_cgs * gam *
speed_of_light_cgs * lam0**2 / boltzmann_constant_cgs
).in_cgs().d

global _cs
if _cs is None:
_cs = speed_of_light_cgs.d[()]

# shift lambda_0 by delta_v
if delta_v is not None:
lam1 = lambda_0 * (1 + delta_v / _cs)
elif delta_lambda is not None:
lam1 = lambda_0 + delta_lambda
else:
lam1 = lambda_0

# create wavelength
if lambda_bins is None:
lambda_bins = lam1 + \
np.arange(n_lambda, dtype=np.float) * dlambda - \
n_lambda * dlambda / 2 # wavelength vector (angstroms)

# tau_0
tau0 = (tau_factor * number_density) / (temperature * h_now)
idx = np.digitize(lam1,lambda_bins,right=True)
if idx == len(lambda_bins):
phi = np.zeros_like(lambda_bins)
else:
phi = signal.unit_impulse(lambda_bins.size,idx)
tauphi = tau0 * phi # profile scaled with tau0

return (lambda_bins, tauphi)


if isinstance(special, NotAModule):
voigt = voigt_old
Expand Down
53 changes: 39 additions & 14 deletions trident/absorption_spectrum/absorption_spectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@

from trident.absorption_spectrum.absorption_line import \
tau_profile
from trident.absorption_spectrum.absorption_line import \
tau_profile_21cm
from yt.utilities.cosmology import Cosmology

pyfits = _astropy.pyfits

Expand Down Expand Up @@ -468,6 +471,10 @@ def make_spectrum(self, input_object, output_file=None,
input_ds.domain_left_edge = input_ds.domain_left_edge.to('code_length')
input_ds.domain_right_edge = input_ds.domain_right_edge.to('code_length')

self.h0 = getattr(input_ds,'hubble_constant')
Anikbh11 marked this conversation as resolved.
Show resolved Hide resolved
self.omega_matter = getattr(input_ds,'omega_matter')
self.omega_lambda = getattr(input_ds,'omega_lambda')

if self.bin_space == 'velocity':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we won't be able to do in velocity space? Seems like leaving this in would allow for it, but maybe not?

self.zero_redshift = getattr(input_ds, 'current_redshift', 0)

Expand Down Expand Up @@ -707,6 +714,7 @@ def _add_lines_to_spectrum(self, field_data, use_peculiar_velocity,
for store, line in parallel_objects(self.line_list, njobs=njobs,
storage=self.line_observables_dict):
column_density = field_data[line['field_name']] * field_data['dl']
number_density = field_data[line['field_name']]
if (column_density < 0).any():
mylog.warning(
"Setting negative densities for field %s to 0! Bad!" % line['field_name'])
Expand Down Expand Up @@ -738,19 +746,26 @@ def _add_lines_to_spectrum(self, field_data, use_peculiar_velocity,

# the total number of absorbers per transition
n_absorbers = len(lambda_obs)
temperature = field_data['temperature'].d
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary to strip off the Kelvin unit?


# thermal broadening b parameter
thermal_b = np.sqrt((2 * boltzmann_constant_cgs *
field_data['temperature']) /
line['atomic_mass'])

# the actual thermal width of the lines
if line['wavelength'].d == 2.1e9:
Anikbh11 marked this conversation as resolved.
Show resolved Hide resolved
thermal_b = YTArray(np.ones(redshift.size),'km/s')
else:
thermal_b = np.sqrt((2 * boltzmann_constant_cgs *
field_data['temperature']) /
line['atomic_mass'])
# the actual thermal width of the lines
thermal_width = (lambda_obs * thermal_b /
c_kms).to('angstrom')


co = Cosmology(self.h0,self.omega_matter,self.omega_lambda,0.0)
h_now = co.hubble_parameter(np.max(redshift)).d #H(z)
# Sanitize units for faster runtime of the tau_profile machinery.
lambda_0 = line['wavelength'].d # line's rest frame; angstroms
cdens = column_density.in_units("cm**-2").d # cm**-2
ndens = number_density.in_units("cm**-3").d # cm**-2
thermb = thermal_b.to('cm/s').d # thermal b coefficient; cm / s
dlambda = delta_lambda.d # lambda offset; angstroms
# Array to store sum of the tau values for each index in the
Expand Down Expand Up @@ -786,10 +801,9 @@ def _add_lines_to_spectrum(self, field_data, use_peculiar_velocity,
raise RuntimeError('What bin space is this?')

resolution = my_width / self.bin_width
n_vbins_per_bin = (10 ** (np.ceil( np.log10( subgrid_resolution /
resolution) ).clip(0, np.inf) ) ).astype('int')
n_vbins_per_bin = (10 ** (np.ceil( np.log10(subgrid_resolution/
resolution)).clip(0, np.inf))).astype('int')
vbin_width = self.bin_width.d / n_vbins_per_bin

# a note to the user about which lines components are unresolved
if (my_width < self.bin_width).any():
mylog.info("%d out of %d line components will be " +
Expand Down Expand Up @@ -872,6 +886,7 @@ def _add_lines_to_spectrum(self, field_data, use_peculiar_velocity,
my_vbins = vbins * \
wavelength_zero_point.d / c_kms.d + \
wavelength_zero_point.d

else:
raise RuntimeError('What bin_space is this?')

Expand All @@ -882,11 +897,18 @@ def _add_lines_to_spectrum(self, field_data, use_peculiar_velocity,
'increasing the bin size.') % my_vbins.size)

# the virtual bins and their corresponding opacities
my_vbins, vtau = \
tau_profile(
lambda_0, line['f_value'], line['gamma'],
thermb[i], cdens[i],
delta_lambda=dlambda[i], lambda_bins=my_vbins)
if (line['wavelength'].d == 2.1e9):
Anikbh11 marked this conversation as resolved.
Show resolved Hide resolved
my_vbins, vtau = \
tau_profile_21cm(
lambda_0, line['f_value'], line['gamma'],
temperature[i], ndens[i], h_now,
delta_lambda=dlambda[i], lambda_bins=my_vbins)
else:
my_vbins, vtau = \
tau_profile(
lambda_0, line['f_value'], line['gamma'],
thermb[i], cdens[i],
delta_lambda=dlambda[i], lambda_bins=my_vbins)

# If tau has not dropped below min tau threshold by the
# edges (ie the wings), then widen the wavelength
Expand Down Expand Up @@ -925,7 +947,10 @@ def _add_lines_to_spectrum(self, field_data, use_peculiar_velocity,
# normal use of the word by observers. It is an equivalent
# with in tau, not in flux, and is only used internally in
# this subgrid deposition as EW_tau.
vEW_tau = vtau * vbin_width[i]
if lambda_0 == 2.1e9:
vEW_tau = vtau
Anikbh11 marked this conversation as resolved.
Show resolved Hide resolved
else:
vEW_tau = vtau * vbin_width[i]
EW_tau = np.zeros(right_index - left_index)
EW_tau_indices = np.arange(left_index, right_index)
for k, val in enumerate(EW_tau_indices):
Expand Down