Source code for bhpwave.waveform
import numpy as np
from bhpwaveformcy import (WaveformHarmonicGeneratorPyWrapper,
WaveformFourierGeneratorPy,
WaveformGeneratorPy,
TrajectoryDataPy,
InspiralGeneratorPy,
HarmonicAmplitudesPy)
from bhpwave.trajectory.geodesic import A_MAX
import os
from bhpwave.constants import *
import warnings
path_to_file = os.path.dirname(os.path.abspath(__file__))
traj_path = path_to_file + "/data/trajectory.txt"
amplitude_path = path_to_file + "/data/circ_data"
try:
CPU_MAX = len(os.sched_getaffinity(0))
except:
CPU_MAX = os.cpu_count()
[docs]def check_source_frame_parameters(a, x0, theta, phi, Phi_phi0):
assert np.abs(x0) == 1
assert np.abs(a) <= A_MAX
if x0 < 0:
a = -a
x0 = -x0
theta = np.pi - theta
phi = -phi
Phi_phi0 = -Phi_phi0
return a, x0, theta, phi, Phi_phi0
[docs]def check_ssb_frame_parameters(a, x0, qK, phiK, Phi_phi0):
assert np.abs(x0) == 1
assert np.abs(a) <= A_MAX
if x0 < 0:
a = -a
x0 = -x0
qK = np.pi - qK
phiK = np.pi + phiK
Phi_phi0 = np.pi + Phi_phi0
return a, x0, qK, phiK, Phi_phi0
[docs]class KerrCircularWaveform:
"""Class that generates the gravitational waveform produced by an extreme-mass-ratio inspiral
using the adiabatic approximation from black hole perturbation theory and the self-force formalism.
By default, the waveform is generated in the solar system barycenter frame.
Waveform generation is limited to quasi-circular inspirals in Kerr spacetime, but the generator mirrors the generic
parametrization used in other EMRI waveform generators (e.g., https://bhptoolkit.org/FastEMRIWaveforms/html/user/main.html)
Parameters
----------
trajectory_data : TrajectoryData or None, optional
TrajectoryData class which holds interpolants of the relevant trajectory data
harmonic_data : HarmonicAmplitudes or None, optional
HarmonicAmplitudes class which holds interpolants of the harmonic mode amplitudes
num_threads: int or None, optional
Number of threads used to evaluate the waveform
"""
def __init__(self, trajectory_data=None, harmonic_data=None, num_threads=None):
if num_threads is None:
num_threads = CPU_MAX
if trajectory_data is None:
self.trajectory_data = TrajectoryDataPy(filename=traj_path, dealloc_flag=False)
else:
self.trajectory_data = trajectory_data.base_class
if harmonic_data is None:
self.harmonic_data = HarmonicAmplitudesPy(filebase=amplitude_path, dealloc_flag=False)
else:
self.harmonic_data = harmonic_data.base_class
waveform_kwargs = {
"num_threads": num_threads
}
self.waveform_generator = WaveformGeneratorPy(self.trajectory_data, self.harmonic_data, waveform_kwargs=waveform_kwargs)
[docs] def select_modes(self, M, mu, a, r0, qS, phiS, qK, phiK, Phi_phi0, dt=10., T=1., **kwargs):
"""Selects the harmonic modes that are used for calculating the waveform
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact object
Parameters
----------
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
T : double, optional
Duration of the waveform in years
Returns
-------
1d-array[tuples(doubles)]
"""
return self.waveform_generator.select_modes(M, mu, a, r0, qS, phiS, qK, phiK, Phi_phi0, dt, T, **kwargs)
[docs] def __call__(self, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt=10., T=1., **kwargs):
"""Calculate the complex gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples in seconds
T : double, optional
Duration of the waveform in years
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
1d-array[complex] or list[two 1d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
include_negative_m = True
if "include_negative_m" in kwargs.keys():
include_negative_m = kwargs["include_negative_m"]
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
if include_negative_m:
for mode in kwargs["select_modes"]:
if mode[1] > 0: # if include_negative_m is True then only keep positive m
lmodes.append(mode[0])
mmodes.append(mode[1])
else:
warnings.warn("Warning: Only keeping modes in select_modes with m > 0. Set include_negative_m = False to keep m < 0 modes.")
else: # if include_negative_m is False then keep all m
for mode in kwargs["select_modes"]:
lmodes.append(mode[0])
mmodes.append(mode[1])
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics(l, m, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform(M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt, T, **kwargs)
return h
[docs] def harmonics(self, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt=10., T=1., **kwargs):
"""Calculate the spin-weighted spherical harmonic modes of the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples in seconds
T : double, optional
Duration of the waveform in years
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
2d-array[complex] or list[two 2d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
include_negative_m = True
if "include_negative_m" in kwargs.keys():
include_negative_m = kwargs["include_negative_m"]
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
if include_negative_m:
for mode in kwargs["select_modes"]:
if mode[1] > 0: # if include_negative_m is True then only keep positive m
lmodes.append(mode[0])
mmodes.append(mode[1])
else:
warnings.warn("Warning: Only keeping modes in select_modes with m > 0. Set include_negative_m = False to keep m < 0 modes.")
else: # if include_negative_m is False then keep all m
for mode in kwargs["select_modes"]:
lmodes.append(mode[0])
mmodes.append(mode[1])
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics_grid(l, m, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform_select_harmonics_grid(M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt, T, **kwargs)
return h
[docs] def harmonics_data(self, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt=10., T=1., **kwargs):
"""Calculate the amplitudes and phases of the spin-weighted spherical harmonic :math:`(l, m)`-modes of the gravitational wave strain. The
function returns mode data for both positive and negative m-modes. Given a list of modes :math:`[(l_1, m_1), (l_2, m_2), \dots , (l_N, m_N)]`
the function returns data in the order :math:`[(l_1, m_1), (l_1, -m_1), (l_2, m_2), (l_2, -m_2), \dots, (l_N, m_N), (l_N, -m_N)]`.
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples in seconds
T : double, optional
Duration of the waveform in years
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation. Only positive m-modes
are used.
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
Returns
-------
2d-array[complex] or list[two 2d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
for mode in kwargs["select_modes"]:
if mode[1] > 0: # only keep positive m
lmodes.append(mode[0])
mmodes.append(mode[1])
else:
warnings.warn("Warning: Only keeping modes in select_modes with m > 0. Set include_negative_m = False to keep m < 0 modes.")
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics_phase_amplitude(l, m, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform_select_harmonics_phase_amplitude(M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt, T, **kwargs)
return h
[docs] def source_frame(self, M, mu, a, r0, theta, phi, Phi_phi0, dt=10., T=1., **kwargs):
"""Calculate the scaled gravitational wave strain :math:`r\\times h/\\mu` in the source frame
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial radial separation
theta : double
polar angle of the observor with respect to the Kerr spin
vector
phi : double
azimuthal angle of the observor with respect to the Kerr
spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples in seconds. Default is 10 seconds.
T : double, optional
Duration of the waveform in years. Default is 1 year.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
1d-array[complex] or list[two 1d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
include_negative_m = True
if "include_negative_m" in kwargs.keys():
include_negative_m = kwargs["include_negative_m"]
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
if include_negative_m:
for mode in kwargs["select_modes"]:
if mode[1] > 0: # if include_negative_m is True then only keep positive m
lmodes.append(mode[0])
mmodes.append(mode[1])
else:
warnings.warn("Warning: Only keeping modes in select_modes with m > 0. Set include_negative_m = False to keep m < 0 modes.")
else: # if include_negative_m is False then keep all m
for mode in kwargs["select_modes"]:
lmodes.append(mode[0])
mmodes.append(mode[1])
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics_source_frame(l, m, M, mu, a, r0, theta, phi, Phi_phi0, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform_source_frame(M, mu, a, r0, theta, phi, Phi_phi0, dt, T, **kwargs)
return h
[docs]class KerrWaveform(KerrCircularWaveform):
"""Class that generates the gravitational waveform produced by an extreme-mass-ratio inspiral
using the adiabatic approximation from black hole perturbation theory and the self-force formalism.
By default, the waveform is generated in the solar system barycenter frame.
Waveform generation is limited to quasi-circular inspirals in Kerr spacetime, but the generator mirrors the generic
parametrization used in other EMRI waveform generators (e.g., https://bhptoolkit.org/FastEMRIWaveforms/html/user/main.html)
Parameters
----------
trajectory_data : TrajectoryData or None, optional
a TrajectoryData class which holds interpolants of the relevant
trajectory data
harmonic_data : HarmonicAmplitudes or None, optional
a HarmonicAmplitudes class which holds interpolants of the
harmonic mode amplitudes
num_threads : int or None, optional
the number of threads used to evaluate the waveform
"""
[docs] def __call__(self, M, mu, a, p0, e0, x0, dist, qS, phiS, qK, phiK, Phi_phi0, Phi_r0, Phi_theta0, dt=10., T=1., **kwargs):
"""Calculate the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
p0 : double
initial semi-latus rectum
e0 : double
initial orbital eccentricity
x0 : double
intial cosine of the orbital inclination
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
Phi_r0 : double
Phase describing the initial radial position and velocity of
the small compact object
Phi_theta0 : double
Phase describing the initial polar position and velocity of
the small compact object
dt : double, optional
Spacing of time samples in seconds
T : double, optional
Duration of the waveform in years
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
1d-array[complex] or list[two 1d-arrays[double]]
"""
a, x0, qK, phiK, Phi_phi0 = check_ssb_frame_parameters(a, x0, qK, phiK, Phi_phi0)
return super().__call__(M, mu, a, p0, dist, qS, phiS, qK, phiK, Phi_phi0, dt = dt, T = T, **kwargs)
[docs] def harmonics(self, M, mu, a, p0, e0, x0, dist, qS, phiS, qK, phiK, Phi_phi0, Phi_r0, Phi_theta0, dt=10., T=1., **kwargs):
"""Calculate the spin-weighted spherical harmonic modes of the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
p0 : double
initial semi-latus rectum
e0 : double
initial orbital eccentricity
x0 : double
intial cosine of the orbital inclination
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
Phi_r0 : double
Phase describing the initial radial position and velocity of
the small compact object
Phi_theta0 : double
Phase describing the initial polar position and velocity of
the small compact object
dt : double, optional
Spacing of time samples in seconds
T : double, optional
Duration of the waveform in years
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
2d-array[complex] or list[two 2d-arrays[double]]
"""
a, x0, qK, phiK, Phi_phi0 = check_ssb_frame_parameters(a, x0, qK, phiK, Phi_phi0)
return super().harmonics(M, mu, a, p0, dist, qS, phiS, qK, phiK, Phi_phi0, dt = dt, T = T, **kwargs)
[docs] def harmonics_data(self, M, mu, a, p0, e0, x0, dist, qS, phiS, qK, phiK, Phi_phi0, Phi_r0, Phi_theta0, dt=10., T=1., **kwargs):
"""Calculate the amplitudes and phases of the spin-weighted spherical harmonic (l, m)-modes of the gravitational wave strain. The
function returns mode data for both positive and negative m-modes. Given a list of modes :math:`[(l_1, m_1), (l_2, m_2), \dots , (l_N, m_N)]`
the function returns data in the order :math:`[(l_1, m_1), (l_1, -m_1), (l_2, m_2), (l_2, -m_2), \dots, (l_N, m_N), (l_N, -m_N)]`.
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
p0 : double
initial semi-latus rectum
e0 : double
initial orbital eccentricity
x0 : double
intial cosine of the orbital inclination
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
Phi_r0 : double
Phase describing the initial radial position and velocity of
the small compact object
Phi_theta0 : double
Phase describing the initial polar position and velocity of
the small compact object
dt : double, optional
Spacing of time samples in seconds
T : double, optional
Duration of the waveform in years
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation. Only positive m-modes
are used.
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
Returns
-------
2d-array[complex] or list[two 2d-arrays[double]]
"""
a, x0, qK, phiK, Phi_phi0 = check_ssb_frame_parameters(a, x0, qK, phiK, Phi_phi0)
return super().harmonics_data(M, mu, a, p0, dist, qS, phiS, qK, phiK, Phi_phi0, dt = dt, T = T, **kwargs)
[docs]class KerrCircularFrequencyWaveform:
"""Class that generates the gravitational waveform produced by an extreme-mass-ratio inspiral
in the frequency domain using the adiabatic approximation from black hole perturbation theory and the self-force formalism.
By default, the waveform is generated in the solar system barycenter frame.
Waveform generation is limited to quasi-circular inspirals in Kerr spacetime, but the generator mirrors the generic
parametrization used in other EMRI waveform generators (e.g., https://bhptoolkit.org/FastEMRIWaveforms/html/user/main.html)
Parameters
----------
trajectory_data : TrajectoryData or None, optional
a TrajectoryData class which holds interpolants of the relevant
trajectory data
harmonic_data : HarmonicAmplitudes or None, optional
a HarmonicAmplitudes class which holds interpolants of the
harmonic mode amplitudes
num_threads : int or None, optional
the number of threads used to evaluate the waveform
"""
def __init__(self, trajectory_data=None, harmonic_data=None, num_threads=None):
if num_threads is None:
num_threads = CPU_MAX
if trajectory_data is None:
self.trajectory_data = TrajectoryDataPy(filename=traj_path, dealloc_flag=False)
else:
self.trajectory_data = trajectory_data.base_class
if harmonic_data is None:
self.harmonic_data = HarmonicAmplitudesPy(filebase=amplitude_path, dealloc_flag=False)
else:
self.harmonic_data = harmonic_data.base_class
waveform_kwargs = {
"num_threads": num_threads
}
self.waveform_generator = WaveformFourierGeneratorPy(self.trajectory_data, self.harmonic_data, waveform_kwargs=waveform_kwargs)
[docs] def select_modes(self, M, mu, a, r0, qS, phiS, qK, phiK, Phi_phi0, T = 1., **kwargs):
"""Selects the harmonic modes that are used for calculating the waveform
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
T : double, optional
Duration of the waveform in years
Returns
-------
1d-array[tuples(doubles)]
"""
return self.waveform_generator.select_modes(M, mu, a, r0, qS, phiS, qK, phiK, Phi_phi0, T, **kwargs)
[docs] def __call__(self, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt=10., T = 1., df = None, fmax = None, frequencies = None, **kwargs):
"""Calculate the Fourier transform of the plus and cross polarizations of the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples for corresponding time-domain
waveform in seconds. Default is 10. This option is only
considered if df, fmax, and frequencies are None.
T : double, optional
Duration of the observed waveform in years. Default is 1. If
None, T is set to be 1/df.
df : double, optional
Spacing of the frequency samples in Hertz. Default is None.
If df is None, then one must specify values for frequencies
or T.
fmax : double, optional
Maximum sampled frequency in Hertz. Default is None. If fmax
is None, then one must specify values for frequencies or dt.
frequencies : list[double] or ndarray[double], optional
Array of frequency samples in Hertz. Default is None. This
option overrides df and fmax.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
eps : double, optional
The tolerance to include modes that are subdominant to the
power in the (2,2)-mode.
max_samples : double, optional
Returns
-------
list[two 1d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
if "df" in kwargs.keys():
df = kwargs["df"]
if "fmax" in kwargs.keys():
fmax = kwargs["fmax"]
if "frequencies" in kwargs.keys():
frequencies = kwargs["frequencies"]
frequencies, dt, T = sort_frequency_and_time_sampling_arguments(df, fmax, frequencies, dt, T)
include_negative_m = True
if "include_negative_m" in kwargs.keys():
include_negative_m = kwargs["include_negative_m"]
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
if include_negative_m:
for mode in kwargs["select_modes"]:
if mode[1] > 0: # if include_negative_m is True then only keep positive m
lmodes.append(mode[0])
mmodes.append(mode[1])
else:
warnings.warn("Warning: Only keeping modes in select_modes with m > 0. Set include_negative_m = False to keep m < 0 modes.")
else: # if include_negative_m is False then keep all m
for mode in kwargs["select_modes"]:
lmodes.append(mode[0])
mmodes.append(mode[1])
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics(l, m, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, frequencies, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform(M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, frequencies, dt, T, **kwargs)
return h
[docs] def harmonics(self, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt=10., T = 1., df = None, fmax = None, frequencies = None, **kwargs):
"""Calculate the spin-weighted spherical harmonic :math:`(l, m)`-modes of the
Fourier transform of the plus and cross polarizations of the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples for corresponding time-domain
waveform in seconds. Default is 10. This option is only
considered if df, fmax, and frequencies are None.
T : double, optional
Duration of the observed waveform in years. Default is 1. If
None, T is set to be 1/df.
df : double, optional
Spacing of the frequency samples in Hertz. Default is None.
If df is None, then one must specify values for frequencies
or T.
fmax : double, optional
Maximum sampled frequency in Hertz. Default is None. If fmax
is None, then one must specify values for frequencies or dt.
frequencies : list[double] or ndarray[double], optional
Array of frequency samples in Hertz. Default is None. This
option overrides df and fmax.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
list[two 2d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
if "df" in kwargs.keys():
df = kwargs["df"]
if "fmax" in kwargs.keys():
fmax = kwargs["fmax"]
if "frequencies" in kwargs.keys():
frequencies = kwargs["frequencies"]
frequencies, dt, T = sort_frequency_and_time_sampling_arguments(df, fmax, frequencies, dt, T)
include_negative_m = True
if "include_negative_m" in kwargs.keys():
include_negative_m = kwargs["include_negative_m"]
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
if include_negative_m:
for mode in kwargs["select_modes"]:
if mode[1] > 0: # if include_negative_m is True then only keep positive m
lmodes.append(mode[0])
mmodes.append(mode[1])
else:
warnings.warn("Warning: Only keeping modes in select_modes with m > 0. Set include_negative_m = False to keep m < 0 modes.")
else: # if include_negative_m is False then keep all m
for mode in kwargs["select_modes"]:
lmodes.append(mode[0])
mmodes.append(mode[1])
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics_grid(l, m, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, frequencies, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform_select_harmonics_grid(M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, frequencies, dt, T, **kwargs)
return h
[docs] def harmonics_data(self, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, dt=10., T = 1., df = None, fmax = None, frequencies = None, **kwargs):
"""Calculate the phases and amplitudes for the spin-weighted spherical harmonic :math:`(l, m)`-modes of the
Fourier transform of the plus and cross polarizations of the gravitational wave strain. The
function returns mode data for both positive and negative m-modes. Given a list of modes :math:`[(l_1, m_1), (l_2, m_2), \dots , (l_N, m_N)]`
the function returns data in the order :math:`[(l_1, m_1), (l_1, -m_1), (l_2, m_2), (l_2, -m_2), \dots, (l_N, m_N), (l_N, -m_N)]`.
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial orbital separation of the two objects
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples for corresponding time-domain
waveform in seconds. Default is 10. This option is only
considered if df, fmax, and frequencies are None.
T : double, optional
Duration of the observed waveform in years. Default is 1. If
None, T is set to be 1/df.
df : double, optional
Spacing of the frequency samples in Hertz. Default is None.
If df is None, then one must specify values for frequencies
or T.
fmax : double, optional
Maximum sampled frequency in Hertz. Default is None. If fmax
is None, then one must specify values for frequencies or dt.
frequencies : list[double] or ndarray[double], optional
Array of frequency samples in Hertz. Default is None. This
option overrides df and fmax.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
list[two 2d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
if "df" in kwargs.keys():
df = kwargs["df"]
if "fmax" in kwargs.keys():
fmax = kwargs["fmax"]
if "frequencies" in kwargs.keys():
frequencies = kwargs["frequencies"]
frequencies, dt, T = sort_frequency_and_time_sampling_arguments(df, fmax, frequencies, dt, T)
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
for mode in kwargs["select_modes"]:
if mode[1] > 0:
lmodes.append(mode[0])
mmodes.append(mode[1])
else:
warnings.warn("Warning: Only keeping modes in select_modes with m > 0.")
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics_phase_amplitude(l, m, M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, frequencies, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform_select_harmonics_phase_amplitude(M, mu, a, r0, dist, qS, phiS, qK, phiK, Phi_phi0, frequencies, dt, T, **kwargs)
return h
[docs] def source_frame(self, M, mu, a, r0, theta, phi, Phi_phi0, dt=10., T = 1., df = None, fmax = None, frequencies = None, **kwargs):
"""Calculate the Fourier transform of the plus and cross polarizations of the
scaled gravitational wave strain :math:`r\\times h/\\mu` in the source frame
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
r0 : double
initial radial separation
theta : double
polar angle of the observor with respect to the Kerr spin
vector
phi : double
azimuthal angle of the observor with respect to the Kerr
spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
dt : double, optional
Spacing of time samples for corresponding time-domain
waveform in seconds. Default is 10. If None, dt is set to be
1/(2 fmax).
T : double, optional
Duration of the observed waveform in years. Default is 1. If
None, T is set to be 1/df.
df : double, optional
Spacing of the frequency samples in Hertz. Default is None.
If df is None, then one must specify values for frequencies
or T.
fmax : double, optional
Maximum sampled frequency in Hertz. Default is None. If fmax
is None, then one must specify values for frequencies or dt.
frequencies : list[double] or ndarray[double], optional
Array of frequency samples in Hertz. Default is None. This
option overrides df and fmax.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
Returns
-------
list[two 1d-arrays[double]]
"""
if "T" in kwargs.keys():
T = kwargs["T"]
if "dt" in kwargs.keys():
dt = kwargs["dt"]
if "df" in kwargs.keys():
df = kwargs["df"]
if "fmax" in kwargs.keys():
fmax = kwargs["fmax"]
if "frequencies" in kwargs.keys():
frequencies = kwargs["frequencies"]
frequencies, dt, T = sort_frequency_and_time_sampling_arguments(df, fmax, frequencies, dt, T)
if "select_modes" in kwargs.keys():
lmodes = []
mmodes = []
for mode in kwargs["select_modes"]:
lmodes.append(mode[0])
mmodes.append(mode[1])
l = np.ascontiguousarray(lmodes, dtype=np.intc)
m = np.ascontiguousarray(mmodes, dtype=np.intc)
h = self.waveform_generator.waveform_harmonics_source_frame(l, m, M, mu, a, r0, theta, phi, Phi_phi0, frequencies, dt, T, **kwargs)
else:
h = self.waveform_generator.waveform_source_frame(M, mu, a, r0, theta, phi, Phi_phi0, frequencies, dt, T, **kwargs)
return h
[docs]def sort_frequency_and_time_sampling_arguments(df, fmax, frequencies, dt, T):
if df is None and frequencies is None and T is None:
raise ValueError("Values for df, frequencies, and T cannot all be None.")
if fmax is None and frequencies is None and dt is None:
raise ValueError("Values for fmax, frequencies, and dt cannot all be None.")
# dt is only relevant if it is set to a numerical value and none of the frequency data is specified
if dt is None or fmax is not None or df is not None or frequencies is not None:
dt = 0.
if frequencies is not None:
if not isinstance(frequencies, list) and not isinstance(frequencies, np.ndarray):
raise ValueError("frequencies must be a list or a ndarray.")
else:
frequencies = np.ascontiguousarray(frequencies)
df = np.min(np.diff(frequencies))
fmax = np.max(frequencies)
if T is None:
T = 1/df
if frequencies is None:
if df is None:
df = 1/years_to_seconds(T)
if fmax is None:
fmax = 1/(2*dt)
if T is None:
T = seconds_to_years(1/df)
frequencies = np.arange(0, fmax, df)
return frequencies, dt, T
[docs]class KerrFrequencyWaveform(KerrCircularFrequencyWaveform):
"""Class that generates the gravitational waveform produced by an extreme-mass-ratio inspiral in the
frequency domain using the adiabatic approximation from black hole perturbation theory and the self-force formalism.
By default, the waveform is generated in the solar system barycenter frame.
Waveform generation is limited to quasi-circular inspirals in Kerr spacetime, but the generator mirrors the generic
parametrization used in other EMRI waveform generators (e.g., https://bhptoolkit.org/FastEMRIWaveforms/html/user/main.html)
Parameters
----------
trajectory_data : TrajectoryData or None, optional
a TrajectoryData class which holds interpolants of the relevant
trajectory data
harmonic_data : HarmonicAmplitudes or None, optional
a HarmonicAmplitudes class which holds interpolants of the
harmonic mode amplitudes
num_threads : int or None, optional
the number of threads used to evaluate the waveform
"""
[docs] def __call__(self, M, mu, a, p0, e0, x0, dist, qS, phiS, qK, phiK, Phi_phi0, Phi_r0, Phi_theta0, dt=10., T = 1., df = None, fmax = None, frequencies = None, **kwargs):
"""Calculate the Fourier transform of the plus and cross polarizations of the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
p0 : double
initial semi-latus rectum
e0 : double
initial orbital eccentricity
x0 : double
intial cosine of the orbital inclination
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
Phi_r0 : double
Phase describing the initial radial position and velocity of
the small compact object
Phi_theta0 : double
Phase describing the initial polar position and velocity of
the small compact object
dt : double, optional
Spacing of time samples for corresponding time-domain
waveform in seconds. Default is 10. If None, dt is set to be
1/(2 fmax).
T : double, optional
Duration of the observed waveform in years. Default is 1. If
None, T is set to be 1/df.
df : double, optional
Spacing of the frequency samples in Hertz. Default is None.
If df is None, then one must specify values for frequencies
or T.
fmax : double, optional
Maximum sampled frequency in Hertz. Default is None. If fmax
is None, then one must specify values for frequencies or dt.
frequencies : list[double] or ndarray[double], optional
Array of frequency samples in Hertz. Default is None. This
option overrides df and fmax.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
list[two 1d-arrays[double]]
"""
a, x0, qK, phiK, Phi_phi0 = check_ssb_frame_parameters(a, x0, qK, phiK, Phi_phi0)
return super().__call__(M, mu, a, p0, dist, qS, phiS, qK, phiK, Phi_phi0, dt = dt, T = T, df = df, fmax = fmax, frequencies = frequencies, **kwargs)
[docs] def harmonics(self, M, mu, a, p0, e0, x0, dist, qS, phiS, qK, phiK, Phi_phi0, Phi_r0, Phi_theta0, dt=10., T = 1., df = None, fmax = None, frequencies = None, **kwargs):
"""Calculate the spin-weighted spherical harmonic :math:`(l, m)`-modes of the
Fourier transform of the plus and cross polarizations of the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
p0 : double
initial semi-latus rectum
e0 : double
initial orbital eccentricity
x0 : double
intial cosine of the orbital inclination
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
Phi_r0 : double
Phase describing the initial radial position and velocity of
the small compact object
Phi_theta0 : double
Phase describing the initial polar position and velocity of
the small compact object
dt : double, optional
Spacing of time samples for corresponding time-domain
waveform in seconds. Default is 10. If None, dt is set to be
1/(2 fmax).
T : double, optional
Duration of the observed waveform in years. Default is 1. If
None, T is set to be 1/df.
df : double, optional
Spacing of the frequency samples in Hertz. Default is None.
If df is None, then one must specify values for frequencies
or T.
fmax : double, optional
Maximum sampled frequency in Hertz. Default is None. If fmax
is None, then one must specify values for frequencies or dt.
frequencies : list[double] or ndarray[double], optional
Array of frequency samples in Hertz. Default is None. This
option overrides df and fmax.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
list[two 2d-arrays[double]]
"""
a, x0, qK, phiK, Phi_phi0 = check_ssb_frame_parameters(a, x0, qK, phiK, Phi_phi0)
return super().harmonics(M, mu, a, p0, dist, qS, phiS, qK, phiK, Phi_phi0, dt = dt, T = T, df = df, fmax = fmax, frequencies = frequencies, **kwargs)
[docs] def harmonics_data(self, M, mu, a, p0, e0, x0, dist, qS, phiS, qK, phiK, Phi_phi0, Phi_r0, Phi_theta0, dt=10., T = 1., df = None, fmax = None, frequencies = None, **kwargs):
"""Calculate the phases and amplitudes for spin-weighted spherical harmonic :math:`(l, m)`-modes of the
Fourier transform of the plus and cross polarizations of the gravitational wave strain
Parameters
----------
M : double
mass (in solar masses) of the massive black hole
mu : double
mass (in solar masses) of the (smaller) stellar-mass compact
object
a : double
dimensionless black hole spin
p0 : double
initial semi-latus rectum
e0 : double
initial orbital eccentricity
x0 : double
intial cosine of the orbital inclination
dist : double
luminosity distance to the source in Gpc
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Phi_phi0 : double
Initial azimuthal position of the small compact object
Phi_r0 : double
Phase describing the initial radial position and velocity of
the small compact object
Phi_theta0 : double
Phase describing the initial polar position and velocity of
the small compact object
dt : double, optional
Spacing of time samples for corresponding time-domain
waveform in seconds. Default is 10. If None, dt is set to be
1/(2 fmax).
T : double, optional
Duration of the observed waveform in years. Default is 1. If
None, T is set to be 1/df.
df : double, optional
Spacing of the frequency samples in Hertz. Default is None.
If df is None, then one must specify values for frequencies
or T.
fmax : double, optional
Maximum sampled frequency in Hertz. Default is None. If fmax
is None, then one must specify values for frequencies or dt.
frequencies : list[double] or ndarray[double], optional
Array of frequency samples in Hertz. Default is None. This
option overrides df and fmax.
pad_output : bool, optional
True returns the waveform for the full duration T years even
if the system merges before T years has elasped
select_modes : list[tuple(double)] or ndarray[tuple(double)], optional
A list of tuples :math:`(l, m)` that select which modes to
include in the waveform calculation
return_list : bool, optional
True returns the plus and cross polarizations of the
waveform as separate ndarrays
include_negative_m : bool, optional
True returns the sum of the positive and negative m-modes
for each mode in select_modes
Returns
-------
list[two 2d-arrays[double]]
"""
a, x0, qK, phiK, Phi_phi0 = check_ssb_frame_parameters(a, x0, qK, phiK, Phi_phi0)
return super().harmonics_data(M, mu, a, p0, dist, qS, phiS, qK, phiK, Phi_phi0, dt = dt, T = T, df = df, fmax = fmax, frequencies = frequencies, **kwargs)
[docs]def source_angles(qS, phiS, qK, phiK):
"""Calculate the sky location :math:`(\\theta, \\phi)` of the observor in the
source frame using the sky location and orientation of the source in
the SSB frame
Parameters
----------
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Returns
-------
tuple(double, double)
"""
phi = -0.5*np.pi
theta = np.arccos(-(np.sin(qS)*np.sin(qK)*np.cos(phiS - phiK) + np.cos(qS)*np.cos(qK)))
return (theta, phi)
[docs]def polarization(qS, phiS, qK, phiK):
"""Calculate the rotation of polarization angle :math:`e^{i\\psi}` due to transforming from
the plus and cross polarizations in the source frame to the plus and
cross polarization in the SSB frame.
Parameters
----------
qS : double
polar angle of the source's sky location
phiS : double
azimuthal angle of the source's sky location
qK : double
polar angle of the Kerr spin vector
phiK : double
azimuthal angle of the Kerr spin vector
Returns
-------
complex
"""
real_part = np.cos(qS)*np.sin(qK)*np.cos(phiS - phiK) - np.cos(qK)*np.sin(qS)
imag_part = -np.sin(qK)*np.sin(phiS - phiK)
if abs(real_part) + abs(imag_part) == 0.:
return 1.
return (real_part + 1.j*imag_part)/(real_part - 1.j*imag_part)
[docs]def solar_mass_to_seconds(mass):
"""Converts units of solar mass in :math:`G=c=1` convention to units of seconds in the MKS convention
Parameters
----------
mass : double
mass in units of solar masses
Returns
-------
double
"""
return mass*Modot_GC1_to_S
[docs]def seconds_to_solar_mass(time):
"""Converts units of seconds in the MKS convention to units of solar mass in :math:`G=c=1` convention
Parameters
----------
time : double
time in units of seconds
Returns
-------
double
"""
return time/Modot_GC1_to_S
[docs]def solar_mass_to_meters(mass):
"""Converts units of solar mass in :math:`G=c=1` convention to units of meters in the MKS convention
Parameters
----------
mass : double
mass in units of solar masses
Returns
-------
double
"""
return mass*Modot_GC1_to_M
[docs]def solar_mass_to_parsecs(mass):
"""Converts units of solar mass in :math:`G=c=1` convention to units of parsecs in the MKS convention
Parameters
----------
mass : double
mass in units of solar masses
Returns
-------
double
"""
return mass*Modot_GC1_to_PC
[docs]def parsecs_to_solar_mass(length):
"""Converts units of parsecs in the MKS convention to units of solar mass in :math:`G=c=1` convention
Parameters
----------
length : double
length in units of solar masses
Returns
-------
double
"""
return length/Modot_GC1_to_PC
[docs]def seconds_to_years(time):
"""Converts units of seconds to units of sidereal years
Parameters
----------
time : double
time in seconds
Returns
-------
double
"""
return time/yr_MKS
[docs]def years_to_seconds(time):
"""Converts units of sidereal years to units of seconds
Parameters
----------
time : double
time in sidereal years
Returns
-------
double
"""
return time*yr_MKS
[docs]def scaled_amplitude(mu, dist):
"""Gives the overall scaling of the waveform amplitude :math:`\\mu/D_L` for a binary with
small mass :math:`\\mu` and an observer at distance :math:`D_L`
Parameters
----------
mu : double
mass of the small body in solar masses
dist : double
distance between the binary and observor in Gpc
Returns
-------
double
"""
return Modot_GC1_to_PC*mu/(dist*1.e9)
[docs]def frequencies(dt, T):
"""Frequency sampling of the frequency-domain gravitational wave signal for a given
time step and signal duration
Parameters
----------
dt : double
time step in seconds
T : double
signal duration in years
Returns
-------
array[double]
"""
samples = int(T*yr_MKS/dt + 1)
return np.fft.rfftfreq(samples, d=dt)