LALSimulation  5.4.0.1-fe68b98
LALSimIMRPhenomTPHM.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 Hector Estelles
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with with program; see the file COPYING. If not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  * MA 02110-1301 USA
18  */
19 
20 /* Standard LAL */
21 #include <lal/Sequence.h>
22 #include <lal/Date.h>
23 #include <lal/Units.h>
24 #include <lal/XLALError.h>
25 
26 /* LAL datatypes and constants */
27 #include <lal/LALDatatypes.h>
28 #include <lal/LALStdlib.h>
29 #include <lal/LALConstants.h>
30 
31 /* Time series, frequency series and spherical harmonics */
32 #include <lal/TimeSeries.h>
33 #include <lal/TimeFreqFFT.h>
34 #include <lal/SphericalHarmonics.h>
35 #include <lal/LALSimSphHarmMode.h>
36 #include <lal/FrequencySeries.h>
37 #include "LALSimInspiralPrecess.h"
38 
39 /* LALSimulation */
40 #include <lal/LALSimIMR.h>
41 #include <lal/LALSimInspiral.h>
42 
43 /* Standard C */
44 #include <math.h>
45 #include <complex.h>
46 #include <stdbool.h>
47 
48 /* Link IMRPhenomTHM routines */
50 #include "LALSimIMRPhenomTHM.h"
51 #include "LALSimIMRPhenomX.h"
54 
55 #define MAX(a,b) (((a)>(b))?(a):(b))
56 
57 /**
58  * @addtogroup LALSimIMRPhenomT_c
59  * @{
60  *
61  * @name Routines for IMRPhenomTP
62  * @{
63  *
64  * @author Héctor Estellés
65  *
66  * @brief C code for the IMRPhenomTP phenomenological waveform model.
67  *
68  * This is a precessing time domain model covering the L=2 sector of Spin-Weighted Spherical Harmonic modes through applying the 'twisting-up' procedure
69  * [Phys. Rev. D 91, 024043 (2015), Phys.Rev.D85,084003 (2012), Phys. Rev. D 86, 104063 (2012)] to the dominant non-precessing mode from the IMRPhenomT model.
70  *
71  * Different versions for the Euler angles employed in the 'twisting-up' of IMRPhenomT can be selected through
72  * the WaveformParams option 'PhenomXPrecVersion'.
73  *
74  * A specific version can be passed with a 5-digit number specification: #####, where tree first digits have to correspond to a valid
75  * precessing version of the models IMRPhenomXP/IMRPhenomXPHM, fourth digit selects EulerRDVersion internal option, and 5 digit selects
76  * EulerGammaVersion internal option (example, 22310 will select PhenomXPrecVersion=223 for the MSA/NNLO angles calculation, EulerRDVersion=1
77  * and EulerGammaVersion=0.)
78  *
79  * If only three digits are passed, these have to correspond to a valid precessing version of the models IMRPhenomXP/IMRPhenomXPHM, or to be 300
80  * for computing Euler angles from a numerical PN evolution of the precessing equations. In the case of numerical PN evolution, other options don't apply
81  * (for example, it is invalid to call 30010; version 300 always incorporate an approximation of the Euler angles during the ringdown and a numerical
82  * determination of gamma through the minimal rotation condition.)
83  *
84  * Final spin options from IMRPhenomXP/XPHM can also be employed, with the same LAL parameter 'PhenomXFinalSpinMod'. Additional final spin option can be employed when PrecVersion=300, calling PhenomXFinalSpinMod=4.
85  * This new final spin option computes the total in-plane spin at the coalescence (t=0 in model convention) for constructing the geometrical precessing final spin, and employs the parallel components to L of
86  * the individual spins to evaluate the non-precessing final spin fit.
87  *
88  * Summary of options for analytical PN angles:
89  * - EulerRDVersion: 0 (no RD angles attached, MSA/NNLO computed for the whole waveform)
90  * 1 (MSA/NNLO computed up to the peak time of the 22 mode, then RD angles are attached.)
91  * 2 (MSA/NNLO computed up to MECO time, linear continuation performed up to the peak time, then RD angles are attached.)
92  *
93  * - GammaVersion: 0 (Gamma is computed from the MSA/NNLO PN expressions.)
94  * 1 (Gamma computed numerically from minimal rotation condition.)
95  *
96  * List of model versions (values of PhenomXPrecVersion LAL parameters):
97  * - 22300: MSA during the whole waveform duration, including ringdown. Closest to 223 PhenomXP/HM.
98  * - 223/22310: MSA up to the t=0 (peak time of non-precessing 22 mode) and then ringdown angles addition.
99  * - 22311: MSA up to the t=0 (peak time of non-precessing 22 mode), but gamma angle computed numerically from minimal rotation condition, and then ringdown angles addition.
100  * - 22320: MSA up to t=tMECO, then linear continuation of alpha and beta up to t=0, then ringdown angles addition (gamma computed from minimal rotation condition from tMECO).
101  * - 22321: MSA up to t=tMECO, then linear continuation of alpha and beta up to t=0, then ringdown angles addition (gamma computed from minimal rotation during the whole waveform).
102  * - 10200: NNLO during the whole waveform duration, including ringdown. Closest to 102 PhenomXP/HM.
103  * - 102/10210: NNLO up to the t=0 (peak time of non-precessing 22 mode) and then ringdown angles addition.
104  * - 10211: NNLO up to the t=0 (peak time of non-precessing 22 mode), but gamma angle computed numerically from minimal rotation condition, and then ringdown angles addition.
105  * - 10220: NNLO up to t=tMECO, then linear continuation of alpha and beta up to t=0, then ringdown angles addition (gamma computed from minimal rotation condition from tMECO).
106  * - 10221: NNLo up to t=tMECO, then linear continuation of alpha and beta up to t=0, then ringdown angles addition (gamma computed from minimal rotation during the whole waveform).
107  * - 300: Numerical evolution of the precessing spin equations, employing PhenomT 22 mode frequency for approximating orbital frequency. Angles determined by the direction evolution of L(t).
108  * This version accepts the same FinalSpinMod options as 102* versions (i.e, FS=3 corresponds to FS=0) but also admits a computation of final spin reading the spin components at merger, this is specified by FinalSpinMod = 4.
109  *
110  * All analytical versions (MSA/NNLO + different options) can be called with non-default implementations of MSA/NNLO in XP/XPHM (i.e, 224, 104, 220, etc ...)
111  */
112 
113 /**
114  * Routine to compute time-domain polarizations for the IMRPhenomTP model.
115  *
116  * This is a precessing time domain model covering the L=2 sector of Spin-Weighted Spherical Harmonic modes through
117  * applying the 'twisting-up' procedure [Phys. Rev. D 91, 024043 (2015), Phys.Rev.D85,084003 (2012), Phys. Rev. D 86, 104063 (2012)] to the dominant non-precessing mode from the IMRPhenomT/HM models.
118  *
119  */
121  REAL8TimeSeries **hp, /**< [out] TD waveform for plus polarisation */
122  REAL8TimeSeries **hc, /**< [out] TD waveform for cross polarisation */
123  REAL8 m1_SI, /**< Mass of companion 1 (kg) */
124  REAL8 m2_SI, /**< Mass of companion 2 (kg) */
125  REAL8 chi1x, /**< x component of primary spin*/
126  REAL8 chi1y, /**< y component of primary spin*/
127  REAL8 chi1z, /**< z component of primary spin */
128  REAL8 chi2x, /**< x component of secondary spin*/
129  REAL8 chi2y, /**< y component of secondary spin*/
130  REAL8 chi2z, /**< z component of secondary spin */
131  REAL8 distance, /**< Luminosity distance (m) */
132  REAL8 inclination, /**< inclination (in rad) */
133  REAL8 deltaT, /**< sampling interval (s) */
134  REAL8 fmin, /**< starting GW frequency (Hz) */
135  REAL8 fRef, /**< reference GW frequency (Hz) */
136  REAL8 phiRef, /**< reference orbital phase (rad) */
137  LALDict *lalParams /**< LAL dictionary containing accessory parameters */
138  )
139 {
140 
141  UINT4 status;
142 
143  /* Check if aligned spin limit is reached for version 300.
144  If in plane spin is below 10^-8, then fallback to IMRPhenomT model. */
145  REAL8 chi_in_plane = sqrt(pow(chi1x + chi2x,2) + pow(chi1y + chi2y,2));
146  if(chi_in_plane<1e-8 && XLALSimInspiralWaveformParamsLookupPhenomXPrecVersion(lalParams)==300)
147  {
148  status = XLALSimIMRPhenomT(hp, hc, m1_SI, m2_SI, chi1z, chi2z, distance, inclination, deltaT, fmin, fRef, phiRef, lalParams);
149  return status;
150  }
151 
152 
153  /* Compute modes in the L0 frame */
154 
155  SphHarmTimeSeries *hlm = NULL;
156 
157  status = XLALSimIMRPhenomTPHM_L0Modes(&hlm, m1_SI, m2_SI, chi1x,chi1y,chi1z,chi2x,chi2y,chi2z,distance,inclination,deltaT,fmin,fRef,phiRef,lalParams, 1);
158  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: function XLALSimIMRPhenomTPHM_L0Modes has failed.");
159 
160  LIGOTimeGPS epoch = (hlm)->mode->epoch;
161  size_t length = (hlm)->mode->data->length;
162 
163  /* Compute polarisations */
164 
165  /* Auxiliary time series for setting the polarisations to zero */
166  REAL8TimeSeries *hplus = XLALCreateREAL8TimeSeries ("hplus", &epoch, 0.0, deltaT, &lalStrainUnit,length);
167  REAL8TimeSeries *hcross = XLALCreateREAL8TimeSeries ("hcross", &epoch, 0.0, deltaT, &lalStrainUnit,length);
168  memset( hplus->data->data, 0, hplus->data->length * sizeof(REAL8) );
169  memset( hcross->data->data, 0, hcross->data->length * sizeof(REAL8) );
170 
171  /* Add the modes to the polarisations using lalsim routines.
172  Negative modes are explicitely passed, instead of using the symmetry flag */
173 
174  SphHarmTimeSeries *hlms_temp = hlm;
175  while ( hlms_temp )
176  {
177  XLALSimAddMode(hplus, hcross, hlms_temp->mode, inclination, LAL_PI/2. - phiRef, hlms_temp->l, hlms_temp->m, 0);
178  hlms_temp = hlms_temp->next;
179  }
180 
181  /* Point the output pointers to the relevant time series */
182  (*hp) = hplus;
183  (*hc) = hcross;
184 
185  /* Destroy intermediate time series */
187  XLALDestroySphHarmTimeSeries(hlms_temp);
188 
189  return status;
190 }
191 
192 /** @} */
193 /**
194 * @name Routines for IMRPhenomTPHM
195 * @{
196 *
197 * @author Héctor Estellés
198 *
199 * @brief C Code for the IMRPhenomTPHM phenomenological waveform model.
200 *
201 * This is a precessing time domain model covering up to the L=5 sector of Spin-Weighted Spherical Harmonic modes through
202 * applying the 'twisting-up' procedure [Phys. Rev. D 91, 024043 (2015), Phys.Rev.D85,084003 (2012), Phys. Rev. D 86, 104063 (2012)] to the non-precessing modes from the IMRPhenomTHM model.
203 *
204 * @note The same precessing versions specified for the IMRPhenomTP model are available here.
205 */
206 
207 
208 /**
209  * Routine to compute time-domain polarizations for the IMRPhenomTPHM model.
210  *
211  */
213  REAL8TimeSeries **hp, /**< [out] TD waveform for plus polarisation */
214  REAL8TimeSeries **hc, /**< [out] TD waveform for cross polarisation */
215  REAL8 m1_SI, /**< Mass of companion 1 (kg) */
216  REAL8 m2_SI, /**< Mass of companion 2 (kg) */
217  REAL8 chi1x, /**< x component of primary spin*/
218  REAL8 chi1y, /**< y component of primary spin*/
219  REAL8 chi1z, /**< z component of primary spin */
220  REAL8 chi2x, /**< x component of secondary spin*/
221  REAL8 chi2y, /**< y component of secondary spin*/
222  REAL8 chi2z, /**< z component of secondary spin */
223  REAL8 distance, /**< Luminosity distance (m) */
224  REAL8 inclination, /**< inclination (in rad) */
225  REAL8 deltaT, /**< sampling interval (s) */
226  REAL8 fmin, /**< starting GW frequency (Hz) */
227  REAL8 fRef, /**< reference GW frequency (Hz) */
228  REAL8 phiRef, /**< reference orbital phase (rad) */
229  LALDict *lalParams /**< LAL dictionary containing accessory parameters */
230  )
231 {
232 
233  UINT4 status;
234 
235  /* Check if aligned spin limit is reached for version 300.
236  If in plane spin is below 10^-8, then fallback to IMRPhenomTHM model. */
237  REAL8 chi_in_plane = sqrt(pow(chi1x + chi2x,2) + pow(chi1y + chi2y,2));
238  if(chi_in_plane<1e-8 && XLALSimInspiralWaveformParamsLookupPhenomXPrecVersion(lalParams)==300)
239  {
240  status = XLALSimIMRPhenomTHM(hp, hc, m1_SI, m2_SI, chi1z, chi2z, distance, inclination, deltaT, fmin, fRef, phiRef, lalParams);
241  return status;
242  }
243 
244  /* Compute modes in the L0 frame */
245 
246  SphHarmTimeSeries *hlm = NULL;
247 
248  status = XLALSimIMRPhenomTPHM_L0Modes(&hlm, m1_SI, m2_SI, chi1x,chi1y,chi1z,chi2x,chi2y,chi2z,distance,inclination,deltaT,fmin,fRef,phiRef,lalParams,0);
249  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: function XLALSimIMRPhenomTPHM_L0Modes has failed.");
250 
251  LIGOTimeGPS epoch = (hlm)->mode->epoch;
252  size_t length = (hlm)->mode->data->length;
253 
254  /* Compute polarisations */
255 
256  /* Auxiliary time series for setting the polarisations to zero */
257  REAL8TimeSeries *hplus = XLALCreateREAL8TimeSeries ("hplus", &epoch, 0.0, deltaT, &lalStrainUnit,length);
258  REAL8TimeSeries *hcross = XLALCreateREAL8TimeSeries ("hcross", &epoch, 0.0, deltaT, &lalStrainUnit,length);
259  memset( hplus->data->data, 0, hplus->data->length * sizeof(REAL8) );
260  memset( hcross->data->data, 0, hcross->data->length * sizeof(REAL8) );
261 
262  /* Add the modes to the polarisations using lalsim routines.
263  Negative modes are explicitely passed, instead of using the symmetry flag */
264 
265  SphHarmTimeSeries *hlms_temp = hlm;
266  while ( hlms_temp )
267  {
268  XLALSimAddMode(hplus, hcross, hlms_temp->mode, inclination, LAL_PI/2. - phiRef, hlms_temp->l, hlms_temp->m, 0);
269  hlms_temp = hlms_temp->next;
270  }
271 
272  /* Point the output pointers to the relevant time series */
273  (*hp) = hplus;
274  (*hc) = hcross;
275 
276  /* Destroy intermediate time series */
278  XLALDestroySphHarmTimeSeries(hlms_temp);
279 
280  return status;
281 }
282 
283 /**
284  * Routine to be used by ChooseTDModes, it returns a list of the time-domain modes of the IMRPhenomTPHM model in the inertial L0-frame.
285  This is a wrapper for ChooseTDModes with the following justification: it is desirable to mantain a formal dependence on reference phase
286  and inclination for producing the L0 modes employed in the polarisations, in the function XLALSimIMRPhenomTPHM_L0Modes. Although by construction
287  L0 frame modes are independent of these parameters, this will allow to check if this actually satisfied if a new angle description is included.
288  Since for ChooseTDModes one cannot pass these parameters, they are set to 0 in this wrapper.
289  */
291  REAL8 m1_SI, /**< Mass of companion 1 (kg) */
292  REAL8 m2_SI, /**< Mass of companion 2 (kg) */
293  REAL8 chi1x, /**< x component of primary spin*/
294  REAL8 chi1y, /**< y component of primary spin*/
295  REAL8 chi1z, /**< z component of primary spin */
296  REAL8 chi2x, /**< x component of secondary spin*/
297  REAL8 chi2y, /**< y component of secondary spin*/
298  REAL8 chi2z, /**< z component of secondary spin */
299  REAL8 distance, /**< Luminosity distance (m) */
300  REAL8 deltaT, /**< sampling interval (s) */
301  REAL8 fmin, /**< starting GW frequency (Hz) */
302  REAL8 fRef, /**< reference GW frequency (Hz) */
303  LALDict *lalParams /**< LAL dictionary containing accessory parameters */
304  )
305 {
306 
307  INT4 status;
308 
309  /* L0 frame modes are independent of reference phase and inclination */
310  REAL8 phiRef = 0.0;
311  REAL8 inclination = 0.0;
312 
313  /* Compute modes (if a subset of modes is desired, it should be passed through lalParams */
314  SphHarmTimeSeries *hlms = NULL;
315 
316  status = XLALSimIMRPhenomTPHM_L0Modes(&hlms, m1_SI, m2_SI, chi1x,chi1y,chi1z,chi2x,chi2y,chi2z,distance,inclination,deltaT,fmin,fRef,phiRef,lalParams,0);
317  XLAL_CHECK_NULL(status != XLAL_FAILURE, XLAL_EFUNC, "Error: Internal function LALSimIMRPhenomTPHM_L0Modes has failed producing the modes.");
318 
319  return hlms;
320 }
321 
322 /**
323  * Routine to compute a list of the time-domain modes of the IMRPhenomTPHM model in the inertial L0-frame.
324  * This function calls XLALSimIMRPhenomTPHM_JModes for producing the modes in the J-frame and the Euler angles employed
325  * in the rotation between the co-precessing frame and the J-frame. Then it reads the angles value corresponding to the
326  * specified reference frequency and performs and inverse global rotation with these angles from the J-frame to the L0-frame.
327  */
329  SphHarmTimeSeries **hlmI, /**< [out] Modes in the intertial L0=z frame*/
330  REAL8 m1_SI, /**< Mass of companion 1 (kg) */
331  REAL8 m2_SI, /**< Mass of companion 2 (kg) */
332  REAL8 chi1x, /**< x component of primary spin*/
333  REAL8 chi1y, /**< y component of primary spin*/
334  REAL8 chi1z, /**< z component of primary spin */
335  REAL8 chi2x, /**< x component of secondary spin*/
336  REAL8 chi2y, /**< y component of secondary spin*/
337  REAL8 chi2z, /**< z component of secondary spin */
338  REAL8 distance, /**< Luminosity distance (m) */
339  REAL8 inclination, /**< inclination (in rad) */
340  REAL8 deltaT, /**< sampling interval (s) */
341  REAL8 fmin, /**< starting GW frequency (Hz) */
342  REAL8 fRef, /**< reference GW frequency (Hz) */
343  REAL8 phiRef, /**< reference orbital phase (rad) */
344  LALDict *lalParams, /**< LAL dictionary containing accessory parameters */
345  UINT4 only22 /**< Flag for calling only IMRPhenomTP (dominant 22 coprec mode only) */
346  )
347 {
348 
349  UINT4 status;
350 
351 
352  *hlmI = NULL;
353  REAL8TimeSeries *alphaTS = NULL;
354  REAL8TimeSeries *cosbetaTS= NULL;
355  REAL8TimeSeries *gammaTS = NULL;
356  REAL8 af;
357 
358  /* Compute J frame modes */
359  status = XLALSimIMRPhenomTPHM_JModes(hlmI, &alphaTS, &cosbetaTS, &gammaTS, &af, m1_SI, m2_SI, chi1x,chi1y,chi1z,chi2x,chi2y,chi2z,distance,inclination,deltaT,fmin,fRef,phiRef,lalParams,only22);
360  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: function XLALSimIMRPhenomTPHM_JModes has failed.");
361 
362  /* Set up structs for computing tref index */
364  pWF = XLALMalloc(sizeof(IMRPhenomTWaveformStruct));
365  status = IMRPhenomTSetWaveformVariables(pWF, m1_SI, m2_SI, chi1z, chi2z, distance, deltaT, fmin, fRef, phiRef, lalParams);
366  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function IMRPhenomTSetWaveformVariables has failed.");
367 
368  IMRPhenomTPhase22Struct *pPhase;
369  pPhase = XLALMalloc(sizeof(IMRPhenomTPhase22Struct));
371  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function IMRPhenomTSetPhase22Coefficients has failed.");
372 
373  // Compute tref index
374 
375  if(pPhase->tmin<0.0 && pPhase->tRef>=0.0) // Sanity check for reference frequency, to be consistent with _JModes procedure. Proper warning message raised there.
376  {
377  pPhase->tRef = MAX(-8*pWF->dtM, pPhase->tmin);
378  }
379 
380 
381  REAL8 tend = -pPhase->tmin;
382  REAL8 tint1 = tend + pPhase->tRef;
383  size_t length1 = floor(fabs(tint1)/pWF->dtM);
384 
385  // Angles for the global rotation from J-frame to L0-frame: Euler angles evaluated at tref.
386  REAL8 alphaJtoI, cosbetaJtoI, gammaJtoI;
387  alphaJtoI = (alphaTS)->data->data[length1];
388  cosbetaJtoI = (cosbetaTS)->data->data[length1];
389  gammaJtoI = (gammaTS)->data->data[length1];
390 
391  // Perform global rotation from J frame to L0 frame
393  SQRT = XLALMalloc(sizeof(PhenomT_precomputed_sqrt));
395 
396  size_t length = (*hlmI)->mode->data->length;
397  status = PhenomTPHM_RotateModes_Global(*hlmI, -alphaJtoI, cosbetaJtoI, -gammaJtoI, length, SQRT);
398  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function PhenomTPHM_RotateModes_Global has failed.");
399 
400  // Destroy time series
402  XLALDestroyREAL8TimeSeries(cosbetaTS);
404 
405  // Free structs
406  LALFree(pWF);
407  LALFree(pPhase);
408  LALFree(SQRT);
409 
410  return status;
411 }
412 
413 
414 
415 /**
416  * Routine to compute a list of the time-domain modes of the IMRPhenomTPHM model in the inertial J-frame.
417  * It also outputs the time series for the precessing Euler angles in the J-frame.
418  */
420  SphHarmTimeSeries **hlmJ, /**< [out] Modes in the intertial J0=z frame*/
421  REAL8TimeSeries **alphaTS, /**< [out] Precessing Euler angle alpha */
422  REAL8TimeSeries **cosbetaTS, /**< [out] Precessing Euler angle beta */
423  REAL8TimeSeries **gammaTS, /**< [out] Precessing Euler angle gamma */
424  REAL8 *af, /**< [out] Final spin */
425  REAL8 m1_SI, /**< Mass of companion 1 (kg) */
426  REAL8 m2_SI, /**< Mass of companion 2 (kg) */
427  REAL8 chi1x, /**< x component of primary spin*/
428  REAL8 chi1y, /**< y component of primary spin*/
429  REAL8 chi1z, /**< z component of primary spin */
430  REAL8 chi2x, /**< x component of secondary spin*/
431  REAL8 chi2y, /**< y component of secondary spin*/
432  REAL8 chi2z, /**< z component of secondary spin */
433  REAL8 distance, /**< Luminosity distance (m) */
434  REAL8 inclination, /**< inclination (in rad) */
435  REAL8 deltaT, /**< sampling interval (s) */
436  REAL8 fmin, /**< starting GW frequency (Hz) */
437  REAL8 fRef, /**< reference GW frequency (Hz) */
438  REAL8 phiRef, /**< reference orbital phase (rad) */
439  LALDict *lalParams, /**< LAL dictionary containing accessory parameters */
440  UINT4 only22 /**< Flag for calling only IMRPhenomTP (dominant 22 coprec mode only) */
441  )
442 {
443 
444  UINT4 status;
445 
446  /* Compute co-precessing modes and Euler angles */
447  *hlmJ = NULL;
448  status = XLALSimIMRPhenomTPHM_CoprecModes(hlmJ, alphaTS, cosbetaTS, gammaTS, af, m1_SI, m2_SI, chi1x,chi1y,chi1z,chi2x,chi2y,chi2z,distance,inclination,deltaT,fmin,fRef,phiRef,lalParams,only22);
449  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: function XLALSimIMRPhenomTPHM_JModes has failed.");
450 
451  /* Rotate coprecessing modes to J frame */
452 
454  SQRT = XLALMalloc(sizeof(PhenomT_precomputed_sqrt));
456 
457  status = PhenomTPHM_RotateModes(*hlmJ, *gammaTS, *cosbetaTS, *alphaTS, SQRT);
458  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function PhenomTPHM_RotateModes has failed.");
459 
460  LALFree(SQRT);
461 
462  return status;
463 }
464 
465 /**
466  * Routine to compute a list of the time-domain modes of the IMRPhenomTPHM model in the co-precessing frame.
467  * It also outputs the time series for the precessing Euler angles in the J-frame.
468  */
470  SphHarmTimeSeries **hlmJ, /**< [out] Modes in the intertial J0=z frame*/
471  REAL8TimeSeries **alphaTS, /**< [out] Precessing Euler angle alpha */
472  REAL8TimeSeries **cosbetaTS, /**< [out] Precessing Euler angle beta */
473  REAL8TimeSeries **gammaTS, /**< [out] Precessing Euler angle gamma */
474  REAL8 *af, /**< [out] Final spin */
475  REAL8 m1_SI, /**< Mass of companion 1 (kg) */
476  REAL8 m2_SI, /**< Mass of companion 2 (kg) */
477  REAL8 chi1x, /**< x component of primary spin*/
478  REAL8 chi1y, /**< y component of primary spin*/
479  REAL8 chi1z, /**< z component of primary spin */
480  REAL8 chi2x, /**< x component of secondary spin*/
481  REAL8 chi2y, /**< y component of secondary spin*/
482  REAL8 chi2z, /**< z component of secondary spin */
483  REAL8 distance, /**< Luminosity distance (m) */
484  REAL8 inclination, /**< inclination (in rad) */
485  REAL8 deltaT, /**< sampling interval (s) */
486  REAL8 fmin, /**< starting GW frequency (Hz) */
487  REAL8 fRef, /**< reference GW frequency (Hz) */
488  REAL8 phiRef, /**< reference orbital phase (rad) */
489  LALDict *lalParams, /**< LAL dictionary containing accessory parameters */
490  UINT4 only22 /**< Flag for calling only IMRPhenomTP (dominant 22 coprec mode only) */
491  )
492 {
493 
494  /* Sanity checks */
495  if(fRef < 0.0) { XLAL_ERROR(XLAL_EDOM, "fRef_In must be positive or set to 0 to ignore.\n"); }
496  if(deltaT <= 0.0) { XLAL_ERROR(XLAL_EDOM, "deltaT must be positive.\n"); }
497  if(m1_SI <= 0.0) { XLAL_ERROR(XLAL_EDOM, "m1 must be positive.\n"); }
498  if(m2_SI <= 0.0) { XLAL_ERROR(XLAL_EDOM, "m2 must be positive.\n"); }
499  if(fmin <= 0.0) { XLAL_ERROR(XLAL_EDOM, "f_min must be positive.\n"); }
500  if(distance <= 0.0) { XLAL_ERROR(XLAL_EDOM, "Distance must be positive and greater than 0.\n"); }
501  if(fRef > 0.0 && fRef < fmin){ XLAL_ERROR(XLAL_EDOM, "fRef must be >= f_min or =0 to use f_min.\n"); }
502 
503  /* Swap components if m2>m1 */
504  if(m1_SI < m2_SI)
505  {
506  REAL8 auxswap;
507 
508  auxswap = m2_SI;
509  m2_SI = m1_SI;
510  m1_SI = auxswap;
511 
512  auxswap = chi2x;
513  chi2x = chi1x;
514  chi1x = auxswap;
515 
516  auxswap = chi2y;
517  chi2y = chi1y;
518  chi1y = auxswap;
519 
520  auxswap = chi2z;
521  chi2z = chi1z;
522  chi1z = auxswap;
523  }
524 
525  REAL8 mass_ratio = m1_SI / m2_SI;
526  REAL8 chi1L = chi1z;
527  REAL8 chi2L = chi2z;
528 
529  /*
530  Perform a basic sanity check on the region of the parameter space in which model is evaluated. Behaviour is as follows:
531  - For mass ratios <= 20.0 and spins <= 0.99: no warning messages.
532  - For 200 > mass ratio > 20 and spins <= 0.9: print a warning message that model can be pathological.
533  - For mass ratios > 200: throw a hard error that model is not valid.
534  - For spins > 0.99: throw a warning that we are extrapolating the model to extremal
535  */
536 
537  if(mass_ratio > 20.0 && chi1L < 0.9 && m2_SI/LAL_MSUN_SI >= 0.5 ) { XLAL_PRINT_INFO("Warning: Extrapolating outside of Numerical Relativity calibration domain."); }
538  if(mass_ratio > 20.0 && (chi1L >= 0.9 || m2_SI/LAL_MSUN_SI < 0.5) ) { XLAL_PRINT_INFO("Warning: Model can be pathological at these parameters"); }
539  if(mass_ratio > 200. && fabs(mass_ratio - 200) > 1e-12) { XLAL_ERROR(XLAL_EDOM, "ERROR: Model not valid at mass ratios beyond 200."); } // The 1e-12 is to avoid rounding errors
540  if(fabs(chi1L) > 0.99 || fabs(chi2L) > 0.99) { XLAL_PRINT_INFO("Warning: Extrapolating to extremal spins, model is not trusted."); }
541 
542  /* Set up model options specified in precessing version */
543  UNUSED INT4 precVer, precVerX, EulerRDVersion, EulerGammaVersion, EulerInspVersion, FSVer;
544  UNUSED INT4 evolvedFS = 0;
547  UINT4 reconsMerger = XLALSimInspiralWaveformParamsLookupPhenomTPHMMergerVersion(lalParams); // FIXME:Internal option, will be deleted for release
548  char digits[6];
549  INT4 lendigits = snprintf(digits, 6, "%d", precVer);
550 
551  if(lendigits == 5)
552  {
553  sprintf(digits, "%d", precVer);
554  sscanf(digits, "%3d%1d%1d", &precVerX, &EulerRDVersion, &EulerGammaVersion);
555  EulerInspVersion = 0;
556  if(EulerRDVersion>2 || EulerRDVersion<0){XLAL_ERROR(XLAL_EDOM, "Invalid EulerRDVersion. Choose between 0, 1, and 2.\n");}
557  if(EulerGammaVersion>1 || EulerGammaVersion<0){XLAL_ERROR(XLAL_EDOM, "Invalid EulerGammaVersion. Choose between 0, 1.\n");}
558 
559  }
560  else if(lendigits==3 && precVer==300)
561  {
562  EulerInspVersion = 1;
563  precVerX = 102; // Default version for IMRPhenomX struct
564  if(FSVer==4)
565  {
566  evolvedFS = 1;
567  FSVer = 2;
568  }
569  }
570  else if(lendigits==3 && precVer!=300)
571  {
572  EulerInspVersion = 0;
573  precVerX = precVer;
574  EulerRDVersion = 1; // Default ringdown version for analytical angles
575  EulerGammaVersion = 0;
576  }
577  else
578  {
579  XLAL_ERROR(XLAL_EDOM, "Incorrect format/values for PhenomXPrecVersion option.\n");
580  }
581 
582 
583  INT4 status;
584 
585  /* Use an auxiliar laldict to not overwrite the input argument */
586  LALDict *lalParams_aux;
587  if (lalParams == NULL)
588  {
589  lalParams_aux = XLALCreateDict();
590  }
591  else{
592  lalParams_aux = XLALDictDuplicate(lalParams);
593  }
594  /* Setup mode array */
595  UINT4 LMAX;
596  LALValue *ModeArray = NULL;
597 
598  if(only22==0)
599  {
600  XLAL_CHECK(check_input_mode_array_THM(lalParams_aux) == XLAL_SUCCESS, XLAL_EFAULT, "Not available mode chosen.\n");
601  lalParams_aux = IMRPhenomTHM_setup_mode_array(lalParams_aux);
602  ModeArray = XLALSimInspiralWaveformParamsLookupModeArray(lalParams_aux);
603  }
604  else if(only22==1)
605  {
606  XLAL_CHECK(check_input_mode_array_22_THM(lalParams_aux) == XLAL_SUCCESS, XLAL_EFAULT, "Not available mode chosen.\n");
607  ModeArray = XLALSimInspiralWaveformParamsLookupModeArray(lalParams_aux);
608  if(ModeArray==NULL)
609  {
610  ModeArray = XLALSimInspiralCreateModeArray();
611  /* Activate (2,2) and (2,-2) modes*/
612  XLALSimInspiralModeArrayActivateMode(ModeArray, 2, 2);
613  XLALSimInspiralModeArrayActivateMode(ModeArray, 2, -2);
614  /* Insert ModeArray into lalParams */
615  XLALSimInspiralWaveformParamsInsertModeArray(lalParams_aux, ModeArray);
616  }
617  LMAX = 2;
618  }
619 
620  /* Select maximum L for which modes have to be activated */
621 
622  if(XLALSimInspiralModeArrayIsModeActive(ModeArray, 5, 5)==1||XLALSimInspiralModeArrayIsModeActive(ModeArray, 5, -5)==1)
623  {
624  LMAX = 5;
625  }
626  else if(XLALSimInspiralModeArrayIsModeActive(ModeArray, 4, 4)==1||XLALSimInspiralModeArrayIsModeActive(ModeArray, 4, -4)==1)
627  {
628  LMAX = 4;
629  }
630  else if(XLALSimInspiralModeArrayIsModeActive(ModeArray, 3, 3)==1||XLALSimInspiralModeArrayIsModeActive(ModeArray, 3, -3)==1)
631  {
632  LMAX = 3;
633  }
634  else{
635  LMAX=2;}
636 
637  /* Add PrecVersion and FinalSpin options */
640 
641  /* Initialise waveform struct and phase/frequency struct for the 22, needed for any mode */
643  pWF = XLALMalloc(sizeof(IMRPhenomTWaveformStruct));
644  status = IMRPhenomTSetWaveformVariables(pWF, m1_SI, m2_SI, chi1L, chi2L, distance, deltaT, fmin, fRef, phiRef, lalParams_aux);
645  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function IMRPhenomTSetWaveformVariables has failed.");
646 
647  /* Initialize IMR PhenomX Waveform struct and check that it initialized correctly */
649  pWFX = XLALMalloc(sizeof(IMRPhenomXWaveformStruct));
650  status = IMRPhenomXSetWaveformVariables(pWFX, m1_SI, m2_SI, chi1L, chi2L, 0.1, fRef, phiRef, fmin, 1./deltaT, distance, inclination, lalParams_aux, 0);
651  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: IMRPhenomXSetWaveformVariables failed.\n");
652 
653  /* Initialize IMR PhenomX Precession struct and check that it generated successfully */
655  pPrec = XLALMalloc(sizeof(IMRPhenomXPrecessionStruct));
656  status = IMRPhenomXGetAndSetPrecessionVariables(pWFX, pPrec, m1_SI, m2_SI, chi1x, chi1y, chi1z, chi2x, chi2y, chi2z, lalParams_aux, 0);
657  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: IMRPhenomXSetPrecessionVariables failed.\n");
658 
659  pWF->afinal_prec = pWFX->afinal; // Set final spin to its precessing value
660  if(reconsMerger!=1)
661  {
662  pWF->afinal = pWFX->afinal; // FIXME: Internal option, will be removed before merging to master.
663  }
664 
665  IMRPhenomTPhase22Struct *pPhase;
666  pPhase = XLALMalloc(sizeof(IMRPhenomTPhase22Struct));
668  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function IMRPhenomTSetPhase22Coefficients has failed.");
669 
670  /* Length of the required sequence and length of the different inspiral regions of the 22 phase. */
671  size_t length = pPhase->wflength;
672  size_t length_insp_early = pPhase->wflength_insp_early;
673  size_t length_insp_late = pPhase->wflength_insp_late;
674  size_t length_insp = length_insp_early + length_insp_late;
675 
676  /*Initialize time */
677  REAL8 t, thetabar, theta, w22, ph22;
678  REAL8 factheta = pow(5.0,1./8);
679 
680  /* Initialize REAL8 sequences for storing the phase and the frequency of the 22 */
681  UNUSED REAL8Sequence *phi22 = NULL;
682  REAL8Sequence *xorb = NULL;
683  xorb = XLALCreateREAL8Sequence(length);
684  REAL8Sequence *timesVec = NULL;
685  timesVec = XLALCreateREAL8Sequence(length);
686 
687  phi22 = XLALCreateREAL8Sequence(length);
688 
689  LIGOTimeGPS ligotimegps_zero = LIGOTIMEGPSZERO; // = {0,0}
690  XLALGPSAdd(&ligotimegps_zero, pPhase->tminSec);
691 
692  /* Compute 22 phase and x=(0.5*omega_22)^(2/3), needed for all modes.
693  Depending on the inspiral region, theta is defined with a fitted t0 parameter or with t0=0. */
694 
695  if(pWF->inspVersion!=0) // If reconstruction is non-default, this will compute frequency, phase and PN expansion parameter x from TaylorT3 with fitted t0 for the early inspiral region-
696  {
697  for(UINT4 jdx = 0; jdx < length_insp_early; jdx++)
698  {
699  t = pPhase->tmin + jdx*pWF->dtM;
700  thetabar = pow(pWF->eta*(pPhase->tt0-t),-1./8);
701  theta = factheta*thetabar;
702  w22 = IMRPhenomTomega22(t, theta, pWF, pPhase);
703  xorb->data[jdx] = pow(0.5*w22,2./3);
704  ph22 = IMRPhenomTPhase22(t, thetabar, pWF, pPhase);
705  phi22->data[jdx] = ph22;
706  }
707 
708  for(UINT4 jdx = length_insp_early; jdx < length_insp; jdx++) // For times later than the early-late inspiral boundary, it computes phase, frequency and x with the extended TaylorT3 (with tt0=0)
709  {
710  t = pPhase->tmin + jdx*pWF->dtM;
711  thetabar = pow(-pWF->eta*t,-1./8);
712  theta = factheta*thetabar;
713  w22 = IMRPhenomTomega22(t, theta, pWF, pPhase);
714  xorb->data[jdx] = pow(0.5*w22,2./3);
715  ph22 = IMRPhenomTPhase22(t, thetabar, pWF, pPhase);
716  phi22->data[jdx] = ph22;
717  }
718  }
719 
720  else // If default reconstruction, only one inspiral region with extended TaylorT3 (with tt0=0) is employed up to the inspiral-merger boundary time
721  {
722  for(UINT4 jdx = 0; jdx < length_insp; jdx++)
723  {
724  t = pPhase->tmin + jdx*pWF->dtM;
725  thetabar = pow(-pWF->eta*t,-1./8);
726  theta = factheta*thetabar;
727  w22 = IMRPhenomTomega22(t, theta, pWF, pPhase);
728  xorb->data[jdx] = pow(0.5*w22,2./3);
729  ph22 = IMRPhenomTPhase22(t, thetabar, pWF, pPhase);
730  phi22->data[jdx] = ph22;
731  }
732 
733  }
734 
735  /* During the 22 phase merger region, phase and x are also computed because the higher modes end the inspiral at a fixed time,
736  which can occur later than the end of the 22 inspiral. */
737  for(UINT4 jdx = length_insp; jdx < length; jdx++)
738  {
739  t = pPhase->tmin + jdx*pWF->dtM;
740  w22 = IMRPhenomTomega22(t, 0.0, pWF, pPhase);
741  xorb->data[jdx] = pow(0.5*w22,2./3);
742  ph22 = IMRPhenomTPhase22(t, 0.0, pWF, pPhase);
743  phi22->data[jdx] = ph22;
744  }
745 
746  /****** Compute Euler angles *******/
747 
748  *alphaTS = XLALCreateREAL8TimeSeries( "alphaPtoJ", &ligotimegps_zero, 0.0, deltaT, &lalStrainUnit,length);
749  *cosbetaTS = XLALCreateREAL8TimeSeries( "cosbetaPtoJ", &ligotimegps_zero, 0.0, deltaT, &lalStrainUnit,length);
750  *gammaTS = XLALCreateREAL8TimeSeries( "epsilonPtoJ", &ligotimegps_zero, 0.0, deltaT, &lalStrainUnit,length);
751 
752  /* Check validity of fRef and fmin. If fmin>f_peak, proceed with analytical angles with EulerRDVersion=1, to just have ringdown waveforms.
753  If f_min<f_peak but fRef>fpeak, and numerical angles are selected, then default fRef to some maximal allowed value, close to the peak, warning the user. */
754 
755  if(pPhase->tmin>=-10*pWF->dtM)
756  {
757  EulerInspVersion = 0;
758  EulerRDVersion = 1;
759  EulerGammaVersion = 0;
760 
761  XLAL_PRINT_WARNING("Waveform only contains ringdown, version 300 not meaningful. Defaulting to analytical ringdown angles (EulerInspVersion=0, EulerRDVersion=1.)\n");
762  }
763  else if(pPhase->tRef>=-8*pWF->dtM)
764  {
765  pPhase->tRef = MAX(-8*pWF->dtM, pPhase->tmin);
766  XLAL_PRINT_WARNING("Waveform contains pre-peak cycles but reference frequency is specified post-peak, which may be not meaningful. Reference frequency will be set close before the peak. \n");
767  }
768 
769  if(EulerInspVersion==1)
770  {
771  REAL8 af_evolved;
772  status = IMRPhenomTPHM_NumericalEulerAngles(alphaTS,cosbetaTS,gammaTS, &af_evolved, xorb, pPhase->dtM,m1_SI, m2_SI, chi1x,chi1y,chi1z,chi2x,chi2y,chi2z,pPhase->tmin, pWF, pPhase, pPrec);
773  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function IMRPhenomTPHM_NumericalEulerAngles has failed.");
774 
775  if(evolvedFS==1)
776  {
777  pWF->afinal_prec = af_evolved;
778  if(!(reconsMerger==1))
779  {
780  pWF->afinal = af_evolved;
781  }
782 
783  IMRPhenomTPhase22Struct *pPhase2;
784  pPhase2 = XLALMalloc(sizeof(IMRPhenomTPhase22Struct));
786  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function IMRPhenomTSetPhase22Coefficients has failed.");
787 
788  for(UINT4 jdx = length_insp; jdx < length; jdx++)
789  {
790  t = pPhase->tmin + jdx*pWF->dtM;
791 
792  w22 = IMRPhenomTomega22(t, 0.0, pWF, pPhase2);
793  xorb->data[jdx] = pow(0.5*w22,2./3);
794  ph22 = IMRPhenomTPhase22(t, 0.0, pWF, pPhase2);
795 
796  phi22->data[jdx] = ph22;
797  }
798 
799  LALFree(pPhase2);
800  }
801  }
802  else
803  {
804  status = PNAnalyticalInspiralEulerAngles(alphaTS, cosbetaTS, gammaTS, xorb, pWF, pPhase, pWFX, pPrec, EulerRDVersion, EulerGammaVersion);
805  XLAL_CHECK(XLAL_SUCCESS == status, XLAL_EFUNC, "Error: Internal function PNAnalyticalInspiralEulerAngles has failed.");
806  }
807 
808  *af = pWF->afinal;
809 
810  /***** Loop over modes ******/
811 
812  *hlmJ = NULL;
813 
814  INT4 posMode, negMode;
815 
816  for (UINT4 ell = 2; ell <= LMAX; ell++)
817  {
818  for (UINT4 emm = 0; emm <= ell; emm++)
819  { /* Loop over only positive m is intentional.*/
820 
821  posMode = XLALSimInspiralModeArrayIsModeActive(ModeArray, ell, emm);
822  negMode = XLALSimInspiralModeArrayIsModeActive(ModeArray, ell, -emm);
823  if ( posMode != 1 && negMode != 1)
824  { /* skip mode */
825  COMPLEX16TimeSeries *tmp_mode = XLALCreateCOMPLEX16TimeSeries( "hlm", &ligotimegps_zero, 0.0, deltaT, &lalStrainUnit,length);
826  memset( tmp_mode->data->data, 0, tmp_mode->data->length * sizeof(COMPLEX16) );
827  *hlmJ = XLALSphHarmTimeSeriesAddMode(*hlmJ, tmp_mode, ell, emm);
828  *hlmJ = XLALSphHarmTimeSeriesAddMode(*hlmJ, tmp_mode, ell, -emm);
830  continue;
831  } /* else: generate mode */
832 
833  COMPLEX16TimeSeries *tmp_mode = NULL;
834 
835  status = LALSimIMRPhenomTHM_OneMode(&tmp_mode, pWF, pPhase, phi22, xorb, ell, emm);
836 
837  if(posMode==1) /* Modes are generated only for positive m. If positive m is requested, simply add to the SphHarmTimeSeries structure */
838  {
839  *hlmJ = XLALSphHarmTimeSeriesAddMode(*hlmJ, tmp_mode, ell, emm);
840  }
841 
842  if(negMode==1) /* If negative m is requested, transform from positive m mode using symmetry property for aligned spin systems */
843  {
844  for(UINT4 jdx = 0; jdx < length; jdx++)
845  {
846  ((*tmp_mode).data)->data[jdx] = pow(-1,ell)*conj(((*tmp_mode).data)->data[jdx]);
847  }
848  *hlmJ = XLALSphHarmTimeSeriesAddMode(*hlmJ, tmp_mode, ell, -emm);
849  }
850 
851  XLALDestroyCOMPLEX16TimeSeries(tmp_mode); /* Destroy temporary structure once the desired mode is added */
852  }
853 
854  }
855 
856  /*Free structures and destroy sequences and dict */
857  XLALDestroyValue(ModeArray);
858  LALFree(pPhase);
859  LALFree(pWF);
860  LALFree(pWFX);
861  LALFree(pPrec);
862 
864 
866  XLALDestroyREAL8Sequence(timesVec);
867 
868  XLALDestroyDict(lalParams_aux);
869 
870  return status;
871 }
872 
873 /** @} */
874 /** @} */
void XLALDestroyDict(LALDict *dict)
LALDict * XLALDictDuplicate(LALDict *old)
LALDict * XLALCreateDict(void)
#define LALFree(p)
INT4 check_input_mode_array_THM(LALDict *lalParams)
int LALSimIMRPhenomTHM_OneMode(COMPLEX16TimeSeries **hlm, IMRPhenomTWaveformStruct *pWF, IMRPhenomTPhase22Struct *pPhase, REAL8Sequence *phase22, REAL8Sequence *xorb, UINT4 ell, UINT4 emm)
INT4 check_input_mode_array_22_THM(LALDict *lalParams)
LALDict * IMRPhenomTHM_setup_mode_array(LALDict *lalParams)
double IMRPhenomTomega22(REAL8 t, REAL8 theta, IMRPhenomTWaveformStruct *pWF, IMRPhenomTPhase22Struct *pPhase)
int IMRPhenomTSetPhase22Coefficients(IMRPhenomTPhase22Struct *pPhase, IMRPhenomTWaveformStruct *wf)
int IMRPhenomTSetWaveformVariables(IMRPhenomTWaveformStruct *wf, const REAL8 m1_SI, const REAL8 m2_SI, const REAL8 chi1L_In, const REAL8 chi2L_In, const REAL8 distance, const REAL8 deltaT, const REAL8 fmin, const REAL8 fRef, const REAL8 phiRef, LALDict *lalParams)
double IMRPhenomTPhase22(REAL8 t, REAL8 thetabar, IMRPhenomTWaveformStruct *pWF, IMRPhenomTPhase22Struct *pPhase)
#define MAX(a, b)
int PNAnalyticalInspiralEulerAngles(REAL8TimeSeries **alphaTS, REAL8TimeSeries **cosbetaTS, REAL8TimeSeries **gammaTS, REAL8Sequence *xorb, IMRPhenomTWaveformStruct *pWF, IMRPhenomTPhase22Struct *pPhase, IMRPhenomXWaveformStruct *pWFX, IMRPhenomXPrecessionStruct *pPrec, INT4 EulerRDVersion, INT4 GammaVersion)
This function provides a wrapper to the analytical PN angle descriptions computed by the IMRPhenomXP(...
int IMRPhenomTPHM_NumericalEulerAngles(REAL8TimeSeries **alphaInt, REAL8TimeSeries **cosbetaInt, REAL8TimeSeries **gammaInt, REAL8 *af_evolved, REAL8Sequence *xorb, REAL8 deltaT, REAL8 m1_SI, REAL8 m2_SI, REAL8 s1x, REAL8 s1y, REAL8 s1z, REAL8 s2x, REAL8 s2y, REAL8 s2z, REAL8 epochT, IMRPhenomTWaveformStruct *pWF, IMRPhenomTPhase22Struct *pPhase, UNUSED IMRPhenomXPrecessionStruct *pPrec)
int PhenomTPHM_RotateModes_Global(SphHarmTimeSeries *h_lm, REAL8 alpha, REAL8 cosbeta, REAL8 gam, size_t length, PhenomT_precomputed_sqrt *SQRT)
void IMRPhenomTPHM_SetPrecomputedSqrt(PhenomT_precomputed_sqrt *SQRT)
int PhenomTPHM_RotateModes(SphHarmTimeSeries *h_lm, REAL8TimeSeries *alpha, REAL8TimeSeries *cosbeta, REAL8TimeSeries *gam, PhenomT_precomputed_sqrt *SQRT)
int IMRPhenomXSetWaveformVariables(IMRPhenomXWaveformStruct *wf, const REAL8 m1_SI, const REAL8 m2_SI, const REAL8 chi1L_In, const REAL8 chi2L_In, const REAL8 deltaF, const REAL8 fRef, const REAL8 phi0, const REAL8 f_min, const REAL8 f_max, const REAL8 distance, const REAL8 inclination, LALDict *LALParams, UNUSED const UINT4 debug)
int IMRPhenomXGetAndSetPrecessionVariables(IMRPhenomXWaveformStruct *pWF, IMRPhenomXPrecessionStruct *pPrec, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, LALDict *lalParams, INT4 debug_flag)
Function to populate the IMRPhenomXPrecessionStruct:
int XLALSimInspiralWaveformParamsInsertModeArray(LALDict *params, LALValue *value)
LALValue * XLALSimInspiralWaveformParamsLookupModeArray(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXPrecVersion(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXPFinalSpinMod(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomTPHMMergerVersion(LALDict *params)
int XLALSimInspiralWaveformParamsInsertPhenomXPFinalSpinMod(LALDict *params, INT4 value)
int XLALSimInspiralWaveformParamsInsertPhenomXPrecVersion(LALDict *params, INT4 value)
void XLALDestroyValue(LALValue *value)
double e
Definition: bh_ringdown.c:117
double theta
Definition: bh_sphwf.c:118
sigmaKerr data[0]
#define LAL_MSUN_SI
#define LAL_PI
#define LIGOTIMEGPSZERO
double complex COMPLEX16
double REAL8
uint32_t UINT4
int32_t INT4
void * XLALMalloc(size_t n)
SphHarmTimeSeries * XLALSimIMRPhenomTPHM_ChooseTDModes(REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, REAL8 distance, REAL8 deltaT, REAL8 fmin, REAL8 fRef, LALDict *lalParams)
Routine to be used by ChooseTDModes, it returns a list of the time-domain modes of the IMRPhenomTPHM ...
int XLALSimIMRPhenomTHM(REAL8TimeSeries **hp, REAL8TimeSeries **hc, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1L, REAL8 chi2L, REAL8 distance, REAL8 inclination, REAL8 deltaT, REAL8 fmin, REAL8 fRef, REAL8 phiRef, LALDict *lalparams)
Routine to compute time domain polarisations for IMRPhenomTHM model.
int XLALSimIMRPhenomTPHM_JModes(SphHarmTimeSeries **hlmJ, REAL8TimeSeries **alphaTS, REAL8TimeSeries **cosbetaTS, REAL8TimeSeries **gammaTS, REAL8 *af, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, REAL8 distance, REAL8 inclination, REAL8 deltaT, REAL8 fmin, REAL8 fRef, REAL8 phiRef, LALDict *lalParams, UINT4 only22)
Routine to compute a list of the time-domain modes of the IMRPhenomTPHM model in the inertial J-frame...
int XLALSimIMRPhenomTPHM_CoprecModes(SphHarmTimeSeries **hlmJ, REAL8TimeSeries **alphaTS, REAL8TimeSeries **cosbetaTS, REAL8TimeSeries **gammaTS, REAL8 *af, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, REAL8 distance, REAL8 inclination, REAL8 deltaT, REAL8 fmin, REAL8 fRef, REAL8 phiRef, LALDict *lalParams, UINT4 only22)
Routine to compute a list of the time-domain modes of the IMRPhenomTPHM model in the co-precessing fr...
int XLALSimIMRPhenomT(REAL8TimeSeries **hp, REAL8TimeSeries **hc, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1L, REAL8 chi2L, REAL8 distance, REAL8 inclination, REAL8 deltaT, REAL8 fmin, REAL8 fRef, REAL8 phiRef, LALDict *lalParams)
Routine to compute time domain polarisations for IMRPhenomT model.
int XLALSimIMRPhenomTPHM(REAL8TimeSeries **hp, REAL8TimeSeries **hc, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, REAL8 distance, REAL8 inclination, REAL8 deltaT, REAL8 fmin, REAL8 fRef, REAL8 phiRef, LALDict *lalParams)
Routine to compute time-domain polarizations for the IMRPhenomTPHM model.
int XLALSimIMRPhenomTP(REAL8TimeSeries **hp, REAL8TimeSeries **hc, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, REAL8 distance, REAL8 inclination, REAL8 deltaT, REAL8 fmin, REAL8 fRef, REAL8 phiRef, LALDict *lalParams)
Routine to compute time-domain polarizations for the IMRPhenomTP model.
int XLALSimIMRPhenomTPHM_L0Modes(SphHarmTimeSeries **hlmI, REAL8 m1_SI, REAL8 m2_SI, REAL8 chi1x, REAL8 chi1y, REAL8 chi1z, REAL8 chi2x, REAL8 chi2y, REAL8 chi2z, REAL8 distance, REAL8 inclination, REAL8 deltaT, REAL8 fmin, REAL8 fRef, REAL8 phiRef, LALDict *lalParams, UINT4 only22)
Routine to compute a list of the time-domain modes of the IMRPhenomTPHM model in the inertial L0-fram...
LALValue * XLALSimInspiralCreateModeArray(void)
Create a LALValue pointer to store the mode array.
int XLALSimInspiralModeArrayIsModeActive(LALValue *modes, unsigned l, int m)
LALValue * XLALSimInspiralModeArrayActivateMode(LALValue *modes, unsigned l, int m)
int XLALSimAddMode(REAL8TimeSeries *hplus, REAL8TimeSeries *hcross, COMPLEX16TimeSeries *hmode, REAL8 theta, REAL8 phi, int l, int m, int sym)
Multiplies a mode h(l,m) by a spin-2 weighted spherical harmonic to obtain hplus - i hcross,...
SphHarmTimeSeries * XLALSphHarmTimeSeriesAddMode(SphHarmTimeSeries *appended, const COMPLEX16TimeSeries *inmode, UINT4 l, INT4 m)
Prepend a node to a linked list of SphHarmTimeSeries, or create a new head.
void XLALDestroySphHarmTimeSeries(SphHarmTimeSeries *ts)
Delete list from current pointer to the end of the list.
void XLALDestroyREAL8Sequence(REAL8Sequence *sequence)
REAL8Sequence * XLALCreateREAL8Sequence(size_t length)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
void XLALDestroyCOMPLEX16TimeSeries(COMPLEX16TimeSeries *series)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
COMPLEX16TimeSeries * XLALCreateCOMPLEX16TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalStrainUnit
#define XLAL_PRINT_INFO(...)
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
#define XLAL_PRINT_WARNING(...)
#define XLAL_CHECK_NULL(assertion,...)
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_FAILURE
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
string status
COMPLEX16Sequence * data
COMPLEX16 * data
REAL8Sequence * data
REAL8 * data
Structure to carry a collection of spherical harmonic modes in COMPLEX16 time series.
struct tagSphHarmTimeSeries * next
next pointer
COMPLEX16TimeSeries * mode
The sequences of sampled data.
INT4 m
Node submode m
UINT4 l
Node mode l
LIGOTimeGPS epoch
Definition: unicorn.c:20
double deltaT
Definition: unicorn.c:24