Source code for pynbody.analysis.ionfrac
"""
ionfrac
=======
calculates ionization fractions - NEEDS DOCUMENTATION
"""
import numpy as np
import os
from ..array import SimArray
from pynbody import config
import logging
logger = logging.getLogger('pynbody.analysis.ionfrac')
from .interpolate import interpolate3d
[docs]def calculate(sim, ion='ovi', mode='old'):
"""
calculate -- documentation placeholder
"""
global config
# ionization fractions calculated for optically thin case with
# CLOUDY v 10.0. J. Xavier Prochaska + Joe Hennawi have many
# helper idl routines for running CLOUDY
iffile = os.path.join(os.path.dirname(__file__), "ionfracs.npz")
if os.path.exists(iffile):
# import data
logger.info("Loading %s" % iffile)
ifs = np.load(iffile)
else:
raise IOError("ionfracs.npz (Ion Fraction table) not found")
# allocate temporary metals that we can play with
# before inlining, the views on the arrays must be standard np.ndarray
# otherwise the normal numpy macros are not generated
x_vals = ifs['redshiftvals'].view(np.ndarray)
y_vals = ifs['tempvals'].view(np.ndarray)
z_vals = ifs['denvals'].view(np.ndarray)
vals = ifs[ion + 'if'].view(np.ndarray)
x = np.zeros(len(sim.gas))
x[:] = sim.properties['z']
y = np.log10(sim.gas['temp']).view(np.ndarray)
z = np.log10(sim.gas['rho'].in_units('m_p cm^-3')).view(np.ndarray)
n = len(sim.gas)
n_x_vals = len(x_vals)
n_y_vals = len(y_vals)
n_z_vals = len(z_vals)
# get values off grid to minmax
x[np.where(x < np.min(x_vals))] = np.min(x_vals)
x[np.where(x > np.max(x_vals))] = np.max(x_vals)
y[np.where(y < np.min(y_vals))] = np.min(y_vals)
y[np.where(y > np.max(y_vals))] = np.max(y_vals)
z[np.where(z < np.min(z_vals))] = np.min(z_vals)
z[np.where(z > np.max(z_vals))] = np.max(z_vals)
# interpolate
logger.info("Interpolation %s values" % ion)
result_array = interpolate3d(x, y, z, x_vals, y_vals, z_vals, vals)
return 10 ** result_array