The RAYTHEIA Algorithm
RAYTHEIA is a standalone, three-dimensional, hybrid MPI/OpenMP reverse ray-tracing tool that computes the angle-averaged effective visual extinction, \(A_{V,\rm eff}\), at every cell of a Cartesian density grid. It runs independently of 3D-PDR as a fast post-processing/pre-processing step on simulation outputs (e.g. SILCC, AREPO) before they are fed into 3D-PDR.
The core ray-tracing engine (linear octree and adaptive DDA traversal) was written by Zhengping Zhu.
Algorithm
For every grid cell, RAYTHEIA casts a set of rays distributed isotropically using the HEALPix pixelization scheme (NESTED ordering), and integrates the local density along each ray to obtain a column density. The number of rays is set by the HEALPix resolution parameter level in params.dat:
To avoid tracing rays cell-by-cell through the full resolution grid, each MPI rank compresses its local sub-domain into a linear (Morton-code) octree:
The local grid is recursively subdivided in blocks of 8 octants (Z-order/Morton curve).
A block is kept as a leaf (not split further) if it is a single cell, if it is effectively vacuum (peak density below a fixed threshold), or if its density is sufficiently uniform (max/min spread below 1%); otherwise it is split into 8 children at the next level.
Each leaf stores a 64-bit Morton code, its octree level, and its (single-precision) average density — this is what makes the
RAYTHEIA = 1mode of 3D-PDR memory-efficient: large uniform or empty regions collapse into a single node instead of one entry per cell.
Rays are then marched through this compressed structure with an adaptive DDA (Digital Differential Analyser): at each step the ray’s current position is mapped to a local cell index, Morton-encoded, and located in the sorted leaf array via binary search; the ray then advances directly to the exit point of the (possibly large) leaf it landed in, rather than one grid cell at a time. Each rank only holds the octree for its own MPI sub-domain, so a ray crossing multiple ranks accumulates partial column densities from each rank’s broadcasted tree.
The column density accumulated along ray \(i\) (in \(\rm cm^{-2}\)) is converted to extinction and the angle-averaged effective extinction is
with \(\gamma = 3.02\) and \(A_{V,\rm fac} = 6.29\times10^{-22}\,{\rm cm^{2}}\) hard-coded in m_calc_columndens.f90.
Note
src/m_Ray_box.f90 implements an earlier, alternative per-ray AMR approach (pointer-based octree, raytheia_amr) by the same author. It is not included in the Makefile’s source list and is not compiled or used — keep this in mind if browsing the source tree.
Compiling RAYTHEIA
Edit the top of the Makefile:
CMP = intel
OPENMP = 1
HAMMER = 1
CMP: compiler suite.
intel— usesmpiifx(Intel MPI Fortran compiler).gcc— usesmpif90(GNU MPI Fortran wrapper).
OPENMP:
1enables hybrid MPI+OpenMP parallelism over rays/cells (recommended);0disables it.HAMMER: selects the run mode at compile time.
1— builds the single-cell diagnostic mode (see Running RAYTHEIA below).0— builds the production mode that computes \(A_{V,\rm eff}\) for the whole grid.
Then build with:
make clean; make
Important
The produced executable is named cd (set by exeName in the Makefile). Run it as ./cd — note that this name shadows the cd shell builtin if you ever try to source the Makefile directly.
The params.dat File
params.dat must be present in the run directory and follows a fixed line order, split into two blocks:
===========================|
Grid parameters |
===========================|
125.0 !xlx - domain size in x (pc)
125.0 !yly - domain size in y (pc)
125.0 !zlz - domain size in z (pc)
128 !nxc - global grid cells in x
128 !nyc - global grid cells in y
128 !nzc - global grid cells in z
1 !npx - MPI processes in x
1 !npy - MPI processes in y
1 !npz - MPI processes in z
0 !level - HEALPix refinement level
===========================|
Input/Output - Densities |
===========================|
ics !indir - ICs directory
silcc_128.dat !input - ICs file (inside indir)
sims !outdir - output directory
Entries 1-3 (
xlx,yly,zlz): physical domain size in parsecs.Entries 4-6 (
nxc,nyc,nzc): number of grid cells along each axis. The cell size isdx = xlx/nxc(and similarly fordy,dz).Entries 7-9 (
npx,npy,npz): MPI Cartesian decomposition — number of processes along each axis.Entry 10 (
level): HEALPix refinement level; sets \(N_{\rm rays} = 12 \times 2^{2\,\rm level}\).Entries 11-13: ICs directory, ICs filename (read as
indir/input), and output directory.
Note
The density input file (e.g. ics/silcc_128.dat) is read in full by every MPI rank, which then keeps only the cells belonging to its own sub-domain. Each line is expected to contain x y z density for one cell, with the same fastest-varying axis convention (z fastest) as 3D-PDR’s XYZ = 0 density format — see ics.
Parallel Decomposition Constraints
readparams enforces, and stops the run if violated:
The number of MPI ranks launched must equal
npx*npy*npz.nxc,nyc,nzcmust each be exactly divisible bynpx,npy,npzrespectively.The resulting local grid dimensions (
nxnp = nxc/npx, and similarly for y, z) must each be a power of two — required by the linear-octree builder, which recursively bisects each local sub-domain down to single cells.
Running RAYTHEIA
mpirun -np <npx*npy*npz> ./cd
Two run modes are selected at compile time via HAMMER in the Makefile:
Production mode (
HAMMER = 0): computes \(A_{V,\rm eff}\) for every cell of the grid (subroutinecalc_columndens) and writesAveff.dat(see Outputs below). Can be run with any valid MPI decomposition.HAMMER diagnostic mode (
HAMMER = 1): traces all \(N_{\rm rays}\) from a single cell at the centre of the full domain (nxc/2,nyc/2,nzc/2) out to the domain boundary, and writes the raw per-ray column densities tocdMaps.dat. This mode requires exactly one MPI rank (nproc = 1); running it with more ranks aborts with"Error: hammermap only for OpenMP".
Outputs
Aveff.dat(production mode): plain ASCII file written by rank 0 in the current working directory (note: unlikecdMaps.dat, this filename is hard-coded and does not use theoutdirentry ofparams.dat). One line per cell, loopingi(x), thenj(y), thenk(z) fastest, with two columns:rho(i,j,k) Aveff(i,j,k)
cdMaps.dat(HAMMER mode): written tooutdir/cdMaps.dat. One line per HEALPix ray, in ray order (ipix = 0 .. nrays-1), with three columns:theta phi single_cd(ipix)
where
theta,phiare the ray direction angles frompix2ang_nest, andsingle_cdis the raw (un-converted-to-extinction) column density accumulated along that ray.
Implementation Notes
healpix_types.f90,bit_manipulation.f90, and most ofm_Healpix.f90are standard HEALPix Fortran library routines (Gorski, Hivon, Wandelt et al.), carried in the source tree for self-containment. Of these, RAYTHEIA itself only callspix2ang_nestto generate the ray directions; the remaining routines are unused library boilerplate.Leaf densities in the linear octree (
LinearDensity) are stored in single precision to reduce memory footprint, consistent with the goal of the memory-optimized (RAYTHEIA = 1) mode in 3D-PDR.