40 #include <lal/Sequence.h>
41 #include <lal/LALConstants.h>
42 #include <lal/FrequencySeries.h>
43 #include <lal/Units.h>
44 #include <lal/SphericalHarmonics.h>
51 #define L_MAX_PLUS_1 5
52 #define PHENOM_DEFAULT_MAXF 0.5
65 if (extraParams == NULL)
68 if (ModeArray == NULL)
114 for (
INT4 ell = 2; ell <= 8; ell++)
116 for (
INT4 mm = -ell; mm < ell + 1; mm++)
118 if (ell == 2 && mm == 2){
121 else if (ell == 2 && mm == 1)
125 else if (ell == 3 && mm == 3)
129 else if (ell == 3 && mm == 2)
133 else if (ell == 4 && mm == 4)
137 else if (ell == 4 && mm == 3)
144 XLAL_ERROR(
XLAL_EFUNC,
"(%i,%i) mode in ModeArray but model does not include this!\n", ell, mm);
166 const REAL8 distance,
167 const REAL8 inclination,
181 if (S1x == 0. && S1y == 0. && S2x == 0. && S2y == 0.)
195 p->distance_SI = distance;
215 "PhenomInternal_AlignedSpinEnforcePrimaryIsm1 failed");
220 p->Mtot_SI =
p->m1_SI +
p->m2_SI;
221 p->Mtot_Msun =
p->m1_Msun +
p->m2_Msun;
223 p->eta =
p->m1_Msun *
p->m2_Msun / (
p->Mtot_Msun *
p->Mtot_Msun);
224 p->q =
p->m1_Msun /
p->m2_Msun;
227 if (
p->eta > 0.25 ||
p->q < 1.0)
238 REAL8 chi1_l, chi2_l;
242 &chi1_l, &chi2_l, &(
p->chip), &(
p->thetaJN), &(
p->alpha0), &(
p->phi_aligned), &(
p->zeta_polariz),
243 p->m1_SI,
p->m2_SI,
p->f_ref,
p->phiRef, inclination,
244 p->chi1x,
p->chi1y,
p->chi1z,
248 p->inclination =
p->thetaJN;
256 if (
p->PRECESSING != 1)
260 p->f_ref_Orb_Hz = 0.5 *
p->f_ref;
267 int ExpansionOrder = 5;
271 cos(
p->chi1_theta),
p->chi1_phi,
p->chi1_mag,
272 cos(
p->chi2_theta),
p->chi2_phi,
p->chi2_mag,
273 p->f_ref, ExpansionOrder);
295 UNUSED
const REAL8 distance,
296 UNUSED
const REAL8 inclination,
297 UNUSED
const REAL8 phiRef,
298 UNUSED
const REAL8 deltaF,
300 UNUSED LALDict *extraParams
307 LALDict *extraParams_aux;
310 if (extraParams == NULL)
331 if ((freqs->length == 2) && (deltaF > 0.))
334 f_min = freqs->data[0];
335 f_max = freqs->data[1];
344 for (
size_t j = 0; j < npts; j++)
346 freqs_seq->
data[j] = j * deltaF;
349 freqs_seq->
data[0] = 1
e-13;
355 "Failed to shift coalescence time to t=0,\
356 tried to apply shift of -1.0/deltaF with deltaF=%g.",
360 else if ((freqs->length != 2) && (deltaF <= 0.))
363 f_min = freqs->data[0];
364 f_max = freqs->data[freqs->length - 1];
365 npts = freqs->length;
367 for (
size_t j = 0; j < npts; j++)
369 freqs_seq->
data[j] = freqs->data[j];
388 distance, inclination, phiRef,
413 XLAL_EFUNC,
"XLALSimIMRPhenomHMGethlmModes failed");
419 memset((*hptilde)->data->data, 0, npts *
sizeof(
COMPLEX16));
425 memset((*hctilde)->data->data, 0, npts *
sizeof(
COMPLEX16));
460 XLAL_CHECK(
XLAL_SUCCESS == ret, ret,
"IMRPhenomPv3HM_Compute_Mode failed for the %i, %i mode\n", ell, mprime);
469 XLAL_CHECK(
XLAL_SUCCESS == ret, ret,
"IMRPhenomPv3HM_Compute_Mode failed for the %i, %i mode\n", ell, mprime);
477 XLAL_CHECK(
XLAL_SUCCESS == ret, ret,
"IMRPhenomPv3HM_Compute_Mode failed for the %i, %i mode\n", ell, mprime);
485 XLAL_CHECK(
XLAL_SUCCESS == ret, ret,
"IMRPhenomPv3HM_Compute_Mode failed for the %i, %i mode\n", ell, mprime);
493 XLAL_CHECK(
XLAL_SUCCESS == ret, ret,
"IMRPhenomPv3HM_Compute_Mode failed for the %i, %i mode\n", ell, mprime);
501 XLAL_CHECK(
XLAL_SUCCESS == ret, ret,
"IMRPhenomPv3HM_Compute_Mode failed for the %i, %i mode\n", ell, mprime);
512 REAL8 cos_2zeta, sin_2zeta;
517 for (
UINT4 i = 0;
i < (*hptilde)->data->length;
i++)
521 PhPpolp = amp0 * (*hptilde)->data->data[
i];
522 PhPpolc = amp0 * (*hctilde)->data->data[
i];
523 (*hptilde)->data->data[
i] = cos_2zeta * PhPpolp + sin_2zeta * PhPpolc;
524 (*hctilde)->data->data[
i] = cos_2zeta * PhPpolc - sin_2zeta * PhPpolp;
563 const REAL8 distance,
564 const REAL8 inclination,
568 LALDict *extraParams)
572 LALDict *extraParams_aux;
575 if (extraParams == NULL)
608 "XLALSimIMRPhenomPv3HMGetHplusHcross failed in IMRPhenomPv3");
626 f_mprime = fHz / mprime;
627 xi = pow(f_mprime * twopi_Msec, pAngles->
onethird);
633 *mprime_epsilon = mprime * epsilon;
639 *
beta = acos(angles.
z);
659 if (ell == 2 && mprime == 2)
661 for (
int mm = -ell; mm <= ell; mm++)
666 Term1_sum += ylms->
Ylm2[0][mm + ell] * WigD;
667 Term2_sum += minus1l * ylms->
Ylm2[1][mm + ell] * WigDmConj;
670 else if (ell == 2 && mprime == 1)
672 for (
int mm = -ell; mm <= ell; mm++)
677 Term1_sum += ylms->
Ylm2[0][mm + ell] * WigD;
678 Term2_sum += minus1l * ylms->
Ylm2[1][mm + ell] * WigDmConj;
681 else if (ell == 3 && mprime == 3)
683 for (
int mm = -ell; mm <= ell; mm++)
688 Term1_sum += ylms->
Ylm3[0][mm + ell] * WigD;
689 Term2_sum += minus1l * ylms->
Ylm3[1][mm + ell] * WigDmConj;
692 else if (ell == 3 && mprime == 2)
694 for (
int mm = -ell; mm <= ell; mm++)
699 Term1_sum += ylms->
Ylm3[0][mm + ell] * WigD;
700 Term2_sum += minus1l * ylms->
Ylm3[1][mm + ell] * WigDmConj;
703 else if (ell == 4 && mprime == 4)
705 for (
int mm = -ell; mm <= ell; mm++)
710 Term1_sum += ylms->
Ylm4[0][mm + ell] * WigD;
711 Term2_sum += minus1l * ylms->
Ylm4[1][mm + ell] * WigDmConj;
714 else if (ell == 4 && mprime == 3)
716 for (
int mm = -ell; mm <= ell; mm++)
721 Term1_sum += ylms->
Ylm4[0][mm + ell] * WigD;
722 Term2_sum += minus1l * ylms->
Ylm4[1][mm + ell] * WigDmConj;
745 const REAL8 Mtot_Msun,
780 UNUSED
INT4 minus1l = 0;
786 REAL8 mprime_epsilon = 0.;
805 for (
size_t j = 0; j < freqs_seq->
length; j++)
807 fHz = freqs_seq->
data[j];
813 "IMRPhenomPv3HM_Compute_a_b_e failed");
819 "XLALSimIMRPhenomPv3HMComputeWignerdElements failed");
825 "XLALSimIMRPhenomPv3HMComputeAlphaElements failed");
830 "IMRPhenomPv3HM_wigner_loop failed");
833 half_amp_eps = 0.5 * hlmD_j * cexp(-I * mprime_epsilon);
834 (*hptilde)->data->data[j] += half_amp_eps * (Term1_sum + Term2_sum);
835 (*hctilde)->data->data[j] += -I * half_amp_eps * (Term1_sum - Term2_sum);
864 LALDict *extraParams)
872 LALDict *extraParams_aux;
875 if (extraParams == NULL)
896 if ((freqs->
length == 2) && (deltaF > 0.))
909 for (
size_t j = 0; j < npts; j++)
911 freqs_seq->
data[j] = j * deltaF;
918 "Failed to shift coalescence time to t=0,\
919 tried to apply shift of -1.0/deltaF with deltaF=%g.",
922 else if ((freqs->
length != 2) && (deltaF <= 0.))
929 for (
size_t j = 0; j < npts; j++)
931 freqs_seq->
data[j] = freqs->
data[j];
950 REAL8 inclination = 0.;
956 distance, inclination, phiRef,
980 XLAL_EFUNC,
"XLALSimIMRPhenomHMGethlmModes failed");
991 REAL8 mprime_epsilon = 0.;
998 if (ModeArray == NULL)
1004 for (
INT4 mm = -ell; mm < (
INT4)ell + 1; mm++)
1010 for (
INT4 mprime = 1; mprime < (
INT4)ell + 1; mprime++)
1024 XLAL_ERROR(
XLAL_EFUNC,
"XLALSphHarmFrequencySeriesGetMode failed for (%i,%i) mode\n", ell, mprime);
1027 for (
size_t j = 0; j < freqs_seq->
length; j++)
1030 fHz = freqs_seq->
data[j];
1036 "IMRPhenomPv3HM_Compute_a_b_e failed");
1042 "XLALSimPhenomUtilsPhenomPv3HMWignerdElement failed");
1045 hlm->
data->
data[j] += hlmD_j * cexp(-I * mprime_epsilon) * cexp(I * mm *
alpha) * wig_d;
void XLALDestroyDict(LALDict *dict)
LALDict * XLALDictDuplicate(LALDict *old)
LALDict * XLALCreateDict(void)
int XLALSimIMRPhenomHMGethlmModes(SphHarmFrequencySeries **hlms, REAL8Sequence *freqs, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, const REAL8 phiRef, const REAL8 deltaF, REAL8 f_ref, LALDict *extraParams)
void PhenomInternal_ComputeIMRPhenomPv3CartesianToPolar(REAL8 *polar, REAL8 *azimuthal, REAL8 *magnitude, REAL8 x, REAL8 y, REAL8 z)
function to convert from 3d cartesian components to polar angles and vector magnitude.
int PhenomInternal_IMRPhenomHMFDAddMode(COMPLEX16FrequencySeries *hptilde, COMPLEX16FrequencySeries *hctilde, COMPLEX16FrequencySeries *hlmtilde, REAL8 theta, REAL8 phi, INT4 l, INT4 m, INT4 sym)
helper function to multiple hlm with Ylm.
size_t PhenomInternal_NextPow2(const size_t n)
Return the closest higher power of 2.
int PhenomInternal_PrecessingSpinEnforcePrimaryIsm1(REAL8 *m1, REAL8 *m2, REAL8 *chi1x, REAL8 *chi1y, REAL8 *chi1z, REAL8 *chi2x, REAL8 *chi2y, REAL8 *chi2z)
Given m1 with spins (chi1x, chi1y, chi1z) and m2 with spins (chi2x,chi2y,chi2z).
void PhenomInternal_nudge(REAL8 *x, REAL8 X, REAL8 epsilon)
If x and X are approximately equal to relative accuracy epsilon then set x = X.
int XLALSimIMRPhenomPv3HMModes(SphHarmFrequencySeries **hlms, REAL8Sequence *freqs, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, const REAL8 phiRef, const REAL8 deltaF, const REAL8 f_ref, LALDict *extraParams)
Returns frequency domain hlm's in inertial frame.
int XLALSimIMRPhenomPv3HMGetHplusHcross(UNUSED COMPLEX16FrequencySeries **hptilde, UNUSED COMPLEX16FrequencySeries **hctilde, UNUSED REAL8Sequence *freqs, UNUSED REAL8 m1_SI, UNUSED REAL8 m2_SI, UNUSED REAL8 chi1x, UNUSED REAL8 chi1y, UNUSED REAL8 chi1z, UNUSED REAL8 chi2x, UNUSED REAL8 chi2y, UNUSED REAL8 chi2z, UNUSED const REAL8 distance, UNUSED const REAL8 inclination, UNUSED const REAL8 phiRef, UNUSED const REAL8 deltaF, UNUSED REAL8 f_ref, UNUSED LALDict *extraParams)
This version doesn't construct precessing hlm modes but instead constructs hplus, hcross directly.
static int IMRPhenomPv3HM_check_mode_array(LALValue *ModeArray)
Reads in a ModeArray and checks that it is valid.
int XLALSimIMRPhenomPv3(COMPLEX16FrequencySeries **hptilde, COMPLEX16FrequencySeries **hctilde, REAL8Sequence *freqs, REAL8 m1_SI, REAL8 m2_SI, REAL8 S1x, REAL8 S1y, REAL8 S1z, REAL8 S2x, REAL8 S2y, REAL8 S2z, const REAL8 distance, const REAL8 inclination, const REAL8 phiRef, const REAL8 deltaF, const REAL8 f_ref, LALDict *extraParams)
Driver routine to compute the precessing inspiral-merger-ringdown phenomenological waveform IMRPhenom...
static UNUSED int init_PhenomPv3HM_Storage(PhenomPv3HMStorage *p, sysq *pAngles, REAL8 m1_SI, REAL8 m2_SI, REAL8 S1x, REAL8 S1y, REAL8 S1z, REAL8 S2x, REAL8 S2y, REAL8 S2z, const REAL8 distance, const REAL8 inclination, const REAL8 phiRef, const REAL8 deltaF, const REAL8 f_min, const REAL8 f_max, const REAL8 f_ref)
Precomputes useful quantities and populates the PhenomPv3HMStorage and sysq (for precession angles) s...
static int IMRPhenomPv3HM_wigner_loop(COMPLEX16 *Term1, COMPLEX16 *Term2, INT4 ell, INT4 mprime, IMRPhenomPv3HMYlmStruct *ylms, IMRPhenomPv3HMAlphaStruct *als, IMRPhenomPv3HMWignderStruct *wigs)
This is an internal function computes terms required to compute hptilde and hctilde.
#define PHENOM_DEFAULT_MAXF
static int IMRPhenomPv3HM_Compute_a_b_e(REAL8 *alpha, REAL8 *beta, REAL8 *mprime_epsilon, REAL8 fHz, INT4 mprime, const REAL8 twopi_Msec, PhenomPv3HMStorage *pv3HM, sysq *pAngles)
This is an internal function that returns the precession angles at a single frequency.
static int IMRPhenomPv3HM_Compute_Mode(COMPLEX16FrequencySeries **hptilde, COMPLEX16FrequencySeries **hctilde, UINT4 ell, INT4 mprime, const REAL8 Mtot_Msun, PhenomPv3HMStorage *pv3HM, SphHarmFrequencySeries **hlmsD, sysq *pAngles, REAL8Sequence *freqs_seq)
This is an internal function that returns hptilde and hctilde for a single mode in the inertial frame...
static LALDict * IMRPhenomPv3HM_setup_mode_array(LALDict *extraParams)
read in a LALDict.
double XLALSimPhenomUtilsFDamp0(REAL8 Mtot_Msun, REAL8 distance)
compute the frequency domain amplitude pre-factor
int XLALSimIMRPhenomPv3HMComputeAlphaElements(IMRPhenomPv3HMAlphaStruct **p, UINT4 ell, REAL8 alpha)
int XLALSimIMRPhenomPv3HMComputeWignerdElements(IMRPhenomPv3HMWignderStruct **p, UNUSED UINT4 ell, UNUSED INT4 mprime, UNUSED REAL8 b)
computes the wigner-d elements for -beta in batches.
double XLALSimPhenomUtilsMftoHz(REAL8 Mf, REAL8 Mtot_Msun)
Convert from geometric frequency to frequency in Hz.
IMRPhenomPv3HMYlmStruct * XLALSimIMRPhenomPv3HMComputeYlmElements(REAL8 theta, REAL8 phi, INT4 ell)
int XLALSimPhenomUtilsPhenomPv3HMWignerdElement(REAL8 *wig_d, UINT4 ell, INT4 mprime, INT4 mm, REAL8 b)
Hard coded expressions for relevant Wignerd matrix elements.
static UNUSED int InitializeSystem(sysq *system, const double m1, const double m2, const double mul, const double phl, const double mu1, const double ph1, const double ch1, const double mu2, const double ph2, const double ch2, const double f_0, const int ExpansionOrder)
InitializeSystem computes all the prefactors needed to generate precession angles from Chatziioannou ...
static UNUSED vector compute_phiz_zeta_costhetaL3PN(const double xi, const sysq *system)
Internal function that computes phiz, zeta, and costhetaL at 3PN.
static double beta(const double a, const double b, const sysq *system)
Internal function that computes the spin-orbit couplings.
void XLALDestroyValue(LALValue *value)
COMPLEX16FrequencySeries * XLALCreateCOMPLEX16FrequencySeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaF, const LALUnit *sampleUnits, size_t length)
void XLALDestroyCOMPLEX16FrequencySeries(COMPLEX16FrequencySeries *series)
void * XLALMalloc(size_t n)
@ IMRPhenomPv3_V
version 3: based on IMRPhenomD and the precession angles from Katerina Chatziioannou PhysRevD....
int XLALSimIMRPhenomPCalculateModelParametersFromSourceFrame(REAL8 *chi1_l, REAL8 *chi2_l, REAL8 *chip, REAL8 *thetaJN, REAL8 *alpha0, REAL8 *phi_aligned, REAL8 *zeta_polariz, const REAL8 m1_SI, const REAL8 m2_SI, const REAL8 f_ref, const REAL8 phiRef, const REAL8 incl, const REAL8 s1x, const REAL8 s1y, const REAL8 s1z, const REAL8 s2x, const REAL8 s2y, const REAL8 s2z, IMRPhenomP_version_type IMRPhenomP_version)
Function to map LAL parameters (masses, 6 spin components, phiRef and inclination at f_ref) (assumed ...
COMPLEX16FrequencySeries * XLALSphHarmFrequencySeriesGetMode(SphHarmFrequencySeries *ts, UINT4 l, INT4 m)
Get the time series of a waveform's (l,m) spherical harmonic mode from a SphHarmFrequencySeries linke...
SphHarmFrequencySeries * XLALSphHarmFrequencySeriesAddMode(SphHarmFrequencySeries *appended, const COMPLEX16FrequencySeries *inmode, UINT4 l, INT4 m)
Prepend a node to a linked list of SphHarmFrequencySeries, or create a new head.
void XLALDestroySphHarmFrequencySeries(SphHarmFrequencySeries *ts)
Delete list from current pointer to the end of the list.
void XLALDestroyREAL8Sequence(REAL8Sequence *sequence)
REAL8Sequence * XLALCreateREAL8Sequence(size_t length)
const LALUnit lalStrainUnit
const LALUnit lalSecondUnit
LALUnit * XLALUnitMultiply(LALUnit *output, const LALUnit *unit1, const LALUnit *unit2)
#define XLAL_PRINT_INFO(...)
#define XLAL_CHECK(assertion,...)
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
a strcut to keep the complex exponential terms of the alpha precession angle
COMPLEX16 alpha4[9]
optimised elements for complex exponential of the alpha angle for ell = 4
COMPLEX16 alpha3[7]
optimised elements for complex exponential of the alpha angle for ell = 3
COMPLEX16 alpha2[5]
optimised elements for complex exponential of the alpha angle for ell = 2
a strcut to keep the wigner-d matrix elements
REAL8 d33[2][7]
wigner-d matrix elements for ell=3, mprime=+/-3 and positive[0] and negative[1] mprime
REAL8 d43[2][9]
wigner-d matrix elements for ell=4, mprime=+/-3 and positive[0] and negative[1] mprime
REAL8 d21[2][5]
wigner-d matrix elements for ell=2, mprime=+/-1 and positive[0] and negative[1] mprime
REAL8 d44[2][9]
wigner-d matrix elements for ell=4, mprime=+/-4 and positive[0] and negative[1] mprime
REAL8 d32[2][7]
wigner-d matrix elements for ell=3, mprime=+/-2 and positive[0] and negative[1] mprime
REAL8 d22[2][5]
wigner-d matrix elements for ell=2, mprime=+/-2 and positive[0] and negative[1] mprime
a strcut to keep the spherical harmonic terms
COMPLEX16 Ylm2[2][5]
optimised elements Ylms for ell = 2.
COMPLEX16 Ylm4[2][9]
optimised elements Ylms for ell = 4.
COMPLEX16 Ylm3[2][7]
optimised elements Ylms for ell = 3.
Structure storing initial and derived variables for IMRPhenomPv3HM.
REAL8 inclination
inclination - used to compute the angle thetaJN (rad)
REAL8 alpha0
Initial value of alpha angle (azimuthal precession angle)
REAL8 zeta_polariz
Angle to rotate the polarizations.
INT4 PRECESSING
integer to signify if system is precessing, 1 for false (not precessing), 0 for true (precessing)