LALSimulation  5.4.0.1-fe68b98
LALSimIMRTEOBResumS.c
Go to the documentation of this file.
1 
2 /**
3  * Copyright (C) 2017-2018 Alessandro Nagar, Sebastiano Bernuzzi,
4  * Sarp Ackay, Gregorio Carullo, Walter Del Pozzo, Ka Wa Tsang, Michalis Agathos
5  * LALSimulation implementation by Michalis Agathos
6  *
7  * This file is part of the LALSimulation version of TEOBResumS.
8  * The review of this implementation of the TEOBResumS waveform approximant
9  * can be found at https://git.ligo.org/waveforms/reviews/teobresums/wikis/
10  */
11 
12 /**
13  * TEOBResumS is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * TEOBResumS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see http://www.gnu.org/licenses/.
25  *
26  */
27 
28 #ifdef __GNUC__
29 #define UNUSED __attribute__ ((unused))
30 #else
31 #define UNUSED
32 #endif
33 
34 //#ifndef _OPENMP
35 //#define omp ignore
36 //#endif
37 
38 #include <complex.h>
39 #include <math.h>
40 
41 #include <gsl/gsl_const.h>
42 #include <gsl/gsl_errno.h>
43 #include <gsl/gsl_math.h>
44 #include <gsl/gsl_odeiv.h>
45 
46 #include "LALSimTEOBResumS.h"
47 
48 #define ODE_ABSTOL (1e-13)
49 #define ODE_RELTOL (1e-11)
50 #define INTERP_UNIFORM_GRID 1
51 
52 /**
53  * GSL routines for ODE integration
54  * https://www.gnu.org/software/gsl/doc/html/ode-initval.html
55  * http://www.csse.uwa.edu.au/programming/gsl-1.0/gsl-ref_24.html
56  */
57 
58 /** Global vars, defined as external in header */
59 const INT4 TEOB_LINDEX[KMAX] = {
60  2,2,
61  3,3,3,
62  4,4,4,4,
63  5,5,5,5,5,
64  6,6,6,6,6,6,
65  7,7,7,7,7,7,7,
66  8,8,8,8,8,8,8,8};
67 
68 const INT4 TEOB_MINDEX[KMAX] = {
69  1,2,
70  1,2,3,
71  1,2,3,4,
72  1,2,3,4,5,
73  1,2,3,4,5,6,
74  1,2,3,4,5,6,7,
75  1,2,3,4,5,6,7,8};
76 
77 /**
78  * @addtogroup LALSimIMRTEOBResumS_c
79  * @brief Routines to generate time-domain effective-one-body gravitational waveforms for coalescing compact binaries with non-precessing spins, tides and self-spin effects.
80  * inspiral-merger-ringdown waveforms.
81  *
82  * See:
83  * A. Nagar et al, TEOBResumS, arXiv:1806.01772, PRD, 98, 104052, (2018) - TEOBResumS main paper
84  * A. Nagar et al, arXiv:1805.03891, PRD, 99, 021501, (2019) - post-Adiabatic approximation
85  * A. Nagar et al, arXiv:1812.07923, PRD, 99, 044007, (2019) - Nonlinear-in-spin effects.
86  * S. Ackay et al, arXiv:1812.02744, PRD, 99, 044051, (2019) - Effective-one-body multipolar waveform for tidally interacting binary neutron stars up to merger
87  *
88  * @review by Geraint Pratten, Gunnar Riemenschneider, Piero Rettegno, Rachael Huxford, Rossella Gamba
89  * Combined review wiki:
90  * https://git.ligo.org/waveforms/reviews/teobresums/-/wikis/home
91  *
92  *
93  */
94 
95  /**
96  * @addtogroup LALSimIMRTEOBResumS_c
97  * @{
98  *
99  * @name Routines for TEOBResumS
100  * @{
101  *
102  * @author Alessandro Nagar, Sebastiano Bernuzzi, Sarp Ackay, Gregorio Carullo, Walter Del Pozzo, Ka Wa Tsang, Michalis Agathos (LALSimulation implementation by Michalis Agathos)
103  *
104  * @brief C code for TEOBResumS.
105  *
106  * This is an aligned-spin time-domain model for coalescing compact binaries. The model contains only the 22-mode for BBHs but (optional) inspiral-only higher multipoles (l<8) for BNS and NSBH systems.
107  * The model contains equation-of-state specific self-spin interactions (monopole-quadrupole) that are incorporated at leading-order PN. Gravitoelectric tides up to NNLO are modelled and
108  * gravitomagnetic tides up to NLO.
109  *
110  * See:
111  * - A. Nagar et al, TEOBResumS, arXiv:1806.01772, PRD, 98, 104052, (2018) - TEOBResumS main paper
112  * - A. Nagar et al, arXiv:1805.03891, PRD, 99, 021501, (2019) - post-Adiabatic approximation
113  * - A. Nagar et al, arXiv:1812.07923, PRD, 99, 044007, (2019) - Nonlinear-in-spin effects.
114  * - S. Ackay et al, arXiv:1812.02744, PRD, 99, 044051, (2019) - Effective-one-body multipolar waveform for tidally interacting binary neutron stars up to merger
115  *
116  * @note The model was calibrated to NR simulations at mass-ratios 1 to 20.
117  *
118  * @attention The model is usable outside this parameter range,
119  * and in tests to date gives sensible physical results up to mass ratios ~ 30 and spins ~ 0.99.
120  * For higher mass ratios and very negative spins memory allocation errors were found.
121  * These occur for \f$\eta < 0.073\f$ and \f$S < -0.8\f$. An approximate fit of the region to exclude was found to be: \f$\chi_1\f$ = -51.2 * \f$\eta^2\f$ +2.2456 * \f$\eta\f$ - 0.8804.
122  * For more information, see the review wiki https://git.ligo.org/waveforms/reviews/teobresums/-/wikis/home
123  *
124  *
125  */
126 
127 
128 /**
129  * Driver routine to calculate a TEOBResumS
130  * inspiral-merger-ringdown waveform model
131  * in the time domain.
132  *
133  * All input parameters should be in SI units. Angles should be in radians.
134  *
135  * Returns the plus and cross polarizations as a complex time series.
136  *
137  */
138 int XLALSimIMRTEOBResumS(REAL8TimeSeries **hplus, /**< +-polarization waveform */
139  REAL8TimeSeries **hcross, /**< x-polarization waveform */
140  const REAL8 phiRef, /**< reference orbital phase (rad) */
141  const REAL8 deltaT, /**< sampling interval (s) */
142  const REAL8 m1, /**< mass of companion 1 (kg) */
143  const REAL8 m2, /**< mass of companion 2 (kg) */
144  const REAL8 S1x, /**< x-component of the dimensionless spin of object 1 */
145  const REAL8 S1y, /**< y-component of the dimensionless spin of object 1 */
146  const REAL8 S1z, /**< z-component of the dimensionless spin of object 1 */
147  const REAL8 S2x, /**< x-component of the dimensionless spin of object 2 */
148  const REAL8 S2y, /**< y-component of the dimensionless spin of object 2 */
149  const REAL8 S2z, /**< z-component of the dimensionless spin of object 2 */
150  const REAL8 lambda1, /**< (tidal deformation of body 1)/(mass of body 1)^5 */
151  const REAL8 lambda2, /**< (tidal deformation of body 2)/(mass of body 2)^5 */
152  const REAL8 distance, /**< distance of source (m) */
153  const REAL8 inclination, /**< inclination of source (rad) */
154  const REAL8 UNUSED longAscNodes, /**< longitude of ascending nodes, degenerate with the polarization angle, Omega in documentation */
155  LALDict *LALparams, /**< LAL dictionary containing option parameters */
156  const REAL8 UNUSED eccentricity, /**< eccentrocity at reference epoch */
157  const REAL8 UNUSED meanPerAno, /**< mean anomaly of periastron */
158  const REAL8 f_min, /**< starting GW frequency (Hz) */
159  const REAL8 UNUSED f_ref /**< reference GW frequency (Hz) */
160 )
161 {
162  /* DOMAIN CHECKS */
163  XLAL_CHECK(hplus, XLAL_EFAULT, "hplus points to NULL");
164  XLAL_CHECK(hcross, XLAL_EFAULT, "hcross points to NULL");
165  XLAL_CHECK(*hplus == NULL, XLAL_EFAULT, "*hplus is not empty.\n");
166  XLAL_CHECK(*hcross == NULL, XLAL_EFAULT, "*hcross is not empty.\n");
167 
168  XLAL_CHECK(deltaT >= 0.0, XLAL_EDOM, "deltaT cannot take negative values.\n");
169  XLAL_CHECK((m1>0.0) && (m2>0.0), XLAL_EDOM, "Masses need to be positive.\n");
170  XLAL_CHECK(f_ref >= 0.0, XLAL_EDOM, "Reference frequency f_ref cannot be negative.\n");
171  XLAL_CHECK(distance > 0.0, XLAL_EDOM, "Distance needs to be positive");
172 
173  /* check for the presence of in-plane spins */
174  XLAL_CHECK(((S1x==0)&&(S1y==0)&&(S2x==0)&&(S2y==0)), XLAL_EDOM, "ERROR! Non-aligned spins not supported (yet)! Aborting.\n");
175 
176 
177  /* *****************************************
178  * Init
179  * *****************************************
180  */
181 
182  REAL8 m1_SI, m2_SI, LambdaAl2, LambdaAl3, LambdaAl4, LambdaBl2, LambdaBl3, LambdaBl4;
183 
184  m1_SI = m1;
185  m2_SI = m2;
186  REAL8 spin1x, spin1y, spin1z, spin2x, spin2y, spin2z;
187  spin1x = S1x;
188  spin1y = S1y;
189  spin1z = S1z;
190  spin2x = S2x;
191  spin2y = S2y;
192  spin2z = S2z;
193 
194  /* Tidal polarizability parameters: l=2 are nudged to zero */
195  LambdaAl2 = fabs(lambda1) > TEOB_LAMBDA_TOL ? lambda1 : 0.0;
196  LambdaAl3 = 0.0;
197  LambdaAl4 = 0.0;
198  LambdaBl2 = fabs(lambda2) > TEOB_LAMBDA_TOL ? lambda2 : 0.0;
199  LambdaBl3 = 0.0;
200  LambdaBl4 = 0.0;
201 
202  /* l=3,4 tidal parameters are read from LALDict if present */
203  if(XLALDictContains(LALparams, "TidalOctupolarLambda1"))
205  if(XLALDictContains(LALparams, "TidalOctupolarLambda2"))
207  if(XLALDictContains(LALparams, "TidalHexadecapolarLambda1"))
209  if(XLALDictContains(LALparams, "TidalHexadecapolarLambda2"))
211 
212 
213  /* Swap parameters if mass convention m1>m2 is not respected */
214  if (m2 > m1)
215  {
216  SWAPTRS(m1_SI, m2_SI);
217  SWAPTRS(spin1x, spin2x);
218  SWAPTRS(spin1y, spin2y);
219  SWAPTRS(spin1z, spin2z);
220  SWAPTRS(LambdaAl2, LambdaBl2);
221  SWAPTRS(LambdaAl3, LambdaBl3);
222  SWAPTRS(LambdaAl4, LambdaBl4);
223  }
224 
225  /* Switch to mass-rescaled geometric units */
226  REAL8 M = (m1_SI + m2_SI) / LAL_MSUN_SI; /* total mass in Msun */
227  REAL8 time_unit_fact = time_units_factor(M);
228 
229  /* Set useful pars/vars */
230  REAL8 q = m1_SI/m2_SI;
231  REAL8 nu = q_to_nu(q);
232 
233  /* HARDCODED 0.5 in geom units */
234  const REAL8 dt = 0.5;
235 
236  /* Initialize list of modes */
237  LALValue *ModeArray = XLALSimInspiralWaveformParamsLookupModeArray(LALparams);
238 
239  /* *****************************************
240  * Set Memory & do preliminary computations
241  * *****************************************
242  */
243 
244  /* Alloc memory for dynamics and multipolar waveform */
246  SphHarmPolarTimeSeries *hlm, *this_hlm;
247  REAL8Sequence *tdata;
248  LIGOTimeGPS epoch0 = LIGOTIMEGPSZERO;
250  SphHarmPolarTimeSeries *hlm_nqc=NULL;
251 
252  SphHarmPolarTimeSeries *hlm_mrg=NULL; /* merger chunk */
253  LALTEOBResumSDynamics *dyn_mrg=NULL;
254 
255  const INT4 chunk = 500;
256  INT4 size = chunk; /* note: size can vary */
257 
258  INT4 store_dynamics = 0;
259 
260  INT4 use_postadiab_dyn = 1;
261  INT4 rush_only = 0;
262 
263  /* Parse usage flags for postadiabatic (rush) speed-up */
264  if (XLALDictContains(LALparams, "TEOB_use_postadiabatic"))
265  {
266  switch (XLALDictLookupINT4Value(LALparams, "TEOB_use_postadiabatic"))
267  {
268  case TEOB_PA_ON:
269  break;
270  case TEOB_PA_OFF:
271  use_postadiab_dyn = 0;
272  break;
273  case TEOB_PA_ONLY:
274  rush_only = 1;
275  break;
276  default: XLAL_ERROR(XLAL_EINVAL, "Postadiabatic usage option not recognized.");
277  }
278  }
279 
280  /* Define lower radius limit for PA */
283 
284  /* Compute initial radius (NOTE: this may change) */
285  const REAL8 f0M = f_min/time_unit_fact;
286  REAL8 r0byM = eob_dyn_r0_Kepler(f0M);
287  //REAL8 r0byM = eob_dyn_r0_eob(f0M, dyn); /* Radius from EOB equations. This is what should be used. */
288  // if (DEBUG) fprintf(stdout, "r0 = %f\n", r0byM);
289 
290  /* If f_min is too high fall back to a minimum acceptable initial radius */
291  if (r0byM < TEOB_R0_THRESHOLD) {
292  r0byM = TEOB_R0_THRESHOLD;
293  }
294 
295  size = floor((r0byM - pa_rmin)/POSTADIABATIC_DR) + 1;
296 
297  /* If initial radius is too close to PA limit then skip PA and go directly to ODE */
298  if (size - 1 < POSTADIABATIC_NSTEP_MIN) {
299  size = chunk;
300  use_postadiab_dyn = 0;
301  }
302 
303  /*
304  XLAL_CHECK(size>1, XLAL_EINVAL, "Start of waveform at r < %f. Exiting...\n", pa_rmin);
305  if (DEBUG)
306  {
307  fprintf(stdout, "size = %d\n", size);
308  fprintf(stdout, "r0 = %f\n", r0byM);
309  }
310  */
311 
312  /* Initialize dynamics structure */
313  XLALTEOBDynamicsInit(&dyn, size, "dyn");
314 
315  /* Set quick-access parameters dyn (be careful here) */
316  XLALTEOBDynamicsSetParams(dyn, &ModeArray, m1_SI, m2_SI, spin1x, spin1y, spin1z, spin2x, spin2y, spin2z, dt, LambdaAl2, LambdaBl2, LambdaAl3, LambdaBl3, LambdaAl4, LambdaBl4, LALparams);
317  dyn->store = dyn->noflux = 0; /* Default: do not store vars, flux on */
318 
319  /* Set some flags (to be later controlled by LALDict) */
320  INT4 use_tidal, use_spins;
321  INT4 merger_interp = 0;
322  use_spins = dyn->use_spins;
323  use_tidal = dyn->use_tidal;
324  INT4 interp_uniform_grid = INTERP_UNIFORM_GRID_DEFAULT;
325 
326  /* Use rk45 by default for ODE */
327  INT4 use_rk45 = 1;
328 
329  /* Parse interpolation scheme flag from LALDict */
330  if (XLALDictContains(LALparams, "TEOB_interp_scheme"))
331  {
332  interp_uniform_grid = XLALDictLookupINT4Value(LALparams, "TEOB_interp_scheme");
333  }
334 
335  /* Parse ODE integrator flag from LALDict */
336  if (XLALDictContains(LALparams, "TEOB_use_rk45"))
337  {
338  use_rk45 = XLALDictLookupINT4Value(LALparams, "TEOB_use_rk45");
339  }
340 
341  const INT4 ode_tstep = dyn->ode_timestep;
342  REAL8 t_peak = 0.0;
343 
344  store_dynamics = (use_postadiab_dyn || !use_tidal);
345 
346  /* Amplitude and phase TimeSeries */
347  REAL8TimeSeries *Alm_adt, *philm_adt;
349 
350  Alm_adt = XLALCreateREAL8TimeSeries("A_lm", &gpst0, 0, deltaT, &lalStrainUnit, (size_t) size);
351  philm_adt = XLALCreateREAL8TimeSeries("phi_lm", &gpst0, 0, deltaT, &lalDimensionlessUnit, (size_t) size);
352  XLAL_CHECK (Alm_adt && philm_adt, XLAL_ENOMEM, "Could not allocate memory for hlm data.\n");
353 
354  /* Time series sequence */
355  tdata = XLALCreateREAL8Sequence(size);
356  XLAL_CHECK (tdata, XLAL_ENOMEM, "Could not allocate memory for time data.\n");
357 
358  /* Populate the mode list with head pointing at l=2, m=1 mode */
359  hlm = NULL;
360  for (int k=KMAX-1; k>=0; k--)
361  {
362  hlm = XLALSphHarmPolarTimeSeriesAddMode(hlm, Alm_adt, philm_adt, TEOB_LINDEX[k], TEOB_MINDEX[k]);
363  XLAL_CHECK(hlm, XLAL_ENOMEM, "Could not allocate hlm mode.\n");
364  }
365  XLALSphHarmPolarTimeSeriesSetTData(hlm, tdata); // MA: tdata still needs to be filled in
366  Waveform_lm_t_alloc (&hlm_t);
368  XLALDestroyREAL8TimeSeries(philm_adt);
369 
370  /* Set r.h.s. fun pointer */
371  int (*p_eob_dyn_rhs)(REAL8, const REAL8*, REAL8*, void*);
372  if (use_spins) p_eob_dyn_rhs = &eob_dyn_rhs_s;
373  else p_eob_dyn_rhs = &eob_dyn_rhs;
374 
375  /* Iteration index */
376  INT4 iter = 0;
377 
378  if (use_postadiab_dyn)
379  {
380  /* *****************************************
381  * Post-adiabatic dynamics
382  * *****************************************
383  */
384 
385  /* Calculate dynamics */
386  eob_dyn_Npostadiabatic(dyn, r0byM);
387 
388  /* Calculate waveform */
389  for (int i = 0; i < size; i++) tdata->data[i] = dyn->time[i];
390 
391  dyn->store = dyn->noflux = 1;
392 
393  for (int i = 0; i < size; i++)
394  {
395  dyn->y[TEOB_EVOLVE_RAD] = dyn->data[TEOB_RAD][i];
396  dyn->y[TEOB_EVOLVE_PHI] = dyn->data[TEOB_PHI][i];
397  dyn->y[TEOB_EVOLVE_PRSTAR] = dyn->data[TEOB_PRSTAR][i];
398  dyn->y[TEOB_EVOLVE_PPHI] = dyn->data[TEOB_PPHI][i];
399  p_eob_dyn_rhs(dyn->t, dyn->y, dyn->dy, dyn);
400  eob_wav_hlm(dyn, hlm_t);
401 
402  this_hlm = hlm;
403  for (int k = 0; k < KMAX; k++)
404  {
405  if (DEBUG)
406  {
407  XLAL_CHECK(((int) this_hlm->l == TEOB_LINDEX[k]) && ((int) this_hlm->m == TEOB_MINDEX[k]), XLAL_EDATA, "Mode numbers do not match\n");
408  }
409  XLAL_CHECK(this_hlm, XLAL_EFAULT, "Missing modes.\n");
410  this_hlm->ampl->data->data[i] = hlm_t->ampli[k];
411  this_hlm->phase->data->data[i] = hlm_t->phase[k];
412  this_hlm = this_hlm->next;
413  }
414  XLAL_CHECK(this_hlm==NULL, XLAL_EFAULT, "More modes present than expected.\n");
415  }
416 
417  dyn->store = dyn->noflux = 0;
418  if (rush_only)
419  {
420  /* SKIP ODE EVOLUTION */
421  goto END_ODE_EVOLUTION;
422  }
423 
424  /* Prepare for evolution */
425 
426  /* start counting from here */
427  iter = size-1;
428  dyn->dt = 0.5*(dyn->time[iter]-dyn->time[iter-1]);
429 
430  /* Set arrays with initial conditions
431  Note current time is already set in dyn->t */
432  dyn->y0[TEOB_ID_RAD] = dyn->r;
433  dyn->y0[TEOB_ID_PHI] = dyn->phi;
434  dyn->y0[TEOB_ID_PPHI] = dyn->pphi;
435  dyn->y0[TEOB_ID_OMGJ] = dyn->Omg;
436  dyn->y0[TEOB_ID_PRSTAR] = dyn->prstar;
437  dyn->y[TEOB_EVOLVE_RAD] = dyn->r;
438  dyn->y[TEOB_EVOLVE_PHI] = dyn->phi;
439  dyn->y[TEOB_EVOLVE_PRSTAR] = dyn->prstar;
440  dyn->y[TEOB_EVOLVE_PPHI] = dyn->pphi;
441 
442  }
443  else
444  {
445  /* *****************************************
446  * Initial conditions for the evolution
447  * *****************************************
448  */
449 
450  /* Compute the initial conditions */
451  if (use_spins) eob_dyn_ic_s(r0byM, dyn, dyn->y0);
452  else eob_dyn_ic(r0byM, dyn, dyn->y0);
453 
454  /* Se arrays with initial conditions */
455  dyn->t = 0.;
456  dyn->r = dyn->y0[TEOB_ID_RAD];
457  dyn->phi = 0.;
458  dyn->pphi = dyn->y0[TEOB_ID_PPHI];
459  dyn->Omg = dyn->y0[TEOB_ID_OMGJ];
460  dyn->ddotr = 0.;
461  dyn->prstar = dyn->y0[TEOB_ID_PRSTAR];
462  dyn->Omg_orb = 0.; //FIXME
463  dyn->y[TEOB_EVOLVE_RAD] = dyn->r;
464  dyn->y[TEOB_EVOLVE_PHI] = dyn->phi;
465  dyn->y[TEOB_EVOLVE_PRSTAR] = dyn->prstar;
466  dyn->y[TEOB_EVOLVE_PPHI] = dyn->pphi;
467  if (store_dynamics)
468  {
469  dyn->time[0] = dyn->t;
470  dyn->data[TEOB_RAD][0] = dyn->r;
471  dyn->data[TEOB_PHI][0] = dyn->phi;
472  dyn->data[TEOB_PPHI][0] = dyn->pphi;
473  dyn->data[TEOB_MOMG][0] = dyn->Omg;
474  dyn->data[TEOB_DDOTR][0] = dyn->ddotr;
475  dyn->data[TEOB_PRSTAR][0] = dyn->prstar;
476  dyn->data[TEOB_OMGORB][0] = dyn->Omg_orb;
477  dyn->data[TEOB_E0][0] = dyn->E;
478  }
479 
480  /* Waveform computation at t = 0
481  Needs a r.h.s. evaluation for some vars (no flux) */
482  dyn->store = dyn->noflux = 1;
483  p_eob_dyn_rhs(dyn->t, dyn->y, dyn->dy, dyn);
484  dyn->store = dyn->noflux = 0;
485  eob_wav_hlm(dyn, hlm_t);
486 
487  /* Append waveform to mode list */
488  this_hlm = hlm;
489  hlm->tdata->data[0] = 0.;
490  for (int k = 0; k < KMAX; k++)
491  {
492  if ( (DEBUG) && (this_hlm->l -TEOB_LINDEX[k] != 0 || this_hlm->m != TEOB_MINDEX[k]) )
493  {
494  XLAL_ERROR(XLAL_EDATA, "Mode numbers do not match!");
495  }
496  XLAL_CHECK(this_hlm, XLAL_EFAULT, "Missing modes.\n");
497  this_hlm->ampl->data->data[0] = hlm_t->ampli[k];
498  this_hlm->phase->data->data[0] = hlm_t->phase[k];
499  this_hlm = this_hlm->next;
500  }
501  XLAL_CHECK(this_hlm==NULL, XLAL_EFAULT, "More modes present than expected.\n");
502 
503  /* Prepare for evolution */
504  dyn->dt = dt;
505 
506  }
507 
508 
509  /* *****************************************
510  * ODE Evolution
511  * *****************************************
512  */
513 
514  /* Initialize ODE system solver */
515  dyn->ode_stop = false;
516  dyn->ode_stop_MOmgpeak = false;
517  dyn->ode_stop_radius = false;
518 
519  // Currently hardcoded to 1.0
520  const REAL8 rstop = dyn->r_stop;
521  if (rstop>0.)
522  {
523  dyn->ode_stop_radius = true;
524  }
525 
526  /* GSL integrator memory */
527  gsl_odeiv2_system sys = {p_eob_dyn_rhs, NULL , TEOB_EVOLVE_NVARS, dyn};
528  const gsl_odeiv2_step_type * T;
529  gsl_odeiv2_driver * d;
530 
531  if (use_rk45)
532  {
533  T = gsl_odeiv2_step_rkf45;
534  d = gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, (double) dyn->dt, ODE_ABSTOL, ODE_RELTOL);
535  }
536  else
537  {
538  // If we prefer rk8:
539  T = gsl_odeiv2_step_rk8pd;
540  d = gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd, dyn->dt, ODE_ABSTOL, ODE_RELTOL);
541  }
542 
543  gsl_odeiv2_step * s = gsl_odeiv2_step_alloc (T, TEOB_EVOLVE_NVARS);
544  gsl_odeiv2_control * c = gsl_odeiv2_control_y_new (ODE_ABSTOL, ODE_RELTOL);
545  gsl_odeiv2_evolve * e = gsl_odeiv2_evolve_alloc (TEOB_EVOLVE_NVARS);
546 
547  /* Set optimized dt around merger */
548  const double dt_tuned_mrg = get_mrg_timestep(q, dyn->chi1, dyn->chi2);
549 
550  /* Solve ODE */
551  int STATUS = 0;
552  while (!(dyn->ode_stop))
553  {
554  iter++;
555 
556  switch (ode_tstep)
557  {
558  case ODE_TSTEP_UNIFORM:
559  {
560  /* Uniform timestepping */
561  dyn->ti = dyn->t + dyn->dt;
562  STATUS = gsl_odeiv2_driver_apply (d, &dyn->t, (double) dyn->ti, dyn->y);
563  break;
564  }
565  case ODE_TSTEP_ADAPTIVE:
566  {
567  /* Adaptive timestepping */
568  if ( dyn->ode_stop_MOmgpeak == true )
569  /* if we are after the peak, slow down and fix the last steps ! */
570  STATUS = gsl_odeiv2_evolve_apply_fixed_step (e, c, s, &sys, &dyn->t, dyn->dt, dyn->y);
571  else
572  STATUS = gsl_odeiv2_evolve_apply (e, c, s, &sys, &dyn->t, (double) dyn->t_stop, &dyn->dt, dyn->y);
573  break;
574  }
576  {
577  /* Adaptive timestepping until LSO ... */
578  if (dyn->r > dyn->rLSO)
579  {
580  STATUS = gsl_odeiv2_evolve_apply (e, c, s, &sys, &dyn->t, (double) dyn->t_stop, &dyn->dt, dyn->y);
581  }
582  else
583  {
584  /* ... uniform afterwards */
585  dyn->dt = dt_tuned_mrg;
586  dyn->ti = dyn->t + dyn->dt;
587  STATUS = gsl_odeiv2_evolve_apply_fixed_step (e, c, s, &sys, &dyn->t, dyn->dt, dyn->y);
588  }
589  break;
590  }
591  default: XLAL_ERROR(XLAL_EINVAL, "Unknown ODE time step method. Aborting\n");
592  }
593 
594  /* Check for failures */
595 
596  if (dyn->ode_stop_MOmgpeak == true)
597  {
598  /* ...if after the Omega_orb peak, stop integration */
599  if ( (STATUS != GSL_SUCCESS) || (!isfinite(dyn->y[TEOB_EVOLVE_RAD])) )
600  {
601  iter--; /* do count this iter! */
602  dyn->ode_stop = true;
603  break; /* (while) stop */
604  }
605  }
606 
607  XLAL_CHECK(STATUS == GSL_SUCCESS, XLAL_EFAULT | STATUS, "GSL ODE solver failed. Error = %d\n", STATUS);
608 
609  /* Checking whether the dynamics produces NaN values this can happen if radius r becomes too small */
610  XLAL_CHECK(isfinite(dyn->r), XLAL_ESING, "ODE solver returned NaN radius.\n");
611 
612  /* Unpack data */
613  dyn->r = dyn->y[TEOB_EVOLVE_RAD];
614  dyn->phi = dyn->y[TEOB_EVOLVE_PHI];
615  dyn->prstar = dyn->y[TEOB_EVOLVE_PRSTAR];
616  dyn->pphi = dyn->y[TEOB_EVOLVE_PPHI];
617 
618  /* Waveform computation
619  Needs a r.h.s. evaluation for some vars (but no flux) */
620  dyn->store = dyn->noflux = 1;
621  p_eob_dyn_rhs(dyn->t, dyn->y, dyn->dy, dyn);
622  dyn->store = dyn->noflux = 0;
623  eob_wav_hlm(dyn, hlm_t);
624 
625  /* Update size and push arrays (if needed) */
626  if (iter==size)
627  {
628  size += chunk;
629  /* Resize time sequence, padding with 0s */
630  XLALResizeREAL8Sequence(tdata, 0, size);
631 
632  /* Resize mode series and dynamics */
633  XLALResizeSphHarmPolarTimeSeries(hlm, 0, size);
634  XLALTEOBDynamicsPush(&dyn, size);
635 
636  XLAL_CHECK(tdata && hlm && dyn, XLAL_ENOMEM, "Could not resize waveform structures.\n");
637  }
638 
639  /* Append waveform and dynamics to mode list */
640  tdata->data[iter] = hlm_t->time;
641  this_hlm = hlm;
642  for (int k = 0; k < KMAX; k++)
643  {
644  if ( (DEBUG) && (this_hlm->l - TEOB_LINDEX[k] != 0 || this_hlm->m != TEOB_MINDEX[k]) )
645  {
646  XLAL_ERROR(XLAL_EDATA, "Mode numbers do not match!");
647  }
648  XLAL_CHECK(this_hlm, XLAL_EFAULT, "Missing modes.\n");
649  this_hlm->ampl->data->data[iter] = hlm_t->ampli[k];
650  this_hlm->phase->data->data[iter] = hlm_t->phase[k];
651  this_hlm = this_hlm->next;
652  }
653  XLAL_CHECK(this_hlm==NULL, XLAL_EFAULT, "More modes present than expected.\n");
654 
655  if (store_dynamics)
656  {
657  dyn->time[iter] = dyn->t;
658  dyn->data[TEOB_RAD][iter] = dyn->r;
659  dyn->data[TEOB_PHI][iter] = dyn->phi;
660  dyn->data[TEOB_PPHI][iter] = dyn->pphi;
661  dyn->data[TEOB_MOMG][iter] = dyn->Omg;
662  dyn->data[TEOB_DDOTR][iter] = dyn->ddotr;
663  dyn->data[TEOB_PRSTAR][iter] = dyn->prstar;
664  dyn->data[TEOB_OMGORB][iter] = dyn->Omg_orb;
665  dyn->data[TEOB_E0][iter] = dyn->E;
666  }
667 
668  /* Stop integration if reached max time */
669  if (dyn->t >= dyn->t_stop) dyn->ode_stop = true;
670 
671  /* Stop integration at given radius (if rstop >= 0) */
672  if ((dyn->ode_stop_radius) && (dyn->r < rstop) ) dyn->ode_stop = true;
673 
674  /* Check when to break the computation
675  find peak of omega curve and continue for 2M */
676  dyn->MOmg = use_spins ? dyn->Omg_orb : dyn->Omg;
677 
678  if (dyn->ode_stop_MOmgpeak == false)
679  {
680  /* Before the Omega_orb peak */
681  if (dyn->MOmg < dyn->MOmg_prev)
682  /* This is the first step after the peak
683  Set things for uniform tstep evolution */
684  {
685  dyn->tMOmgpeak = dyn->t; // = dyn->t-0.5*dyn->dt;
686  dyn->ode_stop_MOmgpeak = true;
687  dyn->dt = MIN(dyn->dt, dt_tuned_mrg);
688  // dyn->t_stop = dyn->t + nstep_stop*dyn->dt; // continue for nstep_stop iters
689  dyn->t_stop = dyn->t + 2.;
690  t_peak = dyn->t;
691  }
692  else
693  {
694  /* Peak not reached, update the max */
695  dyn->MOmg_prev = dyn->MOmg;
696  }
697  }
698  else
699  {
700  if (dyn->t >= dyn->t_stop) dyn->ode_stop = true;
701  }
702 
703  }
704  /* end time iteration */
705 
706  /* Free ODE system solver */
707  gsl_odeiv2_evolve_free (e);
708  gsl_odeiv2_control_free (c);
709  gsl_odeiv2_step_free (s);
710  gsl_odeiv2_driver_free (d);
711 
712  /* Update waveform and dynamics size
713  resize to actual size */
714  size = iter+1;
715 
716  /* Size down mode series and time sequence */
717  XLALResizeSphHarmPolarTimeSeries(hlm, 0, size);
718  XLALResizeREAL8Sequence(hlm->tdata, 0, size);
719 
720  /* Size down dynamics */
721  XLALTEOBDynamicsPush(&dyn, size);
722 
723 END_ODE_EVOLUTION:;
724 
725  if (!(use_tidal) && !(rush_only))
726  {
727 
728  /* *****************************************
729  * Following is for BBH : NQC & Ringdown
730  * *****************************************
731  */
732 
733  /*
734  This is a BBH run. NQC and ringdown attachment currently assume uniform grids.
735  Do we need to interpolate ?
736  */
737 
738  /* In general, yes interpolate... */
739  merger_interp = 1;
740 
741  /* HARDCODED default value */
742  REAL8 dt_merger_interp = 0.5;
743 
744  /* ... except if merger is covered by uniform tstep, then we do NOT interpolate */
745  if (ode_tstep != ODE_TSTEP_ADAPTIVE) merger_interp = 0;
746 
747  if (merger_interp)
748  {
749  /* NQC and ringdown attachment is done around merger
750  using auxiliary variables defined around [tmin,tmax]
751  Recall that parameters are NOT stored into these auxiliary vars */
752 
753  const REAL8 tmin = hlm->tdata->data[size-1] - 20; /* Use last 20M points */
754  const REAL8 tmax = hlm->tdata->data[size-1] + 2*dt; /* Make sure to use or get last point */
755 
756  /* Find indexes of closest elements to (to, tn) */
757  INT4 imin = 0;
758  INT4 imax = hlm->tdata->length - 1;
759  /* Check limits first */
760  XLAL_CHECK((tmin<tmax) && (tmin < hlm->tdata->data[imax]) && (tmax > hlm->tdata->data[imin]), XLAL_EDOM, "Bad choice of times.");
761 
762  if (tmin > hlm->tdata->data[0])
763  imin = find_point_bisection(tmin, hlm->tdata->length, hlm->tdata->data, 1);
764  if (tmax < hlm->tdata->data[imax])
765  imax = find_point_bisection(tmax, hlm->tdata->length, hlm->tdata->data, 0);
766 
767  /* Create a new mode list and dynamics by extracting a part of the original */
768  hlm_mrg = XLALCutSphHarmPolarTimeSeries(hlm, imin, (size_t) imax - imin);
769  XLALTEOBDynamicsExtract (dyn, tmin, tmax, &dyn_mrg, "dyn_mrg");
770 
771  /* Interpolate mrg on uniform grid */
772 
773  /* Build uniform grid of width dt and alloc tmp memory */
774  //dt_merger_interp = MIN(dt_merger_interp, (dyn->time[size-1] - dyn->tMOmgpeak)/4 ); /* Make sure to have always 3 points */
775  dt_merger_interp = MIN(dt_merger_interp, dyn->dt);
776 
777  const INT4 size_mrg = get_uniform_size(hlm_mrg->tdata->data[hlm_mrg->tdata->length-1], hlm_mrg->tdata->data[0], dt_merger_interp);
778 
779  /* Fill new time array */
780  REAL8Sequence *mrgtime_interp;
781  mrgtime_interp = XLALCreateREAL8Sequence(size_mrg);
782  for (int i = 0; i < size_mrg; i++)
783  mrgtime_interp->data[i] = i*dt_merger_interp + hlm_mrg->tdata->data[0];
784 
785  /* Interp Waveform */
786 
787  REAL8TimeSeries *Alm_mrg, *philm_mrg;
788  this_hlm = hlm_mrg;
789  while (this_hlm)
790  {
791  /* Interpolate mode amplitude and replace */
792  Alm_mrg = XLALCreateREAL8TimeSeries(this_hlm->ampl->name, &epoch0, 0, dt_merger_interp, &(lalStrainUnit), (size_t) size_mrg);
793  interp_spline(this_hlm->tdata->data, this_hlm->ampl->data->data, this_hlm->ampl->data->length, mrgtime_interp->data, size_mrg, Alm_mrg->data->data);
794  XLALDestroyREAL8TimeSeries(this_hlm->ampl);
795  this_hlm->ampl = Alm_mrg;
796 
797  /* Interpolate mode phase and replace */
798  philm_mrg = XLALCreateREAL8TimeSeries(this_hlm->phase->name, &epoch0, 0, dt_merger_interp, &(lalDimensionlessUnit), (size_t) size_mrg);
799  interp_spline(this_hlm->tdata->data, this_hlm->phase->data->data, this_hlm->phase->data->length, mrgtime_interp->data, size_mrg, philm_mrg->data->data);
801  this_hlm->phase = philm_mrg;
802 
803  Alm_mrg = NULL;
804  philm_mrg = NULL;
805  this_hlm = this_hlm->next;
806  }
807 
808  /* Replace time sequence */
809  if (hlm_mrg->tdata) XLALDestroyREAL8Sequence(hlm_mrg->tdata);
810  XLALSphHarmPolarTimeSeriesSetTData(hlm_mrg, mrgtime_interp);
811  mrgtime_interp = NULL;
812  LALFree(mrgtime_interp);
813 
814  /* Interp Dynamics */
815  XLALTEOBDynamicsInterp (dyn_mrg, size_mrg, dyn_mrg->time[0], dt_merger_interp, "dyn_mrg_interp");
816 
817  } /* End of merger interp */
818 
819  if (dyn->nqc_coeffs_hlm == NQC_COMPUTE) {
820 
821  /* BBH : compute and add NQC */
822 
823  UINT4 size_nqc = merger_interp ? hlm_mrg->tdata->length : (UINT4) size;
824 
825  /* Populate NQC mode list */
826  for (int k=KMAX-1; k>=0; k--)
827  {
828  REAL8TimeSeries *Alm, *philm;
829  Alm = XLALCreateREAL8TimeSeries("A_nqc", &epoch0, 0, deltaT, &(lalStrainUnit), (size_t) size_nqc);
830  philm = XLALCreateREAL8TimeSeries("phi_nqc", &epoch0, 0, deltaT, &(lalDimensionlessUnit), (size_t) size_nqc);
831  hlm_nqc = XLALSphHarmPolarTimeSeriesAddMode(hlm_nqc, Alm, philm, TEOB_LINDEX[k], TEOB_MINDEX[k]);
832  XLAL_CHECK(hlm_nqc, XLAL_ENOMEM, "Could not allocate hlm_nqc mode.\n");
835  }
836 
837 
838  if (merger_interp) {
839 
840  /* Compute NQC only around merger,
841  add to both merger and full waveform */
842  XLALSphHarmPolarTimeSeriesSetTData(hlm_nqc, hlm_mrg->tdata);
843  eob_wav_hlmNQC_find_a1a2a3_mrg(dyn_mrg, hlm_mrg, hlm_nqc, dyn, hlm);
844  this_hlm = hlm_mrg;
845  while (this_hlm) {
846  strcat(this_hlm->ampl->name,"_nqc");
847  strcat(this_hlm->phase->name,"_nqc");
848  this_hlm = this_hlm->next;
849  }
850 
851  /* Join merger to full waveform */
852  XLALSphHarmPolarJoin(hlm, hlm_mrg, hlm_mrg->tdata->data[0]);
853  XLALTEOBDynamicsJoin (dyn, dyn_mrg, dyn_mrg->time[0]);
854  size = hlm->tdata->length;
855 
856  }
857  else
858  {
859 
860  /* Compute NQC and add them to full waveform */
862  eob_wav_hlmNQC_find_a1a2a3(dyn, hlm, hlm_nqc);
863 
864  }
865  /* Suffix to hlm name */
866  this_hlm = hlm;
867  while (this_hlm)
868  {
869  strcat(this_hlm->ampl->name,"_nqc");
870  strcat(this_hlm->phase->name,"_nqc");
871  this_hlm = this_hlm->next;
872  }
873 
874  }
875 
876  /* BBH : add Ringdown */
877 
878  /* Extend arrays */
879  const UINT4 size_ringdown = RINGDOWN_EXTEND_ARRAY;
880  REAL8 dt_rngdn = dt;
881 
882  /* If ODE does not finish with uniform timestep, then match merger interp timestep */
883  if (merger_interp)
884  dt_rngdn = dt_merger_interp;
885 
886  /* Resize waveform and time array */
887 
888  XLALResizeSphHarmPolarTimeSeries(hlm, 0, (size+size_ringdown));
889  XLALResizeREAL8Sequence(tdata, 0, (size+size_ringdown));
890  for (UINT4 i = size; i < (size+size_ringdown); i++)
891  {
892  hlm->tdata->data[i] = hlm->tdata->data[i-1] + dt_rngdn;
893  }
894  size += size_ringdown;
895 
896  /* Ringdown attachment */
897  eob_wav_ringdown(dyn, hlm);
898  strcat(hlm->ampl->name,"_ringdown");
899  strcat(hlm->phase->name,"_ringdown");
900  } /* End of BBH section */
901 
902 
903  /* *****************************************
904  * Compute h+, hx
905  * *****************************************
906  */
907 
908  /* Scale to physical units (if necessary) */
909  REAL8 amplitude_prefactor = nu * M * LAL_MRSUN_SI / distance;
910 
911  /* Azimuthal angle phi follows LAL convention of LIGO-T1800226 for master,
912  * where the polarization basis is defined with \f$\Omega=\pi/2\f$ and
913  * \f$Z = \sin{\iota}\sin{\Phi}x + \sin{\iota}\cos{\Phi}y + \cos{\iota}z\f$
914  */
915  const REAL8 phi = LAL_PI_2 - phiRef;
916  const REAL8 iota = inclination;
917 
918  /* Time to use as the epoch of the returned time series.
919  * Time of merger is centered at zero.
920  * If ODE did not integrate up to peak then defaults to 0.
921  */
923  XLALGPSAdd(&epoch, -t_peak/time_unit_fact);
924 
925 
926  /*
927  * Interpolate on uniform grid
928  */
929 
930  /* Auxiliary Structures */
931  REAL8Sequence *utime=NULL;
932 
933  /* Build uniform grid of width dt and alloc tmp memory */
934  const UINT4 size_out = get_uniform_size(tdata->data[size-1], tdata->data[0], deltaT*time_unit_fact);
935 
936  /* Waveform */
937 
938  /* Create a new mode list to store uniform time data */
939  utime = XLALCreateREAL8Sequence(size_out);
940  XLAL_CHECK (utime, XLAL_ENOMEM, "Could not allocate memory for time data.\n");
941 
942  for (UINT4 i = 0; i < size_out; i++) utime->data[i] = i*deltaT*time_unit_fact;
943 
944  /* Interp to uniform grid the multipoles before hpc computation if
945  *INTERP_UNIFORM_GRID_HLM scheme is used
946  */
947  if (interp_uniform_grid == INTERP_UNIFORM_GRID_HLM)
948  {
949  //#pragma omp parallel
950  //{
951  /* Interpolate ampl and phase */
952  //#pragma omp single private(this_hlm)
953  //{
954  this_hlm = hlm;
955  while (this_hlm)
956  {
957  //#pragma omp task
958  //{
959  //fprintf(stderr, "In thread%d/%d\n", omp_get_thread_num(), omp_get_num_threads());
960  REAL8TimeSeries *A_ut=NULL;
961  REAL8TimeSeries *phi_ut=NULL;
962  /* Interpolate mode amplitude and replace */
963  A_ut = XLALCreateREAL8TimeSeries(this_hlm->ampl->name, &epoch, 0, deltaT, &(lalStrainUnit), (size_t) size_out);
964  // XLAL_CHECK (A_ut, XLAL_ENOMEM, "Could not allocate memory for hlm amplitude data.\n");
965  interp_spline(tdata->data, this_hlm->ampl->data->data, size, utime->data,
966  size_out, A_ut->data->data);
967  XLALDestroyREAL8TimeSeries(this_hlm->ampl);
968  this_hlm->ampl = A_ut;
969 
970  /* Interpolate mode phase and replace */
971  phi_ut = XLALCreateREAL8TimeSeries(this_hlm->phase->name, &epoch, 0, deltaT, &(lalDimensionlessUnit), (size_t) size_out);
972  // XLAL_CHECK (phi_ut, XLAL_ENOMEM, "Could not allocate memory for hlm phase data.\n");
973  interp_spline(tdata->data, this_hlm->phase->data->data, size, utime->data,
974  size_out, phi_ut->data->data);
976  this_hlm->phase = phi_ut;
977 
978  A_ut = NULL;
979  phi_ut = NULL;
982  //}
983  this_hlm = this_hlm->next;
984  }
985  //}
986  //}
987 
988  /* Replace time sequence */
989  size = size_out;
991  }
992 
993  /* Computation of (h+,hx) */
994 
995  /* Allocate hplus and hcross */
996  *hplus = XLALCreateREAL8TimeSeries( "h_plus", &epoch, 0.0, deltaT, &lalStrainUnit, size_out);
997  XLAL_CHECK(*hplus, XLAL_EFAULT, "ERROR allocating hplus.\n");
998 
999  *hcross = XLALCreateREAL8TimeSeries( "h_cross", &epoch, 0.0, deltaT, &lalStrainUnit, size_out);
1000  XLAL_CHECK(*hcross, XLAL_EFAULT, "ERROR allocating hplus.\n");
1001 
1002  memset ((*hplus)->data->data, 0, (*hplus)->data->length*sizeof(*(*hplus)->data->data));
1003  memset ((*hcross)->data->data, 0, (*hcross)->data->length*sizeof(*(*hcross)->data->data));
1004 
1005  /* Spherical harmonics projection **/
1006  /* construct hplus and hcross **/
1007  /* h22 = 1/R * (nu*M)*G/c^2 h_code_output */
1008 
1009  /* Computation of (h+,hx) */
1010  // NOTE that we set the phase angle for the m mode equal to zero by definition and to be consistent with the PA approximation
1011  if (interp_uniform_grid == INTERP_UNIFORM_GRID_HLM)
1012  {
1013  XLALSimIMRComputePolarisationsPolar((*hplus)->data, (*hcross)->data, hlm, ModeArray, amplitude_prefactor, iota, phi);
1014  }
1015  else if (interp_uniform_grid == INTERP_UNIFORM_GRID_HPC)
1016  {
1017 
1018  /* TEMPORARY ERROR MESSAGE */
1019  XLAL_ERROR(XLAL_EINVAL, "Only HLM interpolation scheme is available. HPC is under reconstruction! Exiting...\n");
1020 
1021  /* Interpolate (h+,hx) if INTERP_UNIFORM_GRID_HPC scheme is used
1022  * This is much faster in the current implementation but may smear
1023  * out higher-mode features.
1024  */
1025 
1026  /* Allocate non-uniform hplus and hcross */
1028  XLAL_CHECK(hp, XLAL_EFAULT, "ERROR allocating hplus.\n");
1029 
1031  XLAL_CHECK(hc, XLAL_EFAULT, "ERROR allocating hcross.\n");
1032 
1033  memset (hp->data, 0, hp->length*sizeof(REAL8));
1034  memset (hc->data, 0, hc->length*sizeof(REAL8));
1035 
1036  XLALSimIMRComputePolarisationsPolar(hp, hc, hlm, ModeArray, 1.0, iota, phi);
1037 
1038  REAL8 *Apc, *A_interp;
1039  REAL8 *phipc, *phi_interp;
1040 
1041  Apc = malloc(size * sizeof(REAL8));
1042  phipc = malloc(size * sizeof(REAL8));
1043  A_interp = malloc(size_out * sizeof(REAL8));
1044  phi_interp = malloc(size_out * sizeof(REAL8));
1045 
1046  for (int i=0; i<size; i++) {
1047  Apc[i] = sqrt( SQ(hp->data[i]) + SQ(hc->data[i]) );
1048  phipc[i] = - atan2(hc->data[i], hp->data[i]);
1049  }
1050  unwrap_proxy(phipc, hlm->next->phase->data->data, size, 0); /* ... but use phi22 as unwrap proxy */
1051 
1052 
1053  /* Interp to uniform grid after AP computation */
1054 
1055  /* Interpolate amplitude and phase */
1056  // FIXME: this is wrong, amplitude interpolation gives unphyiscal modulation when not perfectly face-on!
1057  interp_spline(tdata->data, Apc, size, utime->data,
1058  size_out, A_interp);
1059  interp_spline(tdata->data, phipc, size, utime->data,
1060  size_out, phi_interp);
1061 
1062  // FIXME: this is currently wrong, always gives circular polarization
1063  for (UINT4 i=0; i<size_out; i++)
1064  {
1065  (*hplus)->data->data[i] = amplitude_prefactor * A_interp[i] * cos(phi_interp[i]);
1066  (*hcross)->data->data[i] = amplitude_prefactor * A_interp[i] * sin(phi_interp[i]);
1067  }
1068 
1071  free(Apc);
1072  free(phipc);
1073  free(A_interp);
1074  free(phi_interp);
1075 
1076  } else XLAL_ERROR(XLAL_EINVAL, "Only HLM and HPC interpolation schemes are available.");
1077 
1078 
1079  /* Free memory */
1080  XLALDestroyREAL8Sequence(tdata);
1081  XLALDestroyREAL8Sequence(utime);
1082 
1083  XLALFreeTEOBDynamics(dyn);
1084  if (merger_interp)
1085  {
1086  XLALFreeTEOBDynamics(dyn_mrg);
1088  }
1089 
1092 
1093  /* tdata of NQC mode list used to point to hlm->tdata or hlm_mrg->tdata which is now destroyed */
1094  XLALSphHarmPolarTimeSeriesSetTData(hlm_nqc, NULL);
1096 
1097  Waveform_lm_t_free(hlm_t);
1098 
1099  XLALDestroyValue(ModeArray);
1100 
1101  return XLAL_SUCCESS;
1102 }
1103 
1104 /** @} */
1105 /** @} */
int XLALDictContains(const LALDict *dict, const char *key)
INT4 XLALDictLookupINT4Value(LALDict *dict, const char *key)
#define LALFree(p)
#define MIN(a, b)
#define DEBUG
const INT4 TEOB_MINDEX[KMAX]
#define ODE_ABSTOL
const INT4 TEOB_LINDEX[KMAX]
GSL routines for ODE integration https://www.gnu.org/software/gsl/doc/html/ode-initval....
#define ODE_RELTOL
void eob_wav_hlm(LALTEOBResumSDynamics *dyn, LALTEOBResumSWaveformModeSingleTime *hlm)
int eob_dyn_Npostadiabatic(LALTEOBResumSDynamics *dyn, const REAL8 r0)
void eob_dyn_ic_s(REAL8 r0, LALTEOBResumSDynamics *dyn, REAL8 y_init[])
int eob_dyn_rhs(REAL8 t, const REAL8 y[], REAL8 dy[], void *d)
void eob_wav_hlmNQC_find_a1a2a3_mrg(LALTEOBResumSDynamics *dyn_mrg, SphHarmPolarTimeSeries *hlm_mrg, SphHarmPolarTimeSeries *hnqc, LALTEOBResumSDynamics *dyn, SphHarmPolarTimeSeries *hlm)
void eob_wav_ringdown(LALTEOBResumSDynamics *dyn, SphHarmPolarTimeSeries *hlm)
void eob_wav_hlmNQC_find_a1a2a3(LALTEOBResumSDynamics *dyn, SphHarmPolarTimeSeries *h, SphHarmPolarTimeSeries *hnqc)
int eob_dyn_rhs_s(REAL8 t, const REAL8 y[], REAL8 dy[], void *d)
REAL8 eob_dyn_r0_Kepler(REAL8 f0)
void eob_dyn_ic(REAL8 r0, LALTEOBResumSDynamics *dyn, REAL8 y_init[])
INT4 find_point_bisection(REAL8 x, INT4 n, REAL8 *xp, INT4 o)
void interp_spline(double *t, double *y, int n, double *ti, int ni, REAL8 *yi)
void XLALTEOBDynamicsPush(LALTEOBResumSDynamics **dyn, INT4 size)
void Waveform_lm_t_free(LALTEOBResumSWaveformModeSingleTime *wav)
void XLALTEOBDynamicsInit(LALTEOBResumSDynamics **dyn, INT4 size, const char *name)
void XLALFreeTEOBDynamics(LALTEOBResumSDynamics *dyn)
void XLALTEOBDynamicsSetParams(LALTEOBResumSDynamics *dyn, UNUSED LALValue **pModeArray, const REAL8 m1, const REAL8 m2, const REAL8 UNUSED S1x, const REAL8 UNUSED S1y, const REAL8 S1z, const REAL8 UNUSED S2x, const REAL8 UNUSED S2y, const REAL8 S2z, const REAL8 dt, const REAL8 lambda1, const REAL8 lambda2, const REAL8 lambda1oct, const REAL8 lambda2oct, const REAL8 lambda1hex, const REAL8 lambda2hex, LALDict *LALparams)
REAL8 time_units_factor(REAL8 M)
void XLALSimIMRComputePolarisationsPolar(REAL8Sequence *hplus_out, REAL8Sequence *hcross_out, SphHarmPolarTimeSeries *hlm, LALValue *modeArray, REAL8 amplitude_prefactor, REAL8 theta, REAL8 phi)
void XLALTEOBDynamicsInterp(LALTEOBResumSDynamics *dyn, const INT4 size, const REAL8 t0, const REAL8 dt, const char *name)
void XLALTEOBDynamicsExtract(LALTEOBResumSDynamics *dyna, const REAL8 to, const REAL8 tn, LALTEOBResumSDynamics **dynb, const char *name)
REAL8 get_mrg_timestep(REAL8 q, REAL8 chi1, REAL8 chi2)
void XLALTEOBDynamicsJoin(LALTEOBResumSDynamics *dyna, LALTEOBResumSDynamics *dynb, REAL8 to)
REAL8 q_to_nu(const REAL8 q)
void XLALSphHarmPolarJoin(SphHarmPolarTimeSeries *hlma, SphHarmPolarTimeSeries *hlmb, REAL8 to)
INT4 get_uniform_size(const REAL8 tN, const REAL8 t0, const REAL8 dt)
void unwrap_proxy(REAL8 *p, REAL8 *r, const INT4 size, const INT4 shift0)
void Waveform_lm_t_alloc(LALTEOBResumSWaveformModeSingleTime **wav)
Replaced by LAL COMPLEX16TimeSeries functions.
static vector d(const double L_norm, const double J_norm, const vector roots)
Internal function that returns the coefficients "d_0", "d_2" and "d_4" from 1703.03967 corresponding ...
#define c
LALValue * XLALSimInspiralWaveformParamsLookupModeArray(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalHexadecapolarLambda1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalHexadecapolarLambda2(LALDict *params)
INT4 XLALSimInspiralWaveformParamsLookupPNTidalOrder(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalOctupolarLambda1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalOctupolarLambda2(LALDict *params)
This file is part of TEOBResumS.
#define POSTADIABATIC_RMIN_BBH
@ INTERP_UNIFORM_GRID_HPC
@ INTERP_UNIFORM_GRID_HLM
#define TEOB_LAMBDA_TOL
#define SWAPTRS(a, b)
#define POSTADIABATIC_DR
#define TEOB_R0_THRESHOLD
#define INTERP_UNIFORM_GRID_DEFAULT
#define KMAX
@ TEOB_EVOLVE_RAD
@ TEOB_EVOLVE_NVARS
@ TEOB_EVOLVE_PHI
@ TEOB_EVOLVE_PPHI
@ TEOB_EVOLVE_PRSTAR
#define POSTADIABATIC_RMIN_BNS
#define POSTADIABATIC_NSTEP_MIN
@ TEOB_PA_OFF
@ TEOB_PA_ONLY
@ TEOB_PA_ON
#define RINGDOWN_EXTEND_ARRAY
@ NQC_COMPUTE
@ TEOB_ID_PRSTAR
@ TEOB_ID_PHI
@ TEOB_ID_RAD
@ TEOB_ID_PPHI
@ TEOB_ID_OMGJ
@ ODE_TSTEP_UNIFORM
@ ODE_TSTEP_ADAPTIVE_UNIFORM_AFTER_LSO
@ ODE_TSTEP_ADAPTIVE
#define SQ(a)
@ TEOB_PRSTAR
@ TEOB_OMGORB
@ TEOB_DDOTR
@ TEOB_E0
@ TEOB_RAD
@ TEOB_MOMG
@ TEOB_PHI
@ TEOB_PPHI
void XLALDestroyValue(LALValue *value)
int s
Definition: bh_qnmode.c:137
REAL8 M
Definition: bh_qnmode.c:133
double dt
Definition: bh_ringdown.c:113
double i
Definition: bh_ringdown.c:118
double e
Definition: bh_ringdown.c:117
#define LAL_PI_2
#define LAL_MSUN_SI
#define LAL_MRSUN_SI
#define LIGOTIMEGPSZERO
double REAL8
uint32_t UINT4
int32_t INT4
int XLALSimIMRTEOBResumS(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, const REAL8 phiRef, const REAL8 deltaT, const REAL8 m1, const REAL8 m2, const REAL8 S1x, const REAL8 S1y, const REAL8 S1z, const REAL8 S2x, const REAL8 S2y, const REAL8 S2z, const REAL8 lambda1, const REAL8 lambda2, const REAL8 distance, const REAL8 inclination, const REAL8 UNUSED longAscNodes, LALDict *LALparams, const REAL8 UNUSED eccentricity, const REAL8 UNUSED meanPerAno, const REAL8 f_min, const REAL8 UNUSED f_ref)
Driver routine to calculate a TEOBResumS inspiral-merger-ringdown waveform model in the time domain.
LALSimInspiralTidalOrder
Enumeration of allowed PN orders of tidal effects.
@ LAL_SIM_INSPIRAL_TIDAL_ORDER_0PN
SphHarmPolarTimeSeries * XLALSphHarmPolarTimeSeriesAddMode(SphHarmPolarTimeSeries *appended, const REAL8TimeSeries *inAmpl, const REAL8TimeSeries *inphase, UINT4 l, INT4 m)
Prepend a node to a linked list of SphHarmPolarTimeSeries, or create a new head.
void XLALDestroySphHarmPolarTimeSeries(SphHarmPolarTimeSeries *ts)
Delete list from current pointer to the end of the list.
void XLALSphHarmPolarTimeSeriesSetTData(SphHarmPolarTimeSeries *ts, REAL8Sequence *tdata)
Set the tdata member for all nodes in the list.
SphHarmPolarTimeSeries * XLALResizeSphHarmPolarTimeSeries(SphHarmPolarTimeSeries *ts, int first, size_t length)
For every (l,m) node in the SphHarmPolarTimeSeries linked list, call XLALResizeREAL8TimeSeries(ts->am...
SphHarmPolarTimeSeries * XLALCutSphHarmPolarTimeSeries(SphHarmPolarTimeSeries *ts, int first, size_t length)
Create a new SphHarmPolarTimeSeries linked listby extracting a section of an existing SphHarmPolarTim...
static const INT4 q
void XLALDestroyREAL8Sequence(REAL8Sequence *sequence)
REAL8Sequence * XLALResizeREAL8Sequence(REAL8Sequence *sequence, int first, size_t length)
REAL8Sequence * XLALCreateREAL8Sequence(size_t length)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
const LALUnit lalStrainUnit
const LALUnit lalDimensionlessUnit
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
XLAL_ESING
XLAL_ENOMEM
XLAL_EDATA
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EDOM
XLAL_EINVAL
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
Dynamics data type.
REAL8 y[TEOB_EVOLVE_NVARS]
REAL8 y0[TEOB_ID_NVARS]
REAL8 * data[TEOB_DYNAMICS_NVARS]
REAL8 dy[TEOB_EVOLVE_NVARS]
Multipolar waveform at given time, comes at handy.
REAL8Sequence * data
CHAR name[LALNameLength]
REAL8 * data
REAL8TimeSeries * ampl
The sequences of mode amplitude.
REAL8TimeSeries * phase
The sequences of mode phase (not modulo 2Pi).
struct tagSphHarmPolarTimeSeries * next
next pointer
REAL8Sequence * tdata
Timestamp values.
LIGOTimeGPS epoch
Definition: unicorn.c:20
double f_min
Definition: unicorn.c:22
double deltaT
Definition: unicorn.c:24