A Julia-based radiative transfer code for curved spacetimes with automatic differentiation capabilities. More details available on the paper published in ApJ.
Jipole is an ipole-based Julia implementation designed to perform radiative transfer calculations in curved spacetimes, with a particular focus on black hole imaging. The code leverages Julia's automatic differentiation (autodiff) to compute derivatives of input parameters, enabling gradient based optimization methods. For this project, we used ForwardDiff.jl (Revels et al. 2016).
The current version of Jipole is capable of producing images for Iharm3D file types. We also have implemented the test problems described in Section 3.2 of Gold et al. 2020 and thin disk model as described in the Prather et al. 2023.
The code is currently able to perform slow-light runs and has been compared with the well estabished code Blacklight (C. White. 2022) and ipole (Moscibrodzka & Gammie 2017).
If this is your first time using Jipole, you'll need to set up the Julia environment and install the required dependencies:
-
Navigate to the project directory:
cd /path/to/jipole -
Start Julia with multithreading capabilities:
julia --project="." -
Install Packages
using Pkg Pkg.instantiate()
This command will install all the packages specified in the Project.toml and Manifest.toml files.
To use Jipole with Jupyter notebooks, install the project-specific kernel:
using IJulia
IJulia.installkernel("Jipole", "--project=" * Base.current_project())This creates a dedicated Jupyter kernel that automatically loads the Jipole project environment.
Jipole is a regular Julia package (src/Jipole.jl). Every file under src/ is its own
capitalized submodule, reachable as Jipole.<ModuleName>, e.g. Jipole.Camera.camera_position,
Jipole.Geodesics.get_pixel, Jipole.Radiation.integrate_emission!.
Three interchangeable emission models are provided as submodules — Jipole.Analytic,
Jipole.ThinDisk, and Jipole.Iharm — each defining its own parameters type
(AnalyticParams, ThinDiskParams, IharmParams). Which model runs is decided by which
parameters object you construct and pass around, via Julia's multiple dispatch — there is no
global model switch to edit.
using Jipole
# Analytic torus (Gold et al. 2020)
model = Jipole.Analytic.AnalyticParams(bhspin, Rout, cstartx, cstopx, MBH)
# Thin disk
model = Jipole.ThinDisk.ThinDiskParams(bhspin, Rout, cstartx, cstopx, MBH, Mdot)
# GRMHD simulation dump
model = Jipole.Iharm.read_header(dump_filepath, MBH)From there, the same calls (Jipole.Camera.camera_position(...), Jipole.Geodesics.get_pixel(...),
Jipole.Radiation.integrate_emission!(...)) work regardless of which model you constructed —
see example_notebooks/GenerateImages.ipynb for the analytic/thin-disk models side by side, and
example_notebooks/GenerateImageGRMHD.ipynb for the GRMHD model.
-
Navigate to the project directory:
cd /path/to/jipole -
Start Julia with multithreading capabilities:
JULIA_NUM_THREADS=xx julia --project="."Replace
xxwith the number of CPU cores you want to utilize. -
Launch JupyterLab:
using IJulia IJulia.jupyterlab(dir=pwd())
- Open your web browser and navigate to the JupyterLab interface (typically
http://localhost:8888) - When creating or opening a notebook, ensure you select the Jipole kernel for this project from the kernel menu
(install one with
using IJulia; IJulia.installkernel("Jipole", "--project=" * abspath("."))if you don't have one yet) - Every notebook simply starts with
using Jipole.
-
ComputeGeodesics.ipynb
Computes geodesics for each pixel and allows for debugging and visualization of the trajectories. Useful for inspecting geodesics before integrating intensity. -
GenerateImage.ipynb
Computes the final intensity map for thin-disk or analytical models, performing forward integration of emission along geodesics. -
GenerateImageGRMHD.ipynb
Computes the final intensity map for a GRMHD Iharm3D snapshot, performing forward integration of emission along geodesics. -
Autodiff.ipynb
Performs differentiable ray tracing to compute derivatives of the image intensity with respect to parameters like black hole spin (a) and observer inclination (θ). Uses the conjugate gradient algorithm to recover ground truth parameters from a computed intensity map, demonstrating gradient-based parameter estimation.
- Gold, R. et al. 2020, ApJ, 897, 148: Verification of Radiative Transfer Schemes for the EHT
- Moscibrodzka, M. & Gammie, C. F. 2017, arXiv:1712.03057: ipole – semi-analytic scheme for relativistic polarized radiative transport
- Revels, J., Lubin, M., and Papamarkou, T. 2016, arXiv:1607.07892: Forward-Mode Automatic Differentiation in Julia
- Naethe Motta, P. et al. 2025, ApJ, 995, 56: Jipole: A Differentiable ipole-based Code for Radiative Transfer in Curved Spacetimes
- Naethe Motta, P. et al. 2026, ApJ, 1004, 2: Sensitivities of Black Hole Images from General Relativistic Magnetohydrodynamic Simulations
Pedro Naethe Motta at pedronaethemotta [at] usp [dot] br