# COSMO·EMU > Neural-network emulator of the matter power spectrum P(k, z): linear and non-linear (CAMB + HMcode-2020) for flat w0waCDM with massive neutrinos, 8 cosmological parameters plus redshift. It runs in the browser and behind a free JSON API at https://cosmo.azemar.eu/api/pk. Units: k in h/Mpc, P(k) in (Mpc/h)^3. Author: Daniel Azemar (https://azemar.eu). Use it when you need a fast, reproducible P(k) or sigma8 for a cosmology inside the box below, for example for quick forecasts, plots, sanity checks or teaching. It is an emulator: inputs outside the training box are refused unless you explicitly ask it to extrapolate. The "truth" it reproduces is CAMB 2.0.5 with HMcode-2020 and no baryonic feedback, not real data. ## What it computes - `pk`: total-matter power spectrum (CDM + baryons + massive neutrinos, CAMB delta_tot). It is non-linear (HMcode-2020) by default and linear with `nonlinear=0`. `pk_lin` is always returned too unless `lin=0`. - `sigma8` (z = 0) and `sigma8_z` (at the requested z): the rms linear density contrast in 8 Mpc/h top-hat spheres, integrated from the emulated linear P(k). - k grid: 256 log-spaced points from 0.0001 to 10 h/Mpc, or any k list you pass (interpolated). Redshift z is in [0, 3]. ## Parameter box (uniform priors; fiducial = Planck-2018-like) | name | meaning | min | max | fiducial | |---|---|---|---|---| | Omega_m | total matter density parameter Ω_m (CDM + baryons + neutrinos) | 0.24 | 0.4 | 0.315 | | Omega_b | baryon density parameter Ω_b | 0.04 | 0.06 | 0.049 | | h | H0 / (100 km/s/Mpc) | 0.61 | 0.73 | 0.674 | | n_s | scalar spectral index | 0.92 | 1 | 0.965 | | ln10As | ln(10^10 A_s) | 2.7 | 3.3 | 3.044 | | w0 | dark energy, w(a) = w0 + wa (1 - a) | -1.3 | -0.7 | -1 | | wa | dark energy evolution | -0.7 | 0.5 | 0 | | mnu | sum of neutrino masses [eV] | 0 | 0.3 | 0.06 | | z | redshift | 0 | 3 | 0 | Any parameter you leave out (or pass empty) takes its fiducial value. The model is flat (Omega_k = 0) with N_eff = 3.044, tau = 0.0544 and one degenerate massive-neutrino eigenstate. Aliases such as `om`, `ob`, `ns` and `lnAs` are accepted. `Omega_m` and `Omega_b` are density parameters, not physical densities: lowercase `omega_m`, `omega_b` (and `ombh2`, `ω_b`), which conventionally mean Ω h², are rejected with 400 instead of being guessed. Convert with Omega_b = omega_b / h^2. ## Method - Training data: CAMB 2.0.5 spectra (linear, plus HMcode-2020 `mead2020` non-linear; PPF dark energy) on a Latin hypercube. That is 21000 training, 1000 validation and 1500 held-out test cosmologies. Training and validation cosmologies are each evaluated at 16 redshifts (336000 training spectra); test cosmologies at 8 redshifts. Training and validation points were drawn from the box padded by 4% per side. Test points lie strictly inside the nominal box and were never used for training or model selection. - Two networks in the CosmoPower style. One predicts log10 P_lin(k, z) and the other predicts log10 B(k, z), where B = P_nl / P_lin is the HMcode-2020 boost. Each is PCA with 40 components on the k grid, followed by an MLP with layers 9-256-256-256-256-40 (SiLU activations). The 9 inputs are the 8 normalized parameters plus z. Seeds are fixed (12345). - The same weights file (https://cosmo.azemar.eu/data/emulator.json) runs in Python (numpy/torch), in the browser and in the Cloudflare Pages Function. The JS runtime matches the Python predictions to a maximum |Δlog10 P| of 2.1e-7 over the 64 published test vectors. ## Accuracy (held-out test set: 1500 cosmologies × 8 z = 12000 spectra, k ≤ 5 h/Mpc) The tables give the relative error |P_emu / P_CAMB − 1|, pooled over all spectra and k ≤ 5 h/Mpc. "Test-set max" is the single worst point of the whole held-out test set, not a guaranteed bound. | quantity | median | 68% | 95% | 99% | test-set max | |---|---|---|---|---|---| | linear P_lin | 0.011% | 0.016% | 0.040% | 0.064% | 0.39% | | non-linear P_nl (HMcode-2020) | 0.012% | 0.018% | 0.045% | 0.073% | 0.36% | | boost P_nl/P_lin | 0.00088% | 0.0057% | 0.028% | 0.049% | 0.33% | | sigma8 (z = 0) | 0.021% | 0.026% | 0.048% | 0.058% | 0.067% | - Targets were a 95th percentile below 0.50% for linear and below 1.0% for non-linear, and both are met. The worst single-k 95th percentile is 0.089% for linear (at k ≈ 0.37 h/Mpc) and 0.078% for non-linear (at k ≈ 0.34 h/Mpc). - 100% of linear test spectra and 100% of non-linear test spectra have their maximum error below 1% for k ≤ 5 h/Mpc (100% and 100% below 0.5%). - The non-linear 95th percentile is largest at z = 0 (0.057%). - Full error distributions by k and z: https://cosmo.azemar.eu/data/metrics.json ## Speed - CAMB (idle laptop, 8 redshifts, linear + HMcode-2020, 256 k values) takes about 1.3 s per cosmology on 1 thread and about 0.21 s on 16 threads (median). For reference, during data generation with 15 concurrent single-thread processes on a fully loaded machine it averaged about 2.1 s per cosmology. - Emulator in Python/numpy: about 0.11 ms for a single spectrum, about 0.061 ms per spectrum in batches of 1000, and about 4.1 µs per spectrum on a GPU (RTX 4070 Laptop, batch of 100k). - Emulator in browser JS: about 0.25–0.5 ms per linear + non-linear spectrum. That is fast enough to run an MCMC in a Web Worker on the page. ## API - [OpenAPI 3.1 spec](https://cosmo.azemar.eu/openapi.json): machine-readable description of the endpoints below - [GET /api/describe](https://cosmo.azemar.eu/api/describe): parameter box, fiducial, method, accuracy, citations (`/api/pk?describe=1` returns the same body) - [GET /api/pk](https://cosmo.azemar.eu/api/pk?Omega_m=0.3&w0=-0.9&z=0.5&k=0.01,0.1,1): the power spectrum All endpoints return JSON and send CORS `*`. They accept GET with query parameters or POST with a JSON body. No key is needed. Any other `/api/*` path returns 404 JSON. Query fields (all optional): - `Omega_m`, `Omega_b`, `h`, `n_s`, `ln10As`, `w0`, `wa`, `mnu`: the cosmological parameters - `z`: redshift - `nonlinear=1|0`: non-linear (default) or linear spectrum - `k=0.01,0.1,1`: k values to interpolate to, at most 2048 - `kmin` and `kmax`: restrict the native grid to a k range - `lin=0`: drop `pk_lin` from the response - `precision=3..10`: significant digits (default 6) - `extrapolate=1`: answer outside the training box. The result is flagged `inBox: false` and is unreliable. Status codes: - 200: success - 400: malformed input, such as a non-numeric value, invalid JSON or a physical density name like `omega_b` - 404: unknown endpoint - 422: outside the training box. The response lists the `violations` and the `box`. Examples (outputs generated from the current weights by `npm run build:llms`): ``` curl 'https://cosmo.azemar.eu/api/pk?Omega_m=0.3&w0=-0.9&z=0.5&k=0.01,0.1,1' → {"model":"cosmo-emu","z":0.5,"nonlinear":true,"params":{"Omega_m":0.3,...,"w0":-0.9,...},"inBox":true, "sigma8":0.760577,"sigma8_z":0.591602,"k":[0.01,0.1,1],"pk":[13061.1,2972.91,137.103], "pk_lin":[13062.5,2907.26,34.4987],"units":{"k":"h/Mpc","pk":"(Mpc/h)^3",...},"warnings":[],"pk_kind":"nonlinear (HMcode-2020)","box":{...}} curl -X POST https://cosmo.azemar.eu/api/pk -H 'content-type: application/json' \ -d '{"params":{"Omega_m":0.3,"w0":-0.9},"z":0.5,"k":[0.1],"nonlinear":0}' curl 'https://cosmo.azemar.eu/api/pk?Omega_m=0.5' → 422 {"error":"outside the emulator training box","violations":["Omega_m=0.5 outside [0.24, 0.4]"],...} ``` To get only sigma8, request a single k point and drop the linear spectrum, then read `sigma8` and `sigma8_z`: ``` curl 'https://cosmo.azemar.eu/api/pk?Omega_m=0.3&ln10As=3.0&k=0.1&lin=0' → "sigma8":0.765838,"sigma8_z":0.765838 ``` ## In-page tools (WebMCP) Browsers that implement WebMCP (`navigator.modelContext` / `document.modelContext`) can call four tools registered by https://cosmo.azemar.eu: - `get_power_spectrum` - `get_sigma8` - `describe_emulator` - `set_parameters`, which moves the page's sliders so the user sees the cosmology The tools run the same emulator in the page. ## Limits - The emulator is valid only inside the box above, for 0 ≤ z ≤ 3, and for 0.0001 ≤ k ≤ 10 h/Mpc. Accuracy is quoted for k ≤ 5 h/Mpc. - The non-linear model is HMcode-2020 without baryonic feedback. Its own accuracy against N-body simulations (a few percent) is not included in the figures above. - The emulator does not compute the CMB, redshift-space distortions, galaxy bias or curvature. ## References - Lewis, Challinor & Lasenby 2000, ApJ 538, 473: CAMB (arXiv:astro-ph/9911177) - Mead, Brieden, Tröster & Heymans 2021, MNRAS 502, 1401: HMcode-2020 (arXiv:2009.01858) - Spurio Mancini et al. 2022, MNRAS 511, 1771: CosmoPower (arXiv:2106.03846) - Chevallier & Polarski 2001; Linder 2003: the w0–wa parametrisation - Planck Collaboration 2020, A&A 641, A6: fiducial cosmology ## Optional - [Live site](https://cosmo.azemar.eu/): interactive P(k), BAO correlation function, cosmic-web field, MCMC inference lab, accuracy and speed panels - [Weights](https://cosmo.azemar.eu/data/emulator.json): emulator weights (JSON, about 2.4 MB) - [Test vectors](https://cosmo.azemar.eu/data/test_vectors.json): held-out CAMB test vectors - [Author](https://azemar.eu): Daniel Azemar