Installation

From PyPI:

pip install phenomxpy

From source:

git clone https://gitlab.com/imrphenom-dev/phenomxpy.git
cd phenomxpy
pip install .

For GPU support, user needs to install cupy according to the CUDA version of their installation (e.g. 12 or 13):

pip install cupy-cuda12x
pip install cupy-cuda13x

The CUDA installation might need cuda-toolkit.

Constants backend

Physical constants can be read from different backends: lisaconstants, astropy or hardcoded.

To choose the backend:

from phenomxpy import load_constants
load_constants("astropy")

or with an evironment variable at kernel initialization:

import os
os.environ["PHENOMXPY_CONSTANTS"] = "astropy"
import phenomxpy

or

PHENOMXPY_CONSTANTS=astropy python myscript.py

If no backend is provided, the priority is: lisaconstants, astropy, hardcoded. If the packages is not installed, it will try the next one.

Units convention

Whether input frequencies and times are interpreted in SI or NR (mass) units depends on whether total_mass is provided at initialization.

Quantity

SI (total_mass > 0)

NR (no total_mass)

f_min f_ref delta_t times input waveform output

Hz Hz seconds seconds strain (with distance)

mass units mass units mass units mass units dimensionless NR amplitude

If total_mass and distance are provided, the waveform is returned in SI units. If total_mass is not provided, input arguments are assumed to be in NR units and the waveform is returned in NR units.

Note

Fourier-domain evaluation only supports SI units (total_mass must be provided).

Simple usage

import phenomxpy

# Initialize approximant class
# Available approximants are: IMRPhenomT, IMRPhenomTHM, IMRPhenomTP, IMRPhenomTPHM
phen = IMRPhenomTHM(
    eta=0.2,
    total_mass=40.0,
    s1=[0.0, 0.0, 0.5],
    s2=[0.0, 0.0, -0.3],
    f_min=20.0,
    delta_t=1.0 / 4096.0,
    distance=100.0,
)

# Compute time domain polarizations
hp, hc, times = phen.compute_polarizations(times=None)

# Compute Fourier domain polarizations (requires condition=True)
hpf, hcf, frequencies = phen.compute_fd_polarizations()

# Compute individual modes (in time domain)
hlms, times = phen.compute_hlms(times=None)

# In the case of precessing approximants, we can compute modes in different frames
hlms, times = phen.compute_CPmodes(times=None)
hlms, times = phen.compute_Jmodes(times=None)
hlms, times = phen.compute_L0modes(times=None)

The time array times can be a custom array. If None, then it computes an equispaced array with delta_t given in the class initialization.

See also Direct Python usage for a runnable notebook example.