Metadata-Version: 2.4
Name: nrhjsurrogate
Version: 1.0.0
Summary: NR waveform surrogate in a Hamilton-Jacobi (action-angle) representation with hp-spectral elements and a Kokkos evaluator
Author: Vaishak Prasad
License-Expression: MIT
Project-URL: Homepage, https://psu-edu.github.io/nrhjsurrogate/
Project-URL: Documentation, https://psu-edu.github.io/nrhjsurrogate/
Project-URL: Model files (Zenodo), https://doi.org/10.5281/zenodo.22262339
Keywords: gravitational-waves,numerical-relativity,surrogate-model,waveform,action-angle
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: C++
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy<3,>=2.0
Requires-Dist: scipy>=1.14
Requires-Dist: h5py>=3.11
Requires-Dist: spectools>=2026.8.8
Requires-Dist: lalsuite>=7.26
Provides-Extra: build
Requires-Dist: pybind11>=2.12; extra == "build"
Requires-Dist: cmake>=3.22; extra == "build"
Provides-Extra: plot
Requires-Dist: matplotlib>=3.8; extra == "plot"
Provides-Extra: train
Requires-Dist: sxs>=2024.0; extra == "train"
Requires-Dist: pandas>=2.0; extra == "train"
Requires-Dist: scikit-learn>=1.4; extra == "train"
Provides-Extra: pe
Requires-Dist: pycbc>=2.3; extra == "pe"
Requires-Dist: bilby>=2.2; extra == "pe"
Requires-Dist: lalsuite>=7.26; extra == "pe"
Requires-Dist: gwsurrogate>=1.1; extra == "pe"
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Dynamic: license-file

# NRHJSur3dq8

A surrogate model for gravitational waves from **non-eccentric, aligned-spin**
binary black hole mergers, trained on numerical relativity.

It is built on a Hamilton-Jacobi (action-angle) representation of the binary
dynamics: the orbital phase rather than time is the independent coordinate, so
simulations of different lengths simply occupy different phase ranges. The
waveform is carried in hp-adaptive spectral elements and evaluated either in
NumPy or through a compiled Kokkos kernel.

**Documentation:** https://psu-edu.github.io/nrhjsurrogate/

**Range of validity.** Non-eccentric orbits, mass ratio 1 to 8, aligned spin
components within 0.8 in magnitude. Seven modes: (2,2), (2,1), (3,3), (3,2),
(4,4), (4,3), (5,5).

## Install

```bash
pip install nrhjsurrogate
```

Every dependency resolves from PyPI. Installing the source distribution also
builds the compiled evaluator, fetching Kokkos if it is not already on the
system; if that compile cannot run, the install still succeeds and the model
falls back to NumPy and says so. `NRHJ_BUILD_KOKKOS=0` skips the compile,
`=1` requires it. See [INSTALL.md](INSTALL.md) for the detail, including the
CUDA build.

The model files are **not** in the package. They are distributed separately
and located at run time, in order: an explicit path, then `$NRHJ_MODEL_DIR`,
then the directories on `$LAL_DATA_PATH`, then a per-user cache. A miss
raises `FileNotFoundError` naming the file, its SHA-256 and how to get it.
Nothing degrades silently. If nothing on that list has a released model you
named, the package downloads it into the per-user cache and checks its
SHA-256 before using it; `NRHJ_AUTO_FETCH=0` turns that off, and
`nrhjsurrogate.fetch_model` does the same thing explicitly.

## A first waveform

```python
from nrhjsurrogate import NRHJSurAA

model = NRHJSurAA.load_h5("NRHJSur3dq8_AA_v3")

# geometric units: time in M, modes as r h_lm / M
times, modes = model.get_td_waveform_modes_geometric(4.0, 0.3, -0.2)

# physical units, LAL spelling: the two polarizations
h_plus, h_cross = model.get_td_waveform(
    mass1=40.0, mass2=10.0, spin1z=0.3, spin2z=-0.2,
    delta_t=1.0 / 4096.0, f_min=30.0, inclination=0.7, distance=400.0)
```

Then check the installation against shipped reference values:

```bash
nrhjsur-verify
```

Beyond waveforms the model serves analytic parameter derivatives, its own
predictive uncertainty, post-Newtonian extension below the stored inspiral,
the orbital dynamics and the remnant mass and spin. The runnable examples in
`examples/usage/` take one capability each, and `00_walkthrough.ipynb` is a
guided tour of the main ones.

## The public import surface

Everything you are meant to use is importable straight from the package:
`from nrhjsurrogate import NRHJSurAA` (and `NRHJSurAdA`, `AABatch`,
`AAHMCLikelihood`, `InnerProduct`, `fetch_model`, and more; `dir(nrhjsurrogate)`
lists them). The submodule layout underneath, `driver/`, `physics/`,
`execution/`, `numerical_methods/`, is internal and may be rearranged in any
release. Import from the top level and a reorganisation cannot reach you;
import `nrhjsurrogate.driver.something` and it can.

Importing the package also sets `OMP_PROC_BIND=close` and `OMP_PLACES=cores`
unless you have chosen otherwise; INSTALL.md gives the measured basis, the
caveats and the off switch.

## What is released

Two model flavours, both `3dq8`, meaning aligned-spin `(q, chi1z, chi2z)` with
q up to 8, matching the `NRHybSur3dq8` convention. Both are built on the
**N2** numerical-relativity extrapolation, which the names do not encode and
each file records as the root attribute `extrapolation = "N2"`.

| file | what it is |
| --- | --- |
| `NRHJSur3dq8_AA_v3` | action-angle inspiral. **The default.** |
| `NRHJSur3dq8_AdA_v3` | adiabatic-angle inspiral, 14 elements |
| `NRHJSur3dq8_MR_v3` | the merger-ringdown arm both v3 inspirals name |
| `NRHJSur3dq8_AA_v2` | previous generation |
| `NRHJSur3dq8_AdA_v2` | previous generation |
| `NRHJSur3dq8_MR_v2` | previous generation |

The inspiral files are de-embedded: each composes at load with the shared
merger-ringdown arm it names, resolved by name and checked by content digest,
so a crossed pair is refused rather than served. The version digit is the
generation, not a patch level. Both generations are deposited; v3 is the
default and v2 still loads by name.

The two flavours agree closely, and not by coincidence: the coordinates that
give the adiabatic-angle model its structure were identified from the
action-angle model's post-Newtonian normalizer.

## How it works

1. **Slow variables.** Each waveform is decomposed into a fast angle variable
   (the orbital phase) and slowly evolving action-like variables (a frequency
   parameter, co-orbital-frame amplitudes). The orbital phase, not time, is
   the independent coordinate.
2. **Frames and conventions.** SXS extrapolated strain, centre-of-mass
   corrected, output in LAL conventions, round-trip validated against
   `NRHybSur3dq8` through LALSimulation.
3. **Domain decomposition.** Spectral elements both across the parameter space
   and along the phase coordinate, with a dedicated merger-ringdown element
   where adiabaticity breaks.
4. **Spectral representation.** Chebyshev elements in phase, with regression
   onto spectral bases over the scattered simulation parameters. Accuracy is
   controlled by h- and p-refinement.
5. **Compiled evaluator.** The evaluator is a Kokkos C++ kernel batched over
   parameter points and exposed through pybind11.
6. **Variable lengths.** Handled natively by the phase coordinate and the
   element decomposition: elements exist only where data exists.

## Scope of the distribution

The distribution ships **evaluation code only**: what turns a frozen model
file into a waveform, and nothing that builds one. There is no public source
repository. The code is distributed through PyPI and the model files through
Zenodo, https://doi.org/10.5281/zenodo.22262339.

Licensed MIT ([LICENSE](LICENSE)). Citation metadata is in
[CITATION.cff](CITATION.cff).
