LALSimulation  5.4.0.1-fe68b98
LALSimIMRPhenomX_internals.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2018 Geraint Pratten
3  *
4  * This code builds on:
5  * LALSimIMRPhenomD_internals.c
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with with program; see the file COPYING. If not, write to the
19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  * MA 02110-1301 USA
21  */
22 
23 
24 /**
25  * \author Geraint Pratten
26  *
27  * Internal functions for IMRPhenomX, arXiv:2001.11412
28  */
29 
30 /* IMRPhenomX Header Files */
33 
37 #include "LALSimIMRPhenomX_qnm.c"
39 
40 /* LAL Header Files */
41 #include <lal/LALSimIMR.h>
42 #include <lal/LALConstants.h>
43 #include <lal/Date.h>
44 #include <lal/FrequencySeries.h>
45 #include <lal/Units.h>
46 
47 /* GSL Header Files */
48 #include <gsl/gsl_linalg.h>
49 
50 /* Link PN coefficients (needed for NRTidal spin-induced quadrupole terms) */
52 
53 /* This struct is used to pre-cache useful powers of frequency, avoiding numerous expensive operations */
55 {
56  XLAL_CHECK(0 != p, XLAL_EFAULT, "p is NULL");
57  XLAL_CHECK(number >= 0, XLAL_EDOM, "number must be non-negative");
58 
59  double sixth = pow(number, 1.0 / 6.0);
60  double m_sixth = 1.0 / sixth;
61 
62  p->one_sixth = sixth;
63  p->m_one_sixth = m_sixth;
64 
65  p->m_one = 1.0 / number;
66  p->itself = number;
67 
68  p->one_third = sixth * sixth;
69  p->m_one_third = 1.0 / (p->one_third);
70 
71  p->two_thirds = p->one_third * p->one_third;
72  p->m_two_thirds = 1.0 / p->two_thirds;
73 
74  p->four_thirds = p->two_thirds * p->two_thirds;
75  p->m_four_thirds = 1.0 / p->four_thirds;
76 
77  p->five_thirds = p->four_thirds * p->one_third;
78  p->m_five_thirds = 1.0 / p->five_thirds;
79 
80  p->seven_thirds = p->four_thirds * number;
81  p->m_seven_thirds = 1.0 / p->seven_thirds;
82 
83  p->eight_thirds = p->seven_thirds * p->one_third;
84  p->m_eight_thirds = 1.0 / p->eight_thirds;
85 
86  p->two = number * number;
87  p->three = p->two * number;
88  p->four = p->three * number;
89  p->five = p->four * number;
90 
91  p->m_two = 1.0 / p->two;
92  p->m_three = 1.0 / p->three;
93  p->m_four = 1.0 / p->four;
94  p->m_five = 1.0 / p->five;
95 
96  p->seven_sixths = p->one_sixth * p->itself;
97  p->m_seven_sixths = p->m_one_sixth * p->m_one;
98 
99  p->log = log(number);
100  p->sqrt = p->one_sixth*p->one_sixth*p->one_sixth;
101 
102  return XLAL_SUCCESS;
103 }
104 
105 /* A stripped down version of IMRPhenomX_Initialize_Powers for main production loop */
107 {
108  XLAL_CHECK(0 != p, XLAL_EFAULT, "p is NULL");
109  XLAL_CHECK(number >= 0, XLAL_EDOM, "number must be non-negative");
110 
111  double sixth = pow(number, 1.0 / 6.0);
112  double m_sixth = 1.0 / sixth;
113 
114  p->one_sixth = sixth;
115  p->m_one_sixth = m_sixth;
116 
117  p->m_one = 1.0 / number;
118  p->itself = number;
119 
120  p->one_third = sixth * sixth;
121  p->two_thirds = p->one_third * p->one_third;
122 
123  p->m_two = p->m_one * p->m_one;
124  p->m_three = p->m_two * p->m_one;
125 
126  p->seven_sixths = p->one_sixth * p->itself;
127  p->m_seven_sixths = p->m_one_sixth * p->m_one;
128 
129  p->log = log(number);
130 
131  return XLAL_SUCCESS;
132 }
133 
134 
137  const REAL8 m1_SI,
138  const REAL8 m2_SI,
139  const REAL8 chi1L_In,
140  const REAL8 chi2L_In,
141  const REAL8 deltaF,
142  const REAL8 fRef,
143  const REAL8 phi0,
144  const REAL8 f_min,
145  const REAL8 f_max,
146  const REAL8 distance,
147  const REAL8 inclination,
148  LALDict *LALParams,
149  UNUSED const UINT4 debug
150 )
151 {
152  /* Place the LALparams into pWF */
153  wf->LALparams = LALParams;
154 
155  /* Copy model version to struct */
159 
163 
165  // NOTE that the line below means that 33 tuning can only be on IFF 22 tuning is on
167 
169 
170  // Get toggle for forcing inspiral phase and phase derivative alignment with XHM/AS
172  wf->IMRPhenomXPNRForceXHMAlignment = PNRForceXHMAlignment;
173 
174  wf->debug = PHENOMXDEBUG;
175 
176  if(PHENOMXDEBUG)
177  {
178  printf("\n");
179  printf("Inspiral Amp Version : %d\n",wf->IMRPhenomXInspiralAmpVersion);
180  printf("Intermediate Amp Version : %d\n",wf->IMRPhenomXIntermediateAmpVersion);
181  printf("Ringdown Amp Version : %d\n",wf->IMRPhenomXRingdownAmpVersion);
182  printf("\n");
183  printf("Inspiral Phase Version : %d\n",wf->IMRPhenomXInspiralPhaseVersion);
184  printf("Intermediate Phase Version : %d\n",wf->IMRPhenomXIntermediatePhaseVersion);
185  printf("Ringdown Phase Version : %d\n",wf->IMRPhenomXRingdownPhaseVersion);
186  printf("\n");
187  }
188 
189  /*
190  First perform a sanity check to make sure that a legitimate waveform version has been called. If not, fail immediately.
191  Every time a new version for one of the regions is added, user must add case below.
192  */
193  int InspPhaseFlag = wf->IMRPhenomXInspiralPhaseVersion;
194 
195  /* Phase : Inspiral */
196  switch( InspPhaseFlag )
197  {
198  // Canonical TaylorF2 up to 3.5PN with 4 pseudo-PN coefficients
199  case 104:
200  {
201  break;
202  }
203  // Canonical TaylorF2 up to 3.5PN with 5 pseudo-PN coefficients
204  case 105:
205  {
206  break;
207  }
208  // Extended TaylorF2 up to 4.5PN with 4 pseudo-PN coefficients
209  case 114:
210  {
211  break;
212  }
213  // Extended TaylorF2 up to 4.5PN with 5 pseudo-PN coefficients
214  case 115:
215  {
216  break;
217  }
218  // We must pass a recognised inspiral phase version. Otherwise fail.
219  default:
220  {
221  XLAL_ERROR(XLAL_EINVAL, "Error in IMRPhenomX_SetWaveformVariables: IMRPhenomXInspiralPhaseVersion not recognized. Recommended flag is 104.\n");
222  }
223  }
224 
225  int IntPhaseFlag = wf->IMRPhenomXIntermediatePhaseVersion;
226  /* Phase : Intermediate */
227  switch( IntPhaseFlag )
228  {
229  // 4 intermediate coefficients
230  case 104:
231  {
232  break;
233  }
234  // 5 intermediate coefficients
235  case 105:
236  {
237  break;
238  }
239  default:
240  {
241  XLAL_ERROR(XLAL_EINVAL,"Error in IMRPhenomX_SetWaveformVariables: IMRPhenomXIntermediatePhaseVersion not recognized. Recommended flag is 105.\n");
242  }
243  }
244 
245  int RDPhaseFlag = wf->IMRPhenomXRingdownPhaseVersion;
246  /* Phase : Ringdown */
247  switch( RDPhaseFlag )
248  {
249  // 5 ringdown coefficients
250  case 105:
251  {
252  break;
253  }
254  default:
255  {
256  XLAL_ERROR(XLAL_EINVAL,"Error in IMRPhenomX_SetWaveformVariables: IMRPhenomXRingdownPhaseVersion not recognized. Recommended flag is 105.\n");
257  }
258  }
259 
260  int InsAmpFlag = wf->IMRPhenomXInspiralAmpVersion;
261  /* Amplitude : Inspiral */
262  switch( InsAmpFlag )
263  {
264  // Canonical TaylorF2 with 4 pseudo-PN coefficients
265  case 103:
266  {
267  break;
268  }
269  default:
270  {
271  XLAL_ERROR(XLAL_EINVAL,"Error in IMRPhenomX_SetWaveformVariables: IMRPhenomXInspiralAmpVersion not recognized. Recommended flag is 103.\n");
272  }
273  }
274 
275  int IntAmpFlag = wf->IMRPhenomXIntermediateAmpVersion;
276  /* Amplitude : Intermediate */
277  switch( IntAmpFlag )
278  {
279  // Intermediate region constructed from 4th order polynomial
280  case 1043:
281  {
282  break;
283  }
284  // Intermediate region constructed from a 4th order polynomial
285  case 104:
286  {
287  break;
288  }
289  // Intermediate region constructed from a 5th order polynomial
290  case 105:
291  {
292  break;
293  }
294  default:
295  {
296  XLAL_ERROR(XLAL_EINVAL,"Error in IMRPhenomX_SetWaveformVariables: IMRPhenomXIntermediateAmpVersion not recognized. Recommended flag is 104.\n");
297  }
298  }
299 
300  int RDAmpFlag = wf->IMRPhenomXRingdownAmpVersion;
301  /* Amplitude : Ringdown */
302  switch( RDAmpFlag )
303  {
304  case 103:
305  {
306  break;
307  }
308  default:
309  {
310  XLAL_ERROR(XLAL_EINVAL,"Error in IMRPhenomX_SetWaveformVariables: IMRPhenomXRingdownAmpVersion not recognized. Recommended flag is 103.\n");
311  }
312  }
313 
314  /* Rescale to mass in solar masses */
315  REAL8 m1_In = m1_SI / LAL_MSUN_SI; // Mass 1 in solar masses
316  REAL8 m2_In = m2_SI / LAL_MSUN_SI; // Mass 2 in solar masses
317 
318  /* Set matter parameters */
319  REAL8 lambda1_In = 0, lambda2_In = 0, quadparam1_In = 1, quadparam2_In = 1; // Tidal deformabilities and quadrupole spin-induced deformation parameters
320 
322  {
323 
324  lambda1_In = XLALSimInspiralWaveformParamsLookupTidalLambda1(LALParams);
325  lambda2_In = XLALSimInspiralWaveformParamsLookupTidalLambda2(LALParams);
326  if( lambda1_In < 0 || lambda2_In < 0 )
327  XLAL_ERROR(XLAL_EFUNC, "lambda1 = %f, lambda2 = %f. Both should be greater than zero for NRTidalv2", lambda1_In, lambda2_In);
328 
329  int retcode;
330 
331  retcode = XLALSimInspiralSetQuadMonParamsFromLambdas(LALParams);
332  XLAL_CHECK(retcode == XLAL_SUCCESS, XLAL_EFUNC, "Failed to set quadparams from Universal relation.\n");
333 
334  quadparam1_In = 1. + XLALSimInspiralWaveformParamsLookupdQuadMon1(LALParams);
335  quadparam2_In = 1. + XLALSimInspiralWaveformParamsLookupdQuadMon2(LALParams);
336  }
337 
338  REAL8 m1, m2, chi1L, chi2L, lambda1, lambda2, quadparam1, quadparam2;
339 
340  /* Check if m1 >= m2, if not then swap masses/spins/lambdas/quadparams */
341  if(m1_In >= m2_In)
342  {
343  chi1L = chi1L_In;
344  chi2L = chi2L_In;
345  m1 = m1_In;
346  m2 = m2_In;
347  lambda1 = lambda1_In;
348  lambda2 = lambda2_In;
349  quadparam1 = quadparam1_In;
350  quadparam2 = quadparam2_In;
351  }
352  else
353  {
354  XLAL_PRINT_WARNING("Warning: m1 < m2, swapping the masses, spins, tidal deformabilities, and spin-induced quadrupole parameters.\n");
355  chi1L = chi2L_In;
356  chi2L = chi1L_In;
357  m1 = m2_In;
358  m2 = m1_In;
359  lambda1 = lambda2_In;
360  lambda2 = lambda1_In;
361  quadparam1 = quadparam2_In;
362  quadparam2 = quadparam1_In;
363  }
364 
365  if(chi1L > 1.0)
366  {
367  IMRPhenomX_InternalNudge(chi1L,1.0,1e-6);
368  }
369  if(chi2L > 1.0)
370  {
371  IMRPhenomX_InternalNudge(chi2L,1.0,1e-6);
372  }
373  if(chi1L < -1.0)
374  {
375  IMRPhenomX_InternalNudge(chi1L,-1.0,1e-6);
376  }
377  if(chi2L < -1.0)
378  {
379  IMRPhenomX_InternalNudge(chi2L,-1.0,1e-6);
380  }
381  /* If spins are still unphysical after checking for small round-off errors, fail. */
382  if( chi1L > 1.0 || chi1L < -1.0 || chi2L > 1.0 || chi2L < -1.0)
383  {
384  //XLALPrintError("Unphyiscal spins: must be in the range [-1,1].\n");
385  XLAL_ERROR(XLAL_EDOM, "Unphysical spins requested: must obey the Kerr bound [-1,1].\n");
386  }
387 
388  // Symmetric mass ratio
389  REAL8 delta = fabs((m1 - m2) / (m1+m2));
390  REAL8 eta = fabs(0.25 * (1.0 - delta*delta) ); // use fabs to prevent negative sign due to roundoff
391  REAL8 q = ((m1 > m2) ? (m1 / m2) : (m2 / m1));
392 
393  /* If eta > 0.25, e.g. roundoff, then set to 0.25 */
394  if(eta > 0.25)
395  {
396  eta = 0.25;
397  }
398  if(eta > 0.25 || eta < 0.0)
399  {
400  XLAL_ERROR(XLAL_EDOM,"Unphysical eta: must be between 0 and 0.25\n");
401  }
402  if(eta == 0.25) q = 1.;
403  //if(eta < MAX_ALLOWED_ETA)
404  //{
405  // XLAL_PRINT_WARNING("Warning: The model is not calibrated against numerical-relativity mass-ratios greater than 18.\n");
406  //}
407 
408  /* Check that masses are correctly ordered. Swap if necessary.
409  return_code = IMRPhenomX_CheckMassOrdering(m1,m2,chi1L,chi2L);
410  XLAL_CHECK(XLAL_SUCCESS == return_code, XLAL_EFUNC, "Failure: IMRPhenomX_CheckMassOrdering");
411  */
412 
413 
414 
415  /* Masses definitions. Note that m1 and m2 are the component masses in solar masses. */
416  wf->m1_SI = m1 * LAL_MSUN_SI; // Mass 1 (larger) in SI units
417  wf->m2_SI = m2 * LAL_MSUN_SI; // Mass 2 (smaller) in SI units
418  wf->q = q; // Mass ratio >= 1
419  wf->eta = eta; // Symmetric mass ratio
420  wf->Mtot_SI = wf->m1_SI + wf->m2_SI; // Total mass in SI units
421  wf->Mtot = m1 + m2; // Total mass in solar masss
422  wf->m1 = m1 / (wf->Mtot); // Mass 1 (larger), dimensionless (i.e. m1 \in [0,1])
423  wf->m2 = m2 / (wf->Mtot); // Mass 2 (smaller), dimensionless
424  wf->M_sec = wf->Mtot * LAL_MTSUN_SI; // Conversion factor Hz to geometric frequency, total mass in seconds
425  wf->delta = delta; // PN symmetry coefficient
426 
427  wf->eta2 = eta * eta;
428  wf->eta3 = eta * wf->eta2;
429 
430  if(wf->debug)
431  {
432  printf("m1 (Msun) = %.6f\n",m1);
433  printf("m2 (Msun) = %.6f\n",m2);
434  printf("m1_SI = %.6f\n",wf->m1_SI);
435  printf("m2_SI = %.6f\n",wf->m2_SI);
436  printf("m1 = %.6f\n",wf->m1);
437  printf("m2 = %.6f\n",wf->m2);
438  }
439 
440  if(wf->q > 1000.0)
441  {
442  XLAL_PRINT_WARNING("Warning: The model is not supported for mass ratios > 1000.\n");
443  }
444 
445  /* Spins */
446  wf->chi1L = chi1L;
447  wf->chi2L = chi2L;
448 
449  wf->chi1L2L = chi1L * chi2L;
450 
451  /* Useful powers of spin */
452  wf->chi1L2 = chi1L*chi1L;
453  wf->chi1L3 = chi1L*chi1L*chi1L;
454 
455  wf->chi2L2 = chi2L*chi2L;
456  wf->chi2L3 = chi2L*chi2L*chi2L;
457 
458  /* Spin parameterisations */
459  wf->chiEff = XLALSimIMRPhenomXchiEff(eta,chi1L,chi2L);
460  wf->chiPNHat = XLALSimIMRPhenomXchiPNHat(eta,chi1L,chi2L);
461  wf->STotR = XLALSimIMRPhenomXSTotR(eta,chi1L,chi2L);
462  wf->dchi = XLALSimIMRPhenomXdchi(chi1L,chi2L);
463  wf->dchi_half = wf->dchi*0.5;
464 
465  wf->SigmaL = (wf->chi2L * wf->m2) - (wf->chi1L * wf->m1); // SigmaL = (M/m2)*(S2.L) - (M/m2)*(S1.L)
466  wf->SL = wf->chi1L * (wf->m1 * wf->m1) + wf->chi2L * (wf->m2 * wf->m2); // SL = S1.L + S2.L
467 
468  if(wf->debug)
469  {
470  printf("eta : %.16e\n",wf->eta);
471  printf("q : %.16e\n",wf->q);
472  printf("chi1L : %.16e\n",wf->chi1L);
473  printf("chi2L : %.16e\n",wf->chi2L);
474  printf("chi_eff : %.16e\n",wf->chiEff);
475  printf("chi_hat : %.16e\n",wf->chiPNHat);
476  printf("STotR : %.16e\n",wf->STotR);
477  }
478 
479  /* Matter parameters */
480  wf->lambda1 = lambda1;
481  wf->lambda2 = lambda2;
482  wf->quadparam1 = quadparam1;
483  wf->quadparam2 = quadparam2;
486 
487  /* If no reference frequency is passed, set it to the starting GW frequency */
488  wf->fRef = (fRef == 0.0) ? f_min : fRef;
489  wf->phiRef_In = phi0;
490  wf->phi0 = phi0; // Orbital phase at reference frequency (as passed from lalsimulation)
491  wf->beta = LAL_PI*0.5 - phi0; // Azimuthal angle of binary at reference frequency
492  wf->phifRef = 0.0; // This is calculated later
493 
494  /* Geometric reference frequency */
496  wf->piM = LAL_PI * wf->M_sec;
497  wf->v_ref = cbrt(wf->piM * wf->fRef);
498 
499  wf->deltaF = deltaF;
501 
502  /* Define the default end of the waveform as: 0.3 Mf. This value is chosen such that the 44 mode also shows the ringdown part. */
503  wf->fCutDef = 0.3;
504  // If chieff is very high the ringdown of the 44 is almost cut it out when using 0.3, so we increase a little bit the cut of freq up 0.33.
505  if(wf->chiEff > 0.99) wf->fCutDef = 0.33;
506 
507  /* Minimum and maximum frequency */
508  wf->fMin = f_min;
509  wf->fMax = f_max;
511 
512  /* Convert fCut to physical cut-off frequency */
513  wf->fCut = wf->fCutDef / wf->M_sec;
514 
515  /* Sanity check that minimum start frequency is less than cut-off frequency */
516  if (wf->fCut <= wf->fMin)
517  {
518  XLALPrintError("(fCut = %g Hz) <= f_min = %g\n", wf->fCut, wf->fMin);
519  }
520 
521  if(wf->debug)
522  {
523  printf("fRef : %.6f\n",wf->fRef);
524  printf("phi0 : %.6f\n",wf->phi0);
525  printf("fCut : %.6f\n",wf->fCut);
526  printf("fMin : %.6f\n",wf->fMin);
527  printf("fMax : %.6f\n",wf->fMax);
528  }
529 
530  /* By default f_max_prime is f_max. If fCut < fMax, then use fCut, i.e. waveform up to fMax will be zeros */
531  wf->f_max_prime = wf->fMax;
532  wf->f_max_prime = wf->fMax ? wf->fMax : wf->fCut;
533  wf->f_max_prime = (wf->f_max_prime > wf->fCut) ? wf->fCut : wf->f_max_prime;
534 
535  if (wf->f_max_prime <= wf->fMin)
536  {
537  XLALPrintError("f_max <= f_min\n");
538  }
539 
540  if(wf->debug)
541  {
542  printf("fMin = %.6f\n",wf->fMin);
543  printf("fMax = %.6f\n",wf->fMax);
544  printf("f_max_prime = %.6f\n",wf->f_max_prime);
545  }
546 
547  /* Final Mass and Spin */
548  // NOTE: These are only default values
551 
552  /* (500) Set default values of physically specific final spin parameters for use with PNR/XCP */
553  wf->afinal_nonprec = wf->afinal; // NOTE: This is only a default value; see LALSimIMRPhenomX_precession.c
554  wf->afinal_prec = wf->afinal; // NOTE: This is only a default value; see LALSimIMRPhenomX_precession.c
555 
556  /* Ringdown and damping frequency of final BH */
557 #if QNMfits == 1
558  wf->fRING = evaluate_QNMfit_fring22(wf->afinal) / (wf->Mfinal);
559  wf->fDAMP = evaluate_QNMfit_fdamp22(wf->afinal) / (wf->Mfinal);
560 #else
561  wf->fRING = interpolateQNMData_fring_22(wf->afinal) / (wf->Mfinal);
562  wf->fDAMP = interpolateQNMData_fdamp_22(wf->afinal) / (wf->Mfinal);
563 #endif
564 
565 
566  if(wf->debug)
567  {
568  printf("Mf = %.6f\n",wf->Mfinal);
569  printf("af = %.6f\n",wf->afinal);
570  printf("frd = %.6f\n",wf->fRING);
571  printf("fda = %.6f\n",wf->fDAMP);
572  }
573 
574  if(wf->Mfinal > 1.0)
575  {
576  XLAL_ERROR(XLAL_EDOM, "IMRPhenomX_FinalMass2018: Final mass > 1.0 not physical.");
577  }
578  if(fabs(wf->afinal) > 1.0)
579  {
580  XLAL_ERROR(XLAL_EDOM, "IMRPhenomX_FinalSpin2018: Final spin > 1.0 is not physical.");
581  }
582 
583  /* Fit to the hybrid minimum energy circular orbit (MECO), Cabero et al, Phys.Rev. D95 (2017) */
584  wf->fMECO = XLALSimIMRPhenomXfMECO(wf->eta,wf->chi1L,wf->chi2L);
585 
586  /* Innermost stable circular orbit (ISCO), e.g. Ori et al, Phys.Rev. D62 (2000) 124022 */
588 
589  if(wf->debug)
590  {
591  printf("fMECO = %.6f\n",wf->fMECO);
592  printf("fISCO = %.6f\n",wf->fISCO);
593  }
594 
595  if(wf->fMECO > wf->fISCO)
596  {
597  /* If MECO > fISCO, throw an error - this may be the case for very corner cases in the parameter space (e.g. q ~ 1000, chi ~ 0.999) */
598  XLAL_ERROR(XLAL_EDOM, "Error: f_MECO cannot be greater than f_ISCO.");
599  }
600 
601  /* Distance and inclination */
602  wf->distance = distance;
603  wf->inclination = inclination;
604 
605  /* Amplitude normalization */
606  wf->amp0 = wf->Mtot * LAL_MRSUN_SI * wf->Mtot * LAL_MTSUN_SI / wf->distance;
607  wf->ampNorm = sqrt(2.0/3.0) * sqrt(wf->eta) * powers_of_lalpi.m_one_sixth;
608 
609  if(wf->debug)
610  {
611  printf("\n\neta = %.6f\n",wf->eta);
612  printf("\nampNorm = %e\n",wf->ampNorm);
613  printf("amp0 : %e",wf->amp0);
614  }
615 
616  /* Phase normalization */
617  wf->dphase0 = 5.0 / (128.0 * pow(LAL_PI,5.0/3.0));
618 
619  if(wf->debug)
620  {
621  printf("\n\n **** Sanity checks complete. Waveform struct has been initialized. **** \n\n");
622  }
623 
624  /* Set nonprecessing value of select precession quantities (PNRUseTunedCoprec)*/
625  wf->chiTot_perp = 0.0;
626  wf->chi_p = 0.0;
627  wf->theta_LS = 0.0;
628  wf->a1 = 0.0;
629  wf->PNR_DEV_PARAMETER = 0.0;
630  wf->PNR_SINGLE_SPIN = 0;
631  wf->MU1 = 0;
632  wf->MU2 = 0;
633  wf->MU3 = 0;
634  wf->MU4 = 0;
635  wf->NU0 = 0;
636  wf->NU4 = 0;
637  wf->NU5 = 0;
638  wf->NU6 = 0;
639  wf->ZETA1 = 0;
640  wf->ZETA2 = 0;
642 
643  wf->f_inspiral_align = 0.0;
648 
649  wf->betaRD = 0.0;
650  wf->fRING22_prec = 0.0;
651  wf->fRINGCP = 0.0;
652  wf->pnr_window = 0.0;
653 
654  wf->APPLY_PNR_DEVIATIONS = 0;
655 
656  return XLAL_SUCCESS;
657 }
658 
662 )
663 {
664  INT4 debug = PHENOMXDEBUG;
665 
666  REAL8 V1, V2, V3, V4;
667  REAL8 F1, F2, F3, F4;
668  REAL8 d1, d4;
669 
670  /* Declare local spin variables for convenience */
671  REAL8 chi1L = pWF->chi1L;
672  REAL8 chi2L = pWF->chi2L;
673  REAL8 chi1L2 = pWF->chi1L2;
674  REAL8 chi1L3 = pWF->chi1L3;
675  REAL8 chi2L2 = pWF->chi2L2;
676 
677  // Local PN symmetry parameter
678  REAL8 delta = pWF->delta;
679 
680  // Local powers of the symmetric mass ratio
681  REAL8 eta = pWF->eta;
682  REAL8 eta2 = pWF->eta2;
683  REAL8 eta3 = pWF->eta3;
684 
685  if(debug)
686  {
687  printf("chi1L = %.6f\n",chi1L);
688  printf("chi1L2 = %.6f\n",chi1L2);
689  printf("chi1L3 = %.6f\n",chi1L3);
690  printf("chi2L2 = %.6f\n",chi2L2);
691  printf("delta = %.6f\n",delta);
692  printf("eta2 = %.6f\n",eta2);
693  printf("eta3 = %.6f\n",eta3);
694  }
695 
696  // Phenomenological ringdown coefficients: note that \gamma2 = \lambda in arXiv:2001.11412 and \gamma3 = \sigma in arXiv:2001.11412
699 
700  /* Apply modifications in the style of PhenomDCP: https://arxiv.org/pdf/2107.08876.pdf (500)*/
701  // pAmp->gamma2 = pAmp->gamma2 + ( pWF->PNR_DEV_PARAMETER * pWF->MU2 );
702  pAmp->gamma3 = pAmp->gamma3 + ( pWF->PNR_DEV_PARAMETER * pWF->MU2 );
703 
704  /* Get peak ringdown frequency, Eq. 5.14 in arXiv:2001.11412: Abs[fring + fdamp * gamma3 * (Sqrt[1 - gamma2^2] - 1)/gamma2 ] */
706 
707  // Value of v1RD at fAmpRDMin is used to calcualte gamma1 \propto the amplitude of the deformed Lorentzian
709  F1 = pAmp->fAmpRDMin;
710 
711  /* Apply modifications in the style of PhenomDCP: https://arxiv.org/pdf/2107.08876.pdf -- here we modify the ringdown amplitude (500)*/
712  pAmp->v1RD = pAmp->v1RD + ( pWF->PNR_DEV_PARAMETER * pWF->MU1 );
713 
714  // Solving linear equation: ansatzRD(F1) == v1
715  pAmp->gamma1 = ( pAmp->v1RD / (pWF->fDAMP * pAmp->gamma3) ) * (F1*F1 - 2.0*F1*pWF->fRING + pWF->fRING*pWF->fRING + pWF->fDAMP*pWF->fDAMP*pAmp->gamma3*pAmp->gamma3)
716  * exp( ( (F1 - pWF->fRING) * pAmp->gamma2 ) / (pWF->fDAMP * pAmp->gamma3) );
717 
718  /* Pre-cache these constants for the ringdown amplitude */
719  pAmp->gammaR = pAmp->gamma2 / (pWF->fDAMP * pAmp->gamma3);
720  pAmp->gammaD2 = (pAmp->gamma3 * pWF->fDAMP) * (pAmp->gamma3 * pWF->fDAMP);
721  pAmp->gammaD13 = pWF->fDAMP * pAmp->gamma1 * pAmp->gamma3;
722 
723  if(debug)
724  {
725  printf("V1 = %.6f\n",pAmp->v1RD);
726  printf("gamma1 = %.6f\n",pAmp->gamma1);
727  printf("gamma2 = %.6f\n",pAmp->gamma2);
728  printf("gamma3 = %.6f\n",pAmp->gamma3);
729  printf("fmax = %.6f\n",pAmp->fAmpRDMin);
730  }
731 
732  /* Inspiral-Intermediate transition frequencies, see Eq. 5.7 in arXiv:2001.11412 */
733  pAmp->fAmpInsMin = 0.0026;
734  pAmp->fAmpInsMax = pWF->fMECO + 0.25*(pWF->fISCO - pWF->fMECO);
735 
736  /* Inspiral-Intermediate matching frequency, Eq. 5.16 in arXiv:2001.11412 */
737  pAmp->fAmpMatchIN = pAmp->fAmpInsMax;
738 
739  /* Intermediate-Ringdown matching frequency */
740  //pAmp->fAmpMatchIM = pAmp->fAmpRDMin;
741 
742  /* End of intermerdiate region, Eq. 5.16 in arXiv:2001.11412 */
743  pAmp->fAmpIntMax = pAmp->fAmpRDMin;
744 
745  /* TaylorF2 PN Amplitude Coefficients from usual PN re-expansion of Hlm's */
746  pAmp->pnInitial = 1.0;
747  pAmp->pnOneThird = 0.0;
748  pAmp->pnTwoThirds = ( (-969 + 1804*eta)/672. ) * powers_of_lalpi.two_thirds;
749  pAmp->pnThreeThirds = ( (81*(chi1L + chi2L) + 81*chi1L*delta - 81*chi2L*delta - 44*(chi1L + chi2L)*eta)/48. ) * powers_of_lalpi.itself;
750  pAmp->pnFourThirds = ( (-27312085 - 10287648*chi1L2*(1 + delta)
751  + 24*(428652*chi2L2*(-1 + delta) + (-1975055 + 10584*(81*chi1L2 - 94*chi1L*chi2L + 81*chi2L2))*eta
752  + 1473794*eta2))/8.128512e6 ) * powers_of_lalpi.one_third * powers_of_lalpi.itself;
753  pAmp->pnFiveThirds = ( (-6048*chi1L3*(-1 - delta + (3 + delta)*eta) + chi2L*(-((287213 + 6048*chi2L2)*(-1 + delta))
754  + 4*(-93414 + 1512*chi2L2*(-3 + delta) + 2083*delta)*eta - 35632*eta2)
755  + chi1L*(287213*(1 + delta) - 4*eta*(93414 + 2083*delta + 8908*eta))
756  + 42840*(-1 + 4*eta)*LAL_PI)/32256. ) * powers_of_lalpi.five_thirds;
757  pAmp->pnSixThirds = ( (-1242641879927 + 12.0*(28.0*(-3248849057.0
758  + 11088*(163199*chi1L2 - 266498*chi1L*chi2L + 163199*chi2L2))*eta2
759  + 27026893936*eta3 - 116424*(147117*(-(chi2L2*(-1.0 + delta)) + chi1L2*(1.0 + delta))
760  + 60928*(chi1L + chi2L + chi1L*delta - chi2L*delta)*LAL_PI)
761  + eta*(545384828789.0 - 77616*(638642*chi1L*chi2L + chi1L2*(-158633 + 282718*delta)
762  - chi2L2*(158633.0 + 282718.0*delta) - 107520.0*(chi1L + chi2L)*LAL_PI
763  + 275520*powers_of_lalpi.two))))/6.0085960704e10 ) * powers_of_lalpi.two;
764 
765 
766  /* These are the same order as the canonical pseudo-PN terms but we can add higher order PN information as and when available here */
767  pAmp->pnSevenThirds = 0.0;
768  pAmp->pnEightThirds = 0.0;
769  pAmp->pnNineThirds = 0.0;
770 
771  /* Generate Pseudo-PN Coefficients for Amplitude. */
772  switch( pWF->IMRPhenomXInspiralAmpVersion)
773  {
774  case 103:
775  {
776  pAmp->CollocationValuesAmpIns[0] = 0.0; // This is not currently used but may be invoked in future recalibration. Leave here, its harmless.
780 
781  pAmp->CollocationPointsAmpIns[0] = 0.25 * pAmp->fAmpMatchIN;
782  pAmp->CollocationPointsAmpIns[1] = 0.50 * pAmp->fAmpMatchIN;
783  pAmp->CollocationPointsAmpIns[2] = 0.75 * pAmp->fAmpMatchIN;
784  pAmp->CollocationPointsAmpIns[3] = 1.00 * pAmp->fAmpMatchIN;
785  break;
786  }
787  default:
788  {
789  XLAL_ERROR(XLAL_EINVAL, "Error in IMRPhenomXGetAmplitudeCoefficients: IMRPhenomXInspiralAmpVersion is not valid.\n");
790  }
791  }
792 
793  // Set collocation points and values
794  V1 = pAmp->CollocationValuesAmpIns[1];
795  V2 = pAmp->CollocationValuesAmpIns[2];
796  V3 = pAmp->CollocationValuesAmpIns[3];
797  F1 = pAmp->CollocationPointsAmpIns[1];
798  F2 = pAmp->CollocationPointsAmpIns[2];
799  F3 = pAmp->CollocationPointsAmpIns[3];
800 
801  if(debug)
802  {
803  printf("\nAmplitude pseudo PN coeffcients\n");
804  printf("fAmpMatchIN = %.6f\n",pAmp->fAmpMatchIN);
805  printf("V1 = %.6f\n",V1);
806  printf("V2 = %.6f\n",V2);
807  printf("V3 = %.6f\n",V3);
808  printf("F1 = %e\n",F1);
809  printf("F2 = %e\n",F2);
810  printf("F3 = %e\n",F3);
811  }
812 
813  /* Using the collocation points and their values, we solve a linear system of equations to recover the pseudo-PN coefficients */
814  pAmp->rho1 = IMRPhenomX_Inspiral_Amp_22_rho1(V1,V2,V3,F1,F2,F3,pWF->IMRPhenomXInspiralAmpVersion);
815  pAmp->rho2 = IMRPhenomX_Inspiral_Amp_22_rho2(V1,V2,V3,F1,F2,F3,pWF->IMRPhenomXInspiralAmpVersion);
816  pAmp->rho3 = IMRPhenomX_Inspiral_Amp_22_rho3(V1,V2,V3,F1,F2,F3,pWF->IMRPhenomXInspiralAmpVersion);
817 
818  /* Set TaylorF2 pseudo-PN coefficients */
819  pAmp->pnSevenThirds = pAmp->rho1;
820  pAmp->pnEightThirds = pAmp->rho2;
821  pAmp->pnNineThirds = pAmp->rho3;
822 
823  if(debug)
824  {
825  printf("\nTaylorF2 PN Amplitude Coefficients\n");
826  printf("pnTwoThirds = %.6f\n",pAmp->pnTwoThirds);
827  printf("pnThreeThirds = %.6f\n",pAmp->pnThreeThirds);
828  printf("pnFourThirds = %.6f\n",pAmp->pnFourThirds);
829  printf("pnFiveThirds = %.6f\n",pAmp->pnFiveThirds);
830  printf("pnSixThirds = %.6f\n",pAmp->pnSixThirds);
831  printf("\n");
832  printf("powers_of_lalpi.itself = %.6f\n",powers_of_lalpi.itself);
833  printf("powers_of_lalpi.four_thirds = %.6f\n",powers_of_lalpi.four_thirds);
834  printf("powers_of_lalpi.five_thirds = %.6f\n",powers_of_lalpi.five_thirds);
835  printf("\n");
836  printf("Pseudo-PN Amplitude Coefficients (Agrees with MMA).\n");
837  printf("alpha1 = %.6f\n",pAmp->pnSevenThirds);
838  printf("alpha2 = %.6f\n",pAmp->pnEightThirds);
839  printf("alpha3 = %.6f\n",pAmp->pnNineThirds);
840  }
841 
842  /* Now we can reconstruct the intermediate region, which depends on the derivative of the inspiral and ringdown fits at the boundaries */
843  F1 = pAmp->fAmpMatchIN;
844  F4 = pAmp->fAmpRDMin;
845 
846  // Initialise useful powers for the boundary points
847  IMRPhenomX_UsefulPowers powers_of_F1;
848  IMRPhenomX_Initialize_Powers(&powers_of_F1,F1);
849 
850  IMRPhenomX_UsefulPowers powers_of_F4;
851  IMRPhenomX_Initialize_Powers(&powers_of_F4,F4);
852 
853  /* Calculate derivative of amplitude on boundary points */
854  d1 = IMRPhenomX_Inspiral_Amp_22_DAnsatz(F1,pWF,pAmp);
855  d4 = IMRPhenomX_Ringdown_Amp_22_DAnsatz(F4,pWF,pAmp);
856 
857  double inspF1 = IMRPhenomX_Inspiral_Amp_22_Ansatz(F1,&powers_of_F1,pWF,pAmp);
858  double rdF4 = IMRPhenomX_Ringdown_Amp_22_Ansatz(F4,pWF,pAmp);
859 
860  /*
861  Use d1 and d4 calculated above to get the derivative of the amplitude on the boundaries:
862 
863  D[ f^{7/6} Ah^{-1}[f] , f] = ( (7/6) * f^{1/6} / Ah[f] ) - ( f^{7/6} Ah'[f] ) / (Ah[f]^2)
864 
865  where d1 = Ah'[F1], inspF1 = Ah[F1] etc.
866 
867  */
868  d1 = ((7.0/6.0) * powers_of_F1.one_sixth / inspF1) - ( powers_of_F1.seven_sixths * d1 / (inspF1*inspF1) );
869  d4 = ((7.0/6.0) * powers_of_F4.one_sixth / rdF4) - ( powers_of_F4.seven_sixths * d4 / (rdF4*rdF4) );
870 
871  if(debug)
872  {
873  printf("d1 = %.6f\n",d1);
874  printf("d4 = %.6f\n",d4);
875  }
876 
877  /* Pass inverse of points to reconstruction function... */
878  switch ( pWF->IMRPhenomXIntermediateAmpVersion )
879  {
880  case 1043:
881  {
882  // Use a 5th order polynomial in intermediate - great agreement to calibration points but poor extrapolation
883  F2 = F1 + (1.0/3.0) * (F4-F1);
884  F3 = F1 + (2.0/3.0) * (F4-F1);
885 
886  V1 = powers_of_F1.m_seven_sixths * inspF1;
889  V4 = powers_of_F4.m_seven_sixths * rdF4;
890 
891  V1 = 1.0 / V1;
892  V2 = 1.0 / V2;
893  V3 = 1.0 / V3;
894  V4 = 1.0 / V4;
895  break;
896  }
897  case 104:
898  {
899  // Use a 4th order polynomial in intermediate - good extrapolation, recommended default fit
900  F2 = F1 + (1.0/2.0) * (F4-F1);
901  F3 = 0.0;
902 
903  V1 = powers_of_F1.m_seven_sixths * inspF1;
905  V4 = powers_of_F4.m_seven_sixths * rdF4;
906 
907  V1 = 1.0 / V1;
908  V2 = 1.0 / V2;
909  V3 = 0.0;
910  V4 = 1.0 / V4;
911 
912  break;
913  }
914  case 105:
915  {
916  // Use a 5th order polynomial in intermediate - great agreement to calibration points but poor extrapolation
917  F2 = F1 + (1.0/3.0) * (F4-F1);
918  F3 = F1 + (2.0/3.0) * (F4-F1);
919 
920  V1 = powers_of_F1.m_seven_sixths * inspF1;
923  V4 = powers_of_F4.m_seven_sixths * rdF4;
924 
925  V1 = 1.0 / V1;
926  V2 = 1.0 / V2;
927  V3 = 1.0 / V3;
928  V4 = 1.0 / V4;
929  break;
930  }
931  default:
932  {
933  XLAL_ERROR(XLAL_EINVAL, "Error: IMRPhenomXIntermediateAmpVersion is not valid.\n");
934  }
935  }
936 
937  /* Let's try directly modifying the (inverse) amplitude values used in the linear system with collocation points (500). See table I of https://arxiv.org/pdf/2001.11412.pdf. NOTE that the 4th order polynomial fit is used by default (500)*/
938  V2 = V2 + ( pWF->PNR_DEV_PARAMETER * pWF->MU3 );
939  // V3 = V3 + ( pWF->PNR_DEV_PARAMETER * pWF->MU4 ); // NOTE that V3 is not used by default in PhenomX, therefore V3 and its deviations have no effect
940 
941  if(debug)
942  {
943  printf("\nIntermediate Region: \n");
944  printf("F1 = %.6f\n",F1);
945  printf("F2 = %.6f\n",F2);
946  printf("F3 = %.6f\n",F3);
947  printf("F4 = %.6f\n",F4);
948  printf("\n");
949  printf("Insp@F1 = %.6f\n",IMRPhenomX_Inspiral_Amp_22_Ansatz(F1,&powers_of_F1,pWF,pAmp));
950  printf("d1 = %.6f\n",d1);
951  printf("d4 = %.6f\n",d4);
952  printf("V1 = %.6f\n",V1);
953  printf("V2 = %.6f\n",V2);
954  printf("V3 = %.6f\n",V3);
955  printf("V4 = %.6f\n",V4);
956  }
957 
958  /*
959  Reconstruct the phenomenological coefficients for the intermediate ansatz:
960  */
961  pAmp->delta0 = IMRPhenomX_Intermediate_Amp_22_delta0(d1,d4,V1,V2,V3,V4,F1,F2,F3,F4,pWF->IMRPhenomXIntermediateAmpVersion);
962  pAmp->delta1 = IMRPhenomX_Intermediate_Amp_22_delta1(d1,d4,V1,V2,V3,V4,F1,F2,F3,F4,pWF->IMRPhenomXIntermediateAmpVersion);
963  pAmp->delta2 = IMRPhenomX_Intermediate_Amp_22_delta2(d1,d4,V1,V2,V3,V4,F1,F2,F3,F4,pWF->IMRPhenomXIntermediateAmpVersion);
964  pAmp->delta3 = IMRPhenomX_Intermediate_Amp_22_delta3(d1,d4,V1,V2,V3,V4,F1,F2,F3,F4,pWF->IMRPhenomXIntermediateAmpVersion);
965  pAmp->delta4 = IMRPhenomX_Intermediate_Amp_22_delta4(d1,d4,V1,V2,V3,V4,F1,F2,F3,F4,pWF->IMRPhenomXIntermediateAmpVersion);
966  pAmp->delta5 = IMRPhenomX_Intermediate_Amp_22_delta5(d1,d4,V1,V2,V3,V4,F1,F2,F3,F4,pWF->IMRPhenomXIntermediateAmpVersion);
967 
968  if(debug)
969  {
970  printf("delta0 = %.6f\n",pAmp->delta0);
971  printf("delta1 = %.6f\n",pAmp->delta1);
972  printf("delta2 = %.6f\n",pAmp->delta2);
973  printf("delta3 = %.6f\n",pAmp->delta3);
974  printf("delta4 = %.6f\n",pAmp->delta4);
975  printf("delta5 = %.6f\n",pAmp->delta5);
976  }
977 
978  return XLAL_SUCCESS;
979 }
980 
981 /*
982  * Function to populate the IMRPhenomXPhaseCoefficients struct:
983 */
987 )
988 {
989  /* Get LALparams */
990  LALDict *LALparams = pWF->LALparams;
991  const INT4 debug = PHENOMXDEBUG;
992 
993  /* GSL objects for solving system of equations via LU decomposition */
994  gsl_vector *b, *x;
995  gsl_matrix *A;
996  gsl_permutation *p;
997  int s;
998 
999  REAL8 deltax;
1000  REAL8 xmin;
1001  REAL8 fi;
1002 
1003  REAL8 gpoints4[4] = {0.0, 1.0/4.0, 3.0/4.0, 1.0};
1004  REAL8 gpoints5[5] = {0.0, 1.0/2 - 1.0/(2*sqrt(2.0)), 1.0/2.0, 1.0/2 + 1.0/(2.0*sqrt(2.0)), 1.0};
1005 
1006  // Matching regions
1007 
1008  /* This is Eq. 5.11 in the paper */
1009  double fIMmatch = 0.6 * (0.5 * pWF->fRING + pWF->fISCO);
1010 
1011  /* This is the MECO frequency */
1012  double fINmatch = pWF->fMECO;
1013 
1014  /* This is Eq. 5.10 in the paper */
1015  double deltaf = (fIMmatch - fINmatch) * 0.03;
1016 
1017  // Transition frequency is just below the MECO frequency and just above the RD fitting region
1018 
1019  /* These are defined in Eq. 7.7 and the text just below, f_H = fPhaseMatchIM and f_L = fPhaseMatchIN */
1020  pPhase->fPhaseMatchIN = fINmatch - 1.0*deltaf;
1021  pPhase->fPhaseMatchIM = fIMmatch + 0.5*deltaf;
1022 
1023  /* Defined in Eq. 7.4, this is f_L */
1024  pPhase->fPhaseInsMin = 0.0026;
1025 
1026  /* Defined in Eq. 7.4, this is f_H */
1027  pPhase->fPhaseInsMax = 1.020 * pWF->fMECO;
1028 
1029  /* Defined in Eq. 7.12, this is f_L */
1030  pPhase->fPhaseRDMin = fIMmatch;
1031 
1032  /* Defined in Eq. 7.12, this is f_L */
1033  pPhase->fPhaseRDMax = pWF->fRING + 1.25*pWF->fDAMP;
1034 
1035  pPhase->phiNorm = -(3.0 * powers_of_lalpi.m_five_thirds) / (128.0);
1036 
1037  /* For convenience, define some variables here */
1038  REAL8 chi1L = pWF->chi1L;
1039  REAL8 chi2L = pWF->chi2L;
1040 
1041  REAL8 chi1L2L = chi1L * chi2L;
1042 
1043  REAL8 chi1L2 = pWF->chi1L * pWF->chi1L;
1044  REAL8 chi1L3 = pWF->chi1L * chi1L2;
1045 
1046  REAL8 chi2L2 = pWF->chi2L * pWF->chi2L;
1047  REAL8 chi2L3 = pWF->chi2L * chi2L2;
1048 
1049  REAL8 eta = pWF->eta;
1050  REAL8 eta2 = eta*eta;
1051  REAL8 eta3 = eta*eta2;
1052 
1053  REAL8 delta = pWF->delta;
1054 
1055  /* Pre-initialize all phenomenological coefficients */
1056  pPhase->a0 = 0.0;
1057  pPhase->a1 = 0.0;
1058  pPhase->a2 = 0.0;
1059  pPhase->a3 = 0.0;
1060  pPhase->a4 = 0.0;
1061 
1062  pPhase->b0 = 0.0;
1063  pPhase->b1 = 0.0;
1064  pPhase->b2 = 0.0;
1065  pPhase->b3 = 0.0;
1066  pPhase->b4 = 0.0;
1067 
1068  pPhase->c0 = 0.0;
1069  pPhase->c1 = 0.0;
1070  pPhase->c2 = 0.0;
1071  pPhase->c3 = 0.0;
1072  pPhase->c4 = 0.0;
1073  pPhase->cL = 0.0;
1074 
1075  pPhase->c2PN_tidal = 0.;
1076  pPhase->c3PN_tidal = 0.;
1077  pPhase->c3p5PN_tidal = 0.;
1078 
1079  pPhase->sigma0 = 0.0;
1080  pPhase->sigma1 = 0.0;
1081  pPhase->sigma2 = 0.0;
1082  pPhase->sigma3 = 0.0;
1083  pPhase->sigma4 = 0.0;
1084  pPhase->sigma5 = 0.0;
1085 
1086 
1087  /*
1088  The general strategy is to initialize a linear system of equations:
1089 
1090  A.x = b
1091 
1092  - A is a matrix with the coefficients of the ansatz evaluated at the collocation nodes.
1093  - b is a vector of the value of the collocation points
1094  - x is the solution vector (i.e. the coefficients) that we must solve for.
1095 
1096  We choose to do this using a standard LU decomposition.
1097  */
1098 
1099  /* Generate list of collocation points */
1100  /*
1101  The Gauss-Chebyshev Points are given by:
1102  GCPoints[n] = Table[Cos[i * pi/n] , {i, 0, n}]
1103 
1104  SamplePoints[xmin,xmax,n] = {
1105  pWF->delta = xmax - xmin;
1106  gpoints = 0.5 * (1 + GCPoints[n-1]);
1107 
1108  return {xmin + pWF->delta * gpoints}
1109  }
1110 
1111  gpoints4 = [1.0, 3.0/4, 1.0/4, 0.0];
1112  gpoints5 = [1.0, 1.0/2 + 1.0/(2.0*sqrt(2.0)), 1.0/2, 1.0/2 - 1.0/(2*sqrt(2.0)), 0.]
1113 
1114  */
1115 
1116  /*
1117  Ringdown phase collocation points:
1118  Here we only use the first N+1 points in the array where N = the
1119  number of pseudo PN terms.
1120 
1121  The size of the array is controlled by: N_MAX_COLLOCATION_POINTS_PHASE_RD
1122 
1123  Default is to use 5 collocation points.
1124  */
1125  deltax = pPhase->fPhaseRDMax - pPhase->fPhaseRDMin;
1126  xmin = pPhase->fPhaseRDMin;
1127  int i;
1128 
1129  double phaseRD; // This is used in intermediate phase reconstruction.
1130 
1131  if(debug)
1132  {
1133  printf("\n");
1134  printf("Solving system of equations for RD phase...\n");
1135  }
1136 
1137  // Initialize collocation points
1138  for(i = 0; i < 5; i++)
1139  {
1140  pPhase->CollocationPointsPhaseRD[i] = gpoints5[i] * deltax + xmin;
1141  }
1142  // Collocation point 4 is set to the ringdown frequency ~ dip in Lorentzian
1143  pPhase->CollocationPointsPhaseRD[3] = pWF->fRING;
1144 
1145  if(debug)
1146  {
1147  printf("Rigndown collocation points : \n");
1148  printf("F1 : %.6f\n",pPhase->CollocationPointsPhaseRD[0]);
1149  printf("F2 : %.6f\n",pPhase->CollocationPointsPhaseRD[1]);
1150  printf("F3 : %.6f\n",pPhase->CollocationPointsPhaseRD[2]);
1151  printf("F4 : %.6f\n",pPhase->CollocationPointsPhaseRD[3]);
1152  printf("F5 : %.6f\n",pPhase->CollocationPointsPhaseRD[4]);
1153  }
1154 
1155  switch(pWF->IMRPhenomXRingdownPhaseVersion)
1156  {
1157  case 105:
1158  {
1159  pPhase->NCollocationPointsRD = 5;
1160  break;
1161  }
1162  default:
1163  {
1164  XLAL_ERROR(XLAL_EINVAL, "Error: IMRPhenomXRingdownPhaseVersion is not valid.\n");
1165  }
1166  }
1167 
1168  if(debug)
1169  {
1170  printf("NCollRD = %d\n",pPhase->NCollocationPointsRD);
1171  }
1172 
1173  // Eq. 7.13 in arXiv:2001.11412
1174  double RDv4 = IMRPhenomX_Ringdown_Phase_22_v4(pWF->eta,pWF->STotR,pWF->dchi,pWF->delta,pWF->IMRPhenomXRingdownPhaseVersion);
1175 
1176  /* These are the calibrated collocation points, as per Eq. 7.13 */
1180  pPhase->CollocationValuesPhaseRD[3] = RDv4;
1182 
1183  /* v_j = d_{j4} + v4 */
1184  pPhase->CollocationValuesPhaseRD[4] = pPhase->CollocationValuesPhaseRD[4] + pPhase->CollocationValuesPhaseRD[3]; // v5 = d54 + v4
1185  pPhase->CollocationValuesPhaseRD[2] = pPhase->CollocationValuesPhaseRD[2] + pPhase->CollocationValuesPhaseRD[3]; // v3 = d34 + v4
1186  pPhase->CollocationValuesPhaseRD[1] = pPhase->CollocationValuesPhaseRD[1] + pPhase->CollocationValuesPhaseRD[3]; // v2 = d24 + v4
1187  pPhase->CollocationValuesPhaseRD[0] = pPhase->CollocationValuesPhaseRD[0] + pPhase->CollocationValuesPhaseRD[1]; // v1 = d12 + v2
1188 
1189  // Debugging information. Leave for convenience later on.
1190  if(debug)
1191  {
1192  printf("\n");
1193  printf("Ringdown Collocation Points: \n");
1194  printf("v1 : %.6f\n",pPhase->CollocationValuesPhaseRD[0]);
1195  printf("v2 : %.6f\n",pPhase->CollocationValuesPhaseRD[1]);
1196  printf("v3 : %.6f\n",pPhase->CollocationValuesPhaseRD[2]);
1197  printf("v4 : %.6f\n",pPhase->CollocationValuesPhaseRD[3]);
1198  printf("v5 : %.6f\n",pPhase->CollocationValuesPhaseRD[4]);
1199  printf("\n");
1200  }
1201 
1202  phaseRD = pPhase->CollocationValuesPhaseRD[0];
1203 
1204  p = gsl_permutation_alloc(pPhase->NCollocationPointsRD);
1205  b = gsl_vector_alloc(pPhase->NCollocationPointsRD);
1206  x = gsl_vector_alloc(pPhase->NCollocationPointsRD);
1207  A = gsl_matrix_alloc(pPhase->NCollocationPointsRD,pPhase->NCollocationPointsRD);
1208 
1209  /*
1210  Populate the b vector
1211  */
1212  gsl_vector_set(b,0,pPhase->CollocationValuesPhaseRD[0]);
1213  gsl_vector_set(b,1,pPhase->CollocationValuesPhaseRD[1]);
1214  gsl_vector_set(b,2,pPhase->CollocationValuesPhaseRD[2]);
1215  gsl_vector_set(b,3,pPhase->CollocationValuesPhaseRD[3]);
1216  gsl_vector_set(b,4,pPhase->CollocationValuesPhaseRD[4]);
1217 
1218  /*
1219  Eq. 7.12 in arXiv:2001.11412
1220 
1221  ansatzRD(f) = a_0 + a_1 f^(-1/3) + a_2 f^(-2) + a_3 f^(-3) + a_4 f^(-4) + ( aRD ) / ( (f_damp^2 + (f - f_ring)^2 ) )
1222 
1223  Canonical ansatz sets a_3 to 0.
1224  */
1225 
1226  /*
1227  We now set up and solve a linear system of equations.
1228  First we populate the matrix A_{ij}
1229  */
1230 
1231  /* Note that ff0 is always 1 */
1232  REAL8 ff, invff, ff0, ff1, ff2, ff3, ff4;
1233 
1234  /* A_{0,i} */
1235  ff = pPhase->CollocationPointsPhaseRD[0];
1236  invff = 1.0 / ff;
1237  ff1 = cbrt(invff); // f^{-1/3}
1238  ff2 = invff * invff; // f^{-2}
1239  ff3 = ff2 * ff2; // f^{-4}
1240  ff4 = -(pWF->dphase0) / (pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
1241  gsl_matrix_set(A,0,0,1.0); // Constant
1242  gsl_matrix_set(A,0,1,ff1); // f^(-1/3) term
1243  gsl_matrix_set(A,0,2,ff2); // f^(-2) term
1244  gsl_matrix_set(A,0,3,ff3); // f^(-4) term
1245  gsl_matrix_set(A,0,4,ff4); // Lorentzian term
1246 
1247  if(debug)
1248  {
1249  printf("For row 0: a0 + a1 %.6f + a2 %.6f + a4 %.6f + aRD %.6f\n",ff1,ff2,ff3,ff4);
1250  }
1251 
1252  /* A_{1,i} */
1253  ff = pPhase->CollocationPointsPhaseRD[1];
1254  invff = 1.0 / ff;
1255  ff1 = cbrt(invff);
1256  ff2 = invff * invff;
1257  ff3 = ff2 * ff2;
1258  ff4 = -(pWF->dphase0) / (pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
1259  gsl_matrix_set(A,1,0,1.0);
1260  gsl_matrix_set(A,1,1,ff1);
1261  gsl_matrix_set(A,1,2,ff2);
1262  gsl_matrix_set(A,1,3,ff3);
1263  gsl_matrix_set(A,1,4,ff4);
1264 
1265  /* A_{2,i} */
1266  ff = pPhase->CollocationPointsPhaseRD[2];
1267  invff = 1.0 / ff;
1268  ff1 = cbrt(invff);
1269  ff2 = invff * invff;
1270  ff3 = ff2 * ff2;
1271  ff4 = -(pWF->dphase0) / (pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
1272  gsl_matrix_set(A,2,0,1.0);
1273  gsl_matrix_set(A,2,1,ff1);
1274  gsl_matrix_set(A,2,2,ff2);
1275  gsl_matrix_set(A,2,3,ff3);
1276  gsl_matrix_set(A,2,4,ff4);
1277 
1278  /* A_{3,i} */
1279  ff = pPhase->CollocationPointsPhaseRD[3];
1280  invff = 1.0 / ff;
1281  ff1 = cbrt(invff);
1282  ff2 = invff * invff;
1283  ff3 = ff2 * ff2;
1284  ff4 = -(pWF->dphase0) / (pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
1285  gsl_matrix_set(A,3,0,1.0);
1286  gsl_matrix_set(A,3,1,ff1);
1287  gsl_matrix_set(A,3,2,ff2);
1288  gsl_matrix_set(A,3,3,ff3);
1289  gsl_matrix_set(A,3,4,ff4);
1290 
1291  /* A_{4,i} */
1292  ff = pPhase->CollocationPointsPhaseRD[4];
1293  invff = 1.0 / ff;
1294  ff1 = cbrt(invff);
1295  ff2 = invff * invff;
1296  ff3 = ff2 * ff2;
1297  ff4 = -(pWF->dphase0) / (pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
1298  gsl_matrix_set(A,4,0,1.0);
1299  gsl_matrix_set(A,4,1,ff1);
1300  gsl_matrix_set(A,4,2,ff2);
1301  gsl_matrix_set(A,4,3,ff3);
1302  gsl_matrix_set(A,4,4,ff4);
1303 
1304  /* We now solve the system A x = b via an LU decomposition */
1305  gsl_linalg_LU_decomp(A,p,&s);
1306  gsl_linalg_LU_solve(A,p,b,x);
1307 
1308  pPhase->c0 = gsl_vector_get(x,0); // x[0]; // a0
1309  pPhase->c1 = gsl_vector_get(x,1); // x[1]; // a1
1310  pPhase->c2 = gsl_vector_get(x,2); // x[2]; // a2
1311  pPhase->c4 = gsl_vector_get(x,3); // x[3]; // a4
1312  pPhase->cRD = gsl_vector_get(x,4);
1313  pPhase->cL = -(pWF->dphase0 * pPhase->cRD); // ~ x[4] // cL = - a_{RD} * dphase0
1314 
1315  /* Apply NR tuning for precessing cases (500) */
1316  pPhase->cL = pPhase->cL + ( pWF->PNR_DEV_PARAMETER * pWF->NU4 );
1317  // pPhase->c0 = pPhase->c0 + ( pWF->PNR_DEV_PARAMETER * pWF->NU0 );
1318 
1319  if(debug)
1320  {
1321  printf("\n");
1322  printf("Ringdown Coefficients: \n");
1323  printf("c0 : %.6f\n",pPhase->c0);
1324  printf("c1 : %.6f\n",pPhase->c1);
1325  printf("c2 : %.6f\n",pPhase->c2);
1326  printf("c4 : %e\n",pPhase->c4);
1327  printf("cRD : %.6f\n",gsl_vector_get(x,4));
1328  printf("d0 : %.6f\n",pWF->dphase0);
1329  printf("cL : %e\n",pPhase->cL);
1330  printf("\n");
1331 
1332  printf("Freeing arrays...\n");
1333  }
1334 
1335  /* Tidy up in preparation for next GSL solve ... */
1336  gsl_vector_free(b);
1337  gsl_vector_free(x);
1338  gsl_matrix_free(A);
1339  gsl_permutation_free(p);
1340 
1341  /*
1342  Inspiral phase collocation points:
1343  Here we only use the first N+1 points in the array where N = the
1344  number of pseudo PN terms. E.g. for 4 pseudo-PN terms, we will
1345  need 4 collocation points. An ansatz with n free coefficients
1346  needs n pieces of information in order to constrain the ansatz.
1347 
1348  The size of the array is controlled by: N_MAX_COLLOCATION_POINTS_PHASE_INS
1349 
1350  Default is to use 4 pseudo-PN coefficients and hence 4 collocation points.
1351 
1352  GC points as per Eq. 7.4 and 7.5, where f_L = pPhase->fPhaseInsMin and f_H = pPhase->fPhaseInsMax
1353  */
1354  deltax = pPhase->fPhaseInsMax - pPhase->fPhaseInsMin;
1355  xmin = pPhase->fPhaseInsMin;
1356 
1357  /*
1358  Set number of pseudo-PN coefficients:
1359  - If you add a new PN inspiral approximant, update with new version here.
1360  */
1361  switch(pWF->IMRPhenomXInspiralPhaseVersion)
1362  {
1363  case 104:
1364  {
1365  pPhase->NPseudoPN = 4;
1366  pPhase->NCollocationPointsPhaseIns = 4;
1367  break;
1368  }
1369  case 105:
1370  {
1371  pPhase->NPseudoPN = 5;
1372  pPhase->NCollocationPointsPhaseIns = 5;
1373  break;
1374  }
1375  case 114:
1376  {
1377  pPhase->NPseudoPN = 4;
1378  pPhase->NCollocationPointsPhaseIns = 4;
1379  break;
1380  }
1381  case 115:
1382  {
1383  pPhase->NPseudoPN = 5;
1384  pPhase->NCollocationPointsPhaseIns = 5;
1385  break;
1386  }
1387  default:
1388  {
1389  XLAL_ERROR_REAL8(XLAL_EINVAL, "Error: IMRPhenomXInspiralPhaseVersion is not valid.\n");
1390  }
1391  }
1392 
1393  if(debug)
1394  {
1395  printf("\n");
1396  printf("NPseudoPN : %d\n",pPhase->NPseudoPN);
1397  printf("NColl : %d\n",pPhase->NCollocationPointsPhaseIns);
1398  printf("\n");
1399  }
1400 
1401  p = gsl_permutation_alloc(pPhase->NCollocationPointsPhaseIns);
1402  b = gsl_vector_alloc(pPhase->NCollocationPointsPhaseIns);
1403  x = gsl_vector_alloc(pPhase->NCollocationPointsPhaseIns);
1404  A = gsl_matrix_alloc(pPhase->NCollocationPointsPhaseIns,pPhase->NCollocationPointsPhaseIns);
1405 
1406  /*
1407  If we are using 4 pseudo-PN coefficients, call the routines below.
1408  The inspiral phase version is still passed to the individual functions.
1409  */
1410  if(pPhase->NPseudoPN == 4)
1411  {
1412  // By default all models implemented use the following GC points.
1413  // If a new model is calibrated with different choice of collocation points, edit this.
1414  for(i = 0; i < pPhase->NCollocationPointsPhaseIns; i++)
1415  {
1416  fi = gpoints4[i] * deltax + xmin;
1417  pPhase->CollocationPointsPhaseIns[i] = fi;
1418  }
1419 
1420  // Calculate the value of the differences between the ith and 3rd collocation points at the GC nodes
1425 
1426  // Calculate the value of the collocation points at GC nodes via: v_i = d_i3 + v3
1430 
1431  if(debug)
1432  {
1433  printf("\n");
1434  printf("Inspiral Collocation Points and Values:\n");
1435  printf("F1 : %.6f\n",pPhase->CollocationPointsPhaseIns[0]);
1436  printf("F2 : %.6f\n",pPhase->CollocationPointsPhaseIns[1]);
1437  printf("F3 : %.6f\n",pPhase->CollocationPointsPhaseIns[2]);
1438  printf("F4 : %.6f\n",pPhase->CollocationPointsPhaseIns[3]);
1439  printf("\n");
1440  printf("V1 : %.6f\n",pPhase->CollocationValuesPhaseIns[0]);
1441  printf("V2 : %.6f\n",pPhase->CollocationValuesPhaseIns[1]);
1442  printf("V3 : %.6f\n",pPhase->CollocationValuesPhaseIns[2]);
1443  printf("V4 : %.6f\n",pPhase->CollocationValuesPhaseIns[3]);
1444  printf("\n");
1445  }
1446 
1447  gsl_vector_set(b,0,pPhase->CollocationValuesPhaseIns[0]);
1448  gsl_vector_set(b,1,pPhase->CollocationValuesPhaseIns[1]);
1449  gsl_vector_set(b,2,pPhase->CollocationValuesPhaseIns[2]);
1450  gsl_vector_set(b,3,pPhase->CollocationValuesPhaseIns[3]);
1451 
1452  /* A_{0,i} */
1453  ff = pPhase->CollocationPointsPhaseIns[0];
1454  ff1 = cbrt(ff);
1455  ff2 = ff1 * ff1;
1456  ff3 = ff;
1457  ff0 = 1.0;
1458  gsl_matrix_set(A,0,0,1.0);
1459  gsl_matrix_set(A,0,1,ff1);
1460  gsl_matrix_set(A,0,2,ff2);
1461  gsl_matrix_set(A,0,3,ff3);
1462 
1463  /* A_{1,i} */
1464  ff = pPhase->CollocationPointsPhaseIns[1];
1465  ff1 = cbrt(ff);
1466  ff2 = ff1 * ff1;
1467  ff3 = ff;
1468  ff0 = 1.0;
1469  gsl_matrix_set(A,1,0,1.0);
1470  gsl_matrix_set(A,1,1,ff1);
1471  gsl_matrix_set(A,1,2,ff2);
1472  gsl_matrix_set(A,1,3,ff3);
1473 
1474  /* A_{2,i} */
1475  ff = pPhase->CollocationPointsPhaseIns[2];
1476  ff1 = cbrt(ff);
1477  ff2 = ff1 * ff1;
1478  ff3 = ff;
1479  ff0 = 1.0;
1480  gsl_matrix_set(A,2,0,1.0);
1481  gsl_matrix_set(A,2,1,ff1);
1482  gsl_matrix_set(A,2,2,ff2);
1483  gsl_matrix_set(A,2,3,ff3);
1484 
1485  /* A_{3,i} */
1486  ff = pPhase->CollocationPointsPhaseIns[3];
1487  ff1 = cbrt(ff);
1488  ff2 = ff1 * ff1;
1489  ff3 = ff;
1490  ff0 = 1.0;
1491  gsl_matrix_set(A,3,0,1.0);
1492  gsl_matrix_set(A,3,1,ff1);
1493  gsl_matrix_set(A,3,2,ff2);
1494  gsl_matrix_set(A,3,3,ff3);
1495 
1496  /* We now solve the system A x = b via an LU decomposition */
1497  gsl_linalg_LU_decomp(A,p,&s);
1498  gsl_linalg_LU_solve(A,p,b,x);
1499 
1500  /* Set inspiral phenomenological coefficients from solution to A x = b */
1501  pPhase->a0 = gsl_vector_get(x,0); // x[0]; // alpha_0
1502  pPhase->a1 = gsl_vector_get(x,1); // x[1]; // alpha_1
1503  pPhase->a2 = gsl_vector_get(x,2); // x[2]; // alpha_2
1504  pPhase->a3 = gsl_vector_get(x,3); // x[3]; // alpha_3
1505  pPhase->a4 = 0.0;
1506 
1507  /*
1508  PSEUDO PN TERMS WORK:
1509  - 104 works.
1510  - 105 not tested.
1511  - 114 not tested.
1512  - 115 not tested.
1513  */
1514  if(debug)
1515  {
1516  printf("\n");
1517  printf("3pPN\n");
1518  printf("Inspiral Pseudo-PN Coefficients:\n");
1519  printf("a0 : %.6f\n",pPhase->a0);
1520  printf("a1 : %.6f\n",pPhase->a1);
1521  printf("a2 : %.6f\n",pPhase->a2);
1522  printf("a3 : %.6f\n",pPhase->a3);
1523  printf("a4 : %.6f\n",pPhase->a4);
1524  printf("\n");
1525  }
1526 
1527  /* Tidy up in preparation for next GSL solve ... */
1528  gsl_vector_free(b);
1529  gsl_vector_free(x);
1530  gsl_matrix_free(A);
1531  gsl_permutation_free(p);
1532 
1533  }
1534  else if(pPhase->NPseudoPN == 5)
1535  {
1536  // Using 5 pseudo-PN coefficients so set 5 collocation points
1537  for(i = 0; i < 5; i++)
1538  {
1539  fi = gpoints5[i] * deltax + xmin;
1540  pPhase->CollocationPointsPhaseIns[i] = fi;
1541  }
1547 
1548  /* v_j = d_j3 + v_3 */
1553 
1554  if(debug)
1555  {
1556  printf("\n");
1557  printf("Inspiral Collocation Points and Values:\n");
1558  printf("F1 : %.6f\n",pPhase->CollocationPointsPhaseIns[0]);
1559  printf("F2 : %.6f\n",pPhase->CollocationPointsPhaseIns[1]);
1560  printf("F3 : %.6f\n",pPhase->CollocationPointsPhaseIns[2]);
1561  printf("F4 : %.6f\n",pPhase->CollocationPointsPhaseIns[3]);
1562  printf("F5 : %.6f\n",pPhase->CollocationPointsPhaseIns[4]);
1563  printf("\n");
1564  printf("V1 : %.6f\n",pPhase->CollocationValuesPhaseIns[0]);
1565  printf("V2 : %.6f\n",pPhase->CollocationValuesPhaseIns[1]);
1566  printf("V3 : %.6f\n",pPhase->CollocationValuesPhaseIns[2]);
1567  printf("V4 : %.6f\n",pPhase->CollocationValuesPhaseIns[3]);
1568  printf("V5 : %.6f\n",pPhase->CollocationValuesPhaseIns[4]);
1569  printf("\n");
1570  }
1571 
1572  gsl_vector_set(b,0,pPhase->CollocationValuesPhaseIns[0]);
1573  gsl_vector_set(b,1,pPhase->CollocationValuesPhaseIns[1]);
1574  gsl_vector_set(b,2,pPhase->CollocationValuesPhaseIns[2]);
1575  gsl_vector_set(b,3,pPhase->CollocationValuesPhaseIns[3]);
1576  gsl_vector_set(b,4,pPhase->CollocationValuesPhaseIns[4]);
1577 
1578  /* A_{0,i} */
1579  ff = pPhase->CollocationPointsPhaseIns[0];
1580  ff1 = cbrt(ff);
1581  ff2 = ff1 * ff1;
1582  ff3 = ff;
1583  ff4 = ff * ff1;
1584  gsl_matrix_set(A,0,0,1.0);
1585  gsl_matrix_set(A,0,1,ff1);
1586  gsl_matrix_set(A,0,2,ff2);
1587  gsl_matrix_set(A,0,3,ff3);
1588  gsl_matrix_set(A,0,4,ff4);
1589 
1590  /* A_{1,i} */
1591  ff = pPhase->CollocationPointsPhaseIns[1];
1592  ff1 = cbrt(ff);
1593  ff2 = ff1 * ff1;
1594  ff3 = ff;
1595  ff4 = ff * ff1;
1596  gsl_matrix_set(A,1,0,1.0);
1597  gsl_matrix_set(A,1,1,ff1);
1598  gsl_matrix_set(A,1,2,ff2);
1599  gsl_matrix_set(A,1,3,ff3);
1600  gsl_matrix_set(A,1,4,ff4);
1601 
1602  /* A_{2,i} */
1603  ff = pPhase->CollocationPointsPhaseIns[2];
1604  ff1 = cbrt(ff);
1605  ff2 = ff1 * ff1;
1606  ff3 = ff;
1607  ff4 = ff * ff1;
1608  gsl_matrix_set(A,2,0,1.0);
1609  gsl_matrix_set(A,2,1,ff1);
1610  gsl_matrix_set(A,2,2,ff2);
1611  gsl_matrix_set(A,2,3,ff3);
1612  gsl_matrix_set(A,2,4,ff4);
1613 
1614  /* A_{3,i} */
1615  ff = pPhase->CollocationPointsPhaseIns[3];
1616  ff1 = cbrt(ff);
1617  ff2 = ff1 * ff1;
1618  ff3 = ff;
1619  ff4 = ff * ff1;
1620  gsl_matrix_set(A,3,0,1.0);
1621  gsl_matrix_set(A,3,1,ff1);
1622  gsl_matrix_set(A,3,2,ff2);
1623  gsl_matrix_set(A,3,3,ff3);
1624  gsl_matrix_set(A,3,4,ff4);
1625 
1626  /* A_{4,i} */
1627  ff = pPhase->CollocationPointsPhaseIns[4];
1628  ff1 = cbrt(ff);
1629  ff2 = ff1 * ff1;
1630  ff3 = ff;
1631  ff4 = ff * ff1;
1632  gsl_matrix_set(A,4,0,1.0);
1633  gsl_matrix_set(A,4,1,ff1);
1634  gsl_matrix_set(A,4,2,ff2);
1635  gsl_matrix_set(A,4,3,ff3);
1636  gsl_matrix_set(A,4,4,ff4);
1637 
1638  /* We now solve the system A x = b via an LU decomposition */
1639  gsl_linalg_LU_decomp(A,p,&s);
1640  gsl_linalg_LU_solve(A,p,b,x);
1641 
1642  /* Set inspiral phenomenological coefficients from solution to A x = b */
1643  pPhase->a0 = gsl_vector_get(x,0); // x[0];
1644  pPhase->a1 = gsl_vector_get(x,1); // x[1];
1645  pPhase->a2 = gsl_vector_get(x,2); // x[2];
1646  pPhase->a3 = gsl_vector_get(x,3); // x[3];
1647  pPhase->a4 = gsl_vector_get(x,4); // x[4];
1648 
1649  if(debug)
1650  {
1651  printf("\n");
1652  printf("4pPN\n");
1653  printf("Inspiral Pseudo-PN Coefficients:\n");
1654  printf("a0 : %.6f\n",pPhase->a0);
1655  printf("a1 : %.6f\n",pPhase->a1);
1656  printf("a2 : %.6f\n",pPhase->a2);
1657  printf("a3 : %.6f\n",pPhase->a3);
1658  printf("a4 : %.6f\n",pPhase->a4);
1659  printf("\n");
1660  }
1661 
1662  /* Tidy up in preparation for next GSL solve ... */
1663  gsl_vector_free(b);
1664  gsl_vector_free(x);
1665  gsl_matrix_free(A);
1666  gsl_permutation_free(p);
1667  }
1668  else
1669  {
1670  XLALPrintError("Error in ComputeIMRPhenomXWaveformVariables: NPseudoPN requested is not valid.\n");
1671  }
1672 
1673  /* The pseudo-PN coefficients are normalized such that: (dphase0 / eta) * f^{8/3} * a_j */
1674  /* So we must re-scale these terms by an extra factor of f^{-8/3} in the PN phasing */
1675  pPhase->sigma1 = (-5.0/3.0) * pPhase->a0;
1676  pPhase->sigma2 = (-5.0/4.0) * pPhase->a1;
1677  pPhase->sigma3 = (-5.0/5.0) * pPhase->a2;
1678  pPhase->sigma4 = (-5.0/6.0) * pPhase->a3;
1679  pPhase->sigma5 = (-5.0/7.0) * pPhase->a4;
1680 
1681  /* Initialize TaylorF2 PN coefficients */
1682  pPhase->dphi0 = 0.0;
1683  pPhase->dphi1 = 0.0;
1684  pPhase->dphi2 = 0.0;
1685  pPhase->dphi3 = 0.0;
1686  pPhase->dphi4 = 0.0;
1687  pPhase->dphi5 = 0.0;
1688  pPhase->dphi6 = 0.0;
1689  pPhase->dphi7 = 0.0;
1690  pPhase->dphi8 = 0.0;
1691  pPhase->dphi9 = 0.0;
1692  pPhase->dphi10 = 0.0;
1693  pPhase->dphi11 = 0.0;
1694  pPhase->dphi12 = 0.0;
1695 
1696  pPhase->dphi5L = 0.0;
1697  pPhase->dphi6L = 0.0;
1698  pPhase->dphi8L = 0.0;
1699  pPhase->dphi9L = 0.0;
1700 
1701  pPhase->phi0 = 0.0;
1702  pPhase->phi1 = 0.0;
1703  pPhase->phi2 = 0.0;
1704  pPhase->phi3 = 0.0;
1705  pPhase->phi4 = 0.0;
1706  pPhase->phi5 = 0.0;
1707  pPhase->phi6 = 0.0;
1708  pPhase->phi7 = 0.0;
1709  pPhase->phi8 = 0.0;
1710  pPhase->phi9 = 0.0;
1711  pPhase->phi10 = 0.0;
1712  pPhase->phi11 = 0.0;
1713  pPhase->phi12 = 0.0;
1714 
1715  pPhase->phi5L = 0.0;
1716  pPhase->phi6L = 0.0;
1717  pPhase->phi8L = 0.0;
1718  pPhase->phi9L = 0.0;
1719 
1720  /* **** TaylorF2 PN Coefficients: Phase **** */
1721 
1722  /*
1723  - These are the PN coefficients normalised by: 3 / (128 * eta * [pi M f]^{5/3} ).
1724  - We add in powers of (M f)^{N/3} later but add powers of pi^{N/3} here
1725  - The log terms are *always* in terms of log(v), so we multiply by log(v) when summing PN phasing series.
1726  - We *do not* overwrite the PN phasing series with pseudo-PN terms. These are added separately.
1727 
1728  PN terms can be found in:
1729  - Marsat et al, CQG, 32, 085008, (2015)
1730  - Bohe et al, CQG, 32, 195010, (2015)
1731  - Bernard et al, PRD, 95, 044026, (2017)
1732  - Bernard et al, PRD, 93, 084037, (2016)
1733  - Damour et al, PRD, 89, 064058, (2014)
1734  - Damour et al, PRD, 95, 084005, (2017)
1735  - Bernard et al, PRD, 96, 104043, (2017)
1736  - Marchand et al, PRD, 97, 044023, (2018)
1737  - Marchand et al, CQG, 33, 244003, (2016)
1738  - Nagar et al, PRD, 99, 044007, (2019)
1739  - Messina et al, PRD, 97, 084016, (2018)
1740  */
1741 
1742  /* Split into non-spinning and spin-dependent coefficients */
1743  UNUSED REAL8 phi0S = 0.0, phi1S = 0.0, phi2S = 0.0;
1744  REAL8 phi0NS = 0.0, phi1NS = 0.0, phi2NS = 0.0;
1745  REAL8 phi3NS = 0.0, phi3S = 0.0, phi4NS = 0.0, phi4S = 0.0, phi5NS = 0.0, phi5S = 0.0;
1746  REAL8 phi5LNS = 0.0, phi5LS = 0.0, phi6NS = 0.0, phi6S = 0.0, phi6LNS = 0.0, phi6LS = 0.0;
1747  REAL8 phi7NS = 0.0, phi7S = 0.0, phi8NS = 0.0, phi8S = 0.0, phi8LNS = 0.0;
1748  REAL8 phi8LS = 0.0, phi9NS = 0.0, phi9S = 0.0, phi9LNS = 0.0, phi9LS = 0.0;
1749 
1750 
1751  /* Analytically known PN coefficients */
1752  /* Newtonian */
1753  phi0NS = 1.0;
1754 
1755  /* ~~ 0.5 PN ~~ */
1756  phi1NS = 0.0;
1757 
1758  /* ~~ 1.0 PN ~~ */
1759  /* 1.0PN, Non-Spinning */
1760  phi2NS = (3715/756. + (55*eta)/9.) * powers_of_lalpi.two_thirds;
1761 
1762  /* ~~ 1.5 PN ~~ */
1763  /* 1.5PN, Non-Spinning */
1764  phi3NS = -16.0 * powers_of_lalpi.two;
1765  /* 1.5PN, Spin-Orbit */
1766  phi3S = ( (113*(chi1L + chi2L + chi1L*delta - chi2L*delta) - 76*(chi1L + chi2L)*eta)/6. ) * powers_of_lalpi.itself;
1767 
1768  /* ~~ 2.0 PN ~~ */
1769  /* 2.0PN, Non-Spinning */
1770  phi4NS = ( 15293365/508032. + (27145*eta)/504. + (3085*eta2)/72. ) * powers_of_lalpi.four_thirds;
1771  /* 2.0PN, Spin-Spin */
1772  phi4S = ( (-5*(81*chi1L2*(1 + delta - 2*eta) + 316*chi1L2L*eta - 81*chi2L2*(-1 + delta + 2*eta)))/16. ) * powers_of_lalpi.four_thirds;
1773 
1774  /* ~~ 2.5 PN ~~ */
1775  phi5NS = 0.0;
1776  phi5S = 0.0;
1777 
1778  /* ~~ 2.5 PN, Log Term ~~ */
1779  /* 2.5PN, Non-Spinning */
1780  phi5LNS = ( (5*(46374 - 6552*eta)*LAL_PI)/4536. ) * powers_of_lalpi.five_thirds;
1781  /* 2.5PN, Spin-Orbit */
1782  phi5LS = ( (-732985*(chi1L + chi2L + chi1L*delta - chi2L*delta) - 560*(-1213*(chi1L + chi2L)
1783  + 63*(chi1L - chi2L)*delta)*eta + 85680*(chi1L + chi2L)*eta2)/4536. ) * powers_of_lalpi.five_thirds;
1784 
1785  /* ~~ 3.0 PN ~~ */
1786  /* 3.0 PN, Non-Spinning */
1787  phi6NS = ( 11583231236531/4.69421568e9 - (5*eta*(3147553127 + 588*eta*(-45633 + 102260*eta)))/3.048192e6 - (6848*LAL_GAMMA)/21.
1788  - (640*powers_of_lalpi.two)/3. + (2255*eta*powers_of_lalpi.two)/12. - (13696*log(2))/21. - (6848*powers_of_lalpi.log)/63. ) * powers_of_lalpi.two;
1789  /* 3.0 PN, Spin-Orbit */
1790  phi6S = ( (5*(227*(chi1L + chi2L + chi1L*delta - chi2L*delta) - 156*(chi1L + chi2L)*eta)*LAL_PI)/3. ) * powers_of_lalpi.two;
1791  /* 3.0 PN, Spin-Spin */
1792  phi6S += ( (5*(20*chi1L2L*eta*(11763 + 12488*eta) + 7*chi2L2*(-15103*(-1 + delta) + 2*(-21683 + 6580*delta)*eta - 9808*eta2) -
1793  7*chi1L2*(-15103*(1 + delta) + 2*(21683 + 6580*delta)*eta + 9808*eta2)))/4032. ) * powers_of_lalpi.two;
1794 
1795  /* ~~ 3.0 PN, Log Term ~~ */
1796  phi6LNS = (-6848/63.) * powers_of_lalpi.two;
1797  phi6LS = 0.0;
1798 
1799  /* ~~ 3.5 PN ~~ */
1800  /* 3.5 PN, Non-Spinning */
1801  phi7NS = ( (5*(15419335 + 168*(75703 - 29618*eta)*eta)*LAL_PI)/254016. ) * powers_of_lalpi.seven_thirds;
1802  /* 3.5 PN, Spin-Orbit */
1803  phi7S = ( (5*(-5030016755*(chi1L + chi2L + chi1L*delta - chi2L*delta) + 4*(2113331119*(chi1L + chi2L) + 675484362*(chi1L - chi2L)*delta)*eta - 1008*(208433*(chi1L + chi2L) + 25011*(chi1L - chi2L)*delta)*eta2 + 90514368*(chi1L + chi2L)*eta3))/6.096384e6 ) * powers_of_lalpi.seven_thirds;
1804  /* 3.5 PN, Spin-Spin */
1805  phi7S += ( -5*(57*chi1L2*(1 + delta - 2*eta) + 220*chi1L2L*eta - 57*chi2L2*(-1 + delta + 2*eta))*LAL_PI ) * powers_of_lalpi.seven_thirds;
1806  /* 3.5 PN, Cubic-in-Spin */
1807  phi7S += ( (14585*(-(chi2L3*(-1 + delta)) + chi1L3*(1 + delta)) - 5*(chi2L3*(8819 - 2985*delta) + 8439*chi1L*chi2L2*(-1 + delta) - 8439*chi1L2*chi2L*(1 + delta) + chi1L3*(8819 + 2985*delta))*eta + 40*(chi1L + chi2L)*(17*chi1L2 - 14*chi1L2L + 17*chi2L2)*eta2)/48. ) * powers_of_lalpi.seven_thirds;
1808 
1809  /* ~~ 4.0 PN ~~ */
1810  /* 4.0 PN, Non-Spinning */
1811  phi8NS = 0.0;
1812  /* 4.0 PN, Spin-Orbit */
1813  phi8S = ( (-5*(1263141*(chi1L + chi2L + chi1L*delta - chi2L*delta) - 2*(794075*(chi1L + chi2L) + 178533*(chi1L - chi2L)*delta)*eta + 94344*(chi1L + chi2L)*eta2)*LAL_PI*(-1 + powers_of_lalpi.log))/9072. ) * powers_of_lalpi.eight_thirds;
1814 
1815  /* ~~ 4.0 PN, Log Term ~~ */
1816  /* 4.0 PN, log term, Non-Spinning */
1817  phi8LNS = 0.0;
1818  /* 4.0 PN, log term, Spin-Orbit */
1819  phi8LS = ((-5*(1263141*(chi1L + chi2L + chi1L*delta - chi2L*delta) - 2*(794075*(chi1L + chi2L) + 178533*(chi1L - chi2L)*delta)*eta
1820  + 94344*(chi1L + chi2L)*eta2)*LAL_PI)/9072.) * powers_of_lalpi.eight_thirds;
1821 
1822  /* ~~ 4.5 PN ~~ */
1823  phi9NS = 0.0;
1824  phi9S = 0.0;
1825 
1826  /* ~~ 4.5 PN, Log Term ~~ */
1827  phi9LNS = 0.0;
1828  phi9LS = 0.0;
1829 
1830  /* This version of TaylorF2 contains an additional 4.5PN tail term and a LO-SS tail term at 3.5PN */
1831  if(pWF->IMRPhenomXInspiralPhaseVersion == 114 || pWF->IMRPhenomXInspiralPhaseVersion == 115)
1832  {
1833  /* 3.5PN, Leading Order Spin-Spin Tail Term */
1834  phi7S += ( (5*(65*chi1L2*(1 + delta - 2*eta) + 252*chi1L2L*eta - 65*chi2L2*(-1 + delta + 2*eta))*LAL_PI)/4. ) * powers_of_lalpi.seven_thirds;
1835 
1836  /* 4.5PN, Tail Term */
1837  phi9NS += ( (5*(-256 + 451*eta)*powers_of_lalpi.three)/6. + (LAL_PI*(105344279473163 + 700*eta*(-298583452147 + 96*eta*(99645337 + 14453257*eta)) -
1838  12246091038720*LAL_GAMMA - 24492182077440*log(2.0)))/1.877686272e10 - (13696*LAL_PI*powers_of_lalpi.log)/63. ) * powers_of_lalpi.three;
1839 
1840  /* 4.5PN, Log Term */
1841  phi9LNS += ( (-13696*LAL_PI)/63.0 ) * powers_of_lalpi.three;
1842  }
1843 
1844  /* 0.0 PN */
1845  pPhase->phi0 = phi0NS;
1846 
1847  /* 0.5 PN */
1848  pPhase->phi1 = phi1NS;
1849 
1850  /* 1.0 PN */
1851  pPhase->phi2 = phi2NS;
1852 
1853  /* 1.5 PN */
1854  pPhase->phi3 = phi3NS + phi3S;
1855 
1856  /* 2.0 PN */
1857  pPhase->phi4 = phi4NS + phi4S;
1858 
1859  /* 2.5 PN */
1860  pPhase->phi5 = phi5NS + phi5S;
1861 
1862  /* 2.5 PN, Log Terms */
1863  pPhase->phi5L = phi5LNS + phi5LS;
1864 
1865  /* 3.0 PN */
1866  pPhase->phi6 = phi6NS + phi6S;
1867 
1868  /* 3.0 PN, Log Term */
1869  pPhase->phi6L = phi6LNS + phi6LS;
1870 
1871  /* 3.5PN */
1872  pPhase->phi7 = phi7NS + phi7S;
1873 
1874  /* 4.0PN */
1875  pPhase->phi8 = phi8NS + phi8S;
1876 
1877  /* 4.0 PN, Log Terms */
1878  pPhase->phi8L = phi8LNS + phi8LS;
1879 
1880  /* 4.5 PN */
1881  pPhase->phi9 = phi9NS + phi9S;
1882 
1883  /* 4.5 PN, Log Terms */
1884  pPhase->phi9L = phi9LNS + phi9LS;
1885 
1886 
1887  if(debug)
1888  {
1889  printf("TaylorF2 PN Coefficients: \n");
1890  printf("phi0 : %.6f\n",pPhase->phi0);
1891  printf("phi1 : %.6f\n",pPhase->phi1);
1892  printf("phi2 : %.6f\n",pPhase->phi2);
1893  printf("phi3 : %.6f\n",pPhase->phi3);
1894  printf("phi4 : %.6f\n",pPhase->phi4);
1895  printf("phi5 : %.6f\n",pPhase->phi5);
1896  printf("phi6 : %.6f\n",pPhase->phi6);
1897  printf("phi7 : %.6f\n",pPhase->phi7);
1898  printf("phi8 : %.6f\n",pPhase->phi8);
1899 
1900  printf("phi5L : %.6f\n",pPhase->phi5L);
1901  printf("phi6L : %.6f\n",pPhase->phi6L);
1902  printf("phi8L : %.6f\n",pPhase->phi8L);
1903 
1904  printf("phi8P : %.6f\n",pPhase->sigma1);
1905  printf("phi9P : %.6f\n",pPhase->sigma2);
1906  printf("phi10P : %.6f\n",pPhase->sigma3);
1907  printf("phi11P : %.6f\n",pPhase->sigma4);
1908  printf("phi12P : %.6f\n",pPhase->sigma5);
1909  }
1910 
1911  pPhase->phi_initial = - LAL_PI_4;
1912 
1913  /* **** TaylorF2 PN Coefficients: Normalized Phase Derivative **** */
1914  pPhase->dphi0 = pPhase->phi0;
1915  pPhase->dphi1 = 4.0 / 5.0 * pPhase->phi1;
1916  pPhase->dphi2 = 3.0 / 5.0 * pPhase->phi2;
1917  pPhase->dphi3 = 2.0 / 5.0 * pPhase->phi3;
1918  pPhase->dphi4 = 1.0 / 5.0 * pPhase->phi4;
1919  pPhase->dphi5 = -3.0 / 5.0 * pPhase->phi5L;
1920  pPhase->dphi6 = -1.0 / 5.0 * pPhase->phi6 - 3.0 / 5.0 * pPhase->phi6L;
1921  pPhase->dphi6L = -1.0 / 5.0 * pPhase->phi6L;
1922  pPhase->dphi7 = -2.0 / 5.0 * pPhase->phi7;
1923  pPhase->dphi8 = -3.0 / 5.0 * pPhase->phi8 - 3.0 / 5.0 * pPhase->phi8L;
1924  pPhase->dphi8L = -3.0 / 5.0 * pPhase->phi8L;
1925  pPhase->dphi9 = -4.0 / 5.0 * pPhase->phi9 - 3.0 / 5.0 * pPhase->phi9L;
1926  pPhase->dphi9L = -3.0 / 5.0 * pPhase->phi9L;
1927 
1928  if(debug)
1929  {
1930  printf("\nTaylorF2 PN Derivative Coefficients\n");
1931  printf("dphi0 : %.6f\n",pPhase->dphi0);
1932  printf("dphi1 : %.6f\n",pPhase->dphi1);
1933  printf("dphi2 : %.6f\n",pPhase->dphi2);
1934  printf("dphi3 : %.6f\n",pPhase->dphi3);
1935  printf("dphi4 : %.6f\n",pPhase->dphi4);
1936  printf("dphi5 : %.6f\n",pPhase->dphi5);
1937  printf("dphi6 : %.6f\n",pPhase->dphi6);
1938  printf("dphi7 : %.6f\n",pPhase->dphi7);
1939  printf("dphi8 : %.6f\n",pPhase->dphi8);
1940  printf("dphi9 : %.6f\n",pPhase->dphi9);
1941  printf("\n");
1942  printf("dphi6L : %.6f\n",pPhase->dphi6L);
1943  printf("dphi8L : %.6f\n",pPhase->dphi8L);
1944  printf("dphi9L : %.6f\n",pPhase->dphi9L);
1945  }
1946 
1947  /*
1948  Calculate phase at fmatchIN. This will be used as the collocation point for the intermediate fit.
1949  In practice, the transition point is just below the MECO frequency.
1950  */
1951  if(debug)
1952  {
1953  printf("\nTransition frequency for ins to int : %.6f\n",pPhase->fPhaseMatchIN);
1954  }
1955 
1956  IMRPhenomX_UsefulPowers powers_of_fmatchIN;
1957  IMRPhenomX_Initialize_Powers(&powers_of_fmatchIN,pPhase->fPhaseMatchIN);
1958 
1959  double phaseIN;
1960  phaseIN = pPhase->dphi0; // f^{0/3}
1961  phaseIN += pPhase->dphi1 * powers_of_fmatchIN.one_third; // f^{1/3}
1962  phaseIN += pPhase->dphi2 * powers_of_fmatchIN.two_thirds; // f^{2/3}
1963  phaseIN += pPhase->dphi3 * powers_of_fmatchIN.itself; // f^{3/3}
1964  phaseIN += pPhase->dphi4 * powers_of_fmatchIN.four_thirds; // f^{4/3}
1965  phaseIN += pPhase->dphi5 * powers_of_fmatchIN.five_thirds; // f^{5/3}
1966  phaseIN += pPhase->dphi6 * powers_of_fmatchIN.two; // f^{6/3}
1967  phaseIN += pPhase->dphi6L * powers_of_fmatchIN.two * powers_of_fmatchIN.log; // f^{6/3}, Log[f]
1968  phaseIN += pPhase->dphi7 * powers_of_fmatchIN.seven_thirds; // f^{7/3}
1969  phaseIN += pPhase->dphi8 * powers_of_fmatchIN.eight_thirds; // f^{8/3}
1970  phaseIN += pPhase->dphi8L * powers_of_fmatchIN.eight_thirds * powers_of_fmatchIN.log; // f^{8/3}
1971  phaseIN += pPhase->dphi9 * powers_of_fmatchIN.three; // f^{9/3}
1972  phaseIN += pPhase->dphi9L * powers_of_fmatchIN.three * powers_of_fmatchIN.log; // f^{9/3}
1973 
1974  // Add pseudo-PN Coefficient
1975  phaseIN += ( pPhase->a0 * powers_of_fmatchIN.eight_thirds
1976  + pPhase->a1 * powers_of_fmatchIN.three
1977  + pPhase->a2 * powers_of_fmatchIN.eight_thirds * powers_of_fmatchIN.two_thirds
1978  + pPhase->a3 * powers_of_fmatchIN.eight_thirds * powers_of_fmatchIN.itself
1979  + pPhase->a4 * powers_of_fmatchIN.eight_thirds * powers_of_fmatchIN.four_thirds
1980  );
1981 
1982  phaseIN = phaseIN * powers_of_fmatchIN.m_eight_thirds * pWF->dphase0;
1983 
1984  /*
1985  Intermediate phase collocation points:
1986  Here we only use the first N points in the array where N = the
1987  number of intermediate collocation points.
1988 
1989  The size of the array is controlled by: N_MAX_COLLOCATION_POINTS_PHASE_INT
1990 
1991  Default is to use 5 collocation points.
1992 
1993  See. Eq. 7.7 and 7.8 where f_H = pPhase->fPhaseMatchIM and f_L = pPhase->fPhaseMatchIN
1994  */
1995  deltax = pPhase->fPhaseMatchIM - pPhase->fPhaseMatchIN;
1996  xmin = pPhase->fPhaseMatchIN;
1997 
1999  {
2000  case 104:
2001  {
2002  // Fourth order polynomial ansatz
2003  pPhase->NCollocationPointsInt = 4;
2004  break;
2005  }
2006  case 105:
2007  {
2008  // Fifth order polynomial ansatz
2009  pPhase->NCollocationPointsInt = 5;
2010  break;
2011  }
2012  default:
2013  {
2014  XLAL_ERROR(XLAL_EINVAL, "Error: IMRPhenomXIntermediatePhaseVersion is not valid.\n");
2015  }
2016  }
2017 
2018  if(debug)
2019  {
2020  printf("\nNColPointsInt : %d\n",pPhase->NCollocationPointsInt);
2021  }
2022 
2023  p = gsl_permutation_alloc(pPhase->NCollocationPointsInt);
2024  b = gsl_vector_alloc(pPhase->NCollocationPointsInt);
2025  x = gsl_vector_alloc(pPhase->NCollocationPointsInt);
2026  A = gsl_matrix_alloc(pPhase->NCollocationPointsInt,pPhase->NCollocationPointsInt);
2027 
2028  // Canonical intermediate model using 4 collocation points
2029  if(pWF->IMRPhenomXIntermediatePhaseVersion == 104)
2030  {
2031  // Using 4 collocation points in intermediate region
2032  for(i = 0; i < 4; i++)
2033  {
2034  fi = gpoints4[i] * deltax + xmin;
2035 
2036  pPhase->CollocationPointsPhaseInt[i] = fi;
2037  }
2038 
2039  // v2IM - v4RD. Using v4RD helps condition the fits with v4RD being very a robust fit.
2041 
2042  // v3IM - v4RD. Using v4RD helps condition the fits with v4RD being very a robust fit.
2044 
2045  // Direct fit to the collocation point at F2. We will take a weighted average of the direct and conditioned fit.
2047 
2048  /* Evaluate collocation points */
2049  pPhase->CollocationValuesPhaseInt[0] = phaseIN;
2050 
2051  // Take a weighted average for these points? Can help condition the fit.
2052  pPhase->CollocationValuesPhaseInt[1] = 0.75*(v2IMmRDv4 + RDv4) + 0.25*v2IM;
2053 
2054  // Use just v2 - v4RD to reconstruct the fit?
2055  //pPhase->CollocationValuesPhaseInt[1] = v2IMmRDv4 + RDv4);
2056 
2057  pPhase->CollocationValuesPhaseInt[2] = v3IMmRDv4 + RDv4;
2058 
2059  pPhase->CollocationValuesPhaseInt[3] = phaseRD;
2060 
2061  /* A_{0,i} */
2062  ff = pPhase->CollocationPointsPhaseInt[0];
2063  ff1 = pWF->fRING / ff;
2064  ff2 = ff1 * ff1;
2065  ff3 = ff1 * ff2;
2066  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2067  gsl_matrix_set(A,0,0,1.0);
2068  gsl_matrix_set(A,0,1,ff1);
2069  gsl_matrix_set(A,0,2,ff2);
2070  gsl_matrix_set(A,0,3,ff3);
2071  gsl_vector_set(b,0,pPhase->CollocationValuesPhaseInt[0] - ff0);
2072 
2073  /* A_{1,i} */
2074  ff = pPhase->CollocationPointsPhaseInt[1];
2075  ff1 = 1.0 / (ff / pWF->fRING);
2076  ff2 = ff1 * ff1;
2077  ff3 = ff1 * ff2;
2078  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2079  gsl_matrix_set(A,1,0,1);
2080  gsl_matrix_set(A,1,1,ff1);
2081  gsl_matrix_set(A,1,2,ff2);
2082  gsl_matrix_set(A,1,3,ff3);
2083  gsl_vector_set(b,1,pPhase->CollocationValuesPhaseInt[1] - ff0);
2084 
2085  /* A_{2,i} */
2086  ff = pPhase->CollocationPointsPhaseInt[2];
2087  ff1 = 1.0 / (ff / pWF->fRING);
2088  ff2 = ff1 * ff1;
2089  ff3 = ff1 * ff2;
2090  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2091  gsl_matrix_set(A,2,0,1);
2092  gsl_matrix_set(A,2,1,ff1);
2093  gsl_matrix_set(A,2,2,ff2);
2094  gsl_matrix_set(A,2,3,ff3);
2095  gsl_vector_set(b,2,pPhase->CollocationValuesPhaseInt[2] - ff0);
2096 
2097  /* A_{3,i} */
2098  ff = pPhase->CollocationPointsPhaseInt[3];
2099  ff1 = 1.0 / (ff / pWF->fRING);
2100  ff2 = ff1 * ff1;
2101  ff3 = ff1 * ff2;
2102  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2103  gsl_matrix_set(A,3,0,1);
2104  gsl_matrix_set(A,3,1,ff1);
2105  gsl_matrix_set(A,3,2,ff2);
2106  gsl_matrix_set(A,3,3,ff3);
2107  gsl_vector_set(b,3,pPhase->CollocationValuesPhaseInt[3] - ff0);
2108 
2109  /* We now solve the system A x = b via an LU decomposition */
2110  gsl_linalg_LU_decomp(A,p,&s);
2111  gsl_linalg_LU_solve(A,p,b,x);
2112 
2113  /* Set intermediate phenomenological coefficients from solution to A x = b */
2114  pPhase->b0 = gsl_vector_get(x,0); // x[0] // Constant
2115  pPhase->b1 = gsl_vector_get(x,1) * pWF->fRING; // x[1] // f^{-1}
2116  pPhase->b2 = gsl_vector_get(x,2) * pWF->fRING * pWF->fRING; // x[2] // f^{-2}
2117  //pPhase->b3 = 0.0;
2118  pPhase->b4 = gsl_vector_get(x,3) * pWF->fRING * pWF->fRING * pWF->fRING * pWF->fRING; // x[3] // f^{-4}
2119 
2120  /* Tidy up in preparation for next GSL solve ... */
2121  gsl_vector_free(b);
2122  gsl_vector_free(x);
2123  gsl_matrix_free(A);
2124  gsl_permutation_free(p);
2125  }
2126  // Canonical intermediate model using 5 collocation points
2127  else if(pWF->IMRPhenomXIntermediatePhaseVersion == 105)
2128  {
2129  // Using 5 collocation points in intermediate region
2130  for(i = 0; i < 5; i++)
2131  {
2132  fi = gpoints5[i] * deltax + xmin;
2133 
2134  pPhase->CollocationPointsPhaseInt[i] = fi;
2135  }
2136 
2137  /* Evaluate collocation points */
2138 
2139  /* The first and last collocation points for the intermediate region are set from the inspiral fit and ringdown respectively */
2140  pPhase->CollocationValuesPhaseInt[0] = phaseIN;
2141  pPhase->CollocationValuesPhaseInt[4] = phaseRD;
2142 
2143  // v2IM - v4RD. Using v4RD helps condition the fits with v4RD being very a robust fit.
2145 
2146  // v3IM - v4RD. Using v4RD helps condition the fits with v4RD being very a robust fit.
2148 
2149  // Direct fit to the collocation point at F2. We will take a weighted average of the direct and conditioned fit.
2151 
2152  // Take a weighted average for these points. Helps condition the fit.
2153  pPhase->CollocationValuesPhaseInt[1] = 0.75*(v2IMmRDv4 + RDv4) + 0.25*v2IM;
2154 
2155  pPhase->CollocationValuesPhaseInt[2] = v3IMmRDv4 + RDv4;
2157 
2158 
2159  // Collocation points: v4 = d43 + v3
2161 
2162  /* A_{0,i} */
2163  ff = pPhase->CollocationPointsPhaseInt[0];
2164  ff1 = pWF->fRING / ff;
2165  ff2 = ff1 * ff1;
2166  ff3 = ff1 * ff2;
2167  ff4 = ff2 * ff2;
2168  ff0 = (4.0 * pPhase->cL) / ((2.0*pWF->fDAMP)*(2.0*pWF->fDAMP) + (ff - pWF->fRING)*(ff - pWF->fRING));
2169  gsl_matrix_set(A,0,0,1.0);
2170  gsl_matrix_set(A,0,1,ff1);
2171  gsl_matrix_set(A,0,2,ff2);
2172  gsl_matrix_set(A,0,3,ff3);
2173  gsl_matrix_set(A,0,4,ff4);
2174  gsl_vector_set(b,0,pPhase->CollocationValuesPhaseInt[0] - ff0);
2175 
2176  if(debug)
2177  {
2178  printf("For row 0: a0 + a1 %.6f + a2 %.6f + a3 %.6f + a4 %.6f = %.6f , ff0 = %.6f, ff = %.6f\n",ff1,ff2,ff3,ff4,pPhase->CollocationValuesPhaseInt[0] - ff0,ff0,ff);
2179  }
2180 
2181  /* A_{1,i} */
2182  ff = pPhase->CollocationPointsPhaseInt[1];
2183  ff1 = pWF->fRING / ff;
2184  ff2 = ff1 * ff1;
2185  ff3 = ff1 * ff2;
2186  ff4 = ff2 * ff2;
2187  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2188  gsl_matrix_set(A,1,0,1.0);
2189  gsl_matrix_set(A,1,1,ff1);
2190  gsl_matrix_set(A,1,2,ff2);
2191  gsl_matrix_set(A,1,3,ff3);
2192  gsl_matrix_set(A,1,4,ff4);
2193  gsl_vector_set(b,1,pPhase->CollocationValuesPhaseInt[1] - ff0);
2194 
2195  if(debug)
2196  {
2197  printf("For row 1: a0 + a1 %.6f + a2 %.6f + a3 %.6f + a4 %.6f = %.6f\n",ff1,ff2,ff3,ff4,pPhase->CollocationValuesPhaseInt[1] - ff0);
2198  }
2199 
2200  /* A_{2,i} */
2201  ff = pPhase->CollocationPointsPhaseInt[2];
2202  ff1 = pWF->fRING / ff;
2203  ff2 = ff1 * ff1;
2204  ff3 = ff1 * ff2;
2205  ff4 = ff2 * ff2;
2206  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2207  gsl_matrix_set(A,2,0,1.0);
2208  gsl_matrix_set(A,2,1,ff1);
2209  gsl_matrix_set(A,2,2,ff2);
2210  gsl_matrix_set(A,2,3,ff3);
2211  gsl_matrix_set(A,2,4,ff4);
2212  gsl_vector_set(b,2,pPhase->CollocationValuesPhaseInt[2] - ff0);
2213 
2214  if(debug)
2215  {
2216  printf("For row 2: a0 + a1 %.6f + a2 %.6f + a3 %.6f + a4 %.6f = %.6f\n",ff1,ff2,ff3,ff4,pPhase->CollocationValuesPhaseInt[2] - ff0);
2217  }
2218 
2219  /* A_{3,i} */
2220  ff = pPhase->CollocationPointsPhaseInt[3];
2221  ff1 = pWF->fRING / ff;
2222  ff2 = ff1 * ff1;
2223  ff3 = ff1 * ff2;
2224  ff4 = ff2 * ff2;
2225  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2226  gsl_matrix_set(A,3,0,1.0);
2227  gsl_matrix_set(A,3,1,ff1);
2228  gsl_matrix_set(A,3,2,ff2);
2229  gsl_matrix_set(A,3,3,ff3);
2230  gsl_matrix_set(A,3,4,ff4);
2231  gsl_vector_set(b,3,pPhase->CollocationValuesPhaseInt[3] - ff0);
2232 
2233  if(debug)
2234  {
2235  printf("For row 3: a0 + a1 %.6f + a2 %.6f + a3 %.6f + a4 %.6f = %.6f\n",ff1,ff2,ff3,ff4,pPhase->CollocationValuesPhaseInt[3] - ff0);
2236  }
2237 
2238  /* A_{4,i} */
2239  ff = pPhase->CollocationPointsPhaseInt[4];
2240  ff1 = pWF->fRING / ff;
2241  ff2 = ff1 * ff1;
2242  ff3 = ff1 * ff2;
2243  ff4 = ff2 * ff2;
2244  ff0 = (4 * pPhase->cL) / (4.0*pWF->fDAMP*pWF->fDAMP + (ff - pWF->fRING)*(ff - pWF->fRING));
2245  gsl_matrix_set(A,4,0,1.0);
2246  gsl_matrix_set(A,4,1,ff1);
2247  gsl_matrix_set(A,4,2,ff2);
2248  gsl_matrix_set(A,4,3,ff3);
2249  gsl_matrix_set(A,4,4,ff4);
2250  gsl_vector_set(b,4,pPhase->CollocationValuesPhaseInt[4] - ff0);
2251 
2252  if(debug)
2253  {
2254  printf("For row 4: a0 + a1 %.6f + a2 %.6f + a3 %.6f + a4 %.6f = %.6f\n",ff1,ff2,ff3,ff4,pPhase->CollocationValuesPhaseInt[4] - ff0);
2255  }
2256 
2257  /* We now solve the system A x = b via an LU decomposition */
2258  gsl_linalg_LU_decomp(A,p,&s);
2259  gsl_linalg_LU_solve(A,p,b,x);
2260 
2261  /* Set intermediate phenomenological coefficients from solution to A x = b */
2262  pPhase->b0 = gsl_vector_get(x,0); // x[0] // Const.
2263  pPhase->b1 = gsl_vector_get(x,1) * pWF->fRING; // x[1] // f^{-1}
2264  pPhase->b2 = gsl_vector_get(x,2) * pWF->fRING * pWF->fRING; // x[2] // f^{-2}
2265  pPhase->b3 = gsl_vector_get(x,3) * pWF->fRING * pWF->fRING * pWF->fRING; // x[3] // f^{-3}
2266  pPhase->b4 = gsl_vector_get(x,4) * pWF->fRING * pWF->fRING * pWF->fRING * pWF->fRING; // x[4] // f^{-4}
2267 
2268  if(debug)
2269  {
2270  printf("\n");
2271  printf("Intermediate Collocation Points and Values:\n");
2272  printf("F1 : %.7f\n",pPhase->CollocationPointsPhaseInt[0]);
2273  printf("F2 : %.7f\n",pPhase->CollocationPointsPhaseInt[1]);
2274  printf("F3 : %.7f\n",pPhase->CollocationPointsPhaseInt[2]);
2275  printf("F4 : %.7f\n",pPhase->CollocationPointsPhaseInt[3]);
2276  printf("F5 : %.7f\n",pPhase->CollocationPointsPhaseInt[4]);
2277  printf("\n");
2278  printf("V's agree with Mathematica...\n");
2279  printf("V1 : %.7f\n",pPhase->CollocationValuesPhaseInt[0]);
2280  printf("V2 : %.7f\n",pPhase->CollocationValuesPhaseInt[1]);
2281  printf("V3 : %.7f\n",pPhase->CollocationValuesPhaseInt[2]);
2282  printf("V4 : %.7f\n",pPhase->CollocationValuesPhaseInt[3]);
2283  printf("V5 : %.7f\n",pPhase->CollocationValuesPhaseInt[4]);
2284  printf("\n");
2285  printf("g0 : %.7f\n",gsl_vector_get(x,0));
2286  printf("g1 : %.7f\n",gsl_vector_get(x,1));
2287  printf("g2 : %.7f\n",gsl_vector_get(x,2));
2288  printf("g3 : %.7f\n",gsl_vector_get(x,3));
2289  printf("g4 : %.7f\n",gsl_vector_get(x,4));
2290  printf("\n");
2291  printf("b0 : %.7f\n",pPhase->b0);
2292  printf("b1 : %.7f\n",pPhase->b1);
2293  printf("b2 : %.7f\n",pPhase->b2);
2294  printf("b3 : %.7f\n",pPhase->b3);
2295  printf("b4 : %.7f\n",pPhase->b4);
2296  printf("\n");
2297  }
2298 
2299  /* Tidy up */
2300  gsl_vector_free(b);
2301  gsl_vector_free(x);
2302  gsl_matrix_free(A);
2303  gsl_permutation_free(p);
2304  }
2305  else
2306  {
2307  XLALPrintError("Error in ComputeIMRPhenomXWaveformVariables: IMRPhenomXIntermediatePhaseVersion is not valid.\n");
2308  }
2309 
2310  /* Ringdown coefficients */
2311  REAL8 nonGR_dc1 = XLALSimInspiralWaveformParamsLookupNonGRDC1(LALparams);
2312  REAL8 nonGR_dc2 = XLALSimInspiralWaveformParamsLookupNonGRDC2(LALparams);
2313  REAL8 nonGR_dc4 = XLALSimInspiralWaveformParamsLookupNonGRDC4(LALparams);
2314  REAL8 nonGR_dcl = XLALSimInspiralWaveformParamsLookupNonGRDCL(LALparams);
2315 
2316  /* Intermediate coefficients */
2317  REAL8 nonGR_db1 = XLALSimInspiralWaveformParamsLookupNonGRDB1(LALparams);
2318  REAL8 nonGR_db2 = XLALSimInspiralWaveformParamsLookupNonGRDB2(LALparams);
2319  REAL8 nonGR_db3 = XLALSimInspiralWaveformParamsLookupNonGRDB3(LALparams);
2320  REAL8 nonGR_db4 = XLALSimInspiralWaveformParamsLookupNonGRDB4(LALparams);
2321 
2322  /* Inspiral coefficients */
2335 
2336  /* Can include these terms in the future as desired... */
2337  REAL8 dchi8 = 0.0;
2338  REAL8 dchi8L = 0.0;
2339  REAL8 dchi9 = 0.0;
2340  REAL8 dchi9L = 0.0;
2341 
2342  /* ~~~~ RINGDOWN ~~~~ */
2343  pPhase->cLGR = pPhase->cL; // Store GR value for reference
2344  pPhase->c1 *= (1.0 + nonGR_dc1);
2345  pPhase->c2 *= (1.0 + nonGR_dc2);
2346  pPhase->c4 *= (1.0 + nonGR_dc4);
2347  pPhase->cL *= (1.0 + nonGR_dcl);
2348 
2349  /* Set pre-cached variables */
2350  pPhase->c4ov3 = pPhase->c4 / 3.0;
2351  pPhase->cLovfda = pPhase->cL / pWF->fDAMP;
2352 
2353  /* Apply NR tuning for precessing cases (500) */
2354  pPhase->b1 = pPhase->b1 + ( pWF->PNR_DEV_PARAMETER * pWF->ZETA2 );
2355  pPhase->b4 = pPhase->b4 + ( pWF->PNR_DEV_PARAMETER * pWF->ZETA1 );
2356 
2357  /* ~~~~ INTERMEDIATE ~~~~ */
2358  if(pWF->IMRPhenomXIntermediatePhaseVersion == 104)
2359  {
2360  pPhase->b1 *= (1.0 + nonGR_db1);
2361  pPhase->b2 *= (1.0 + nonGR_db2);
2362  pPhase->b4 *= (1.0 + nonGR_db4);
2363  }
2364  else if(pWF->IMRPhenomXIntermediatePhaseVersion == 105)
2365  {
2366  pPhase->b1 *= (1.0 + nonGR_db1);
2367  pPhase->b2 *= (1.0 + nonGR_db2);
2368  pPhase->b3 *= (1.0 + nonGR_db3);
2369  pPhase->b4 *= (1.0 + nonGR_db4);
2370  }
2371  else
2372  {
2373  XLALPrintError("Error in ComputeIMRPhenomXWaveformVariables: IMRPhenomXIntermediatePhaseVersion is not valid.\n");
2374  }
2375 
2376  /* ~~~~ INSPIRAL ~~~~ */
2377  /* Initialize -1PN coefficient*/
2378  pPhase->phi_minus2 = 0.0;
2379  pPhase->dphi_minus2 = 0.0;
2380 
2381  pPhase->phi_minus1 = 0.0;
2382  pPhase->dphi_minus1 = 0.0;
2383 
2384  /*
2385  If tgr_parameterization = 1, deform complete PN coefficient. This is an FTA-like parameterization.
2386  If tgr_parameterization = 0, only deform non-spinning coefficient. This is the original TIGER-like implementation.
2387  */
2388  int tgr_parameterization = 0;
2389  tgr_parameterization = XLALSimInspiralWaveformParamsLookupNonGRParameterization(LALparams);
2390 
2391  if(tgr_parameterization == 1)
2392  {
2393  /* -1.0 PN: This vanishes in GR, so is parameterized as an absolute deviation */
2394  pPhase->phi_minus2 = dchi_minus2 / powers_of_lalpi.two_thirds;
2395 
2396  /* -0.5 PN: This vanishes in GR, so is parameterized as an absolute deviation */
2397  pPhase->phi_minus1 = dchi_minus1 / powers_of_lalpi.one_third;
2398 
2399  /* 0.0 PN */
2400  pPhase->phi0 = (phi0NS + phi0S)*(1.0 + dchi0);
2401 
2402  /* 0.5 PN: This vanishes in GR, so is parameterized as an absolute deviation */
2403  pPhase->phi1 = dchi1 * powers_of_lalpi.one_third;
2404 
2405  /* 1.0 PN */
2406  pPhase->phi2 = (phi2NS + phi2S)*(1.0 + dchi2);
2407 
2408  /* 1.5 PN */
2409  pPhase->phi3 = (phi3NS + phi3S)*(1.0 + dchi3);
2410 
2411  /* 2.0 PN */
2412  pPhase->phi4 = (phi4NS + phi4S)*(1.0 + dchi4);
2413 
2414  /* 2.5 PN */
2415  pPhase->phi5 = (phi5NS + phi5S)*(1.0 + dchi5);
2416 
2417  /* 2.5 PN, Log Terms */
2418  pPhase->phi5L = (phi5LNS + phi5LS)*(1.0 + dchi5L);
2419 
2420  /* 3.0 PN */
2421  pPhase->phi6 = (phi6NS + phi6S)*(1.0 + dchi6);
2422 
2423  /* 3.0 PN, Log Term */
2424  pPhase->phi6L = (phi6LNS + phi6LS)*(1.0 + dchi6L);
2425 
2426  /* 3.5PN */
2427  pPhase->phi7 = (phi7NS + phi7S)*(1.0 + dchi7);
2428 
2429  /* 4.0PN */
2430  pPhase->phi8 = (phi8NS + phi8S)*(1.0 + dchi8);
2431 
2432  /* 4.0 PN, Log Terms */
2433  pPhase->phi8L = (phi8LNS + phi8LS)*(1.0 + dchi8L);
2434 
2435  /* 4.0 PN */
2436  pPhase->phi9 = (phi9NS + phi9S)*(1.0 + dchi9);
2437 
2438  /* 4.0 PN, Log Terms */
2439  pPhase->phi9L = (phi9LNS + phi9LS)*(1.0 + dchi9L);
2440  }
2441  else if(tgr_parameterization == 0)
2442  {
2443  /* -1.0 PN: This vanishes in GR, so is parameterized as an absolute deviation */
2444  pPhase->phi_minus2 = dchi_minus2 / powers_of_lalpi.two_thirds;
2445 
2446  /* -0.5 PN: This vanishes in GR, so is parameterized as an absolute deviation */
2447  pPhase->phi_minus1 = dchi_minus1 / powers_of_lalpi.one_third;
2448 
2449  /* 0.0 PN */
2450  pPhase->phi0 = phi0NS*(1.0 + dchi0) + phi0S;
2451 
2452  /* 0.5 PN: This vanishes in GR, so is parameterized as an absolute deviation */
2453  pPhase->phi1 = dchi1 * powers_of_lalpi.one_third;
2454 
2455  /* 1.0 PN */
2456  pPhase->phi2 = phi2NS*(1.0 + dchi2) + phi2S;
2457 
2458  /* 1.5 PN */
2459  pPhase->phi3 = phi3NS*(1.0 + dchi3)+ phi3S;
2460 
2461  /* 2.0 PN */
2462  pPhase->phi4 = phi4NS*(1.0 + dchi4) + phi4S;
2463 
2464  /* 2.5 PN */
2465  pPhase->phi5 = phi5NS*(1.0 + dchi5) + phi5S;
2466 
2467  /* 2.5 PN, Log Terms */
2468  pPhase->phi5L = phi5LNS*(1.0 + dchi5L) + phi5LS;
2469 
2470  /* 3.0 PN */
2471  pPhase->phi6 = phi6NS*(1.0 + dchi6) + phi6S;
2472 
2473  /* 3.0 PN, Log Term */
2474  pPhase->phi6L = phi6LNS*(1.0 + dchi6L) + phi6LS;
2475 
2476  /* 3.5PN */
2477  pPhase->phi7 = phi7NS*(1.0 + dchi7) + phi7S;
2478 
2479  /* 4.0PN */
2480  pPhase->phi8 = phi8NS*(1.0 + dchi8) + phi8S;
2481 
2482  /* 4.0 PN, Log Terms */
2483  pPhase->phi8L = phi8LNS*(1.0 + dchi8L) + phi8LS;
2484 
2485  /* 4.0 PN */
2486  pPhase->phi9 = phi9NS*(1.0 + dchi9) + phi9S;
2487 
2488  /* 4.0 PN, Log Terms */
2489  pPhase->phi9L = phi9LNS*(1.0 + dchi9L) + phi9LS;
2490  }
2491  else
2492  {
2493  XLALPrintError("Error in IMRPhenomXGetPhaseCoefficients: TGR Parameterizataion is not valid.\n");
2494  }
2495 
2496  /* Recalculate phase derivatives including TGR corrections */
2497  pPhase->dphi_minus2 = +(7.0 / 5.0) * pPhase->phi_minus2;
2498  pPhase->dphi_minus1 = +(6.0 / 5.0) * pPhase->phi_minus1;
2499  pPhase->dphi0 = +(5.0 / 5.0) * pPhase->phi0;
2500  pPhase->dphi1 = +(4.0 / 5.0) * pPhase->phi1;
2501  pPhase->dphi2 = +(3.0 / 5.0) * pPhase->phi2;
2502  pPhase->dphi3 = +(2.0 / 5.0) * pPhase->phi3;
2503  pPhase->dphi4 = +(1.0 / 5.0) * pPhase->phi4;
2504  pPhase->dphi5 = -(3.0 / 5.0) * pPhase->phi5L;
2505  pPhase->dphi6 = -(1.0 / 5.0) * pPhase->phi6 - (3.0 / 5.0) * pPhase->phi6L;
2506  pPhase->dphi6L = -(1.0 / 5.0) * pPhase->phi6L;
2507  pPhase->dphi7 = -(2.0 / 5.0) * pPhase->phi7;
2508  pPhase->dphi8 = -(3.0 / 5.0) * pPhase->phi8 - (3.0 / 5.0) * pPhase->phi8L;
2509  pPhase->dphi8L = -(3.0 / 5.0) * pPhase->phi8L;
2510  pPhase->dphi9 = -(4.0 / 5.0) * pPhase->phi9 - (3.0 / 5.0) * pPhase->phi9L;
2511  pPhase->dphi9L = -(3.0 / 5.0) * pPhase->phi9L;
2512 
2513  /* Initialize connection coefficients */
2514  pPhase->C1Int = 0;
2515  pPhase->C2Int = 0;
2516  pPhase->C1MRD = 0;
2517  pPhase->C2MRD = 0;
2518 
2519  /* END OF ROUTINE; RETURN STRUCT */
2520  return XLAL_SUCCESS;
2521 }
2522 
2523 
2525 {
2526  int debug = pWF->debug;
2527 
2528  double fIns = pPhase->fPhaseMatchIN;
2529  double fInt = pPhase->fPhaseMatchIM;
2530 
2531  /*
2532  Assume an ansatz of the form:
2533 
2534  phi_Inspiral (f) = phi_Intermediate (f) + C1 + C2 * f
2535 
2536  where transition frequency is fIns
2537 
2538  phi_Inspiral (fIns) = phi_Intermediate (fIns) + C1 + C2 * fIns
2539  phi_Inspiral'(fIns) = phi_Intermediate'(fIns) + C2
2540 
2541  Solving for C1 and C2
2542 
2543  C2 = phi_Inspiral'(fIns) - phi_Intermediate'(fIns)
2544  C1 = phi_Inspiral (fIns) - phi_Intermediate (fIns) - C2 * fIns
2545 
2546  */
2547  IMRPhenomX_UsefulPowers powers_of_fIns;
2548  IMRPhenomX_Initialize_Powers(&powers_of_fIns,fIns);
2549 
2550  double DPhiIns = IMRPhenomX_Inspiral_Phase_22_Ansatz(fIns,&powers_of_fIns,pPhase);
2551  double DPhiInt = IMRPhenomX_Intermediate_Phase_22_Ansatz(fIns,&powers_of_fIns,pWF,pPhase);
2552 
2553  pPhase->C2Int = DPhiIns - DPhiInt;
2554 
2555  double phiIN = IMRPhenomX_Inspiral_Phase_22_AnsatzInt(fIns,&powers_of_fIns,pPhase);
2556  double phiIM = IMRPhenomX_Intermediate_Phase_22_AnsatzInt(fIns,&powers_of_fIns,pWF,pPhase);
2557 
2558  if(debug)
2559  {
2560  printf("\n");
2561  printf("dphiIM = %.6f and dphiIN = %.6f\n",DPhiInt,DPhiIns);
2562  printf("phiIN(fIns) : %.7f\n",phiIN);
2563  printf("phiIM(fIns) : %.7f\n",phiIM);
2564  printf("fIns : %.7f\n",fIns);
2565  printf("C2 : %.7f\n",pPhase->C2Int);
2566  printf("\n");
2567  }
2568 
2569  pPhase->C1Int = phiIN - phiIM - (pPhase->C2Int * fIns);
2570 
2571  /*
2572  Assume an ansatz of the form:
2573 
2574  phi_Intermediate (f) = phi_Ringdown (f) + C1 + C2 * f
2575 
2576  where transition frequency is fIM
2577 
2578  phi_Intermediate (fIM) = phi_Ringdown (fRD) + C1 + C2 * fIM
2579  phi_Intermediate'(fIM) = phi_Ringdown'(fRD) + C2
2580 
2581  Solving for C1 and C2
2582 
2583  C2 = phi_Inspiral'(fIM) - phi_Intermediate'(fIM)
2584  C1 = phi_Inspiral (fIM) - phi_Intermediate (fIM) - C2 * fIM
2585 
2586  */
2587  IMRPhenomX_UsefulPowers powers_of_fInt;
2588  IMRPhenomX_Initialize_Powers(&powers_of_fInt,fInt);
2589 
2590  double phiIMC = IMRPhenomX_Intermediate_Phase_22_AnsatzInt(fInt,&powers_of_fInt,pWF,pPhase) + pPhase->C1Int + pPhase->C2Int*fInt;
2591  double phiRD = IMRPhenomX_Ringdown_Phase_22_AnsatzInt(fInt,&powers_of_fInt,pWF,pPhase);
2592  double DPhiIntC = IMRPhenomX_Intermediate_Phase_22_Ansatz(fInt,&powers_of_fInt,pWF,pPhase) + pPhase->C2Int;
2593  double DPhiRD = IMRPhenomX_Ringdown_Phase_22_Ansatz(fInt,&powers_of_fInt,pWF,pPhase);
2594 
2595  pPhase->C2MRD = DPhiIntC - DPhiRD;
2596  pPhase->C1MRD = phiIMC - phiRD - pPhase->C2MRD*fInt;
2597 
2598  if(debug)
2599  {
2600  printf("\n");
2601  printf("phiIMC(fInt) : %.7f\n",phiIMC);
2602  printf("phiRD(fInt) : %.7f\n",phiRD);
2603  printf("fInt : %.7f\n",fInt);
2604  printf("C2 : %.7f\n",pPhase->C2Int);
2605  printf("\n");
2606  }
2607 
2608  if(debug)
2609  {
2610  printf("dphiIM = %.6f and dphiRD = %.6f\n",DPhiIntC,DPhiRD);
2611  printf("\nContinuity Coefficients\n");
2612  printf("C1Int : %.6f\n",pPhase->C1Int);
2613  printf("C2Int : %.6f\n",pPhase->C2Int);
2614  printf("C1MRD : %.6f\n",pPhase->C1MRD);
2615  printf("C2MRD : %.6f\n",pPhase->C2MRD);
2616  }
2617 
2618  return;
2619 }
2620 
2622 
2623  REAL8 linb, tshift, dphi22Ref,frefFit;
2624 
2625  // here we align the model to the hybrids, for which psi4 peaks 500M before the end of the waveform
2626  // linb is a parameter-space fit of dphi22(fring22-fdamp22), evaluated on the calibration dataset
2627  linb = XLALSimIMRPhenomXLinb(pWF->eta, pWF->STotR, pWF->dchi, pWF->delta);
2628  frefFit = pWF->fRING-pWF->fDAMP;
2629  IMRPhenomX_UsefulPowers powers_of_frefFit;
2630  IMRPhenomX_Initialize_Powers(&powers_of_frefFit,frefFit);
2631  dphi22Ref = 1.0 / (pWF->eta)*IMRPhenomX_dPhase_22(frefFit, &powers_of_frefFit, pPhase, pWF);
2632  // here we correct the time-alignment of the waveform by first aligning the peak of psi4, and then adding a correction to align the peak of strain instead
2633  REAL8 psi4tostrain=XLALSimIMRPhenomXPsi4ToStrain(pWF->eta, pWF->STotR, pWF->dchi);
2634  tshift = linb-dphi22Ref -2.*LAL_PI*(500+psi4tostrain);
2635 
2636  // Apply PNR deviation (500)
2637  tshift = tshift + ( pWF->PNR_DEV_PARAMETER * pWF->NU0 );
2638 
2639  //phX phase will read phi22=1/eta*IMRPhenomX_Phase_22+tshift f, modulo a residual phase-shift
2640  return(tshift);
2641 
2642 }
2643 
2644 
2645 
2646 /*
2647  * ********** ********** ********** ********** ********** ********** ********** ********** ********** **********
2648  * This function computes the IMRPhenomX phase given a phase coefficients struct pPhase.
2649  * ********** ********** ********** ********** ********** ********** ********** ********** ********** **********
2650  */
2652 {
2653  // Inspiral region, f < fPhaseInsMax
2654  if (!IMRPhenomX_StepFuncBool(ff, pPhase->fPhaseMatchIN))
2655  {
2656  double PhiIns = IMRPhenomX_Inspiral_Phase_22_AnsatzInt(ff, powers_of_f, pPhase);
2657  return PhiIns;
2658  }
2659 
2660  // Ringdown region, f > fPhaseIntMax
2661  if (IMRPhenomX_StepFuncBool(ff, pPhase->fPhaseMatchIM))
2662  {
2663  double PhiMRD = IMRPhenomX_Ringdown_Phase_22_AnsatzInt(ff, powers_of_f, pWF, pPhase)
2664  + pPhase->C1MRD + (pPhase->C2MRD * ff);
2665  return PhiMRD;
2666  }
2667 
2668  // Intermediate region, fPhaseInsMax < f < fPhaseIntMax
2669  double PhiInt = IMRPhenomX_Intermediate_Phase_22_AnsatzInt(ff, powers_of_f, pWF, pPhase)
2670  + pPhase->C1Int + (pPhase->C2Int * ff);
2671 
2672  return PhiInt;
2673 }
2674 
2675 /*
2676  * ********** ********** ********** ********** ********** ********** ********** ********** ********** **********
2677  * This function computes the IMRPhenomX phase derivative given a phase coefficients struct pPhase.
2678  * ********** ********** ********** ********** ********** ********** ********** ********** ********** **********
2679  */
2681 {
2682  // Inspiral region, f < fPhaseInsMax
2683  if (!IMRPhenomX_StepFuncBool(ff, pPhase->fPhaseMatchIN))
2684  {
2685  double dPhiIns = IMRPhenomX_Inspiral_Phase_22_Ansatz(ff, powers_of_f, pPhase);
2686  return dPhiIns;
2687  }
2688 
2689  // Ringdown region, f > fPhaseIntMax
2690  if (IMRPhenomX_StepFuncBool(ff, pPhase->fPhaseMatchIM))
2691  {
2692  double dPhiMRD = IMRPhenomX_Ringdown_Phase_22_Ansatz(ff, powers_of_f, pWF, pPhase)
2693  + (pPhase->C2MRD);
2694  return dPhiMRD;
2695  }
2696 
2697  // Intermediate region, fPhaseInsMax < f < fPhaseIntMax
2698  double dPhiInt = IMRPhenomX_Intermediate_Phase_22_Ansatz(ff, powers_of_f, pWF, pPhase)
2699  + (pPhase->C2Int);
2700 
2701  return dPhiInt;
2702 }
2703 
2704 /*
2705  * ********** ********** ********** ********** ********** ********** ********** ********** ********** **********
2706  * This function computes the IMRPhenomX amplitude given an amplitude coefficients struct pAmp.
2707  * ********** ********** ********** ********** ********** ********** ********** ********** ********** **********
2708  */
2710  //double f_seven_sixths = powers_of_f->seven_sixths;
2711  //double AmpPreFac = pWF->ampNorm / f_seven_sixths; // Use this if we want return normalized amplitudes
2712  double AmpPreFac = pWF->ampNorm / powers_of_f->seven_sixths;
2713 
2714  // Inspiral region, f < fAmpMatchIN
2715  if (!IMRPhenomX_StepFuncBool(ff, pAmp->fAmpMatchIN))
2716  {
2717  double AmpIns = AmpPreFac * IMRPhenomX_Inspiral_Amp_22_Ansatz(ff, powers_of_f, pWF, pAmp);
2718  return AmpIns;
2719  }
2720 
2721  // Ringdown region, f > fAmpRDMin
2722  if (IMRPhenomX_StepFuncBool(ff, pAmp->fAmpRDMin))
2723  {
2724  double AmpMRD = AmpPreFac * IMRPhenomX_Ringdown_Amp_22_Ansatz(ff, pWF, pAmp);
2725  return AmpMRD;
2726  }
2727 
2728  // Intermediate region, fAmpMatchIN < f < fAmpRDMin
2729  double AmpInt = AmpPreFac * IMRPhenomX_Intermediate_Amp_22_Ansatz(ff, powers_of_f, pWF, pAmp);
2730  return AmpInt;
2731 }
2732 
2733 
2734 /* Function to check if the input mode array contains unsupported modes */
2735 INT4 check_input_mode_array(LALDict *lalParams)
2736 {
2737  UINT4 flagTrue = 0;
2738 
2739  if(lalParams == NULL) return XLAL_SUCCESS;
2740 
2741  LALValue *ModeArray = XLALSimInspiralWaveformParamsLookupModeArray(lalParams);
2742 
2743  if(ModeArray!=NULL)
2744  {
2745  INT4 larray[5] = {2, 2, 3, 3, 4};
2746  INT4 marray[5] = {2, 1, 3, 2, 4};
2747 
2748  for(INT4 ell=2; ell<=LAL_SIM_L_MAX_MODE_ARRAY; ell++)
2749  {
2750  for(INT4 emm=0; emm<=ell; emm++)
2751  {
2752  if(XLALSimInspiralModeArrayIsModeActive(ModeArray, ell, emm)==1 || XLALSimInspiralModeArrayIsModeActive(ModeArray, ell, -1*emm)==1)
2753  {
2754  for(UINT4 idx=0; idx<5; idx++)
2755  {
2756  if(ell==larray[idx] && abs(emm)==marray[idx])
2757  {
2758  flagTrue = 1;
2759  }
2760  }
2761  // If flagTrue !=1 means that the input mode array has a mode that is not supported by the model.
2762  if(flagTrue!=1){
2763  XLALPrintError ("Mode (%d,%d) is not available by the model.\n", ell, emm);
2764  XLALDestroyValue(ModeArray);
2765  return XLAL_FAILURE;
2766  }
2767  flagTrue = 0;
2768  }
2769  }//End loop over emm
2770  }//End loop over ell
2771  }//End of if block
2772 
2773  XLALDestroyValue(ModeArray);
2774 
2775  return XLAL_SUCCESS;
2776 }
2777 
2778 /* Function to compute full model phase. This function is designed to be used in in initialization routines, and not for evaluating the phase at many frequencies. */
2779 INT4 IMRPhenomX_FullPhase_22(double *phase, double *dphase, double Mf, IMRPhenomXPhaseCoefficients *pPhase, IMRPhenomXWaveformStruct *pWF){
2780 
2781 
2782  /*
2783  Function to compute full XAS phase at a single frequency point.
2784  See IMRPhenomXASGenerateFD for reference.
2785  */
2786 
2787  /*--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--*/
2788  /* Define useful powers */
2789  /*--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--*/
2790 
2791  // Status indicator
2792  INT4 status;
2793 
2794  // Get useful powers of Mf
2795  IMRPhenomX_UsefulPowers powers_of_Mf;
2796  status = IMRPhenomX_Initialize_Powers(&powers_of_Mf, Mf);
2797  XLAL_CHECK(XLAL_SUCCESS == status, status, "IMRPhenomX_Initialize_Powers failed for Mf.\n");
2798 
2799  /* Initialize a struct containing useful powers of Mf at fRef */
2800  IMRPhenomX_UsefulPowers powers_of_MfRef;
2801  status = IMRPhenomX_Initialize_Powers(&powers_of_MfRef,pWF->MfRef);
2802  XLAL_CHECK(XLAL_SUCCESS == status, status, "IMRPhenomX_Initialize_Powers failed for MfRef.\n");
2803 
2804  /*--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--*/
2805  /* Define needed constants */
2806  /*--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--*/
2807 
2808  /* 1/eta is used to re-scale the pre-phase quantity */
2809  REAL8 inveta = (1.0 / pWF->eta);
2810 
2811  /* We keep this phase shift to ease comparison with
2812  original phase routines */
2813  REAL8 lina = 0;
2814 
2815  /* Get phase connection coefficients
2816  and store them to pWF. This step is to make
2817  sure that teh coefficients are up-to-date */
2819 
2820  /* Compute the timeshift that PhenomXAS uses to align waveforms
2821  with the hybrids used to make their model */
2822  double linb=IMRPhenomX_TimeShift_22(pPhase, pWF);
2823 
2824  /* Calculate phase at reference frequency: phifRef = 2.0*phi0 + LAL_PI_4 + PhenomXPhase(fRef) */
2825  double phifRef = -(inveta * IMRPhenomX_Phase_22(pWF->MfRef, &powers_of_MfRef, pPhase, pWF) + linb*pWF->MfRef + lina) + 2.0*pWF->phi0 + LAL_PI_4;
2826 
2827  /* ~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+
2828  Note that we do not store the value of phifRef to pWF as is done in
2829  IMRPhenomXASGenerateFD. We choose to not do so in order to avoid
2830  potential confusion (e.g. if this function is called within a
2831  workflow that assumes the value defined in IMRPhenomXASGenerateFD).
2832  Note that this concern may not be valid.
2833  ~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+~~+ */
2834 
2835  /*--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--*/
2836  /* Compute the full model phase */
2837  /*--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--(*)--*/
2838 
2839  /* Use previously made function to compute what we call
2840  here the pre-phase, becuase it's not actually a phase! */
2841  double pre_phase = IMRPhenomX_Phase_22(Mf,&powers_of_Mf,pPhase,pWF);
2842 
2843  /* Given the pre-phase, we need to scale and shift according to the
2844  XAS construction */
2845  *phase = pre_phase * inveta;
2846  *phase += linb*Mf + lina + phifRef;
2847 
2848  /* Repeat the excercise above for the phase derivative:
2849  "dphase" is (d/df)phase at Mf */
2850  double pre_dphase = IMRPhenomX_dPhase_22(Mf,&powers_of_Mf,pPhase,pWF);
2851  *dphase = pre_dphase * inveta;
2852  *dphase += linb;
2853 
2854  //
2855  return status;
2856 }
2857 
2858 
2860 
2861  int tidal_version=XLALSimInspiralWaveformParamsLookupPhenomXTidalFlag(lalParams);
2862 
2864 
2865  switch(tidal_version){
2866  case 0:
2867  version=NoNRT_V;
2868  break;
2869  case 1:
2871  break;
2872  case 2:
2874  break;
2875  default:
2876  {
2877  XLAL_ERROR(XLAL_EINVAL, "Error: Tidal version not recognized. Only NRTidal, NRTidalv2, and NoNRT are allowed, and NRTidal is not implemented completely in IMRPhenomX*.\n");
2878  }
2879  }
2880  return(version);
2881 }
2882 
2883 
2887  NRTidal_version_type NRTidal_version){
2888 
2889 
2890  REAL8 quadparam1 = pWF->quadparam1;
2891  REAL8 quadparam2 = pWF->quadparam2;
2892  /* declare HO 3.5PN spin-spin and spin-cubed terms added separately in Pv2_NRTidalv2 */
2893  REAL8 SS_3p5PN = 0., SSS_3p5PN = 0.;
2894 
2895  /* New variables needed for the NRTidalv2 model */
2896  REAL8 X_A = pWF->m1; // Already scaled by Mtot
2897  REAL8 X_B = pWF->m2; // Ibid.
2898 
2899  REAL8 chi1L_sq = pWF->chi1L2;
2900  REAL8 chi2L_sq = pWF->chi2L2;
2901 
2903  + (XLALSimInspiralTaylorF2Phasing_4PNQM2SOCoeff(X_B) + XLALSimInspiralTaylorF2Phasing_4PNQM2SCoeff(X_B)) * (quadparam2 - 1.) * chi2L_sq);
2904  pPhase->c3PN_tidal=(XLALSimInspiralTaylorF2Phasing_6PNQM2SCoeff(X_A) * (quadparam1 - 1.) * chi1L_sq
2905  + XLALSimInspiralTaylorF2Phasing_6PNQM2SCoeff(X_B) * (quadparam2 - 1.) * chi2L_sq);
2906 
2907  if (NRTidal_version == NRTidalv2_V) {
2908  /* Get the PN SS-tail and SSS terms */
2909  XLALSimInspiralGetHOSpinTerms(&SS_3p5PN, &SSS_3p5PN, X_A, X_B, pWF->chi1L, pWF->chi2L, quadparam1, quadparam2);
2910  pPhase->c3p5PN_tidal=(SS_3p5PN + SSS_3p5PN);
2911  }
2912 
2913 }
2914 
2916 
2917  REAL8 X_A = pWF->m1; // Already scaled by Mtot
2918  REAL8 X_B = pWF->m2;
2919 
2920  REAL8 Mf=powers_of_Mf->itself;
2921 
2922  REAL8 phaseTidal=0.;
2923 
2924  REAL8 pfaN=3./(128.*X_A*X_B);
2925 
2926  REAL8 c2pn=pPhase->c2PN_tidal, c3pn=pPhase->c3PN_tidal, c3p5pn=pPhase->c3p5PN_tidal;
2927 
2928  /* 2PN terms */
2929  phaseTidal += pfaN * c2pn* powers_of_lalpi.m_one_third * powers_of_Mf->m_one_third;
2930 
2931  /* 3PN terms */
2932  phaseTidal += pfaN * c3pn* powers_of_lalpi.one_third * powers_of_Mf->one_third;
2933 
2934  if (NRTidal_version == NRTidalv2_V)
2935  {
2936  REAL8 NRTidalv2_coeffs[9];
2937 
2938  int errcode;
2939  errcode = XLALSimNRTunedTidesSetFDTidalPhase_v2_Coeffs(NRTidalv2_coeffs);
2940  XLAL_CHECK(XLAL_SUCCESS == errcode, errcode, "Setting NRTidalv2 coefficients failed.\n");
2941 
2942  const REAL8 cNewt = NRTidalv2_coeffs[0];
2943  const REAL8 n1 = NRTidalv2_coeffs[1];
2944  const REAL8 n3over2 = NRTidalv2_coeffs[2];
2945  const REAL8 n2 = NRTidalv2_coeffs[3];
2946  const REAL8 n5over2 = NRTidalv2_coeffs[4];
2947  const REAL8 n3 = NRTidalv2_coeffs[5];
2948  const REAL8 d1 = NRTidalv2_coeffs[6];
2949  const REAL8 d3over2 = NRTidalv2_coeffs[7];
2950  const REAL8 d2 = NRTidalv2_coeffs[8];
2951 
2952  REAL8 kappa2T = pWF->kappa2T;
2953 
2954  REAL8 NRphase=-((cNewt*kappa2T*powers_of_Mf->five_thirds*powers_of_lalpi.five_thirds*(1 + powers_of_Mf->two_thirds*n1*powers_of_lalpi.two_thirds + Mf*n3over2*LAL_PI + powers_of_Mf->four_thirds*n2*powers_of_lalpi.four_thirds + powers_of_Mf->five_thirds*n5over2*powers_of_lalpi.five_thirds + pow(Mf,2)*n3*powers_of_lalpi.two))/((1 + d1*powers_of_Mf->two_thirds*powers_of_lalpi.two_thirds + d3over2*Mf*LAL_PI + d2*powers_of_Mf->four_thirds*powers_of_lalpi.four_thirds)*X_A*X_B));
2955 
2956  phaseTidal+=NRphase;
2957 
2958  /* Get the PN SS-tail and SSS terms */
2959  phaseTidal += pfaN * c3p5pn * powers_of_lalpi.two_thirds * powers_of_Mf->two_thirds;
2960 
2961  }
2962  else
2963  {
2964  XLAL_ERROR( XLAL_EINVAL, "Error in IMRPhenomX_TidalPhase: Unsupported NRTidal_version. This function currently only supports NRTidalv2.\n");
2965  }
2966 
2967  return(phaseTidal);
2968 
2969 
2970 }
2971 
2973 
2974  REAL8 X_A = pWF->m1; // Already scaled by Mtot
2975  REAL8 X_B = pWF->m2;
2976 
2977  REAL8 Mf_ten_thirds=powers_of_Mf->eight_thirds*powers_of_Mf->two_thirds;
2979  REAL8 Mf=powers_of_Mf->itself;
2980 
2981  REAL8 c2pn=pPhase->c2PN_tidal, c3pn=pPhase->c3PN_tidal, c3p5pn=pPhase->c3p5PN_tidal;
2982 
2983  REAL8 NRTuned_dphase=0.;
2984 
2985  REAL8 pfaN=3./(128.*X_A*X_B);
2986 
2987  REAL8 threePN_dphase=(pfaN*(-c2pn + c3pn*powers_of_Mf->two_thirds*powers_of_lalpi.two_thirds))/(3.*powers_of_Mf->four_thirds*powers_of_lalpi.one_third);
2988 
2989  REAL8 dphase=threePN_dphase;
2990 
2991 
2992  if(NRTidal_version==NRTidalv2_V){
2993 
2994  dphase+=(2.*c3p5pn*pfaN*powers_of_lalpi.two_thirds)/(3.*powers_of_Mf->one_third);
2995 
2996  REAL8 NRTidalv2_coeffs[9];
2997 
2998  int errcode;
2999  errcode = XLALSimNRTunedTidesSetFDTidalPhase_v2_Coeffs(NRTidalv2_coeffs);
3000  XLAL_CHECK(XLAL_SUCCESS == errcode, errcode, "Setting NRTidalv2 coefficients failed.\n");
3001 
3002  const REAL8 cNewt = NRTidalv2_coeffs[0];
3003  const REAL8 n1 = NRTidalv2_coeffs[1];
3004  const REAL8 n3over2 = NRTidalv2_coeffs[2];
3005  const REAL8 n2 = NRTidalv2_coeffs[3];
3006  const REAL8 n5over2 = NRTidalv2_coeffs[4];
3007  const REAL8 n3 = NRTidalv2_coeffs[5];
3008  const REAL8 d1 = NRTidalv2_coeffs[6];
3009  const REAL8 d3over2 = NRTidalv2_coeffs[7];
3010  const REAL8 d2 = NRTidalv2_coeffs[8];
3011 
3012  REAL8 kappa2T = pWF->kappa2T;
3013 
3014  NRTuned_dphase=((cNewt*kappa2T*powers_of_Mf->two_thirds*powers_of_lalpi.five_thirds*(-5 - powers_of_Mf->two_thirds*(3*d1 + 7*n1)*powers_of_lalpi.two_thirds - 2*Mf*(d3over2 + 4*n3over2)*LAL_PI - powers_of_Mf->four_thirds*(d2 + 5*d1*n1 + 9*n2)*powers_of_lalpi.four_thirds - 2*powers_of_Mf->five_thirds*(2*d3over2*n1 + 3*d1*n3over2 + 5*n5over2)*powers_of_lalpi.five_thirds - pow(Mf,2)*(3*d2*n1 + 7*d1*n2 + 11*n3 + 5*d3over2*n3over2)*powers_of_lalpi.two - 2*powers_of_Mf->seven_thirds*(3*d3over2*n2 + 2*d2*n3over2 + 4*d1*n5over2)*powers_of_lalpi.seven_thirds - powers_of_Mf->eight_thirds*(5*d2*n2 + 9*d1*n3 + 7*d3over2*n5over2)*powers_of_lalpi.eight_thirds - 2*pow(Mf,3)*(4*d3over2*n3 + 3*d2*n5over2)*powers_of_lalpi.three - 7*d2*Mf_ten_thirds*n3*pi_ten_thirds))/(3.*pow(1 + d1*powers_of_Mf->two_thirds*powers_of_lalpi.two_thirds + d3over2*Mf*LAL_PI + d2*powers_of_Mf->four_thirds*powers_of_lalpi.four_thirds,2)*X_A*X_B));
3015 
3016  }
3017  else
3018  {
3019  XLAL_ERROR( XLAL_EINVAL, "Error in IMRPhenomX_TidalPhaseDerivative: Unsupported NRTidal_version. This function currently only supports NRTidalv2.\n");
3020  }
3021 
3022  dphase+=NRTuned_dphase;
3023 
3024  return(dphase);
3025 
3026 }
void XLALSimInspiralGetHOSpinTerms(REAL8 *SS_3p5PN, REAL8 *SSS_3p5PN, REAL8 X_A, REAL8 X_B, REAL8 chi1, REAL8 chi2, REAL8 quadparam1, REAL8 quadparam2)
Function to add 3.5PN spin-squared and 3.5PN spin-cubed terms.
int XLALSimNRTunedTidesSetFDTidalPhase_v2_Coeffs(REAL8 *NRTidalv2_coeffs)
Set the NRTidalv2 phase coefficients in an array for use here and in the IMRPhenomX*_NRTidalv2 implem...
double XLALSimNRTunedTidesMergerFrequency(const REAL8 mtot_MSUN, const REAL8 kappa2T, const REAL8 q)
compute the merger frequency of a BNS system.
double XLALSimNRTunedTidesComputeKappa2T(REAL8 m1_SI, REAL8 m2_SI, REAL8 lambda1, REAL8 lambda2)
convenient function to compute tidal coupling constant.
static double evaluate_QNMfit_fdamp22(double finalDimlessSpin)
static double evaluate_QNMfit_fring22(double finalDimlessSpin)
static double double delta
IMRPhenomX_UsefulPowers powers_of_lalpi
#define PHENOMXDEBUG
static double IMRPhenomX_Inspiral_Phase_22_Ansatz(double Mf, IMRPhenomX_UsefulPowers *powers_of_Mf, IMRPhenomXPhaseCoefficients *pPhase)
static double IMRPhenomX_Inspiral_Amp_22_v2(double eta, double S, double dchi, double delta, int InsAmpFlag)
static double IMRPhenomX_Inspiral_Amp_22_v4(double eta, double S, double dchi, double delta, int InsAmpFlag)
static double IMRPhenomX_Inspiral_Phase_22_AnsatzInt(double Mf, IMRPhenomX_UsefulPowers *powers_of_Mf, IMRPhenomXPhaseCoefficients *pPhase)
Ansatz for the inspiral phase.
static double IMRPhenomX_Inspiral_Phase_22_v3(double eta, double S, double dchi, double delta, int InspPhaseFlag)
static double IMRPhenomX_Inspiral_Amp_22_v3(double eta, double S, double dchi, double delta, int InsAmpFlag)
static double IMRPhenomX_Inspiral_Amp_22_Ansatz(double Mf, IMRPhenomX_UsefulPowers *powers_of_Mf, IMRPhenomXWaveformStruct *pWF, IMRPhenomXAmpCoefficients *pAmp)
static double IMRPhenomX_Inspiral_Phase_22_d43(double eta, double S, double dchi, double delta, int InspPhaseFlag)
static double IMRPhenomX_Inspiral_Phase_22_d53(double eta, double S, double dchi, double delta, int InspPhaseFlag)
static double IMRPhenomX_Inspiral_Amp_22_rho3(double v1, double v2, double v3, double F1, double F2, double F3, int InsAmpFlag)
static double IMRPhenomX_Inspiral_Phase_22_d13(double eta, double S, double dchi, double delta, int InspPhaseFlag)
static double IMRPhenomX_Inspiral_Phase_22_d23(double eta, double S, double dchi, double delta, int InspPhaseFlag)
static double IMRPhenomX_Inspiral_Amp_22_DAnsatz(double Mf, IMRPhenomXWaveformStruct *pWF, IMRPhenomXAmpCoefficients *pAmp)
static double IMRPhenomX_Inspiral_Amp_22_rho1(double v1, double v2, double v3, double F1, double F2, double F3, int InsAmpFlag)
static double IMRPhenomX_Inspiral_Amp_22_rho2(double v1, double v2, double v3, double F1, double F2, double F3, int InsAmpFlag)
Internal function for IMRPhenomX phenomenological waveform model, arXiv:2001.11412.
static double IMRPhenomX_Intermediate_Amp_22_v3(double eta, double S, double dchi, double delta, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Amp_22_delta3(double d1, double d4, double v1, double v2, double v3, double v4, double f1, double f2, double f3, double f4, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Phase_22_v2(double eta, double S, double dchi, double delta, int IntPhaseFlag)
static double IMRPhenomX_Intermediate_Amp_22_delta0(double d1, double d4, double v1, double v2, double v3, double v4, double f1, double f2, double f3, double f4, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Phase_22_v3mRDv4(double eta, double S, double dchi, double delta, int IntPhaseFlag)
static double IMRPhenomX_Intermediate_Amp_22_delta1(double d1, double d4, double v1, double v2, double v3, double v4, double f1, double f2, double f3, double f4, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Amp_22_delta4(double d1, double d4, double v1, double v2, double v3, double v4, double f1, double f2, double f3, double f4, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Phase_22_AnsatzInt(double f, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase)
static double IMRPhenomX_Intermediate_Amp_22_v2(double eta, double S, double dchi, double delta, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Phase_22_v2mRDv4(double eta, double S, double dchi, double delta, int IntPhaseFlag)
static double IMRPhenomX_Intermediate_Amp_22_delta5(double d1, double d4, double v1, double v2, double v3, double v4, double f1, double f2, double f3, double f4, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Phase_22_d43(double eta, double S, double dchi, double delta, int IntPhaseFlag)
static double IMRPhenomX_Intermediate_Amp_22_delta2(double d1, double d4, double v1, double v2, double v3, double v4, double f1, double f2, double f3, double f4, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Amp_22_vA(double eta, double S, double dchi, double delta, int IntAmpFlag)
static double IMRPhenomX_Intermediate_Amp_22_Ansatz(double ff, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXWaveformStruct *pWF, IMRPhenomXAmpCoefficients *pAmp)
static double IMRPhenomX_Intermediate_Phase_22_Ansatz(double ff, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase)
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)
NRTidal_version_type IMRPhenomX_SetTidalVersion(LALDict *lalParams)
double IMRPhenomX_TimeShift_22(IMRPhenomXPhaseCoefficients *pPhase, IMRPhenomXWaveformStruct *pWF)
REAL8 IMRPhenomX_TidalPhaseDerivative(IMRPhenomX_UsefulPowers *powers_of_Mf, IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase, NRTidal_version_type NRTidal_version)
void IMRPhenomX_Phase_22_ConnectionCoefficients(IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase)
int IMRPhenomXGetAmplitudeCoefficients(IMRPhenomXWaveformStruct *pWF, IMRPhenomXAmpCoefficients *pAmp)
int IMRPhenomX_Initialize_Powers(IMRPhenomX_UsefulPowers *p, REAL8 number)
double IMRPhenomX_Phase_22(double ff, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXPhaseCoefficients *pPhase, IMRPhenomXWaveformStruct *pWF)
void IMRPhenomXGetTidalPhaseCoefficients(IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase, NRTidal_version_type NRTidal_version)
REAL8 IMRPhenomX_TidalPhase(IMRPhenomX_UsefulPowers *powers_of_Mf, IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase, NRTidal_version_type NRTidal_version)
int IMRPhenomX_Initialize_Powers_Light(IMRPhenomX_UsefulPowers *p, REAL8 number)
int IMRPhenomXGetPhaseCoefficients(IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase)
double IMRPhenomX_dPhase_22(double ff, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXPhaseCoefficients *pPhase, IMRPhenomXWaveformStruct *pWF)
INT4 check_input_mode_array(LALDict *lalParams)
INT4 IMRPhenomX_FullPhase_22(double *phase, double *dphase, double Mf, IMRPhenomXPhaseCoefficients *pPhase, IMRPhenomXWaveformStruct *pWF)
double IMRPhenomX_Amplitude_22(double ff, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXAmpCoefficients *pAmp, IMRPhenomXWaveformStruct *pWF)
Internal function for IMRPhenomX phenomenological waveform model, arXiv:2001.11412 See LALSimIMRPheno...
static double IMRPhenomX_Ringdown_Amp_22_gamma2(double eta, double S, double dchi, double delta, int RDAmpFlag)
static double IMRPhenomX_Ringdown_Phase_22_v4(double eta, double S, double dchi, double delta, int RDPhaseFlag)
static double IMRPhenomX_Ringdown_Phase_22_d24(double eta, double S, double dchi, double delta, int RDPhaseFlag)
static double IMRPhenomX_Ringdown_Amp_22_v1(double eta, double S, double dchi, double delta, int RDAmpFlag)
static double IMRPhenomX_Ringdown_Phase_22_AnsatzInt(double ff, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase)
static double IMRPhenomX_Ringdown_Phase_22_d12(double eta, double S, double dchi, double delta, int RDPhaseFlag)
static double IMRPhenomX_Ringdown_Phase_22_d34(double eta, double S, double dchi, double delta, int RDPhaseFlag)
static double IMRPhenomX_Ringdown_Amp_22_PeakFrequency(double gamma2, double gamma3, double frd, double fda, int RDAmpFlag)
static double IMRPhenomX_Ringdown_Phase_22_Ansatz(double ff, IMRPhenomX_UsefulPowers *powers_of_f, IMRPhenomXWaveformStruct *pWF, IMRPhenomXPhaseCoefficients *pPhase)
static double IMRPhenomX_Ringdown_Amp_22_DAnsatz(double ff, IMRPhenomXWaveformStruct *pWF, IMRPhenomXAmpCoefficients *pAmp)
static double IMRPhenomX_Ringdown_Phase_22_d54(double eta, double S, double dchi, double delta, int RDPhaseFlag)
static double IMRPhenomX_Ringdown_Amp_22_Ansatz(double ff, IMRPhenomXWaveformStruct *pWF, IMRPhenomXAmpCoefficients *pAmp)
static double IMRPhenomX_Ringdown_Amp_22_gamma3(double eta, double S, double dchi, double delta, int RDAmpFlag)
REAL8 XLALSimIMRPhenomXfMECO(REAL8 eta, REAL8 chi1L, REAL8 chi2L)
Phenomenological fit to hybrid minimum energy circular orbit (MECO) function.
void IMRPhenomX_InternalNudge(REAL8 x, REAL8 X, REAL8 epsilon)
If x and X are approximately equal to relative accuracy epsilon then set x = X.
REAL8 XLALSimIMRPhenomXFinalMass2017(REAL8 eta, REAL8 chi1L, REAL8 chi2L)
Final Mass = 1 - Energy Radiated, X Jimenez-Forteza et al, PRD, 95, 064024, (2017),...
REAL8 XLALSimIMRPhenomXfISCO(REAL8 chif)
Fitting function for hybrid minimum energy circular orbit (MECO) function.
REAL8 XLALSimIMRPhenomXFinalSpin2017(REAL8 eta, REAL8 chi1L, REAL8 chi2L)
Final Dimensionless Spin, X Jimenez-Forteza et al, PRD, 95, 064024, (2017), arXiv:1611....
bool IMRPhenomX_StepFuncBool(const double t, const double t1)
REAL8 XLALSimIMRPhenomXUtilsHztoMf(REAL8 fHz, REAL8 Mtot_Msun)
Convert from frequency in Hz to geometric frequency.
REAL8 XLALSimIMRPhenomXSTotR(REAL8 eta, REAL8 chi1L, REAL8 chi2L)
Total spin normalised to [-1,1].
REAL8 XLALSimIMRPhenomXdchi(REAL8 chi1L, REAL8 chi2L)
Spin difference.
REAL8 XLALSimIMRPhenomXPsi4ToStrain(double eta, double S, double dchi)
This is a fit of the time-difference between t_peak of strain and t_peak of psi4 needed to align in t...
REAL8 XLALSimIMRPhenomXchiPNHat(REAL8 eta, REAL8 chi1L, REAL8 chi2L)
Normalised PN reduced spin parameter.
REAL8 XLALSimIMRPhenomXLinb(REAL8 eta, REAL8 S, REAL8 dchi, REAL8 delta)
REAL8 XLALSimIMRPhenomXchiEff(REAL8 eta, REAL8 chi1L, REAL8 chi2L)
Effective aligned spin parameter.
int XLALSimInspiralSetQuadMonParamsFromLambdas(LALDict *LALparams)
if you do NOT provide a quadparam[1,2] term and you DO provide lamdba[1,2] then we calculate quad-mon...
static REAL8 UNUSED XLALSimInspiralTaylorF2Phasing_4PNQM2SOCoeff(REAL8 mByM)
static REAL8 UNUSED XLALSimInspiralTaylorF2Phasing_6PNQM2SCoeff(REAL8 mByM)
static REAL8 UNUSED XLALSimInspiralTaylorF2Phasing_4PNQM2SCoeff(REAL8 mByM)
LALValue * XLALSimInspiralWaveformParamsLookupModeArray(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi5(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXIntermediatePhaseVersion(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChiMinus2(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXTidalFlag(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXRingdownAmpVersion(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi6(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDB2(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXPNRForceXHMAlignment(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDC4(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDC1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDCL(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi6L(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupdQuadMon1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi0(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalLambda2(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChiMinus1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDB1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDC2(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi1(LALDict *params)
int XLALSimInspiralWaveformParamsLookupPhenomXOnlyReturnPhase(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalLambda1(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXPNRUseTunedCoprec(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi4(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXInspiralAmpVersion(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXIntermediateAmpVersion(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupNonGRParameterization(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi3(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDB4(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi7(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi5L(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupdQuadMon2(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXRingdownPhaseVersion(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDB3(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPhenomXInspiralPhaseVersion(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupNonGRDChi2(LALDict *params)
void XLALDestroyValue(LALValue *value)
int s
Definition: bh_qnmode.c:137
double i
Definition: bh_ringdown.c:118
double e
Definition: bh_ringdown.c:117
#define LAL_MSUN_SI
#define LAL_PI
#define LAL_MTSUN_SI
#define LAL_PI_4
#define LAL_GAMMA
#define LAL_MRSUN_SI
double REAL8
uint32_t UINT4
int32_t INT4
NRTidal_version_type
Definition: LALSimIMR.h:80
@ NRTidal_V
version NRTidal: based on https://arxiv.org/pdf/1706.02969.pdf
Definition: LALSimIMR.h:81
@ NoNRT_V
special case for PhenomPv2 BBH baseline
Definition: LALSimIMR.h:85
@ NRTidalv2_V
version NRTidalv2: https://arxiv.org/abs/1905.06011
Definition: LALSimIMR.h:82
#define LAL_SIM_L_MAX_MODE_ARRAY
Maximum L spherical harmonic mode that is supported in Mode Array.
int XLALSimInspiralModeArrayIsModeActive(LALValue *modes, unsigned l, int m)
static const INT4 q
#define XLAL_ERROR_REAL8(...)
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
#define XLAL_PRINT_WARNING(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_EINVAL
XLAL_FAILURE
list x
list p
string status
string version
REAL8 CollocationPointsAmpIns[N_MAX_COLLOCATION_POINTS_AMP_INS]
REAL8 CollocationValuesAmpIns[N_MAX_COLLOCATION_POINTS_AMP_INS]
REAL8 CollocationPointsPhaseRD[N_MAX_COLLOCATION_POINTS_PHASE_RD]
REAL8 CollocationPointsPhaseInt[N_MAX_COLLOCATION_POINTS_PHASE_INT]
REAL8 CollocationValuesPhaseIns[N_MAX_COLLOCATION_POINTS_PHASE_INS]
REAL8 CollocationValuesPhaseInt[N_MAX_COLLOCATION_POINTS_PHASE_INT]
REAL8 CollocationPointsPhaseIns[N_MAX_COLLOCATION_POINTS_PHASE_INS]
REAL8 CollocationValuesPhaseRD[N_MAX_COLLOCATION_POINTS_PHASE_RD]
double f_min
Definition: unicorn.c:22
double f_max
Definition: unicorn.c:23