LALSimulation  5.4.0.1-fe68b98
LALSimIMRLackeyTidal2013.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016 Michael Puerrer, Prayush Kumar
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 #ifdef __GNUC__
21 #define UNUSED __attribute__ ((unused))
22 #else
23 #define UNUSED
24 #endif
25 
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <complex.h>
31 
32 #include <lal/Units.h>
33 #include <lal/SeqFactories.h>
34 #include <lal/LALConstants.h>
35 #include <lal/XLALError.h>
36 #include <lal/FrequencySeries.h>
37 #include <lal/Sequence.h>
38 #include <lal/LALSimIMR.h>
39 
41 
42 
43 /*************** Model coefficients ******************/
44 
45 // Amplitude correction factors for SEOBNRv2
46 // Define constants as per Eq 33 of Lackey et al, arXiv:1303.6298.
47 const double b0 = -1424.2;
48 const double b1 = 6423.4;
49 const double b2 = 0.84203;
50 const double c0 = -9.7628;
51 const double c1 = 33.939;
52 const double c2 = 1.0971;
53 // Phase correction factors
54 const double g0 = -4.6339;
55 const double g1 = 27.719;
56 const double g2 = 10.268;
57 const double g3 = -41.741;
58 
59 
60 /********************* Definitions begin here ********************/
61 
63  double *C,
64  const double eta,
65  const double chi_BH,
66  const double Lambda
67 ) {
68  // Coefficient in the amplitude factor, Eq 33 of Lackey et al
69  *C = exp(b0 + b1*eta + b2*chi_BH)
70  + Lambda * exp(c0 + c1*eta + c2*chi_BH);
71 }
72 
74  const double Mf,
75  const double C,
76  const double eta,
77  const double Lambda
78 ) {
79  const double MfA = 0.01; // amplitude transition frequency
80  if (Mf <= MfA)
81  return 1.0;
82  else {
83  // Generate the amplitude factor, Eq 33 of Lackey et al
84  double dMf = Mf - MfA;
85  double dMf2 = dMf*dMf;
86  double B = C * dMf*dMf2;
87  return exp(-eta * Lambda * B);
88  }
89 }
90 
91 // precompute a0, a1 and G which do not depend on frequency
93  double *a0,
94  double *a1,
95  double *G,
96  const double eta,
97  const double chi_BH,
98  const double Lambda
99 ) {
100  // First compute the PN inspiral phasing correction
101  // see Eq. 7,8 of Lackey et al
102  double eta2 = eta*eta;
103  double eta3 = eta2*eta;
104  double SqrtOneMinus4Eta = sqrt(1.-4.*eta);
105 
106  *a0 = -12 * Lambda * ((1 + 7.*eta - 31*eta2)
107  - SqrtOneMinus4Eta * (1 + 9.*eta - 11*eta2));
108  *a1 = -(585.*Lambda/28.)
109  * ((1. + 3775.*eta/234. - 389.*eta2/6. + 1376.*eta3/117.)
110  - SqrtOneMinus4Eta*(1 + 4243.*eta/234. - 6217*eta2/234. - 10.*eta3/9.));
111 
112  *G = exp(g0 + g1*eta + g2*chi_BH + g3*eta*chi_BH); // Eq 35 of Lackey et al
113 }
114 
115 static double tidalPNPhase(
116  const double Mf,
117  const double a0,
118  const double a1,
119  const double eta
120 ) {
121  // First compute the PN inspiral phasing correction
122  // see Eq. 7,8 of Lackey et al
123  double v = cbrt(LAL_PI * Mf);
124  double v2 = v*v;
125  double v5 = v2*v2*v;
126  double v7 = v5*v2;
127  return 3.*(a0*v5 + a1*v7) / (128.*eta);
128 }
129 
130 static double tidalPNPhaseDeriv(
131  const double Mf,
132  const double a0,
133  const double a1,
134  const double eta
135 ) {
136  // First compute the PN inspiral phasing correction
137  // see Eq. 7,8 of Lackey et al
138  double v = cbrt(LAL_PI * Mf);
139  double v2 = v*v;
140  double v4 = v2*v2;
141  return LAL_PI * (5.*a0*v2 + 7.*a1*v4) / (128.*eta);
142 }
143 
144 // Implements Eq. 34 of Lackey et al
145 static double tidalCorrectionPhase(
146  const double Mf,
147  const double a0,
148  const double a1,
149  const double G,
150  const double eta,
151  const double Lambda
152 )
153 {
154  const double MfP = 0.02; // phase transition frequency
155 
156  if (Mf <= MfP)
157  return tidalPNPhase(Mf, a0, a1, eta);
158 
159  // Beyond the phase transition frequency we evaluate the tidal phase
160  // and its derivative at the transition frequency
161  double psiT = tidalPNPhase(MfP, a0, a1, eta);
162  double DpsiT= (Mf - MfP) * tidalPNPhaseDeriv(MfP, a0, a1, eta);
163  // Now compute the phenomenological term
164  double E = G * pow(Mf - MfP, 5./3.); // Eq 35 of Lackey et al
165  double psiFit = eta * Lambda * E;
166  return psiT + DpsiT - psiFit; // Eq 34 of Lackey et al
167 }
168 
170  struct tagCOMPLEX16FrequencySeries **hptilde, /**< Output: Frequency-domain waveform h+ */
171  struct tagCOMPLEX16FrequencySeries **hctilde, /**< Output: Frequency-domain waveform hx */
172  REAL8 phiRef, /**< Phase at reference time */
173  REAL8 fRef, /**< Reference frequency (Hz); 0 defaults to fLow */
174  REAL8 distance, /**< Distance of source (m) */
175  REAL8 inclination, /**< Inclination of source (rad) */
176  REAL8 mBH_SI, /**< Mass of black hole (kg) */
177  REAL8 mNS_SI, /**< Mass of neutron star (kg) */
178  REAL8 chi_BH, /**< Dimensionless aligned component spin of the BH */
179  REAL8 Lambda, /**< Dimensionless tidal deformability (Eq 1 of Lackey et al) */
180  const REAL8Sequence *freqs_in, /**< Frequency points at which to evaluate the waveform (Hz) */
181  REAL8 deltaF /**< Sampling frequency (Hz) */
182 )
183 {
184  /* Check output arrays */
185  if(!hptilde || !hctilde)
187  if(*hptilde || *hctilde) {
188  XLALPrintError("(*hptilde) and (*hctilde) are supposed to be NULL, but got %p and %p",(*hptilde),(*hctilde));
190  }
191 
192  if (!freqs_in) XLAL_ERROR(XLAL_EFAULT);
193  double fLow = freqs_in->data[0];
194  double fHigh = freqs_in->data[freqs_in->length - 1];
195  if(fRef == 0.0)
196  fRef = fLow;
197 
198  double mBH = mBH_SI / LAL_MSUN_SI;
199  double mNS = mNS_SI / LAL_MSUN_SI;
200  double M = mBH + mNS;
201  double eta = mBH * mNS / (M*M); /* Symmetric mass-ratio */
202  double Mtot_sec = M * LAL_MTSUN_SI; /* Total mass in seconds */
203  double chi_NS = 0; // NS has zero spin
204 
205  // Impose sanity checks and cutoffs on mass-ratio, and BH spins
206  if (mBH < mNS) XLAL_ERROR(XLAL_EDOM, "mBH = %g < mNS = %g ! ", mBH, mNS);
207  if ((eta < 5./36.) || (eta > 2./9.)) XLAL_ERROR(XLAL_EDOM,
208  "eta = %g is not in allowed range 5/36 < eta < 2/9 (5 < q < 2)!", eta);
209  if (chi_BH > 0.5) XLAL_ERROR(XLAL_EDOM, "BH spin = %g > 0.5!", chi_BH);
210  if (chi_BH < -0.5) XLAL_ERROR(XLAL_EDOM, "BH spin = %g < -0.5!", chi_BH);
211  if ((Lambda < 0) || (Lambda > 4382)) XLAL_ERROR(XLAL_EDOM,
212  "Dimensionless tidal deformability = %g is not in allowed range [0, 4382]!", Lambda);
213 
214  // Call the high-resolution SEOBNRv2 ROM that can go to very low total mass
215  // We call either the FrequencySequence version or the regular LAL version depending on how we've been called.
216  int ret = XLAL_SUCCESS;
217  if (deltaF > 0)
219  hptilde, hctilde,
220  phiRef, deltaF, fLow, fHigh, fRef, distance, inclination,
221  mBH_SI, mNS_SI,
222  chi_BH, chi_NS,
223  -1);
224  else
226  hptilde, hctilde,
227  freqs_in,
228  phiRef, fRef, distance, inclination,
229  mBH_SI, mNS_SI,
230  chi_BH, chi_NS,
231  -1);
232  XLAL_CHECK(XLAL_SUCCESS == ret, ret, "XLALSimIMRSEOBNRv2ROMDoubleSpinHI() failed.");
233 
234  UINT4 offset;
235  REAL8Sequence *freqs = NULL;
236  if (deltaF > 0) { // uniform frequencies
237  // Recreate freqs using only the lower and upper bounds
238  UINT4 iStart = (UINT4) ceil(fLow / deltaF);
239  UINT4 iStop = (*hptilde)->data->length - 1; // use the length calculated in the ROM function
240  freqs = XLALCreateREAL8Sequence(iStop - iStart);
241  if (!freqs) XLAL_ERROR(XLAL_EFUNC, "Frequency array allocation failed.");
242  double deltaF_geom = deltaF * Mtot_sec;
243  for (UINT4 i=iStart; i<iStop; i++)
244  freqs->data[i-iStart] = i*deltaF_geom;
245 
246  offset = iStart;
247  }
248  else { // unequally spaced frequency sequence
249  freqs = XLALCreateREAL8Sequence(freqs_in->length);
250  if (!freqs) XLAL_ERROR(XLAL_EFUNC, "Frequency array allocation failed.");
251  for (UINT4 i=0; i<freqs_in->length; i++)
252  freqs->data[i] = freqs_in->data[i] * Mtot_sec; // just copy input and convert to geometric frequency
253  offset = 0;
254  }
255  COMPLEX16 *pdata=(*hptilde)->data->data;
256  COMPLEX16 *cdata=(*hctilde)->data->data;
257 
258  // Precompute coefficients that do not depend on frequency
259  double C, a0, a1, G;
260  tidalPNAmplitudeCoefficient(&C, eta, chi_BH, Lambda);
261  tidalPNPhaseCoefficients(&a0, &a1, &G, eta, chi_BH, Lambda);
262 
263  // Assemble waveform from aplitude and phase
264  for (size_t i=0; i<freqs->length; i++) { // loop over frequency points in sequence
265  double Mf = freqs->data[i];
266  int j = i + offset; // shift index for frequency series if needed
267  // Tidal corrections to be incorporated
268  double ampC = tidalCorrectionAmplitude(Mf, C, eta, Lambda);
269  double phsC = tidalCorrectionPhase(Mf, a0, a1, G, eta, Lambda);
270  COMPLEX16 Corr = ampC * cexp(-I*phsC);
271  pdata[j] *= Corr;
272  cdata[j] *= Corr;
273  }
274 
276 
277  return XLAL_SUCCESS;
278 }
279 
280 /**
281  * @addtogroup LALSimIMRTidal_c
282  *
283  * @{
284  *
285  * @name Lackey et al (2013) tidal model based on SEOBNRv2_ROM
286  *
287  * @author Michael Puerrer, Prayush Kumar
288  *
289  * @brief C code for Lackey et al arXiv:1303.6298 tidal model.
290  *
291  * This is a frequency domain model that adds tidal modifications of amplitude and phasing
292  * to the SEOBNRv2 model. Instead of SEOBNRv2, we use the high resolution ROM.
293  *
294  * @note Parameter ranges:
295  * * 5/36 <= eta <= 2/9 (5 <= q <= 2)
296  * * -0.5 <= chi_BH <= 0.5 [calibration region]
297  * * Lambda_NS <= 4382
298  * * Mtot >= 2 Msun @ 10 Hz (inherited from the ROM)
299  *
300  * Aligned component spin on black hole chi_BH. The NS is assumed to be non-spinning.
301  * Symmetric mass-ratio eta = m1*m2/(m1+m2)^2.
302  * Total mass Mtot.
303  *
304  * @{
305  */
306 
307 
308 /**
309  * Compute waveform in LAL format at specified frequencies for the Lackey et al (2013)
310  * tidal model based on SEOBNRv2_ROM_DoubleSpin_HI.
311  *
312  * XLALSimIMRLackeyTidal2013() returns the plus and cross polarizations as a complex
313  * frequency series with equal spacing deltaF and contains zeros from zero frequency
314  * to the starting frequency and zeros beyond the cutoff frequency in the ringdown.
315  *
316  * In contrast, XLALSimIMRLackeyTidal2013FrequencySequence() returns a
317  * complex frequency series with entries exactly at the frequencies specified in
318  * the sequence freqs (which can be unequally spaced). No zeros are added.
319  *
320  * If XLALSimIMRLackeyTidal2013FrequencySequence() is called with frequencies that
321  * are beyond the maxium allowed geometric frequency for the ROM, zero strain is returned.
322  * It is not assumed that the frequency sequence is ordered.
323  *
324  * This function is designed as an entry point for reduced order quadratures.
325  */
327  struct tagCOMPLEX16FrequencySeries **hptilde, /**< Output: Frequency-domain waveform h+ */
328  struct tagCOMPLEX16FrequencySeries **hctilde, /**< Output: Frequency-domain waveform hx */
329  const REAL8Sequence *freqs, /**< Frequency points at which to evaluate the waveform (Hz) */
330  REAL8 phiRef, /**< Phase at reference time */
331  REAL8 fRef, /**< Reference frequency (Hz); 0 defaults to fLow */
332  REAL8 distance, /**< Distance of source (m) */
333  REAL8 inclination, /**< Inclination of source (rad) */
334  REAL8 mBH_SI, /**< Mass of black hole (kg) */
335  REAL8 mNS_SI, /**< Mass of neutron star (kg) */
336  REAL8 chi_BH, /**< Dimensionless aligned component spin of the BH */
337  REAL8 Lambda) /**< Dimensionless tidal deformability (Eq 1 of Lackey et al) */
338 {
339  if (!freqs) XLAL_ERROR(XLAL_EFAULT);
340 
341  // Call the internal core function with deltaF = 0 to indicate that freqs is non-uniformly
342  // spaced and we want the strain only at these frequencies
343  int retcode = LackeyTidal2013SEOBNRv2ROMCore(hptilde, hctilde,
344  phiRef, fRef, distance, inclination, mBH_SI, mNS_SI, chi_BH, Lambda, freqs, 0);
345 
346  return(retcode);
347 }
348 
349 /**
350  * Compute waveform in LAL format for the Lackey et al (2013) tidal model based on
351  * SEOBNRv2_ROM_DoubleSpin_HI.
352  *
353  * Returns the plus and cross polarizations as a complex frequency series with
354  * equal spacing deltaF and contains zeros from zero frequency to the starting
355  * frequency fLow and zeros beyond the cutoff frequency in the ringdown.
356  */
358  struct tagCOMPLEX16FrequencySeries **hptilde, /**< Output: Frequency-domain waveform h+ */
359  struct tagCOMPLEX16FrequencySeries **hctilde, /**< Output: Frequency-domain waveform hx */
360  REAL8 phiRef, /**< Phase at reference time */
361  REAL8 deltaF, /**< Sampling frequency (Hz) */
362  REAL8 fLow, /**< Starting GW frequency (Hz) */
363  REAL8 fHigh, /**< End frequency; 0 defaults to Mf=0.14 */
364  REAL8 fRef, /**< Reference frequency (Hz); 0 defaults to fLow */
365  REAL8 distance, /**< Distance of source (m) */
366  REAL8 inclination, /**< Inclination of source (rad) */
367  REAL8 mBH_SI, /**< Mass of black hole (kg) */
368  REAL8 mNS_SI, /**< Mass of neutron star (kg) */
369  REAL8 chi_BH, /**< Dimensionless aligned component spin of the BH */
370  REAL8 Lambda /**< Dimensionless tidal deformability (Eq 1 of Lackey et al) */
371 ) {
372  // Use fLow, fHigh, deltaF to compute freqs sequence
373  // Instead of building a full sequence we only transfer the boundaries and let
374  // the internal core function do the rest (and properly take care of corner cases).
376  freqs->data[0] = fLow;
377  freqs->data[1] = fHigh;
378 
379  int retcode = LackeyTidal2013SEOBNRv2ROMCore(hptilde, hctilde,
380  phiRef, fRef, distance, inclination, mBH_SI, mNS_SI, chi_BH, Lambda, freqs, deltaF);
381 
383 
384  return(retcode);
385 }
386 
387 /** @} */
388 /** @} */
const double b1
static void tidalPNPhaseCoefficients(double *a0, double *a1, double *G, const double eta, const double chi_BH, const double Lambda)
static double tidalCorrectionAmplitude(const double Mf, const double C, const double eta, const double Lambda)
static double tidalPNPhaseDeriv(const double Mf, const double a0, const double a1, const double eta)
static void tidalPNAmplitudeCoefficient(double *C, const double eta, const double chi_BH, const double Lambda)
const double c1
const double g3
const double b2
const double b0
const double g2
const double g0
const double g1
const double c2
static double tidalCorrectionPhase(const double Mf, const double a0, const double a1, const double G, const double eta, const double Lambda)
int LackeyTidal2013SEOBNRv2ROMCore(struct tagCOMPLEX16FrequencySeries **hptilde, struct tagCOMPLEX16FrequencySeries **hctilde, REAL8 phiRef, REAL8 fRef, REAL8 distance, REAL8 inclination, REAL8 mBH_SI, REAL8 mNS_SI, REAL8 chi_BH, REAL8 Lambda, const REAL8Sequence *freqs_in, REAL8 deltaF)
const double c0
static double tidalPNPhase(const double Mf, const double a0, const double a1, const double eta)
#define G
REAL8 M
Definition: bh_qnmode.c:133
double i
Definition: bh_ringdown.c:118
const double Lambda
const double B
#define LAL_MSUN_SI
#define LAL_PI
#define LAL_MTSUN_SI
double complex COMPLEX16
double REAL8
uint32_t UINT4
int XLALSimIMRSEOBNRv2ROMDoubleSpinHI(struct tagCOMPLEX16FrequencySeries **hptilde, struct tagCOMPLEX16FrequencySeries **hctilde, REAL8 phiRef, REAL8 deltaF, REAL8 fLow, REAL8 fHigh, REAL8 fRef, REAL8 distance, REAL8 inclination, REAL8 m1SI, REAL8 m2SI, REAL8 chi1, REAL8 chi2, INT4 nk_max)
Compute waveform in LAL format for the SEOBNRv2_ROM_DoubleSpin_HI model.
int XLALSimIMRSEOBNRv2ROMDoubleSpinHIFrequencySequence(struct tagCOMPLEX16FrequencySeries **hptilde, struct tagCOMPLEX16FrequencySeries **hctilde, const REAL8Sequence *freqs, REAL8 phiRef, REAL8 fRef, REAL8 distance, REAL8 inclination, REAL8 m1SI, REAL8 m2SI, REAL8 chi1, REAL8 chi2, INT4 nk_max)
Compute waveform in LAL format at specified frequencies for the SEOBNRv2_ROM_DoubleSpin_HI model.
int XLALSimIMRLackeyTidal2013(struct tagCOMPLEX16FrequencySeries **hptilde, struct tagCOMPLEX16FrequencySeries **hctilde, REAL8 phiRef, REAL8 deltaF, REAL8 fLow, REAL8 fHigh, REAL8 fRef, REAL8 distance, REAL8 inclination, REAL8 mBH_SI, REAL8 mNS_SI, REAL8 chi_BH, REAL8 Lambda)
Compute waveform in LAL format for the Lackey et al (2013) tidal model based on SEOBNRv2_ROM_DoubleSp...
int XLALSimIMRLackeyTidal2013FrequencySequence(struct tagCOMPLEX16FrequencySeries **hptilde, struct tagCOMPLEX16FrequencySeries **hctilde, const REAL8Sequence *freqs, REAL8 phiRef, REAL8 fRef, REAL8 distance, REAL8 inclination, REAL8 mBH_SI, REAL8 mNS_SI, REAL8 chi_BH, REAL8 Lambda)
Compute waveform in LAL format at specified frequencies for the Lackey et al (2013) tidal model based...
void XLALDestroyREAL8Sequence(REAL8Sequence *sequence)
REAL8Sequence * XLALCreateREAL8Sequence(size_t length)
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
REAL8 * data