README_DNNU.md#1
Open
Hdiao112 wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
sagenet-dnnu
What this is
SageNet (
sagenetgw.classes.GWPredictor) predicts astochastic gravitational-wave background (SGWB) spectrum
(f, log10ΩGW(f)). To use that spectrum in a BBN / Cobaya pipeline youtypically need to integrate it into a single number — the extra effective
relativistic species
ΔNₑff, here calleddnnu.Naively, that integral is
In practice running plain
scipy.integrate.simpsonornumpy.trapzon theraw SageNet output is fragile: SageNet returns a non-uniform grid with
extra samples around peaks, the spectrum spans many decades in
ΩGW, andSimpson's parabolic fit can go negative between samples on a sharp peak
(see Why this exists below).
This package implements the integration recipe used in production by the
upstream Cobaya theory in
sagenet_final.py, and ships it as a clean,standalone, testable Python module:
log10Ω-domain — never overshoots, never produces negative values.dnnu; the integrator computes the corresponding raw-integral atol (which depends onH₀).f-mode auto-detection — feed itfin Hz or already inlog10(f); it figures out which.Everything is implemented in pure NumPy + SciPy. No GPU, no
cobaya, nosagenetgwrequired for the integrator itself.Install
Or, from a clone of this repo:
Optional extras:
[cobaya]cobayaSageNetDnnuTheoryin a Cobaya run.[test]pytest[examples]matplotlib[all]pip install "sagenet-dnnu[all]"Quick start
The snippet below is exactly the SageNet example you already have, with one extra line at the end:
That's it.
resultis anIntegrationResultwith three fields:One-shot: predict + integrate
Raw arrays, without a SageNet prediction dict
f_arraymay be either linear Hz (e.g.1e-12 .. 1e8) or already log10(e.g.
-12 .. 8). The integrator detects this from the value range; thedetected mode is reported in
result.diagnostics["f_mode"].Why this exists — algorithm in 1 minute
The upstream Cobaya theory shipped a hand-rolled integrator inside
sagenet_final.py. This repo extracts that integrator, documents it,tests it, and packages it. The choices it makes are not arbitrary; they
fix concrete numerical failure modes.
Failure mode 1: Simpson gives negative integrals
Simpson fits a parabola through three samples. On a non-uniform grid that
straddles a sharp SGWB peak, the parabola can dip below zero between
samples, so the integral of a strictly positive spectrum comes out
negative.
Fix: interpolate
log10ΩGWwith PCHIP (shape-preserving — provablyno overshoot), exponentiate, and integrate that. PCHIP guarantees the
integrand is
> 0everywhere, so Simpson on the interpolated curve isalso positive.
Failure mode 2: fixed tolerances are wrong by orders of magnitude
A point in parameter space with
H₀ = 60and another withH₀ = 80need different raw-integral tolerances to hit the same precision on
dnnu. Hard-coding a Simpsonatoleither over-spends compute on easypoints or under-resolves hard ones.
Fix: the user specifies
dnnu_tol_abs(absolute tolerance on thefinal
ΔNₑff). The integrator translates that into the equivalentraw-integral atol for the current
H₀, every call:Failure mode 3: Simpson refuses to converge
Pathological spectra (
max_evalsexceeded, orS < 0survives despitePCHIP) trigger a fallback: trapezoid integration over the points
Simpson already evaluated. This is monotonic in the integrand and
strictly non-negative, so it always returns a sane answer.
Validation against numerical ODE backend
Reproducible benchmark using
scripts/verify_dnnu_sample.py:200 rows randomly sampled from 50 000 paired SageNet + numerical-ODE
runs (parth backend,
dnnu_tol_abs=1e-6,simpson_rtol=1e-5,device=
cpu).Absolute error vs the ODE ground truth
| Statistic |
|recomputed − numerical|||---|---|
| mean |
1.11e-03|| median |
4.95e-11(half of all rows agree to machine precision) || p90 |
3.90e-03|| p99 |
1.06e-02|| max |
1.66e-02|Interpretation: errors are two orders of magnitude below current
CMB+BBN constraints on ΔNₑff (
σ ~ 0.2–0.3), so for any standardcosmological inference use case the integrator is a drop-in replacement
for the ODE backend.
Reproducibility (recomputed vs the value already in the CSV)
| Statistic |
|recomputed − csv_simpson_local|||---|---|
| mean |
4.43e-05|| median |
4.93e-11(machine precision) || p90 |
1.35e-04|| max |
6.81e-04|The non-zero tail comes from SageNet predictor non-determinism (CPU
vs GPU, PyTorch attention kernels), not from the integrator itself —
feeding identical
(f, log10ΩGW)arrays intocompute_dnnuisbit-identical to the upstream
sagenet_final.py.A note on relative error
|reldiff_vs_numerical|median is0.67, max is18.5. These largevalues are an artefact of dnnu values approaching the floating-point
floor: 100 of the 200 sampled points have
dnnu < 1e-30(effectivelyzero SGWB contribution), where any tiny absolute residual blows up when
divided by ~
1e-50. Always read the absolute error table above forthe physical picture.
Throughput
About 200 rows/s on CPU (the predictor itself is the bottleneck), vs
typical numerical-ODE backends at ~1 row/s — a ~200× speed-up at
~1e-3 absolute accuracy.
Can this replace the numerical ODE backend?
Mostly yes, with two guards on.
1e-6 ≲ dnnu ≲ 5dnnu > 5,dnnu > 1)~0.1%dnnu < 1e-6(predictor noise floor)dnnu > 5gate; in this regime SageNet output is dominated by neural-network noisednnu > 5rejectionThis is the workflow the upstream
SageNetDnnuTheoryalready encodesvia its
legacy(dnnu > 5 → reject) andstrict(dnnu > 1) gates.Tuning:
IntegratorConfigDefaults match the upstream pipeline byte-for-byte. Override only if you
know what you're doing.
dnnu_tol_abs1e-6dnnu. The Simpsonatolis derived from this.simpson_rtol1e-5simpson_max_depth35simpson_max_evals500 000edge_trim0.0edge_trimunits oflog10(f)from each end before integrating. Diagnostic only.clamp_log10omega_nonfinite_to-300.0log10ΩGWwith this (effectively zero contribution).fallback_to_trapz_on_failTrue< 0, fall back to trapezoid on already-evaluated points.Diagnostics
Every call returns a
diagnosticsdict. The fields are stable andmachine-readable — handy for Cobaya runs that want to log per-point
behaviour.
{ "f_mode": "converted_linear_f_to_log10", # or "assume_log10f_by_range" etc. "dnnu_tol_abs": 1e-6, "simpson_atol_raw_from_dnnu": 7.43e-09, "g2_trapz": 1.234e-09, # baseline trapz on native grid "g2_simpson_local_final": 1.235e-09, # Simpson (or trapz fallback) result "g2_rel_diff": 8.1e-04, # (Simpson - trapz) / trapz "simpson_method_final": "simpson_local", # or "trapz_refined_fallback" "simpson_fallback_used": False, "simpson_converged": True, "simpson_eval_count": 137, "simpson_accepted_intervals": 67, "simpson_split_events": 70, "simpson_max_depth_used": 12, "simpson_err_est": 4.2e-12, # ... }Cobaya integration
If you previously used
sagenet_final.py::SageNetTheoryFinal, swap theimport:
Environment variables (all optional, all default to the upstream defaults):
Guard logic (kept identical to upstream
sagenet_final.py):dnnu > 5(legacy gate, always on)hardparthdnnu > 1oreta10 > 9hardalterbbndnnu > 1softparthdnnu > 1softalterbbnAPI reference
Examples
examples/01_minimal.pyexamples/02_advanced.pyIntegratorConfig, parameter sweep.scripts/verify_dnnu_sample.pyTesting
pip install -e ".[test]" pytest -qThe test suite covers:
Project layout
Differences vs
sagenet_final.pyIf you're coming from the upstream file, here's what changed:
cobaya/sagenetgwimport at top level. Both are optional now. The integrator runs on bare numpy/scipy.utils_new.global_paramdependency. The constantsNeff0,Omega_nh2,ln10live insagenet_dnnu.constantsand are derivable.IntegratorConfig. Env vars only apply to the optional Cobaya adapter (where they preserve byte-for-byte upstream behaviour).IntegrationResultandIntegratorConfigreplace the bare tuple(g2, diag). The lower-levelcompute_g2still returns the tuple.SageNetTheoryFinal→SageNetDnnuTheoryto flag the package boundary; behaviour is otherwise identical.The numerical algorithm — PCHIP-in-log10Ω, adaptive Simpson with local error control, dnnu-driven atol, trapz fallback — is byte-for-byte the same.
License
MIT — see LICENSE.
Citation
If you use this package in published work, please cite the SageNet paper
along with this repository.