JAXcosmo and automatic differentiation#
The optional jaxcosmo backend supplies differentiable cosmological theory from
jax-cosmo.
Use options["code"] = "jaxcosmo" to select it, and pass a derivative provider to
FisherMatrix to choose automatic differentiation (AD) or finite differences (FD)
of the JAX-native observables.
Installation#
From a source checkout containing the JAXcosmo implementation:
uv sync --extra jaxcosmo
# Alternatively:
pip install -e '.[jaxcosmo]'
The extra installs JAX, jaxlib, jax-cosmo and its compatibility dependencies.
The shipped backend profile enables JAX float64 (NUMERICS.x64: True), which is
important for small finite-difference steps and Fisher inversions. Initial JIT
compilation contributes to the first evaluation’s runtime; subsequent evaluations
with the same shapes reuse compiled functions.
A photometric forecast#
This example keeps both the neutrino mass and the spectral index fixed. Parameters
omitted from freepars retain their fiducial values; the usual survey nuisance
parameters are added by CosmicJellyfish.
from cosmicjellyfish.fishermatrix.cosmicfish import FisherMatrix
from cosmicjellyfish.fishermatrix.jaxcosmo_derivatives import JaxAutodiffProvider
fiducial = {
"10^9As": 2.1,
"Omegam": 0.32,
"Omegab": 0.05,
"h": 0.67,
"ns": 0.96,
"mnu": 0.0,
}
free = {name: 0.01 for name in ("10^9As", "Omegam", "Omegab", "h")}
options = {
"code": "jaxcosmo",
"accuracy": 1,
"nonlinear": True,
"derivatives": "3PT",
"survey_name_photo": "Euclid-Photometric-ISTF-Pessimistic",
"results_dir": "results/jaxcosmo/",
"outroot": "photo_ad",
}
forecast = FisherMatrix(
fiducialpars=fiducial,
freepars=free,
options=options,
observables=["GCph", "WL"],
cosmoModel="LCDM",
surveyName="Euclid",
derivative_provider=JaxAutodiffProvider(),
)
fisher = forecast.compute()
JaxAutodiffProvider uses jax.jacfwd to differentiate the implemented observable;
the values in freepars select the parameters but do not set an AD step size.
For finite differences they are relative steps (absolute steps when the fiducial
value is zero), as described in Derivative methods.
Three routes with the same theory#
Route |
|
Observable used for derivatives |
|---|---|---|
JAX AD |
|
JAX-native CosmicJellyfish observable |
JAX FD |
|
The same JAX-native observable |
Standard FD |
Omitted, or |
Existing NumPy/SciPy observable |
Import both providers from
cosmicjellyfish.fishermatrix.jaxcosmo_derivatives. All three routes can use
options["code"] = "jaxcosmo".
AD versus JAX FD isolates the derivative method. Decrease the FD step to check
convergence. JAX FD versus standard FD checks the observable port, including its
interpolation, integration and boundary choices. The JAX observables reproduce
CosmicJellyfish’s photometric Limber and spectroscopic galaxy-power calculations;
they do not call jax_cosmo.angular_cl. The existing covariance and Fisher
assembly are retained; selecting AD does not add covariance-derivative terms.
The normal backend adapter returns NumPy/SciPy tables for the existing pipeline. Those tables do not preserve JAX gradients, which is why choosing the backend alone does not enable autodiff. Use a fresh options dictionary for each forecast: configuration initialisation fills defaults into it.
Comparison notebook#
Download 07-JAXcosmo-autodiff-vs-finite-differences.ipynb and run it from
the repository checkout (or open it directly in notebooks/). Select that
checkout’s Python environment, for example .venv/bin/python, as the Jupyter
kernel. Install jupyterlab and ipykernel into that environment if needed.
The notebook compares the three JAXcosmo routes above with the standard CosmicJellyfish SYREN-NEW forecast. It includes:
linear and nonlinear matter power, and the response to the spectral index;
angular spectra from the JAX and standard observable implementations;
FD step-size convergence, marginalized errors and a triangle overlay;
an optional CLASS reference, disabled by default.
The fiducial model is flat LCDM with massless neutrinos. The Fisher runs keep
ns = 0.96 fixed, varying 10^9As, Omegam, Omegab and h, along with the
default photometric nuisance parameters. This avoids using the known SYREN-NEW
nonlinear spectral-index response discrepancy in the forecast comparison; see
SYREN-NEW spectral-tilt response and photometric Fisher discrepancies. The diagnostic response plot still varies ns to show
the theory response, independently of the Fisher parameter list. Fixing ns
does not make the two backends’ predictions identical.
The notebook writes figures and its summary into
results/jaxcosmo_ad_vs_fd/. These are local outputs. Re-run all cells after
changing the free parameters so the displayed tables and figures share the same
configuration.
Why SYREN is a separate theory comparison#
JAXcosmo uses an Eisenstein–Hu transfer function (with baryon wiggles by default) and Halofit nonlinear power. SYREN-NEW uses an Eisenstein–Hu-based linear fit with its own corrections and growth model, and a separate nonlinear emulator. A shared Eisenstein–Hu ingredient does not make their power spectra or derivatives equal. Compare AD against FD with the same JAX observable to assess differentiation; compare SYREN against the standard JAXcosmo route to assess theory dependence.
Where the SYREN amplitude difference comes from#
With ns and mnu fixed, the marginalized 10^9As error differs by about
10% between SYREN-NEW and JAXcosmo. The autodiff and finite-difference routes
through the same JAX observable agree to 1.8e-5 in max|dF|/max|F| (the largest Fisher
change divided by the largest Fisher entry), so the difference is not a differentiation
problem. The following decomposition
locates it.
|
SYREN-NEW |
JAXcosmo AD |
AD/SYREN |
|---|---|---|---|
unmarginalized ( |
0.00191324 |
0.00186387 |
-2.6% |
cosmology only |
0.0223482 |
0.0237162 |
+6.1% |
cosmology + 10 galaxy biases |
0.0294102 |
0.0263472 |
-10.4% |
cosmology + biases + IA (all) |
0.0294396 |
0.0264081 |
-10.3% |
The two models agree closely on the unmarginalized amplitude error and on
dlnP_nl/dlnAs (ratio 0.98-1.00 over k = 10^-3 to 1 h/Mpc). The gap appears
only once the galaxy-bias parameters are marginalized: SYREN’s amplitude error
grows by a factor 1.32, JAXcosmo’s by 1.11. The amplitude-bias correlations
differ in shape, for example r(10^9As, b8) = -0.37 for SYREN and -0.28 for
JAXcosmo, while the amplitude response of the spectra themselves is nearly
identical.
The decisive test replaces the matter power spectrum inside the JAX observable with SYREN-NEW’s, keeping the JAX kernels, integration, covariance and Fisher assembly. That hybrid reproduces the SYREN result:
route |
marginalized |
ratio to SYREN |
|---|---|---|
SYREN-NEW, standard pipeline |
0.0294396 |
1.00000 |
JAXcosmo, autodiff |
0.0264081 |
0.89703 |
SYREN-NEW power inside the JAX observable |
0.0294160 |
0.99920 |
The hybrid’s fiducial angular spectra match the standard SYREN ones to
max|dC|/max|C| = 8.3e-4. The same comparison at a second fiducial gives
-10.3% and -11.3%, so the effect is stable rather than a single-point
accident. The difference is therefore a genuine matter-power-model difference,
not the observable implementation, the covariance, the Fisher assembly or the
autodiff. It cannot be removed without changing the theory.
Both models are “Eisenstein-Hu”, so why do they differ?#
A common objection is that both backends are Eisenstein-Hu based, so the spectra should agree. They are not the same formula:
jax_cosmoevaluates the Eisenstein-Hu 1998 fit including baryon wiggles (eisenhu_osc) and normalises it tosigma8.SYREN-NEW starts from the Eisenstein-Hu no-wiggle fit (
get_eisensteinhu_nw) and multiplies it byexp(logF), an emulated correction of the true linear spectrum relative to the Eisenstein-Hu fit (Bartlett et al. 2023), a growth correctionRand a furtherS(k)correction with its own coefficients. In other words SYREN-NEW’s “linear” model is calibrated to reproduce a full Boltzmann spectrum with Eisenstein-Hu only as a backbone.
At equal As the two linear spectra differ by a few percent with a
k-dependent sign, while the growth factors agree to 4e-4:
band [ |
|
|---|---|
0.001-0.005 |
1.0032 |
0.005-0.02 |
1.0164 |
0.02-0.05 |
1.0093 |
0.05-0.1 |
0.9872 |
0.1-0.2 |
0.9914 |
0.2-0.5 |
1.0093 |
0.5-1 |
1.0161 |
Those percent-level shape changes sit exactly where the galaxy-bias
marginalization operates. Feeding Halofit with SYREN-NEW’s linear shape, while
keeping the JAX observable and the Halofit nonlinear prescription, gives a
marginalized 10^9As error of 0.0301323, i.e. +2.4% with respect to SYREN
(0.0294396) and +14% with respect to plain Eisenstein-Hu plus Halofit
(0.0264081). The linear input therefore carries essentially all of the
difference: the two nonlinear prescriptions (Halofit emulator versus the
SYREN-NEW emulator) contribute at the percent level in the opposite direction.
This is why the gap cannot be removed by changing the derivative method,
the grids or the marginalization; only a common power-spectrum model can.
Reproduce the decomposition with:
uv run --extra jaxcosmo python scripts/validation/compare_theory_amplitude_response.py \
--outdir results/theory_amplitude_response
The script prints the theory response table, the nuisance-marginalization
decomposition, the hybrid test, the linear-shape comparison, the
Halofit-on-SYREN-linear bridge, both fiducials and the AD-versus-FD control, and
writes summary.json. The response-optimised SYREN coefficient sets from the
ns-response study are not a fix here: they increase this amplitude error.
Theory and supported configurations#
Component |
Current implementation |
|---|---|
Cosmology |
Flat |
Matter tracer |
Total matter; clustering/CB tracers are unsupported |
Background and growth |
|
Linear power |
Eisenstein–Hu, with or without baryon wiggles |
Nonlinear power |
Halofit, |
Amplitude |
JAX port of the |
JAX observables |
Photometric |
Outside this implementation |
CMB, intensity-mapping autodiff, massive neutrinos and curvature |
The amplitude fit is re-evaluated inside the traced function, retaining its
cosmology dependence. Supply one amplitude coordinate, for example 10^9As or
sigma8, rather than both. The AD parameter mapping currently exposes
10^9As, Omegam, Omegab, h, ns, w0 and wa; an accepted backend input
alias is not necessarily an available AD coordinate. Use the coordinates in the
example for a controlled comparison.
The GCsp JAX path requires fix_cosmo_nl_terms=True, bfs8terms=False and a
supported bias model (linear, linear_log or linear_Qbias). Photometry
supports the implemented photo-z distributions, galaxy-bias models and eNLA
intrinsic alignments. Unsupported modelling choices raise explicit errors.
For the two-stage GCsp forecast in shape, background, growth and bias parameters, see GCsp forecasts through intermediate parameters. It reuses the GCsp JAX observable and adds paper-style finite differences, autodiff comparisons and a Fisher-space Jacobian projection.
Backend configuration lives in
cosmicjellyfish/configs/default_boltzmann_yaml_files/jaxcosmo/default.yaml.
To customise it, copy the profile and set
options["jaxcosmo_config_yaml"] to the copy’s path. Key controls are
ACCURACY.transfer, ACCURACY.halofit, ACCURACY.distance_steps, and the
NUMERICS power/background grids and x64 flag. Public CosmicJellyfish power uses
k in inverse Mpc and P(k) in cubic Mpc; the theory adapter converts the
internal jax-cosmo h-scaled units.
Smooth Halofit and table boundaries#
The theory layer includes a locally maintained Halofit nonlinear-scale solver.
It uses a converged Newton solve with an implicit derivative to avoid the
fixed-grid root-interpolation derivative artefacts in jax-cosmo 0.1.0. It is
used by both the standard backend adapter and the JAX-native theory path. The
upstream proposal and numerical comparisons are recorded in jaxcosmo backend: review log.
The GCsp JAX observable evaluates power directly by default. Set
NUMERICS.legacy_pk_clamp: True in a custom profile to reproduce the standard
spline’s clamp at its tabulated k boundaries for parity studies. This introduces
a derivative kink at the boundary. Spectroscopic Savitzky–Golay window changes
can also affect finite differences at large steps; inspect step convergence
rather than relying on a single step size.
Reproducible parity checks and development#
For a straight-line terminal example timing SYREN finite differences against
JAXcosmo autodiff with ns fixed:
uv run --extra jaxcosmo python scripts/validation/time_syren_vs_jaxcosmo.py
It prints setup, fiducial spectra, covariance, derivatives and Fisher assembly times, followed by marginalized errors. The first AD derivative call includes compilation and execution; a second call measures the compiled Jacobian’s warm execution. The two backends use different theory, so this timing comparison is distinct from the same-theory parity checks below.
From the checkout, with the extra installed:
uv run --extra jaxcosmo python scripts/validation/compare_jax_photo_fishers.py \
--outdir results/jax_photo_parity
uv run --extra jaxcosmo python scripts/validation/compare_jax_spectro_fishers.py \
--outdir results/jax_spectro_parity --fd-step 0.003
These scripts compare the three same-theory routes and save reports and numerical summaries. They are separate from the SYREN comparison notebook. Existing parity measurements cover a limited Euclid, massless-neutrino LCDM setup; the jaxcosmo backend: review log records metrics, normalisations and remaining review items.
The backend-neutral contract in cosmology/jax_theory.py separates the traceable
theory from observables. A future differentiable backend can implement that
contract; a backend returning NumPy arrays alone cannot supply cosmological AD.
The standard likelihood/context interface remains available to sampling code.
Derivative providers cache compiled observables locally and discard that cache
when pickled; create them within workers. Nautilus serial-versus-spawn parity
with JAX remains a separate validation item, rather than a demonstrated result
of these Fisher comparisons.