The Role of JAX in ExoJAX: Performance and Scalability for Exoplanet Modeling
JAX provides the computational foundation for ExoJAX, enabling JIT-compiled opacity calculations, automatic differentiation for Bayesian inference, and seamless scaling from CPUs to GPUs and TPUs.
ExoJAX is an open-source exoplanet atmospheric retrieval framework that leverages Google's JAX library to solve the computational challenges of high-resolution spectroscopy. By building its entire numerical pipeline—from molecular opacity calculations to radiative transfer—on JAX's functional programming model, ExoJAX achieves orders-of-magnitude speedups over traditional NumPy implementations while maintaining exact gradients for scalable Bayesian inference.
How JAX Accelerates ExoJAX's Numerical Pipeline
JIT Compilation for Opacity Kernels
ExoJAX wraps its core opacity calculations with jax.jit to compile Python loops into XLA-optimized machine code. In src/exojax/opacity/modit/modit.py, functions like xsmatrix_scanfft, line_strength, and gamma_exomol are JIT-compiled【/cache/repos/github.com/hajimekawahara/exojax/master/src/exojax/opacity/modit/modit.py#L324-L351】. Similarly, src/exojax/opacity/lpf/lpf.py applies JIT to the LPF (Line-by-Line Profile Function) implementation【/cache/repos/github.com/hajimekawahara/exojax/master/src/exojax/opacity/lpf/lpf.py#L32-L40】.
This compilation eliminates Python interpreter overhead, turning operations over millions of spectral lines into sub-millisecond GPU kernels.
Automatic Vectorization with vmap
The library uses jax.vmap to automatically batch calculations over molecular line lists without explicit Python loops. Inside the JIT-wrapped opacity functions, vmap handles the per-line computations for Doppler broadening and line strength, providing SIMD-like parallelism. This functional approach keeps the codebase concise while maximizing throughput on vectorized hardware.
End-to-End Automatic Differentiation
ExoJAX relies on jax.grad and jax.jacrev to compute exact gradients of the radiative transfer forward model. Because every component—from the opacity calculators in modit.py to the transmission solvers in src/exojax/rt/trans.py—is implemented with pure JAX functions, gradients flow seamlessly through billions of operations. This capability eliminates finite-difference approximations and enables efficient Hamiltonian Monte Carlo (HMC) and Stochastic Variational Inference (SVI) for atmospheric retrieval.
Hardware-Agnostic Execution and 64-Bit Precision
The same JAX codebase runs on CPU, GPU, or TPU without modification, with runtime dispatch to the best available accelerator. For high-resolution spectroscopy requiring numerical stability, src/exojax/utils/jaxstatus.py provides check_jax64bit to verify 64-bit floating-point mode is active【/cache/repos/github.com/hajimekawahara/exojax/master/src/exojax/utils/jaxstatus.py#L4-L22】. This ensures delicate opacity integrals maintain precision while still allowing 32-bit mode for rapid prototyping.
Practical JAX Implementation in ExoJAX
Computing a JIT-Accelerated Transmission Spectrum
import jax.numpy as jnp
import jax
from exojax import OpaModit, ArtTransPure, MdbExomol, atmprof, atmphys
# Load a molecular database (e.g. H₂O from ExoMol)
mdb = MdbExomol('.data/ExoMol/H2O/').load() # ← heavy I/O, but thereafter JAX handles math
# Atmospheric structure (10 layers)
Tarr = jnp.linspace(1500., 500., 10) # temperature profile (K)
Parr = jnp.logspace(5, -1, 10) # pressure (bar)
# Opacity calculator (Modit = moderate‑speed, on‑the‑fly)
opa = OpaModit(mdb.nu_lines, mdb.alpha_ref, R=100_000)
# JIT‑compile the forward model once
@jax.jit
def forward_spectrum(Tarr, Parr):
sigma = opa.opacity(Tarr, Parr, molmass=mdb.molmass) # JAX‑compatible opacity
trans = ArtTransPure(sigma, Tarr, Parr).spectrum() # radiative transfer
return trans
# Evaluate
wave, flux = forward_spectrum(Tarr, Parr)
Key JAX points: OpaModit.opacity internally uses jax.jit + vmap (see modit.py), and the whole forward_spectrum is JIT‑compiled, giving sub‑second runtimes even for > 10⁶ lines.
Computing Gradients for Bayesian Retrieval
import jax
def loss(Tarr):
# simple squared‑difference to a mock observation
model = forward_spectrum(Tarr, Parr)
return jnp.mean((model - observed_flux)**2)
# Gradient of the loss w.r.t the temperature profile
grad_T = jax.grad(loss)(Tarr) # shape (nlayer,)
print("∂χ²/∂T =", grad_T)
Because every operation inside forward_spectrum is JAX‑native, jax.grad automatically differentiates through the opacity, line‑strength, and radiative‑transfer modules.
Enabling 64-Bit Precision
from jax import config
config.update("jax_enable_x64", True) # enable 64‑bit
from exojax.utils.jaxstatus import check_jax64bit
check_jax64bit(allow_32bit=False) # will raise if 64‑bit not active
See the helper in src/exojax/utils/jaxstatus.py for the diagnostic message.
Summary
- JIT compilation transforms opacity calculations in
modit.pyandlpf.pyinto XLA-optimized machine code, eliminating Python overhead for millions of spectral lines. vmapvectorization automatically batches per-line computations across the line list, providing SIMD-like performance without explicit loops.- Automatic differentiation via
jax.gradenables exact gradients of the radiative transfer model, supporting scalable Hamiltonian Monte Carlo and variational inference. - Hardware-agnostic execution allows the same code to scale from laptop CPUs to GPU clusters, with runtime dispatch to the best available accelerator.
- 64-bit precision control via
check_jax64bitensures numerical stability for high-resolution opacity calculations while maintaining flexibility for faster 32-bit exploration.
Frequently Asked Questions
Why does ExoJAX use JAX instead of NumPy or PyTorch?
JAX provides JIT compilation and automatic differentiation with a NumPy-compatible API, offering better performance for scientific computing workloads without requiring manual CUDA kernels. Unlike PyTorch, JAX's functional programming model and XLA compilation enable more aggressive optimization of the static computational graphs typical in radiative transfer, while jax.vmap provides cleaner batching over massive line lists than PyTorch's explicit looping mechanisms.
Can ExoJAX run on a CPU-only machine?
Yes, ExoJAX is fully functional on CPUs. JAX automatically dispatches operations to the CPU backend when no GPU is detected, though performance will be slower than GPU-accelerated runs. The codebase includes utilities like check_jax64bit in src/exojax/utils/jaxstatus.py to ensure numerical stability regardless of hardware, and the same Python code runs without modification across all backends.
How does JAX's automatic differentiation improve exoplanet retrieval?
JAX's jax.grad enables exact gradients of the forward model with respect to atmospheric parameters, eliminating the numerical noise and computational cost of finite-difference methods. This allows ExoJAX to use gradient-based samplers like Hamiltonian Monte Carlo (HMC) and Stochastic Variational Inference (SVI), which scale efficiently to high-dimensional parameter spaces common in atmospheric retrieval, such as temperature-pressure profiles and molecular abundance gradients.
What hardware configurations are recommended for large-scale ExoJAX simulations?
For large-scale retrievals or high-resolution spectroscopy (R > 100,000), a CUDA-enabled GPU is recommended to leverage JAX's XLA compilation for massive parallelism. The same code can scale to multi-node clusters using JAX's parallel primitives (pmap, pjit), though single-GPU performance is often sufficient for typical exoplanet atmospheric modeling tasks. For development and small-scale tests, any CPU works, but 64-bit precision should be enabled via jax_enable_x64 for numerical stability.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →