Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALSimulation 6.2.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
LALSimIMRSpinAlignedEOB.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2018 Roberto Cotesta, Andrea Taracchini
3* Copyright (C) 2011 Craig Robinson, Enrico Barausse, Yi Pan, Prayush Kumar
4* (minor changes), Andrea Taracchini
5*
6* This program is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License as published by
8* the Free Software Foundation; either version 2 of the License, or
9* (at your option) any later version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU General Public License for more details.
15*
16* You should have received a copy of the GNU General Public License
17* along with with program; see the file COPYING. If not, write to the
18* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19* MA 02110-1301 USA
20*/
21
22
23#include <math.h>
24#include <complex.h>
25#include <lal/LALSimInspiral.h>
26#include <lal/LALSimIMR.h>
27#include <lal/Date.h>
28#include <lal/TimeSeries.h>
29#include <lal/Units.h>
30#include <lal/LALAdaptiveRungeKuttaIntegrator.h>
31#include <lal/SphericalHarmonics.h>
32#include <lal/LALSimSphHarmMode.h>
34#include <lal/VectorOps.h>
35
36#include <gsl/gsl_sf_gamma.h>
37#include <gsl/gsl_matrix.h>
38
39#include "LALSimIMREOBNRv2.h"
40#include "LALSimIMRSpinEOB.h"
43
44/* Include all the static function files we need */
56/* OPTIMIZED */
62/* END OPTIMIZED */
63
64
65#define debugOutput 0
66#define SEOBNRv4HM 41
67#define SEOBNRv4HM_PA 4111
68#define pSEOBNRv4HM_PA 4112
69
70
71//static int debugPK = 0;
72
73#ifdef __GNUC__
74#define UNUSED __attribute__ ((unused))
75#else
76#define UNUSED
77#endif
78
79
80static INT4 IntrpolateDynamics(REAL8Vector* tVec,REAL8Vector* rVec,REAL8Vector* phiVec,REAL8Vector* prVec,REAL8Vector* pphiVec,REAL8Vector* values,REAL8 closestTime){
81 UNUSED gsl_interp_accel *acc1 = gsl_interp_accel_alloc();
82 gsl_spline *spline1 = gsl_spline_alloc(gsl_interp_cspline, tVec->length);
83 gsl_spline_init(spline1, tVec->data, rVec->data, tVec->length);
84
85 UNUSED gsl_interp_accel *acc2 = gsl_interp_accel_alloc();
86 gsl_spline *spline2 = gsl_spline_alloc(gsl_interp_cspline, tVec->length);
87 gsl_spline_init(spline2, tVec->data, phiVec->data, tVec->length);
88
89 UNUSED gsl_interp_accel *acc3 = gsl_interp_accel_alloc();
90 gsl_spline *spline3 = gsl_spline_alloc(gsl_interp_cspline, tVec->length);
91 gsl_spline_init(spline3, tVec->data, prVec->data, tVec->length);
92
93 UNUSED gsl_interp_accel *acc4 = gsl_interp_accel_alloc();
94 gsl_spline *spline4 = gsl_spline_alloc(gsl_interp_cspline, tVec->length);
95 gsl_spline_init(spline4, tVec->data, pphiVec->data, tVec->length);
96 values->data[0] = gsl_spline_eval(spline1, closestTime, acc1);
97 values->data[1] = gsl_spline_eval(spline2, closestTime, acc2);
98 values->data[2] = gsl_spline_eval(spline3, closestTime, acc3);
99 values->data[3] = gsl_spline_eval(spline4, closestTime, acc4);
100 //printf("Interpolated values: r=%.17f, phi = %.17f, pr=%.17f, pphi = %.17f\n",values->data[0],values->data[1],values->data[2],values->data[3]);
101 gsl_spline_free (spline1);
102 gsl_interp_accel_free (acc1);
103
104 gsl_spline_free (spline2);
105 gsl_interp_accel_free (acc2);
106
107 gsl_spline_free (spline3);
108 gsl_interp_accel_free (acc3);
109
110 gsl_spline_free (spline4);
111 gsl_interp_accel_free (acc4);
112
113 return XLAL_SUCCESS;
114
115}
116
117/**
118 * ModeArray is a structure which allows to select the modes to include
119 * in the waveform.
120 * This function will create a structure with the default modes for every model
121 */
123 LALValue *ModeArray, UINT4 SpinAlignedEOBversion)
124{
125
126 /* setup ModeArray */
127
128 if (SpinAlignedEOBversion == SEOBNRv4HM) {
129 /* Adding all the modes of SEOBNRv4HM
130 * i.e. [(2,2),(2,1),(3,3),(4,4),(5,5)]
131 the relative -m modes are added automatically*/
137 }
138 else if (SpinAlignedEOBversion == SEOBNRv4HM_PA || SpinAlignedEOBversion == pSEOBNRv4HM_PA) {
139 /* Adding all the modes of SEOBNRv4HM_PA or pSEOBNRv4HM_PA
140 * i.e. [(2,2),(2,1),(3,3),(4,4),(5,5)]
141 the relative -m modes are added automatically*/
147 }
148 else{
149 /*All the other spin aligned model so far only have the 22 mode
150 */
152 }
153
154
155 return XLAL_SUCCESS;
156}
157
158/**
159 * ModeArray is a structure which allows to select the modes to include
160 * in the waveform.
161 * This function check if the selected modes are available for a given model
162 */
164 LALValue *ModeArray, UINT4 SpinAlignedEOBversion)
165{
166 INT4 flagTrue = 0;
167 UINT4 modeL;
168 UINT4 modeM;
170 const UINT4 lmModes[5][2] = {{2, 2}, {3, 3}, {2, 1}, {4, 4}, {5, 5}};
171
172 if (SpinAlignedEOBversion == SEOBNRv4HM) {
173 /*If one select SEOBNRv4HM all the modes above are selected to check
174 */
175 nModes = 5;
176 }
177 else if (SpinAlignedEOBversion == SEOBNRv4HM_PA || SpinAlignedEOBversion == pSEOBNRv4HM_PA) {
178 /*If one select SEOBNRv4HM_PA all the modes above are selected to check
179 */
180 nModes = 5;
181 }
182 else{
183 /*If not only the 22 mode is selected to check
184 */
185 nModes = 1;
186 }
187 /*Loop over all the possible modes
188 *we only check +m modes, when one select (l,m) mode is actually
189 *selecting (l,|m|) mode
190 */
191 for (UINT4 ELL = 2; ELL <= LAL_SIM_L_MAX_MODE_ARRAY; ELL++) {
192 for (UINT4 EMM = 0; EMM <= ELL; EMM++) {
193 if (XLALSimInspiralModeArrayIsModeActive(ModeArray, ELL, EMM) == 1) {
194 for (UINT4 k = 0; k < nModes; k++) {
195 modeL = lmModes[k][0];
196 modeM = lmModes[k][1];
197 if ((modeL == ELL)&&(modeM == EMM)) {
198 flagTrue=1;
199 }
200 }
201 /*For each active mode check if is available for the selected model
202 */
203 if (flagTrue != 1) {
204 XLALPrintError ("Mode (%d,%d) is not available by the model %d.\n", ELL,
205 EMM, SpinAlignedEOBversion);
206 return XLAL_FAILURE;
207 }
208 flagTrue = 0;
209 }
210 }
211 }
212
213 return XLAL_SUCCESS;
214}
215
216
217
218
219/**
220 * NR fit to the geometric GW frequency M_{total}omega_{22} of a BNS merger,
221 * defined by the time when the (2,2) amplitude peaks
222 * See Eq.(2) in https://arxiv.org/pdf/1504.01764.pdf with coefficients
223 * given by the 3rd row of Table II therein. Compared to NR for 0 <= kappa2T <= 500
224 */
226 TidalEOBParams *tidal1, /**< Tidal parameters of body 1 */
227 TidalEOBParams *tidal2 /**< Tidal parameters of body 2 */
228)
229{
230 REAL8 X1 = tidal1->mByM;
231 REAL8 X2 = tidal2->mByM;
232 REAL8 lambda1 = tidal1->lambda2Tidal; // Dimensionless quadrupolar tidal deformability normalized to M^5
233 REAL8 lambda2 = tidal2->lambda2Tidal; // Dimensionless quadrupolar tidal deformability normalized to M^5
234
235 REAL8 X1v, X2v, lambda1v, lambda2v;
236 if ( X1 >= X2 ) {
237 X1v = X1;
238 X2v = X2;
239 lambda1v = lambda1;
240 lambda2v = lambda2;
241 }
242 else {
243 X1v = X2;
244 X2v = X1;
245 lambda1v = lambda2;
246 lambda2v = lambda1;
247 }
248 REAL8 kappa2T = 3*(X2v/X1v*lambda1v + X1v/X2v*lambda2v);
249 if ( kappa2T < 0. ) {
251 }
252 else {
253 if ( kappa2T > 500. ) {
254 kappa2T = 500.;
255 }
256 return 0.3596*(1. + 0.024384*kappa2T - 0.000017167*kappa2T*kappa2T)/(1. + 0.068865*kappa2T);
257 }
258}
259
260static int UNUSED
261XLALEOBSpinStopCondition (double UNUSED t,/**<< UNUSED */
262 const double values[], /**<< Dynamical variables */
263 double dvalues[], /**<<1st time-derivatives of dynamical variables */
264 void *funcParams /**<< physical parameters*/
265 )
266{
267
268 SpinEOBParams *params = (SpinEOBParams *) funcParams;
269 double omega_x, omega_y, omega_z, omega;
270 double r2;
271
272 omega_x = values[1] * dvalues[2] - values[2] * dvalues[1];
273 omega_y = values[2] * dvalues[0] - values[0] * dvalues[2];
274 omega_z = values[0] * dvalues[1] - values[1] * dvalues[0];
275
276 r2 = values[0] * values[0] + values[1] * values[1] + values[2] * values[2];
277 omega =
278 sqrt (omega_x * omega_x + omega_y * omega_y + omega_z * omega_z) / r2;
279
280 /* Terminate when omega reaches peak, and separation is < 6M */
281 //if ( omega < params->eobParams->omega )
282 if (r2 < 36. && omega < params->eobParams->omega)
283 {
284 return 1;
285 }
286
287 params->eobParams->omega = omega;
288 return GSL_SUCCESS;
289}
290
291
292/**
293 * Stopping condition for the regular resolution EOB orbital evolution
294 * -- stop when reaching max orbital frequency in strong field.
295 * At each test,
296 * if omega starts to decrease, return 1 to stop evolution;
297 * if not, update omega with current value and return GSL_SUCCESS to continue evolution.
298 */
299static int
300XLALEOBSpinAlignedStopCondition (double UNUSED t, /**< UNUSED */
301 const double values[],
302 /**< dynamical variable values */
303 double dvalues[],/**< dynamical variable time derivative values */
304 void *funcParams /**< physical parameters */
305 )
306{
307
308 REAL8 omega, r;
309 SpinEOBParams *params = (SpinEOBParams *) funcParams;
310
311 r = values[0];
312 omega = dvalues[1];
313
314// printf("function 1: r = %.16e, omega = %.16e, pr = %.16e, dpr = %.16e, t = %.16e \n",values[0],dvalues[1],values[2],dvalues[2],t);
315 //if ( omega < params->eobParams->omega )
316 if (r < 6 && (omega < params->eobParams->omega || dvalues[2] >= 0))
317 {
318 params->eobParams->omegaPeaked = 0;
319 return 1;
320 }
321
322 params->eobParams->omega = omega;
323 return GSL_SUCCESS;
324}
325
326/*
327 * Stopping condition for the high resolution EOB orbital evolution
328 * -- stop when reaching a minimum radius 0.3M out of the EOB horizon (Eqs. 9b, 37)
329 * or when getting nan in any of the four ODE equations
330 * At each test,
331 * if conditions met, return 1 to stop evolution;
332 * if not, return GSL_SUCCESS to continue evolution.
333 */
334static int
335XLALSpinAlignedHiSRStopCondition (double UNUSED t, /**< UNUSED */
336 const double UNUSED values[],/**< dynamical variable values */
337 double dvalues[], /**< dynamical variable time derivative values */
338 void UNUSED * funcParams /**< physical parameters */
339 )
340{
341 if (dvalues[0] >= 0. || dvalues[2] >= 0. || isnan (dvalues[3]) || isnan (dvalues[2])
342 || isnan (dvalues[1]) || isnan (dvalues[0]))
343 {
344 return 1;
345 }
346 return GSL_SUCCESS;
347}
348
349/**
350 * This function defines the stopping criteria for the tidal EOB model
351 * Note that here
352 * values[0] = r
353 * values[1] = phi
354 * values[2] = pr
355 * values[3] = pphi
356 * dvalues[0] = dr/dt
357 * dvalues[1] = dphi/dt
358 * dvalues[2] = dpr/dt
359 * dvalues[3] = dpphi/dt = omega
360 */
361static int
362XLALSpinAlignedNSNSStopCondition (double UNUSED t, /**< UNUSED */
363 const double UNUSED values[],
364 /**< dynamical variable values */
365 double dvalues[], /**< dynamical variable time derivative values */
366 void UNUSED * funcParams /**< physical parameters */
367 )
368{
369 REAL8 omega, r;
370 UINT4 counter;
371 SpinEOBParams *params = (SpinEOBParams *) funcParams;
372 REAL8 rMerger = pow ( params->eobParams->omegaMerger/2., -2./3. );
373// printf("rMerger %.16e\n", rMerger);
374 r = values[0];
375 omega = dvalues[1];
376 counter = params->eobParams->omegaPeaked;
377 REAL8 eta = params->eobParams->eta;
378 if (debugOutput) printf("function NSNS: r = %.16e, omega = %.16e, pr = %.16e, dpr = %.16e, count = %.16u\n",values[0],dvalues[1],values[2],dvalues[2],counter);
379// printf("%.16e %.16e %.16e %.16e\n",values[0],dvalues[1],values[2],dvalues[2]);
380 REAL8 rCheck = 1.5*rMerger;
381 if (r < rCheck && omega < params->eobParams->omega)
382 {
383 if (debugOutput) printf("Peak detection %.16e %.16e\n", omega, params->eobParams->omega);
384 params->eobParams->omegaPeaked = counter + 1;
385 }
386 if ( omega >= params->eobParams->omegaMerger/2. ) {
387 if (debugOutput) printf("Stop at Tim's freq at r=%.16e\n", r);
388 return 1;
389 }
390 if ( r < rCheck && values[2] >= 0 ) {
391 if (debugOutput) printf("Stop at pr >= 0 at r=%.16e\n", r);
392 return 1;
393 }
394 if ( r < rCheck && dvalues[0] >= 0 ) {
395 if (debugOutput) printf("Stop at dr/dt >= 0 at r=%.16e\n", r);
396 return 1;
397 }
398 if ( r < rCheck && dvalues[2] >= 0 ) {
399 params->eobParams->omegaPeaked = counter + 1;
400 if (debugOutput) printf("Stop at dpr/dt >= 0 at r=%.16e\n", r);
401 // return 1;
402 }
403 if (r < rCheck && params->eobParams->omegaPeaked == 3 )
404 {
405 params->eobParams->omegaPeaked = 0;
406 if (debugOutput) printf("params->eobParams->omegaPeaked == 3 at r=%.16e\n", r);
407 return 1;
408 }
409 if ( isnan (dvalues[3]) || isnan (dvalues[2]) || isnan (dvalues[1]) || isnan (dvalues[0]) ) {
410 if (debugOutput) printf("Stop at nan's at r=%.16e\n", r);
411 return 1;
412 }
413 if ( fabs(r/params->eobParams->rad - 1.) < 1.e-3*64./5.*eta/(r*r*r*r)*0.02 && fabs(r/params->eobParams->rad - 1.) > 0.) {
414 if (debugOutput) printf("Radius is stalling at r=%.16e and rad=%.16e\n", r, params->eobParams->rad);
415 return 1;
416 }
417 params->eobParams->omega = omega;
418 params->eobParams->rad = r;
419 if( LAL_PI/params->deltaT <= 2.*omega ) {
420 params->eobParams->NyquistStop = 1;
421 if (debugOutput) printf("Stop at Nyquist at r=%.16e\n", r);
422 XLAL_PRINT_WARNING ("Waveform will be generated only up to half the sampling frequency, thus discarding any physical higher-frequency contect above that!\n");
423 return 1;
424 }
425 return GSL_SUCCESS;
426}
427
428static int
429XLALSpinAlignedHiSRStopConditionV4 (double UNUSED t, /**< UNUSED */
430 const double UNUSED values[],
431 /**< dynamical variable values */
432 double dvalues[], /**< dynamical variable time derivative values */
433 void UNUSED * funcParams /**< physical parameters */
434)
435{
436 REAL8 omega, r;
437 UINT4 counter;
438 SpinEOBParams *params = (SpinEOBParams *) funcParams;
439 r = values[0];
440 omega = dvalues[1];
441 counter = params->eobParams->omegaPeaked;
442 //printf("function 2: r = %.16e, omega = %.16e, pr = %.16e, dpr = %.16e, count = %.16u \n",values[0],dvalues[1],values[2],dvalues[2],counter);
443 if (r < 6. && omega < params->eobParams->omega)
444 {
445 // printf("Peak detection %.16e %.16e\n", omega, params->eobParams->omega);
446 params->eobParams->omegaPeaked = counter + 1;
447 }
448 if (dvalues[2] >= 0. || params->eobParams->omegaPeaked == 5
449 || isnan (dvalues[3]) || isnan (dvalues[2]) || isnan (dvalues[1])
450 || isnan (dvalues[0]))
451 {
452 // if ( dvalues[2] >= 0 ) printf("dvalues[2] >= 0\n");
453 // if ( params->eobParams->omegaPeaked == 5 ) printf("params->eobParams->omegaPeaked == 5\n");
454 // if ( isnan( dvalues[3] ) || isnan (dvalues[2]) || isnan (dvalues[1]) || isnan (dvalues[0]) ) printf("%.16e %.16e %.16e %.16e\n", dvalues[0], dvalues[1], dvalues[2], dvalues[3]);
455 return 1;
456 }
457 params->eobParams->omega = omega;
458 return GSL_SUCCESS;
459}
460
461/**
462 * @addtogroup LALSimIMRSpinAlignedEOB_c
463 *
464 * @author Craig Robinson, Yi Pan
465 *
466 * @brief Functions for producing SEOBNRv1 and v2 waveforms.
467 *
468 * Functions for producing SEOBNRv1 waveforms for
469 * spinning binaries, as described in
470 * Taracchini et al. ( PRD 86, 024011 (2012), arXiv 1202.0790 ).
471 * All equation numbers in this file refer to equations of this paper,
472 * unless otherwise specified.
473 *
474 * @review SEOBNRv1 has been reviewd by Riccardo Sturani, B. Sathyaprakash and Prayush Kumar.
475 * The review concluded in fall 2012.
476 *
477 * Functions for producing SEOBNRv2 waveforms for
478 * spinning binaries, as described in
479 * Taracchini et al. ( arXiv 1311.2544 ).
480 *
481 * @review SEOBNRv2 has been reviewed by Riccardo Sturani, Prayush Kumar and Stas Babak.
482 * The review concluded with git hash 5bc6bb861de2eb72ca403b9e0f529d83080490fe (August 2014).
483 *
484 * @{
485 */
486
487/**
488 * This function returns the frequency at which the peak amplitude occurs
489 * in SEOBNRv(x)
490 *
491 */
492double
494 /**< mass of companion 1 (kg) */
495 REAL8 m2SI,
496 /**< mass of companion 2 (kg) */
497 const REAL8 spin1z,
498 /**< z-component of the dimensionless spin of object 1 */
499 const REAL8 spin2z,
500 /**< z-component of the dimensionless spin of object 2 */
501 UINT4 SpinAlignedEOBversion
502 /**< 1 for SEOBNRv1, 2 for SEOBNRv2, 4 for SEOBNRv4 */
503 )
504{
505
506 /* The return variable, frequency in Hz */
507 double retFreq;
508
509 REAL8 nrOmega;
510
511 /* The mode to use; currently, only l=2, m=2 is supported */
512 INT4 ll = 2;
513 INT4 mm = 2;
514
515 /* Mass parameters (we'll work in units of solar mass) */
516 REAL8 m1 = m1SI / LAL_MSUN_SI;
517 REAL8 m2 = m2SI / LAL_MSUN_SI;
518 REAL8 Mtotal = m1 + m2;
519 REAL8 eta = m1 * m2 / (Mtotal * Mtotal);
520
521 /* We need spin vectors for the SigmaKerr function */
522 REAL8Vector *sigmaKerr = XLALCreateREAL8Vector (3);
523 int ii;
524 REAL8 aa;
525
526 REAL8Vector s1Vec, s2Vec;
527 s1Vec.length = s2Vec.length = 3;
528 REAL8 spin1[3] = { 0., 0., spin1z };
529 REAL8 spin2[3] = { 0., 0., spin2z };
530 s1Vec.data = spin1;
531 s2Vec.data = spin2;
532 /* the SigmaKerr function uses spins, not chis */
533 for (ii = 0; ii < 3; ii++)
534 {
535 s1Vec.data[ii] *= m1 * m1;
536 s2Vec.data[ii] *= m2 * m2;
537 }
538
539 /* Calculate the normalized spin of the deformed-Kerr background */
540 if (XLALSimIMRSpinEOBCalculateSigmaKerr (sigmaKerr, m1, m2, &s1Vec, &s2Vec)
541 == XLAL_FAILURE)
542 {
543 XLALDestroyREAL8Vector (sigmaKerr);
545 }
546
547 aa = sigmaKerr->data[2];
548
549 /* Now get the frequency at the peak amplitude */
550 switch (SpinAlignedEOBversion)
551 {
552 case 1:
553 nrOmega = XLALSimIMREOBGetNRSpinPeakOmega (ll, mm, eta, aa);
554 break;
555 case 2:
556 nrOmega = XLALSimIMREOBGetNRSpinPeakOmegav2 (ll, mm, eta, aa);
557 break;
558 case 4:
559 nrOmega = XLALSimIMREOBGetNRSpinPeakOmegaV4 (ll, mm, eta, aa/(1. - 2.*eta));
560 break;
561 case 5:
562 nrOmega = XLALSimIMREOBGetNRSpinPeakOmegaV5 (ll, mm, eta, aa/(1. - 2.*eta));
563 break;
564 default:
566 ("XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1, v2 and v4 are available.\n",
567 __func__);
569 break;
570 }
571
572 retFreq = nrOmega / (2 * LAL_PI * Mtotal * LAL_MTSUN_SI);
573
574 /* Free memory */
575 XLALDestroyREAL8Vector (sigmaKerr);
576
577 return retFreq;
578}
579
580
581
582int
584 REAL8TimeSeries ** hplus,
585 /**<< OUTPUT, +-polarization waveform */
586 REAL8TimeSeries ** hcross,
587 /**<< OUTPUT, x-polarization waveform */
588 const REAL8 phiC,
589 /**<< coalescence orbital phase (rad) */
591 /**<< sampling time step */
592 const REAL8 m1SI,
593 /**<< mass-1 in SI unit */
594 const REAL8 m2SI,
595 /**<< mass-2 in SI unit */
596 const REAL8 fMin,
597 /**<< starting frequency of the 22 mode (Hz) */
598 const REAL8 r,
599 /**<< distance in SI unit */
600 const REAL8 inc,
601 /**<< inclination angle */
602 const REAL8 spin1z,
603 /**<< z-component of spin-1, dimensionless */
604 const REAL8 spin2z,
605 /**<< z-component of spin-2, dimensionless */
606 UINT4 SpinAlignedEOBversion,
607 /**<< 1 for SEOBNRv1, 2 for SEOBNRv2, 4 for SEOBNRv4,
608 201 for SEOBNRv2T,401 for SEOBNRv4T, 41 for SEOBNRv4HM,
609 4111 for SEOBNRv4HM_PA, 4112 for pSEOBNRv4HM_PA */
610 LALDict *LALParams
611 /**<< Dictionary of additional wf parameters, including tidal and nonGR */
612)
613{
614 int ret;
615
616 REAL8 lambda2Tidal1 = 0;
617 REAL8 omega02Tidal1 = 0;
618 REAL8 lambda3Tidal1 = 0;
619 REAL8 omega03Tidal1 = 0;
620 REAL8 lambda2Tidal2 = 0;
621 REAL8 omega02Tidal2 = 0;
622 REAL8 lambda3Tidal2 = 0;
623 REAL8 omega03Tidal2 = 0;
624 REAL8 quadparam1 = 0;
625 REAL8 quadparam2 = 0;
626 REAL8 domega220 = 0;
627 REAL8 dtau220 = 0;
628 REAL8 domega210 = 0;
629 REAL8 dtau210 = 0;
630 REAL8 domega330 = 0;
631 REAL8 dtau330 = 0;
632 REAL8 domega440 = 0;
633 REAL8 dtau440 = 0;
634 REAL8 domega550 = 0;
635 REAL8 dtau550 = 0;
636 UINT2 TGRflag = 0;
637
648
649 if (SpinAlignedEOBversion == 4112) TGRflag = 1;
650
651 LALDict *TGRParams = XLALCreateDict();
652
663
664 XLALDictInsertUINT2Value(TGRParams, "TGRflag", TGRflag);
665
666 lambda2Tidal1 = XLALSimInspiralWaveformParamsLookupTidalLambda1(LALParams);
667 lambda2Tidal2 = XLALSimInspiralWaveformParamsLookupTidalLambda2(LALParams);
668 if ( (SpinAlignedEOBversion == 201 || SpinAlignedEOBversion == 401) && lambda2Tidal1 != 0. ) {
670 if ( omega02Tidal1 == 0. ) {
671 XLALPrintError ("XLAL Error - %s: Tidal parameters are not set correctly! Always provide non-zero f-mode frequency when lambda2 is non-zero!\n", __func__);
673 }
676 if ( lambda3Tidal1 != 0. && omega03Tidal1 == 0. ) {
677 XLALPrintError ("XLAL Error - %s: Tidal parameters are not set correctly! Always provide non-zero octupolar f-mode frequency when lambda3 is non-zero!\n", __func__);
679 }
680 }
681 if ( (SpinAlignedEOBversion == 201 || SpinAlignedEOBversion == 401) && lambda2Tidal2 != 0. ) {
683 if ( omega02Tidal2 == 0. ) {
684 XLALPrintError ("XLAL Error - %s: Tidal parameters are not set correctly! Always provide non-zero f-mode frequency when lambda2 is non-zero!\n", __func__);
686 }
689 if ( lambda3Tidal2 != 0. && omega03Tidal2 == 0. ) {
690 XLALPrintError ("XLAL Error - %s: Tidal parameters are not set correctly! Always provide non-zero octupolar f-mode frequency when lambda3 is non-zero!\n", __func__);
692 }
693 }
694 quadparam1 = 1. + XLALSimInspiralWaveformParamsLookupdQuadMon1(LALParams);
695 quadparam2 = 1. + XLALSimInspiralWaveformParamsLookupdQuadMon2(LALParams);
696
697 LALValue *ModeArray = XLALSimInspiralWaveformParamsLookupModeArray(LALParams);
698 /*ModeArray includes the modes chosen by the user
699 */
700 if (ModeArray == NULL) {
701 /*If the user doesn't choose the modes, use the standard modes
702 */
703 ModeArray = XLALSimInspiralCreateModeArray();
704 XLALSetup_EOB__std_mode_array_structure(ModeArray, SpinAlignedEOBversion);
705 }
706 /*Check that the modes chosen are available for the given model
707 */
708 if(XLALCheck_EOB_mode_array_structure(ModeArray, SpinAlignedEOBversion) == XLAL_FAILURE){
709 XLALPrintError ("Not available mode chosen.\n");
711 }
712
713
714
715 REAL8Vector *nqcCoeffsInput = XLALCreateREAL8Vector(10);
716 INT4 nqcFlag = 0;
717
718
719 if ( SpinAlignedEOBversion == 401 ) {
720 nqcFlag = 1;
721 REAL8 m1BH, m2BH;
722 m1BH = m1SI / (m1SI + m2SI) * 50. * LAL_MSUN_SI;
723 m2BH = m2SI / (m1SI + m2SI) * 50. * LAL_MSUN_SI;
724#if debugOutput
725 printf("First run SEOBNRv4 to compute NQCs\n");
726#endif
728 hplus, hcross,
729 phiC,
730 1./32768,
731 m1BH, m2BH,
732 2*pow(10.,-1.5)/(2.*LAL_PI)/((m1BH + m2BH)*LAL_MTSUN_SI/LAL_MSUN_SI),
733 r,
734 inc,
735 spin1z, spin2z,
736 400,
737 0, 0,
738 0, 0,
739 0, 0,
740 0, 0,
741 0, 0,
742 nqcCoeffsInput, nqcFlag,
743 ModeArray,
744 TGRParams
745 );
746 if (ret == XLAL_FAILURE){
747 if ( nqcCoeffsInput ) XLALDestroyREAL8Vector( nqcCoeffsInput );
748 if(ModeArray) XLALDestroyValue(ModeArray);
749 XLALDestroyDict(TGRParams);
751 }
752 nqcFlag = 2;
753 }
754#if debugOutput
755 printf("Generate EOB wf\n");
756#endif
757 {
758 //REAL8Vector *nqcCoeffsInput = XLALCreateREAL8Vector(10);
759 //INT4 nqcFlag = 0;
761 hplus, hcross,
762 phiC,
763 deltaT,
764 m1SI, m2SI,
765 fMin,
766 r,
767 inc,
768 spin1z, spin2z,
769 SpinAlignedEOBversion,
770 lambda2Tidal1, lambda2Tidal2,
771 omega02Tidal1, omega02Tidal2,
772 lambda3Tidal1, lambda3Tidal2,
773 omega03Tidal1, omega03Tidal2,
774 quadparam1, quadparam2,
775 nqcCoeffsInput, nqcFlag,
776 ModeArray,
777 TGRParams
778 );
779 if (ret == XLAL_FAILURE){
780 if ( nqcCoeffsInput ) XLALDestroyREAL8Vector( nqcCoeffsInput );
781 if (ModeArray) XLALDestroyValue(ModeArray);
782 XLALDestroyDict(TGRParams);
784 }
785 if(ModeArray) XLALDestroyValue(ModeArray);
786
787 if ( nqcCoeffsInput )
788 XLALDestroyREAL8Vector( nqcCoeffsInput );
789
790 XLALDestroyDict(TGRParams);
791 }
792 return ret;
793}
794
795/**
796 * This function generates spin-aligned SEOBNRv1,2,2opt,4,4opt,2T,4T,4HM complex modes hlm.
797 * Currently, only the h22 harmonic is available for all the models with the exception of SEOBNRv4HM
798 * which contains also the modes hlm = ((2,1),(3,3),(4,4),(5,5)) besides the (2,2). For this model
799 * all available harmonics are generated, one cannot choose which harmonic to generate.
800 * STEP 0) Prepare parameters, including pre-computed coefficients
801 * for EOB Hamiltonian, flux and waveform
802 * STEP 1) Solve for initial conditions
803 * STEP 2) Evolve EOB trajectory until reaching the peak of orbital frequency
804 * STEP 3) Step back in time by tStepBack and volve EOB trajectory again
805 * using high sampling rate, stop at 0.3M out of the "EOB horizon".
806 * STEP 4) Locate the peak of orbital frequency for NQC and QNM calculations
807 * STEP 5) Calculate NQC correction using hi-sampling data
808 * STEP 6) Calculate QNM excitation coefficients using hi-sampling data
809 * STEP 7) Generate full inspiral mode using desired sampling frequency
810 * STEP 8) Generate full IMR modes -- attaching ringdown to inspiral
811 * STEP 9) Generate full IMR modes
812 * Note that sanity checks on merger for SEOBNRv4 have revealed that for
813 * eta<=0.15 and chi1>0.95 about 0.04% of the waveforms display either
814 * very shallow double amplitude peak or slightly negave time-derivative of
815 * the GW freq at merger.
816 * Note that SEOBNRv2T and SEOBNRv4T can display similar features. The model was
817 * validated on the range q=[1,3], Sz=[-0.5,0.5], Lambda2=[0,5000]. Waveforms
818 * will not fail on Sz=[-0.7,0.7], but with possibly stronger unwanted features.
819 * The initial conditions solver can also fail for low starting frequencies,
820 * with a failure rate of ~0.3% at fmin=10Hz for M=3Msol.
821 */
822int
824 SphHarmTimeSeries ** hlmmode,
825 /**<< OUTPUT, mode hlm */
826 //SM
827 REAL8Vector ** dynamics_out, /**<< OUTPUT, low-sampling dynamics */
828 REAL8Vector ** dynamicsHi_out, /**<< OUTPUT, high-sampling dynamics */
829 //SM
831 /**<< sampling time step */
832 const REAL8 m1SI,
833 /**<< mass-1 in SI unit */
834 const REAL8 m2SI,
835 /**<< mass-2 in SI unit */
836 const REAL8 fMin,
837 /**<< starting frequency of the 22 mode (Hz) */
838 const REAL8 r,
839 /**<< distance in SI unit */
840 const REAL8 spin1z,
841 /**<< z-component of spin-1, dimensionless */
842 const REAL8 spin2z,
843 /**<< z-component of spin-2, dimensionless */
844 UINT4 SpinAlignedEOBversion,
845 /**<< 1 for SEOBNRv1, 2 for SEOBNRv2, 4 for SEOBNRv4,
846 201 for SEOBNRv2T, 401 for SEOBNRv4T, 41 for SEOBNRv4HM,
847 4111 for SEOBNRv4HM_PA, 4112 for pSEOBNRv4HM_PA */
848 const REAL8 lambda2Tidal1,
849 /**<< dimensionless adiabatic quadrupole tidal deformability for body 1 (2/3 k2/C^5) */
850 const REAL8 lambda2Tidal2,
851 /**<< dimensionless adiabatic quadrupole tidal deformability for body 2 (2/3 k2/C^5) */
852 const REAL8 omega02Tidal1,
853 /**<< quadrupole f-mode angular freq for body 1 m_1*omega_{02,1}*/
854 const REAL8 omega02Tidal2,
855 /**<< quadrupole f-mode angular freq for body 2 m_2*omega_{02,2}*/
856 const REAL8 lambda3Tidal1,
857 /**<< dimensionless adiabatic octupole tidal deformability for body 1 (2/15 k3/C^7) */
858 const REAL8 lambda3Tidal2,
859 /**<< dimensionless adiabatic octupole tidal deformability for body 2 (2/15 k3/C^7) */
860 const REAL8 omega03Tidal1,
861 /**<< octupole f-mode angular freq for body 1 m_1*omega_{03,1}*/
862 const REAL8 omega03Tidal2,
863 /**<< octupole f-mode angular freq for body 2 m_2*omega_{03,2}*/
864 const REAL8 quadparam1,
865 /**<< parameter kappa_1 of the spin-induced quadrupole for body 1, quadrupole is Q_A = -kappa_A m_A^3 chi_A^2 */
866 const REAL8 quadparam2,
867 /**<< parameter kappa_2 of the spin-induced quadrupole for body 2, quadrupole is Q_A = -kappa_A m_A^3 chi_A^2 */
868 REAL8Vector *nqcCoeffsInput,
869 /**<< Input NQC coeffs */
870 const INT4 nqcFlag,
871 /**<< Flag to tell the code to use the NQC coeffs input thorugh nqcCoeffsInput */
872 LALDict *PAParams,
873 /**<< Dictionary containing parameters for the post-adiabatic routine */
874 LALDict *TGRParams
875 /**<< Dictionary containing parameters for tests of General Relativity */
876)
877{
878 UNUSED REAL8 STEP_SIZE = STEP_SIZE_CALCOMEGA;
879 INT4 use_tidal = 0;
880 if ( (lambda3Tidal1 != 0. && lambda2Tidal1 == 0.) || (lambda3Tidal2 != 0. && lambda2Tidal2 == 0.) ) {
881 XLALPrintError ("XLAL Error - %s: Tidal parameters are not set correctly! You must have a non-zero lambda2 if you provide a non-zero lambda3!\n",
882 __func__);
884 }
885 if ( SpinAlignedEOBversion==201 || SpinAlignedEOBversion==401 )
886 {
887 if ( (lambda2Tidal1 != 0. && omega02Tidal1 == 0.)
888 || (lambda2Tidal2 != 0. && omega02Tidal2 == 0.) ) {
889 XLALPrintError ("XLAL Error - %s: Tidal parameters are not set correctly! Always provide non-zero compactness and f-mode frequency when lambda2 is non-zero!\n",
890 __func__);
892 }
893 if ( (lambda3Tidal1 != 0. && omega03Tidal1 == 0.)
894 || (lambda3Tidal2 != 0. && omega03Tidal2 == 0.) ) {
895 XLALPrintError ("XLAL Error - %s: Tidal parameters are not set correctly! Always provide non-zero compactness and f-mode frequency when lambda3 is non-zero!\n",
896 __func__);
898 }
899 if (fmax(m1SI/m2SI, m2SI/m1SI)>3.) {
900 XLALPrintWarning("XLAL Warning - %s: Generating waveform with mass ratio outside the recommended range q=[1,3].\n", __func__);
901 }
902 if (fabs(spin1z)>0.5 || fabs(spin2z)>0.5) {
903 XLALPrintWarning("XLAL Warning - %s: Generating waveform with at least one aligned spin component outside the recommended range chi=[-0.5,0.5].\n", __func__);
904 }
905 if (lambda2Tidal1>5000. || lambda2Tidal2>5000.) {
906 XLALPrintWarning("XLAL Warning - %s: Generating waveform with at least one quadrupole tidal deformability outside the recommended range Lambda2=[0,5000].\n", __func__);
907 }
908 if ((m1SI+m2SI)/LAL_MSUN_SI*LAL_MTSUN_SI*fMin<1.477e-4) {
909 XLALPrintWarning("XLAL Warning - %s: Generating waveform with a low starting frequency. Initial conditions solver can fail when pushing the model to lower frequencies, with a rate of failure ~0.3%% at Mf~1.5e-4 (10Hz for M=3Msol).\n", __func__);
910 }
911 use_tidal = 1;
912 if ( SpinAlignedEOBversion==201 )
913 SpinAlignedEOBversion=2;
914 if ( SpinAlignedEOBversion==401 )
915 SpinAlignedEOBversion=4;
916 }
917 INT4 use_optimized_v2_or_v4 = 0;
918 /* If we want SEOBNRv2_opt, then reset SpinAlignedEOBversion=2 and set use_optimized_v2_or_v4=1 */
919 if (SpinAlignedEOBversion == 200)
920 {
921 SpinAlignedEOBversion = 2;
922 use_optimized_v2_or_v4 = 1;
923 }
924 /* If we want SEOBNRv4_opt, then reset SpinAlignedEOBversion=4 and set use_optimized_v4=1 */
925 if (SpinAlignedEOBversion == 400)
926 {
927 SpinAlignedEOBversion = 4;
928 use_optimized_v2_or_v4 = 1;
929 }
930
931 INT4 use_hm = 0;
932 /* The list of available modes */
933// const UINT4 lmModes[5][2] = {{2, 2}, {2, 1}, {3, 3}, {4, 4}, {5, 5}};
934 const UINT4 lmModes[5][2] = {{2, 2}, {3, 3}, {2, 1}, {4, 4},{5, 5}};
935 REAL8Vector *hLMAllHi = NULL;
936 REAL8Vector *hLMAll = NULL;
937 UINT4 nModes = 1;
938 UINT4 postAdiabaticFlag = 0;
939 UINT2 TGRflag = 0;
940
941 if (SpinAlignedEOBversion == 4111 || SpinAlignedEOBversion == 4112) {
942 postAdiabaticFlag = 1;
943 XLALDictInsertUINT4Value(PAParams, "PAFlag", postAdiabaticFlag);
944 XLALDictInsertUINT4Value(PAParams, "PAOrder", 8);
945
946 XLALDictInsertREAL8Value(PAParams, "rFinal", 1.8);
947 XLALDictInsertREAL8Value(PAParams, "rSwitch", 1.8);
948 XLALDictInsertUINT2Value(PAParams, "analyticFlag", 1);
949 }
950
951 if (SpinAlignedEOBversion == 4112) {
952 TGRflag = 1;
953 }
954
955 /* If we want SEOBNRv4HM, then reset SpinAlignedEOBversion=4 and set use_hm=1 */
956 if (SpinAlignedEOBversion == 41 || SpinAlignedEOBversion == 4111 || SpinAlignedEOBversion == 4112) {
957 SpinAlignedEOBversion = 4;
958 use_hm = 1;
959 nModes = 5;
960 }
961
962 /* If the EOB version flag is neither 1, 2, nor 4, exit */
963 if (SpinAlignedEOBversion != 1 && SpinAlignedEOBversion != 2
964 && SpinAlignedEOBversion != 4)
965 {
967 ("XLAL Error - %s: SEOBNR version flag incorrectly set to %u\n",
968 __func__, SpinAlignedEOBversion);
970 }
971
972 Approximant SpinAlignedEOBapproximant;
973 switch (SpinAlignedEOBversion)
974 {
975 case 1:
976 SpinAlignedEOBapproximant = SEOBNRv1;
977 break;
978 case 2:
979 SpinAlignedEOBapproximant = SEOBNRv2;
980 break;
981 case 4:
982 SpinAlignedEOBapproximant = SEOBNRv4;
983 break;
984 default:
986 ("XLAL Error - %s: SEOBNR version flag incorrectly set to %u\n",
987 __func__, SpinAlignedEOBversion);
989 break;
990 }
991
992 /*
993 * Check spins
994 */
995 if (spin1z < -1.0 || spin2z < -1.0)
996 {
997 XLALPrintError ("XLAL Error - %s: Component spin less than -1!\n",
998 __func__);
1000 }
1001 if (spin1z > 1.0 || spin2z > 1.0)
1002 {
1003 XLALPrintError ("XLAL Error - %s: Component spin bigger than 1!\n",
1004 __func__);
1006 }
1007 /* If either spin > 0.6, model not available, exit */
1008 if (SpinAlignedEOBversion == 1 && (spin1z > 0.6 || spin2z > 0.6))
1009 {
1011 ("XLAL Error - %s: Component spin larger than 0.6!\nSEOBNRv1 is only available for spins in the range -1 < a/M < 0.6.\n",
1012 __func__);
1014 }
1015 /* For v2 the upper bound is 0.99 */
1016 if ((SpinAlignedEOBversion == 2) && (spin1z > 0.99 || spin2z > 0.99))
1017 {
1019 ("XLAL Error - %s: Component spin larger than 0.99!\nSEOBNRv2 and SEOBNRv2_opt are only available for spins in the range -1 < a/M < 0.99.\n",
1020 __func__);
1022 }
1023 //R.C: region where SEOBNRv4HM can be generated, see the test on the review page
1024 //here https://git.ligo.org/waveforms/reviews/SEOBNRv4HM/wikis/visual-inspection#check-if-there-are-cases-for-which-the-maximum-amplitude-of-the-22-mode-is-smaller-than-the-one-of-any-of-the-higher-order-modes
1025 if(use_hm){
1026 if(m1SI>m2SI){
1027 if((m1SI/m2SI > 57.) && (spin1z> 0.96)){
1029 ("XLAL Error - %s: Component spin of the more massive BH larger than 0.96 for mass ratio bigger than 57.!\nSEOBNRv4HM \
1030 for mass ratio bigger than 57 is only available when the spin on the more massive BH in the range -1 < a/M < 0.96.\n",__func__);
1032 }
1033 }
1034 if(m2SI>m1SI){
1035 if((m2SI/m1SI > 57.) && (spin2z> 0.96)){
1037 ("XLAL Error - %s: Component spin of the more massive BH larger than 0.96 for mass ratio bigger than 57.!\nSEOBNRv4HM \
1038 for mass ratio bigger than 57 is only available when the spin on the more massive BH in the range -1 < a/M < 0.96.\n",__func__);
1040 }
1041 }
1042 }
1043
1044 INT4 i;
1045
1046 REAL8Vector *values = NULL;
1047
1048 /* EOB spin vectors used in the Hamiltonian */
1049 REAL8Vector *sigmaStar = NULL;
1050 REAL8Vector *sigmaKerr = NULL;
1051 REAL8 a, tplspin;
1052 REAL8 chiS, chiA;
1053
1054 /* Wrapper spin vectors used to calculate sigmas */
1055 REAL8Vector s1Vec, s1VecOverMtMt;
1056 REAL8Vector s2Vec, s2VecOverMtMt;
1057 REAL8 spin1[3] = { 0, 0, spin1z };
1058 REAL8 spin2[3] = { 0, 0, spin2z };
1059 REAL8 s1Data[3], s2Data[3], s1DataNorm[3], s2DataNorm[3];
1060
1061 /* Parameters of the system */
1062 REAL8 m1, m2, mTotal, eta, mTScaled;
1063 REAL8 amp0;
1065 /* Dynamics of the system */
1066 REAL8Vector rVec, phiVec, prVec, pPhiVec,tVec;
1067 /* OPTIMIZED */
1068 REAL8Vector ampVec, phaseVec;
1069 ampVec.data = NULL;
1070 phaseVec.data = NULL;
1071 /* END OPTIMIZED */
1072
1073 REAL8 omega, v;
1074 REAL8Vector *hamVHi;
1075 REAL8Vector *hamV = NULL;
1076 REAL8Vector *omegaVec = NULL;
1077 REAL8Vector *vPhiVec = NULL; //PA
1078 /* SEOBNRv4HM modes */
1079 INT4 modeL, modeM;
1080
1081 /* Cartesian vectors needed to calculate Hamiltonian */
1082 REAL8Vector cartPosVec, cartMomVec;
1083 REAL8 cartPosData[3], cartMomData[3];
1084
1085 /* Signal mode */
1086 COMPLEX16 hLM, hT;
1087 REAL8Vector *sigReVec = NULL, *sigImVec = NULL;
1088
1089 /* Non-quasicircular correction */
1090 EOBNonQCCoeffs nqcCoeffs;
1091 COMPLEX16 hNQC;
1092 REAL8Vector *ampNQC = NULL, *phaseNQC = NULL;
1093
1094 /* Ringdown freq used to check the sample rate */
1095 COMPLEX16Vector modefreqVec;
1096 COMPLEX16 modeFreq;
1097
1098 /* We will have to switch to a high sample rate for ringdown attachment */
1099 REAL8 deltaTHigh;
1100 UINT4 resampFac;
1101 UINT4 resampPwr;
1102 REAL8 resampEstimate;
1103
1104 /* How far will we have to step back to attach the ringdown? */
1105 REAL8 tStepBack;
1106 INT4 nStepBack;
1107
1108 /* Dynamics and details of the high sample rate part used to attach the ringdown */
1109 UINT4 hiSRndx;
1110 REAL8Vector timeHi, rHi, phiHi, prHi, pPhiHi;
1111 REAL8Vector *sigReHi = NULL, *sigImHi = NULL;
1112 REAL8Vector *omegaHi = NULL;
1113 REAL8Vector *vPhiVecHi = NULL;
1114 /* Indices of peak frequency and final point */
1115 /* Needed to attach ringdown at the appropriate point */
1116 UINT4 peakIdx = 0, finalIdx = 0;
1117
1118 /* Variables for the integrator */
1119 LALAdaptiveRungeKuttaIntegrator *integrator = NULL;
1120 REAL8Array *dynamics = NULL;
1121 REAL8Array *dynamicsHi = NULL;
1122
1123 REAL8Array *dynamicstmp = NULL; // DAVIDS: MOVING THIS OUTSIDE IF-BLOCK FOR NOW
1124 REAL8Array *dynamicsHitmp = NULL; // DAVIDS: MOVING THE VARIABLE DECLARATION OUTSIDE THE IF-BLOCK FOR NOW
1125 INT4 retLen_fromOptStep2 = 0; // DAVIDS: ONLY SETTING TO ZERO TO SUPRESS COMPILER WARNING
1126 INT4 retLen_fromOptStep3 = 0; // DAVIDS: ^ DITTO
1127
1128 INT4 retLen;
1129 REAL8 UNUSED tMax;
1130
1131 /* Accuracies of adaptive Runge-Kutta integrator */
1132 const REAL8 EPS_ABS = 1.0e-10;
1133 const REAL8 EPS_REL = 1.0e-9; // Davids: changed exponent from -9 to -10
1134
1135 /*
1136 * STEP 0) Prepare parameters, including pre-computed coefficients
1137 * for EOB Hamiltonian, flux and waveform
1138 */
1139
1140 /* Parameter structures containing important parameters for the model */
1141 SpinEOBParams seobParams;
1142 SpinEOBHCoeffs seobCoeffs;
1143 EOBParams eobParams;
1144 FacWaveformCoeffs hCoeffs;
1145 NewtonMultipolePrefixes prefixes;
1146 TidalEOBParams tidal1, tidal2;
1147
1148 /* fStart is the start frequency of the 22 mode generation */
1149 REAL8 fStart;
1150
1151 /* Initialize parameters */
1152 m1 = m1SI / LAL_MSUN_SI;
1153 m2 = m2SI / LAL_MSUN_SI;
1154 mTotal = m1 + m2;
1155 mTScaled = mTotal * LAL_MTSUN_SI;
1156 eta = m1 * m2 / (mTotal * mTotal);
1157
1158 /* For v2 the upper bound is mass ratio 100 */
1159 if ((SpinAlignedEOBversion == 2 || SpinAlignedEOBversion == 4)
1160 && eta < 100. / 101. / 101.)
1161 {
1163 ("XLAL Error - %s: Mass ratio larger than 100!\nSEOBNRv2, SEOBNRv2_opt, SEOBNRv4, and SEOBNRv4_opt are only available for mass ratios up to 100.\n",
1164 __func__);
1166 }
1167
1168 amp0 = mTotal * LAL_MRSUN_SI / r;
1169
1170 #if debugOutput
1171 printf("Amp = %.16e\n", amp0);
1172 #endif
1173
1174 fStart = fMin;
1175
1176 /* If fMin is too high, then for safety in the initial conditions we integrate nonetheless from r=10M */
1177 if (pow (10., -3. / 2.)/(LAL_PI * mTScaled) < fMin) {
1178 fStart = pow (10., -3. / 2.)/(LAL_PI * mTScaled);
1179 //FP XLAL_PRINT_WARNING ("Waveform will be generated from %f and stored from %f.",fStart,fMin);
1180 }
1181
1182 /*
1183 if (pow (LAL_PI * fMin * mTScaled, -2. / 3.) < 10.0)
1184 {
1185 XLAL_PRINT_WARNING
1186 ("Waveform generation may fail due to high starting frequency. The starting frequency corresponds to a small initial radius of %.2fM. We recommend a lower starting frequency that corresponds to an estimated starting radius > 10M.",
1187 pow (LAL_PI * fMin * mTScaled, -2.0 / 3.0));
1188 }
1189 */
1190
1191 /* TODO: Insert potentially necessary checks on the arguments */
1192
1193 /* Calculate the time we will need to step back for ringdown */
1194 tStepBack = 100. * mTScaled;
1195 if (SpinAlignedEOBversion == 4)
1196 {
1197 tStepBack = 150. * mTScaled;
1198 }
1199 //nStepBack = ceil (tStepBack / deltaT);
1200
1201 // printf("odeStep = %e, 5*deltaT/mTscaled=%e, nStepBack = %d\n",odeStep,5*deltaT/mTScaled,nStepBack);
1202
1203 /* Calculate the resample factor for attaching the ringdown */
1204 /* We want it to be a power of 2 */
1205 /* If deltaT > Mtot/50, reduce deltaT by the smallest power of two for which deltaT < Mtot/50 */
1206 resampEstimate = 50. * deltaT / mTScaled;
1207 resampFac = 1;
1208 //resampFac = 1 << (UINT4)ceil(log2(resampEstimate));
1209
1210 if (resampEstimate > 1.)
1211 {
1212 resampPwr = (UINT4) ceil (log2 (resampEstimate));
1213 while (resampPwr--)
1214 {
1215 resampFac *= 2u;
1216 }
1217 }
1218
1219
1220 /* Allocate the values vector to contain the initial conditions */
1221 /* Since we have aligned spins, we can use the 4-d vector as in the non-spin case */
1222 UINT4 num_elements_in_values_vector = 4;
1223 if (use_optimized_v2_or_v4)
1224 /* In v2opt/v4opt, we add an additional two elements to this vector, to store amplitude & phase.
1225 After ODE solves EOMs (which involves 4 coupled ODEs & thus 4 solution vectors),
1226 amp & phase are computed explicitly from sparse EOM solution, then interpolated in v2opt/v4opt. */
1227 num_elements_in_values_vector = 6;
1228 if (!(values = XLALCreateREAL8Vector (num_elements_in_values_vector)))
1229 {
1231 }
1232 memset (values->data, 0, values->length * sizeof (REAL8));
1233
1234 /* Set up structures and calculate necessary PN parameters */
1235 /* Unlike the general case, we only need to calculate these once */
1236 memset (&seobParams, 0, sizeof (seobParams));
1237 memset (&seobCoeffs, 0, sizeof (seobCoeffs));
1238 memset (&eobParams, 0, sizeof (eobParams));
1239 memset (&hCoeffs, 0, sizeof (hCoeffs));
1240 memset (&prefixes, 0, sizeof (prefixes));
1241
1242 /* Before calculating everything else, check sample freq is high enough */
1243 modefreqVec.length = 1;
1244 modefreqVec.data = &modeFreq;
1245
1246 UINT4 mode_highest_freqL = 2;
1247 UINT4 mode_highest_freqM = 2;
1248
1249 if (use_hm) {
1250 //RC: if we are using SEOBNRv4HM, the check for the Nyquist frequency
1251 //should be done for the 55 mode, the frequency of the RD scales with l
1252 mode_highest_freqL = 5;
1253 mode_highest_freqM = 5;
1254 }
1255
1257 (&modefreqVec, m1, m2, spin1, spin2, mode_highest_freqL, mode_highest_freqM, 1,
1258 SpinAlignedEOBapproximant) == XLAL_FAILURE)
1259 {
1260 XLALDestroyREAL8Vector (values);
1262 }
1263
1264 /* Check if fMin exceeds 95% the ringdown frequency; if so, don't generate a wf */
1265 REAL8 fRD = 0.95*creal (modeFreq)/(2.*LAL_PI);
1266// UNUSED REAL8 fMerger = GetNRSpinPeakOmegaV4 (2, 2, eta, 0.5*(spin1z + spin2z) + 0.5*(spin1z - spin2z)*(m1 - m2)/(m1 + m2)/(1. - 2.*eta))/(2.*LAL_PI*mTScaled);
1267// printf("fMin %.16e\n", fMin);
1268// printf("fStart %.16e\n", fStart);
1269// printf("fMerger %.16e\n", fMerger);
1270// printf("fRD %.16e\n", fRD);
1271 if ( fMin > fRD ) {
1273 ("XLAL Error - Starting frequency is above ringdown frequency!\n");
1274 XLALDestroyREAL8Vector (values);
1276 }
1277
1278 /* If Nyquist freq < 220 QNM freq for SEOBNRv1/2/4 and freq < 550 QNM for SEOBNRv4HM, exit */
1279 if (use_tidal == 0 && deltaT > LAL_PI / creal (modeFreq))
1280 {
1282 ("XLAL Error - %s: Ringdown frequency > Nyquist frequency!\nAt present this situation is not supported.\n",
1283 __func__);
1284 XLALDestroyREAL8Vector (values);
1286 }
1287
1288 if (!(sigmaStar = XLALCreateREAL8Vector (3)))
1289 {
1290 XLALDestroyREAL8Vector (values);
1292 }
1293
1294 if (!(sigmaKerr = XLALCreateREAL8Vector (3)))
1295 {
1296 XLALDestroyREAL8Vector (sigmaStar);
1297 XLALDestroyREAL8Vector (values);
1299 }
1300
1301// Rescale tidal polarizabilites by powers of mNS/M
1302// Rescale f-mode freqs by M/mNS
1303// No rescaling needed for spin-induced quadrupole parameters
1304 tidal1.mByM = m1SI / (m1SI + m2SI);
1305 tidal1.lambda2Tidal = lambda2Tidal1 * pow(tidal1.mByM,5);
1306 tidal1.omega02Tidal = omega02Tidal1 / tidal1.mByM;
1307 tidal1.lambda3Tidal = lambda3Tidal1 * pow(tidal1.mByM,7);
1308 tidal1.omega03Tidal = omega03Tidal1 / tidal1.mByM;
1309 tidal1.quadparam = quadparam1;
1310
1311 tidal2.mByM = m2SI / (m1SI + m2SI);
1312 tidal2.lambda2Tidal = lambda2Tidal2 * pow(tidal2.mByM,5);
1313 tidal2.omega02Tidal = omega02Tidal2 / tidal2.mByM;
1314 tidal2.lambda3Tidal = lambda3Tidal2 * pow(tidal2.mByM,7);
1315 tidal2.omega03Tidal = omega03Tidal2 / tidal2.mByM;
1316 tidal2.quadparam = quadparam2;
1317
1318 seobCoeffs.tidal1 = &tidal1;
1319 seobCoeffs.tidal2 = &tidal2;
1320
1321 hCoeffs.tidal1 = &tidal1;
1322 hCoeffs.tidal2 = &tidal2;
1323
1324 seobParams.deltaT = deltaT /( (m1 + m2) * LAL_MTSUN_SI );
1325 seobParams.alignedSpins = 1;
1326 seobParams.tortoise = 1;
1327 seobParams.sigmaStar = sigmaStar;
1328 seobParams.sigmaKerr = sigmaKerr;
1329 seobParams.seobCoeffs = &seobCoeffs;
1330 seobParams.eobParams = &eobParams;
1331 seobParams.nqcCoeffs = &nqcCoeffs;
1332 seobParams.use_hm = use_hm;
1333 eobParams.hCoeffs = &hCoeffs;
1334 eobParams.prefixes = &prefixes;
1335 seobParams.postAdiabaticFlag = postAdiabaticFlag;
1336 eobParams.m1 = m1;
1337 eobParams.m2 = m2;
1338 eobParams.eta = eta;
1339
1340 s1Vec.length = s2Vec.length = 3;
1341 s1VecOverMtMt.length = s2VecOverMtMt.length = 3;
1342 s1Vec.data = s1Data;
1343 s2Vec.data = s2Data;
1344 s1VecOverMtMt.data = s1DataNorm;
1345 s2VecOverMtMt.data = s2DataNorm;
1346
1347 if ( use_tidal == 1 ) {
1348 REAL8 omegaMerger = XLALSimNSNSMergerFreq( &tidal1, &tidal2 );
1349 REAL8 rMerger = pow ( omegaMerger/2., -2./3. );
1350 if ( pow( fStart*LAL_PI*mTScaled, -2./3. ) <= 2.*rMerger ) {
1352 ("XLAL Error - %s: fmin is too high for a tidal run, it should be at most %.16e Hz\n", __func__, pow (2.*rMerger, -3. / 2.)/(LAL_PI * mTScaled));
1354 }
1355 }
1356
1357 /* copy the spins into the appropriate vectors, and scale them by the mass */
1358 memcpy (s1Data, spin1, sizeof (s1Data));
1359 memcpy (s2Data, spin2, sizeof (s2Data));
1360 memcpy (s1DataNorm, spin1, sizeof (s1DataNorm));
1361 memcpy (s2DataNorm, spin2, sizeof (s2DataNorm));
1362
1363 /* Calculate chiS and chiA */
1364
1365 chiS = 0.5 * (spin1[2] + spin2[2]);
1366 chiA = 0.5 * (spin1[2] - spin2[2]);
1367
1368 for (i = 0; i < 3; i++)
1369 {
1370 s1Data[i] *= m1 * m1;
1371 s2Data[i] *= m2 * m2;
1372 }
1373 for (i = 0; i < 3; i++)
1374 {
1375 s1DataNorm[i] = s1Data[i] / mTotal / mTotal;
1376 s2DataNorm[i] = s2Data[i] / mTotal / mTotal;
1377 }
1378 seobParams.s1Vec = &s1VecOverMtMt;
1379 seobParams.s2Vec = &s2VecOverMtMt;
1380
1381 cartPosVec.length = cartMomVec.length = 3;
1382 cartPosVec.data = cartPosData;
1383 cartMomVec.data = cartMomData;
1384 memset (cartPosData, 0, sizeof (cartPosData));
1385 memset (cartMomData, 0, sizeof (cartMomData));
1386
1387 /* Populate the initial structures */
1388 if (XLALSimIMRSpinEOBCalculateSigmaStar (sigmaStar, m1, m2, &s1Vec, &s2Vec)
1389 == XLAL_FAILURE)
1390 {
1391 XLALDestroyREAL8Vector (sigmaKerr);
1392 XLALDestroyREAL8Vector (sigmaStar);
1393 XLALDestroyREAL8Vector (values);
1395 }
1396
1397 if (XLALSimIMRSpinEOBCalculateSigmaKerr (sigmaKerr, m1, m2, &s1Vec, &s2Vec)
1398 == XLAL_FAILURE)
1399 {
1400 XLALDestroyREAL8Vector (sigmaKerr);
1401 XLALDestroyREAL8Vector (sigmaStar);
1402 XLALDestroyREAL8Vector (values);
1404 }
1405
1406 /* Calculate the value of a */
1407 /* XXX I am assuming that, since spins are aligned, it is okay to just use the z component XXX */
1408 /* TODO: Check this is actually the way it works in LAL */
1409 switch (SpinAlignedEOBversion)
1410 {
1411 case 1:
1412 tplspin = 0.0;
1413 break;
1414 case 2:
1415 tplspin = (1. - 2. * eta) * chiS + (m1 - m2) / (m1 + m2) * chiA;
1416 break;
1417 case 4:
1418 tplspin = (1. - 2. * eta) * chiS + (m1 - m2) / (m1 + m2) * chiA;
1419 break;
1420 default:
1422 ("XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1, v2, and v4 are available.\n",
1423 __func__);
1424 if(sigmaKerr){
1425 XLALDestroyREAL8Vector (sigmaKerr);
1426 }
1427 if(sigmaStar){
1428 XLALDestroyREAL8Vector (sigmaStar);
1429 }
1430 if(values){
1431 XLALDestroyREAL8Vector (values);
1432 }
1434 break;
1435 }
1436 /*for ( i = 0; i < 3; i++ )
1437 {
1438 a += sigmaKerr->data[i]*sigmaKerr->data[i];
1439 }
1440 a = sqrt( a ); */
1441 seobParams.a = a = sigmaKerr->data[2];
1442 seobParams.chi1 = spin1[2];
1443 seobParams.chi2 = spin2[2];
1444
1445 /* Now compute the spinning H coefficients and store them in seobCoeffs */
1447 (&seobCoeffs, eta, a, SpinAlignedEOBversion) == XLAL_FAILURE)
1448 {
1449 XLALDestroyREAL8Vector (sigmaKerr);
1450 XLALDestroyREAL8Vector (sigmaStar);
1451 XLALDestroyREAL8Vector (values);
1453 }
1454 //RC: SEOBNRv4HM uses the same dynamics of SEOBNRv4, we momentarily put use_hm = 0 such that it uses the SEOBNRv4 coefficients to compute the flux LALSimIMRSpinEOBFactorizedFlux
1455 if(use_hm == 1){
1456 seobParams.use_hm = 0;
1457 }
1459 (&hCoeffs, &seobParams, m1, m2, eta, tplspin, chiS, chiA,
1460 SpinAlignedEOBversion) == XLAL_FAILURE)
1461 {
1462 XLALDestroyREAL8Vector (sigmaKerr);
1463 XLALDestroyREAL8Vector (sigmaStar);
1464 XLALDestroyREAL8Vector (values);
1466 }
1467 if(use_hm == 1){
1468 seobParams.use_hm = 1;
1469 }
1470
1472 (&prefixes, eobParams.m1, eobParams.m2) == XLAL_FAILURE)
1473 {
1474 XLALDestroyREAL8Vector (sigmaKerr);
1475 XLALDestroyREAL8Vector (sigmaStar);
1476 XLALDestroyREAL8Vector (values);
1478 }
1479
1480 switch (SpinAlignedEOBversion)
1481 {
1482 case 1:
1483 if (XLALSimIMRGetEOBCalibratedSpinNQC (&nqcCoeffs, 2, 2, eta, a) ==
1485 {
1486 if(sigmaKerr){
1487 XLALDestroyREAL8Vector (sigmaKerr);
1488 }
1489 if(sigmaStar){
1490 XLALDestroyREAL8Vector (sigmaStar);
1491 }
1492 if(values){
1493 XLALDestroyREAL8Vector (values);
1494 }
1496 }
1497 break;
1498 case 2:
1500 (&nqcCoeffs, 2, 2, m1, m2, a, chiA) == XLAL_FAILURE)
1501 {
1502 if(sigmaKerr){
1503 XLALDestroyREAL8Vector (sigmaKerr);
1504 }
1505 if(sigmaStar){
1506 XLALDestroyREAL8Vector (sigmaStar);
1507 }
1508 if(values){
1509 XLALDestroyREAL8Vector (values);
1510 }
1512 }
1513 break;
1514 case 4:
1515 nqcCoeffs.a1 = 0.;
1516 nqcCoeffs.a2 = 0.;
1517 nqcCoeffs.a3 = 0.;
1518 nqcCoeffs.a3S = 0.;
1519 nqcCoeffs.a4 = 0.;
1520 nqcCoeffs.a5 = 0.;
1521 nqcCoeffs.b1 = 0.;
1522 nqcCoeffs.b2 = 0.;
1523 nqcCoeffs.b3 = 0.;
1524 nqcCoeffs.b4 = 0.;
1525 break;
1526 default:
1528 ("XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1, v2, and v4 are available.\n",
1529 __func__);
1530 if(sigmaKerr){
1531 XLALDestroyREAL8Vector (sigmaKerr);
1532 }
1533 if(sigmaStar){
1534 XLALDestroyREAL8Vector (sigmaStar);
1535 }
1536 if(values){
1537 XLALDestroyREAL8Vector (values);
1538 }
1540 break;
1541 }
1542
1543 /*
1544 * STEP 1) Solve for initial conditions
1545 */
1546
1547 /* Set the initial conditions. For now we use the generic case */
1548 /* Can be simplified if spin-aligned initial conditions solver available. The cost of generic code is negligible though. */
1549 REAL8Vector *tmpValues = XLALCreateREAL8Vector (14);
1550 if (!tmpValues)
1551 {
1552 XLALDestroyREAL8Vector (sigmaKerr);
1553 XLALDestroyREAL8Vector (sigmaStar);
1554 XLALDestroyREAL8Vector (values);
1556 }
1557
1558 memset (tmpValues->data, 0, tmpValues->length * sizeof (REAL8));
1559
1560 /* We set inc zero here to make it easier to go from Cartesian to spherical coords */
1561 /* No problem setting inc to zero in solving spin-aligned initial conditions. */
1562 /* inc is not zero in generating the final h+ and hx */
1564 (tmpValues, m1, m2, fStart, 0, s1Data, s2Data, &seobParams,
1565 use_optimized_v2_or_v4) == XLAL_FAILURE)
1566 {
1567 XLALDestroyREAL8Vector (tmpValues);
1568 XLALDestroyREAL8Vector (sigmaKerr);
1569 XLALDestroyREAL8Vector (sigmaStar);
1570 XLALDestroyREAL8Vector (values);
1572 }
1573
1574// printf( "ICs = %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n", tmpValues->data[0], tmpValues->data[1], tmpValues->data[2],
1575// tmpValues->data[3], tmpValues->data[4], tmpValues->data[5], tmpValues->data[6], tmpValues->data[7], tmpValues->data[8],
1576// tmpValues->data[9], tmpValues->data[10], tmpValues->data[11] );
1577
1578 /* Taken from Andrea's code */
1579/* memset( tmpValues->data, 0, tmpValues->length*sizeof(tmpValues->data[0]));*/
1580#if 0
1581 tmpValues->data[0] = 20;
1582 tmpValues->data[3] = -0.0001008684225106323/eta;
1583 tmpValues->data[4] = 1.16263606988612/eta / tmpValues->data[0]; // q=8 chi1=0.5
1584#endif
1585
1586 /* Now convert to Spherical */
1587 /* The initial conditions code returns Cartesian components of four vectors x, p, S1 and S2,
1588 * in the special case that the binary starts on the x-axis and the two spins are aligned
1589 * with the orbital angular momentum along the z-axis.
1590 * Therefore, in spherical coordinates the initial conditions are
1591 * r = x; phi = 0.; pr = px; pphi = r * py.
1592 */
1593 values->data[0] = tmpValues->data[0];
1594 values->data[1] = 0.;
1595 values->data[2] = tmpValues->data[3];
1596 values->data[3] = tmpValues->data[0] * tmpValues->data[4];
1597
1598 eobParams.rad = values->data[0];
1599 eobParams.omegaPeaked = 0;
1600 eobParams.omegaMerger = XLALSimNSNSMergerFreq( &tidal1, &tidal2 );
1601 eobParams.NyquistStop = 0;
1602
1603 //fprintf( stderr, "Spherical initial conditions: %e %e %e %e\n", values->data[0], values->data[1], values->data[2], values->data[3] );
1604
1605 REAL8Array *dynamicsPA = NULL;
1606
1607 INT4 postAdiabaticOutcome = 0;
1608
1609 if (postAdiabaticFlag)
1610 {
1612 &dynamicsPA,
1613 m1,
1614 m2,
1615 spin1z,
1616 spin2z,
1617 *values,
1618 SpinAlignedEOBversion,
1619 &seobParams,
1620 &nqcCoeffs,
1621 PAParams
1622 ), postAdiabaticOutcome);
1623
1624 if (postAdiabaticOutcome == XLAL_ERANGE)
1625 {
1626 postAdiabaticFlag=0;
1627 }
1628 else if (postAdiabaticOutcome != XLAL_SUCCESS)
1629 {
1630 XLAL_ERROR(XLAL_EFUNC, "XLALSimInspiralEOBPostAdiabatic failed!");
1631 }
1632 else
1633 {
1634 UINT4 rSize;
1635 rSize = dynamicsPA->dimLength->data[1];
1636
1637 values->data[0] = dynamicsPA->data[2*rSize-1];
1638 values->data[1] = 0.;
1639 values->data[2] = dynamicsPA->data[4*rSize-1];
1640 values->data[3] = dynamicsPA->data[5*rSize-1];
1641
1642 eobParams.rad = values->data[0];
1643 }
1644 }
1645
1646 /*
1647 * STEP 2) Evolve EOB trajectory until reaching the peak of orbital frequency
1648 */
1649 REAL8 odeStep = 1.0;
1650
1651 if(postAdiabaticFlag)
1652 {
1653 //odeStep = deltaT/mTScaled;
1654 odeStep = fmax(5*deltaT/mTScaled,1);
1655 }
1656 else
1657 {
1658 odeStep = deltaT/mTScaled;
1659 }
1660
1661 nStepBack = ceil (tStepBack / odeStep/ mTScaled);
1662 /* Now we have the initial conditions, we can initialize the adaptive integrator */
1663#if debugOutput
1664 printf("Begin integration\n");
1665#endif
1666 if ( use_tidal == 1 ) {
1667 if (!
1668 (integrator =
1671 EPS_ABS, EPS_REL)))
1672 {
1673 XLALDestroyREAL8Vector (values);
1675 }
1676 }
1677 else {
1678 if (use_optimized_v2_or_v4)
1679 {
1680 if (!
1681 (integrator =
1685 EPS_ABS, EPS_REL)))
1686 {
1687 XLALDestroyREAL8Vector (values);
1689 }
1690 }
1691 else
1692 {
1693
1694 if(postAdiabaticFlag){
1695 if (!
1696 (integrator =
1699 EPS_ABS, EPS_REL)))
1700 {
1701 XLALDestroyREAL8Vector (values);
1703 }
1704 }
1705 else{
1706 if (!
1707 (integrator =
1710 EPS_ABS, EPS_REL)))
1711 {
1712 XLALDestroyREAL8Vector (values);
1714 }
1715 }
1716 }
1717 }
1718
1719 integrator->stopontestonly = 1;
1720 integrator->retries = 1;
1721
1722
1723 if (use_optimized_v2_or_v4)
1724 {
1725 /* BEGIN OPTIMIZED */
1726 retLen_fromOptStep2 =
1727 XLALAdaptiveRungeKutta4NoInterpolate (integrator, &seobParams,
1728 values->data, 0.,
1729 20. / mTScaled,
1730 deltaT / mTScaled, 0., /* ignore deltaT_min, set it to 0 */
1731 &dynamicstmp,2);/* Last parameter added when funcions were combined in LALAdaptiveRungeKuttaIntegrator.c*/
1732 if (retLen_fromOptStep2 == XLAL_FAILURE || !dynamicstmp)
1733 {
1735 }
1736 retLen =
1738 deltaT / mTScaled,
1739 retLen_fromOptStep2,
1740 &dynamics);
1741 /* END OPTIMIZED */
1742 }
1743 else
1744 {
1745 //retLen =
1746 //XLALAdaptiveRungeKutta4NoInterpolate (integrator, &seobParams, values->data, 0.,
1747 //20. / mTScaled, deltaT / mTScaled,0,
1748 //&dynamics,2);
1749 retLen =
1750 XLALAdaptiveRungeKutta4 (integrator, &seobParams, values->data, 0.,
1751 20. / mTScaled, odeStep,
1752 &dynamics);
1753 }
1754
1755 if (retLen == XLAL_FAILURE || dynamics == NULL)
1756 {
1758 }
1759
1760 REAL8Vector *tVecInterp = NULL;
1761 REAL8Vector *rVecInterp = NULL;
1762 REAL8Vector *phiVecInterp = NULL;
1763 REAL8Vector *prVecInterp = NULL;
1764 REAL8Vector *pphiVecInterp = NULL;
1765 INT4 combinedLenForInterp = 0;
1766
1767 if (postAdiabaticFlag && postAdiabaticOutcome == XLAL_SUCCESS)
1768 {
1769 const INT4 PALen = dynamicsPA->dimLength->data[1];
1770
1771 REAL8 tStepInterp = deltaT/mTScaled;
1772 //const INT4 nInterp = ceil((dynamicsPA->data[PALen-1]-dynamicsPA->data[0]) / tStepInterp);
1773
1774 tVecInterp = XLALCreateREAL8Vector(PALen);
1775 rVecInterp = XLALCreateREAL8Vector(PALen);
1776 phiVecInterp = XLALCreateREAL8Vector(PALen);
1777 prVecInterp = XLALCreateREAL8Vector(PALen);
1778 pphiVecInterp = XLALCreateREAL8Vector(PALen);
1779
1780 for (i = 0; i < PALen; i++)
1781 {
1782 tVecInterp->data[i] = dynamicsPA->data[i];
1783 rVecInterp->data[i] = dynamicsPA->data[PALen + i];
1784 phiVecInterp->data[i] = dynamicsPA->data[2*PALen + i];
1785 prVecInterp->data[i] = dynamicsPA->data[3*PALen + i];
1786 pphiVecInterp->data[i] = dynamicsPA->data[4*PALen + i];
1787 }
1788
1789 REAL8Array *interpDynamicsPA = NULL;
1790 interpDynamicsPA = XLALCreateREAL8ArrayL(2, 5, PALen);
1791
1792 for (i = 0; i < PALen; i++)
1793 {
1794 interpDynamicsPA->data[i] = tVecInterp->data[i];
1795 interpDynamicsPA->data[PALen + i] = rVecInterp->data[i];
1796 interpDynamicsPA->data[2*PALen + i] = phiVecInterp->data[i];
1797 interpDynamicsPA->data[3*PALen + i] = prVecInterp->data[i];
1798 interpDynamicsPA->data[4*PALen + i] = pphiVecInterp->data[i] = dynamicsPA->data[4*PALen + i];
1799 }
1800
1801 REAL8 tOffset = interpDynamicsPA->data[PALen - 1];
1802 REAL8 phiOffset = interpDynamicsPA->data[3*PALen - 1];
1803
1804 const INT4 combinedLen = PALen + retLen - 1;
1805
1806 combinedLenForInterp = ceil((dynamics->data[retLen-1]+tOffset-dynamicsPA->data[0]) / tStepInterp) - 1;
1807 // printf("Last point of integration: %e\n",dynamics->data[retLen-1]+tOffset);
1808 // printf("First point of PA is %e\n",dynamicsPA->data[0]);
1809 // printf("The spacing to interpolate to is %e\n",tStepInterp);
1810 // printf("The length of the array is %d\n",combinedLenForInterp);
1811 //REAL8 nODE = ceil((dynamics->data[retLen-1]-dynamics->data[0])/tStepInterp);
1812 //combinedLenForInterp = ceil((dynamicsPA->data[PALen-1]-dynamicsPA->data[0]) / tStepInterp) + nODE - 1;
1813 REAL8Array *combinedDynamics = NULL;
1814 combinedDynamics = XLALCreateREAL8ArrayL(2, 5, combinedLen);
1815
1816 for (i = 0; i < PALen; i++)
1817 {
1818 combinedDynamics->data[i] = interpDynamicsPA->data[i];
1819 combinedDynamics->data[combinedLen + i] = interpDynamicsPA->data[PALen + i];
1820 combinedDynamics->data[2*combinedLen + i] = interpDynamicsPA->data[2*PALen + i];
1821 combinedDynamics->data[3*combinedLen + i] = interpDynamicsPA->data[3*PALen + i];
1822 combinedDynamics->data[4*combinedLen + i] = interpDynamicsPA->data[4*PALen + i];
1823 }
1824
1825 for (i = 1; i < retLen; i++)
1826 {
1827 combinedDynamics->data[PALen + i - 1] = dynamics->data[i] + tOffset;
1828 combinedDynamics->data[combinedLen + PALen + i - 1] = dynamics->data[retLen + i];
1829 combinedDynamics->data[2*combinedLen + PALen + i - 1] = dynamics->data[2*retLen + i] + phiOffset;
1830 combinedDynamics->data[3*combinedLen + PALen + i - 1] = dynamics->data[3*retLen + i];
1831 combinedDynamics->data[4*combinedLen + PALen + i - 1] = dynamics->data[4*retLen + i];
1832 }
1833
1834 XLALDestroyREAL8Array(dynamics);
1835 dynamics = combinedDynamics;
1836
1837 retLen = combinedLen;
1838
1839 values->data[0] = dynamics->data[retLen];
1840 values->data[1] = dynamics->data[2*retLen];
1841 values->data[2] = dynamics->data[3*retLen];
1842 values->data[3] = dynamics->data[4*retLen];
1843
1844 eobParams.rad = values->data[0];
1845
1846 XLALDestroyREAL8Array(interpDynamicsPA);
1847
1848 XLALDestroyREAL8Array(dynamicsPA);
1849 /*
1850 for (i = 0; i < PALen; i++)
1851 {
1852 combinedDynamics->data[i] = dynamicsPA->data[i];
1853 combinedDynamics->data[combinedLen + i] = dynamicsPA->data[PALen + i];
1854 combinedDynamics->data[2*combinedLen + i] = dynamicsPA->data[2*PALen + i];
1855 combinedDynamics->data[3*combinedLen + i] = dynamicsPA->data[3*PALen + i];
1856 combinedDynamics->data[4*combinedLen + i] = dynamicsPA->data[4*PALen + i];
1857 }
1858
1859 for (i = 1; i < retLen; i++)
1860 {
1861 combinedDynamics->data[PALen + i - 1] = dynamics->data[i] + tOffset;
1862 combinedDynamics->data[combinedLen + PALen + i - 1] = dynamics->data[retLen + i];
1863 combinedDynamics->data[2*combinedLen + PALen + i - 1] = dynamics->data[2*retLen + i] + phiOffset;
1864 combinedDynamics->data[3*combinedLen + PALen + i - 1] = dynamics->data[3*retLen + i];
1865 combinedDynamics->data[4*combinedLen + PALen + i - 1] = dynamics->data[4*retLen + i];
1866 }
1867 */
1868
1869 }
1870
1871 /* Set up pointers to the dynamics */
1872 // REAL8Vector tVec;
1873 // tVec.data = dynamics->data;
1874 // tVec.length = rVec.length = phiVec.length = prVec.length = pPhiVec.length = retLen;
1875 rVec.length = phiVec.length = prVec.length = pPhiVec.length = retLen;
1876 rVec.data = dynamics->data + retLen;
1877 tVec.data = dynamics->data;
1878 tVec.length = rVec.length;
1879 phiVec.data = dynamics->data + 2 * retLen;
1880 prVec.data = dynamics->data + 3 * retLen;
1881 pPhiVec.data = dynamics->data + 4 * retLen;
1882
1883 // printf( "We think we hit the peak at time %e\n", dynamics->data[retLen-1] );
1884
1885 /* TODO : Insert high sampling rate / ringdown here */
1886
1887 if (tStepBack > retLen * odeStep*mTScaled)
1888 {
1889 tStepBack = 0.5 * retLen * odeStep*mTScaled; //YPnote: if 100M of step back > actual time of evolution, step back 50% of the later
1890 nStepBack = ceil (tStepBack / odeStep/mTScaled);
1891 }
1892
1893 //SM
1894 // retLen is going to be reused for the length of the high-sampling dynamics
1895 INT4 retLen_out = retLen;
1896 //SM
1897
1898 /*
1899 * STEP 3) Step back in time by tStepBack and volve EOB trajectory again
1900 * using high sampling rate, stop at 0.3M out of the "EOB horizon".
1901 */
1902
1903 /* Set up the high sample rate integration */
1904 hiSRndx = retLen - nStepBack;
1905 deltaTHigh = deltaT / (REAL8) resampFac;
1906 //printf("deltaT = %.17f, deltaTHigh = %.17f\n",deltaT,deltaTHigh);
1907// #if 1
1908 // printf (
1909 // "Stepping back %d points - we expect %d points at high SR\n",
1910 // nStepBack, nStepBack * resampFac);
1911 // printf (
1912 // "Commencing high SR integration... from %.16e %.16e %.16e %.16e %.16e\n",
1913 // (dynamics->data)[hiSRndx], rVec.data[hiSRndx],
1914 // phiVec.data[hiSRndx], prVec.data[hiSRndx], pPhiVec.data[hiSRndx]);
1915// #endif
1916
1917 values->data[0] = rVec.data[hiSRndx];
1918 values->data[1] = phiVec.data[hiSRndx];
1919 values->data[2] = prVec.data[hiSRndx];
1920 values->data[3] = pPhiVec.data[hiSRndx];
1921 //printf("Before it begins\n");
1922 //printf("t=%.17f values: r=%.17f, phi = %.17f, pr=%.17f, pphi = %.17f\n",tVec.data[hiSRndx],values->data[0],values->data[1],values->data[2],values->data[3]);
1923
1924 eobParams.rad = values->data[0];
1925 eobParams.omegaPeaked = 0;
1926 eobParams.NyquistStop = 0;
1927
1928 /* If we are doing a post-adibatic run, we need to be more careful.
1929 In particular because the grid is *not* uniform and has a different
1930 step than what we want the final waveform on, we need to actually step
1931 back into a point that *will* be on the final grid. This is needed to
1932 ensure that when we insert the high-SR waveform after the low-SR, the times
1933 are consistent.
1934 To do this, we proceed as follows: determine the point on the final grid that
1935 is closest to the desired tStepBack. Then interpolate the dynamics to this point
1936 and begin the high-SR evolution from there. We can also set the highSRndx correctly
1937 here
1938 */
1939 REAL8 tstartHi = 0.0;
1940 if (postAdiabaticFlag && postAdiabaticOutcome == XLAL_SUCCESS)
1941 {
1942 /* The time to which want to step back to */
1943
1944 REAL8 tTarget = tVec.data[retLen-1]-tStepBack/mTScaled;
1945 UINT4 ndx = floor(tTarget*mTScaled/deltaT);
1946 REAL8 closestTime = ndx*deltaT/mTScaled;
1947 tstartHi = closestTime;
1948 //printf("tStepBack = %.17f, tend=%.17f, tTarget=%.17f,ndx=%d,closestTime=%.17f\n",tStepBack,tVec.data[retLen-1],tTarget,ndx,closestTime);
1949 IntrpolateDynamics(&tVec,&rVec,&phiVec,&prVec,&pPhiVec,values,closestTime);
1950 eobParams.rad = values->data[0];
1951 }
1952 /* For HiSR evolution, we stop at a radius 0.3M from the deformed Kerr singularity,
1953 * or when any derivative of Hamiltonian becomes nan */
1955 if (SpinAlignedEOBversion == 4)
1956 {
1958 }
1959 if ( use_tidal == 1 ) {
1961 }
1962
1963 if (use_optimized_v2_or_v4)
1964 {
1965 /* BEGIN OPTIMIZED: */
1966 retLen_fromOptStep3 =
1967 XLALAdaptiveRungeKutta4NoInterpolate (integrator, &seobParams,
1968 values->data, 0.,
1969 20. / mTScaled,
1970 deltaTHigh / mTScaled, 0., /* ignore deltaT_min, set it to 0 */
1971 &dynamicsHitmp,2);/* Last parameter added when funcions were combined in LALAdaptiveRungeKuttaIntegrator.c*/
1972 if (retLen_fromOptStep3 == XLAL_FAILURE || !dynamicsHitmp)
1973 {
1975 }
1976 retLen =
1977 SEOBNRv2OptimizedInterpolatorNoAmpPhase (dynamicsHitmp, 0.,
1978 deltaTHigh / mTScaled,
1979 retLen_fromOptStep3,
1980 &dynamicsHi);
1981 /* END OPTIMIZED */
1982 }
1983 else
1984 {
1985 retLen =
1986 XLALAdaptiveRungeKutta4 (integrator, &seobParams, values->data, 0.,
1987 20. / mTScaled, deltaTHigh / mTScaled,
1988 &dynamicsHi);
1989 }
1990
1991 if (retLen == XLAL_FAILURE || dynamicsHi == NULL)
1992 {
1993 if(tmpValues){
1994 XLALDestroyREAL8Vector (tmpValues);
1995 }
1996 if(sigmaKerr){
1997 XLALDestroyREAL8Vector (sigmaKerr);
1998 }
1999 if(sigmaStar){
2000 XLALDestroyREAL8Vector (sigmaStar);
2001 }
2002 if(values){
2003 XLALDestroyREAL8Vector (values);
2004 }
2006 }
2007
2008 //SM
2009 // retLen now means the length of the high-sampling dynamics
2010 // We also keep track of the starting time of the high-sampling dynamics
2011 INT4 retLenHi_out = retLen;
2012
2013
2014
2015 if(!postAdiabaticFlag)
2016 {
2017 tstartHi = hiSRndx * odeStep;
2018 }
2019 // printf("tstartHi = %e\n",tstartHi);
2020 //SM
2021
2022// fprintf( stderr, "We got %d points at high SR\n", retLen );
2023
2024 /* Set up pointers to the dynamics */
2025 rHi.length = phiHi.length = prHi.length = pPhiHi.length = timeHi.length =
2026 retLen;
2027 timeHi.data = dynamicsHi->data;
2028 rHi.data = dynamicsHi->data + retLen;
2029 phiHi.data = dynamicsHi->data + 2 * retLen;
2030 prHi.data = dynamicsHi->data + 3 * retLen;
2031 pPhiHi.data = dynamicsHi->data + 4 * retLen;
2032
2033 REAL8 domega220 = 0;
2034 REAL8 dtau220 = 0;
2035 REAL8 domega210 = 0;
2036 REAL8 dtau210 = 0;
2037 REAL8 domega330 = 0;
2038 REAL8 dtau330 = 0;
2039 REAL8 domega440 = 0;
2040 REAL8 dtau440 = 0;
2041 REAL8 domega550 = 0;
2042 REAL8 dtau550 = 0;
2043
2044 domega220 = XLALSimInspiralWaveformParamsLookupDOmega220(TGRParams);
2045 dtau220 = XLALSimInspiralWaveformParamsLookupDTau220(TGRParams);
2046 domega210 = XLALSimInspiralWaveformParamsLookupDOmega210(TGRParams);
2047 dtau210 = XLALSimInspiralWaveformParamsLookupDTau210(TGRParams);
2048 domega330 = XLALSimInspiralWaveformParamsLookupDOmega330(TGRParams);
2049 dtau330 = XLALSimInspiralWaveformParamsLookupDTau330(TGRParams);
2050 domega440 = XLALSimInspiralWaveformParamsLookupDOmega440(TGRParams);
2051 dtau440 = XLALSimInspiralWaveformParamsLookupDTau440(TGRParams);
2052 domega550 = XLALSimInspiralWaveformParamsLookupDOmega550(TGRParams);
2053 dtau550 = XLALSimInspiralWaveformParamsLookupDTau550(TGRParams);
2054
2055 if (TGRParams && XLALDictContains(TGRParams, "TGRflag")) {
2056 TGRflag = XLALDictLookupUINT2Value(TGRParams, "TGRflag");
2057 }
2058
2059 /* Allocate the high sample rate vectors */
2060 if(dtau220 > 0)
2061 {
2062 /*If dtau220>0 we need a larger array than in GR case to accomodate the whole ringdown*/
2063 sigReHi =
2064 XLALCreateREAL8Vector (retLen +
2065 (UINT4) ceil (20 * (1. + dtau220) /
2066 (cimag (modeFreq) * deltaTHigh)));
2067 sigImHi =
2068 XLALCreateREAL8Vector (retLen +
2069 (UINT4) ceil (20 * (1. + dtau220) /
2070 (cimag (modeFreq) * deltaTHigh)));
2071 omegaHi =
2072 XLALCreateREAL8Vector (retLen +
2073 (UINT4) ceil (20 * (1. + dtau220) /
2074 (cimag (modeFreq) * deltaTHigh)));
2075 vPhiVecHi =
2076 XLALCreateREAL8Vector (retLen +
2077 (UINT4) ceil (20 * (1. + dtau220) /
2078 (cimag (modeFreq) * deltaTHigh)));
2079 }
2080 else {
2081 /* Allocate the high sample rate vectors */
2082 sigReHi =
2083 XLALCreateREAL8Vector (retLen +
2084 (UINT4) ceil (20 /
2085 (cimag (modeFreq) * deltaTHigh)));
2086 sigImHi =
2087 XLALCreateREAL8Vector (retLen +
2088 (UINT4) ceil (20 /
2089 (cimag (modeFreq) * deltaTHigh)));
2090 omegaHi =
2091 XLALCreateREAL8Vector (retLen +
2092 (UINT4) ceil (20 /
2093 (cimag (modeFreq) * deltaTHigh)));
2094 vPhiVecHi =
2095 XLALCreateREAL8Vector (retLen +
2096 (UINT4) ceil (20 /
2097 (cimag (modeFreq) * deltaTHigh)));
2098
2099 }
2100
2101 ampNQC = XLALCreateREAL8Vector (retLen);
2102 phaseNQC = XLALCreateREAL8Vector (retLen);
2103 hamVHi = XLALCreateREAL8Vector (retLen);
2104 //RC: we save the Hamiltonian in a vector such that we can compute it only once
2105 //and use it for calculate all the modes
2106
2107 if (!sigReHi || !sigImHi || !omegaHi || !ampNQC || !phaseNQC|| !hamVHi)
2108 {
2109 if(tmpValues){
2110 XLALDestroyREAL8Vector (tmpValues);
2111 }
2112 if(sigmaKerr){
2113 XLALDestroyREAL8Vector (sigmaKerr);
2114 }
2115 if(sigmaStar){
2116 XLALDestroyREAL8Vector (sigmaStar);
2117 }
2118 if(values){
2119 XLALDestroyREAL8Vector (values);
2120 }
2122 }
2123
2124 memset (sigReHi->data, 0, sigReHi->length * sizeof (sigReHi->data[0]));
2125 memset (sigImHi->data, 0, sigImHi->length * sizeof (sigImHi->data[0]));
2126
2127 /* Populate the high SR waveform */
2128 REAL8 omegaOld = 0.0;
2129 INT4 phaseCounter = 0;
2130 for (i = 0; i < retLen; i++)
2131 {
2132 values->data[0] = rHi.data[i];
2133 values->data[1] = phiHi.data[i];
2134 values->data[2] = prHi.data[i];
2135 values->data[3] = pPhiHi.data[i];
2136
2137 if (use_optimized_v2_or_v4)
2138 {
2139 /* OPTIMIZED: */
2140 omega =
2142 &seobParams);
2143 /* END OPTIMIZED: */
2144 }
2145 else
2146 {
2147
2148 if(postAdiabaticFlag){
2149 omega =
2150 XLALSimIMRSpinAlignedEOBCalcOmegaOptimized (values->data, &seobParams);
2151 }
2152 else{
2153 omega =
2154 XLALSimIMRSpinAlignedEOBCalcOmega (values->data, &seobParams, STEP_SIZE);
2155 }
2156 }
2157
2158 if (omega < 1.0e-15)
2159 omega = 1.0e-9; //YPnote: make sure omega>0 during very-late evolution when numerical errors are huge.
2160 omegaHi->data[i] = omega; //YPnote: omega<0 is extremely rare and had only happenned after relevant time interval.
2161 v = cbrt (omega);
2162
2163 if (postAdiabaticFlag){
2164 vPhiVecHi->data[i] = XLALSimIMRSpinAlignedEOBNonKeplerCoeffOptimized (values->data, &seobParams);
2165 }
2166 /* Calculate the value of the Hamiltonian */
2167 cartPosVec.data[0] = values->data[0];
2168 cartMomVec.data[0] = values->data[2];
2169 cartMomVec.data[1] = values->data[3] / values->data[0];
2170
2171 if (use_optimized_v2_or_v4)
2172 {
2173 /* OPTIMIZED: */
2174 hamVHi->data[i] =
2175 XLALSimIMRSpinEOBHamiltonianOptimized (eta, &cartPosVec,
2176 &cartMomVec,
2177 &s1VecOverMtMt,
2178 &s2VecOverMtMt, sigmaKerr,
2179 sigmaStar,
2180 seobParams.tortoise,
2181 &seobCoeffs);
2182 /* END OPTIMIZED: */
2183 }
2184 else
2185 {
2186 hamVHi->data[i] =
2187 XLALSimIMRSpinEOBHamiltonian (eta, &cartPosVec, &cartMomVec,
2188 &s1VecOverMtMt, &s2VecOverMtMt,
2189 sigmaKerr, sigmaStar,
2190 seobParams.tortoise, &seobCoeffs);
2191 }
2192
2193 if (omega <= omegaOld && !peakIdx)
2194 {
2195// printf( "Have we got the peak? omegaOld = %.16e, omega = %.16e\n", omegaOld, omega );
2196 peakIdx = i;
2197 }
2198 omegaOld = omega;
2199 }
2200
2201 finalIdx = retLen - 1;
2202 if (!peakIdx)
2203 peakIdx = finalIdx;
2204
2205// printf( "We now think the peak is at %d\n", peakIdx );
2206#if debugOutput
2207 FILE *out = fopen ("saDynamicsHi.dat", "w");
2208 for (i = 0; i < retLen; i++)
2209 {
2210 fprintf (out, "%.16e %.16e %.16e %.16e %.16e %.16e\n", timeHi.data[i],
2211 rHi.data[i], phiHi.data[i], prHi.data[i], pPhiHi.data[i], omegaHi->data[i]);
2212 }
2213 fclose (out);
2214#endif
2215
2216 /*
2217 * STEP 4) Locate the peak of orbital frequency for NQC and QNM calculations
2218 */
2219
2220 /* Stuff to find the actual peak time */
2221 gsl_spline *spline = NULL;
2222 gsl_interp_accel *acc = NULL;
2223 REAL8 omegaDeriv1; //, omegaDeriv2;
2224 REAL8 time1, time2;
2225 REAL8 timePeak, timewavePeak = 0., omegaDerivMid;
2226 REAL8 sigAmpSqHi = 0., oldsigAmpSqHi = 0.;
2227 INT4 peakCount = 0;
2228
2229 spline = gsl_spline_alloc (gsl_interp_cspline, retLen);
2230 acc = gsl_interp_accel_alloc ();
2231
2232 time1 = dynamicsHi->data[peakIdx];
2233
2234 gsl_spline_init (spline, dynamicsHi->data, omegaHi->data, retLen);
2235 omegaDeriv1 = gsl_spline_eval_deriv (spline, time1, acc);
2236 if (omegaDeriv1 > 0.)
2237 {
2238 time2 = dynamicsHi->data[peakIdx + 1];
2239 //omegaDeriv2 = gsl_spline_eval_deriv( spline, time2, acc );
2240 }
2241 else
2242 {
2243 //omegaDeriv2 = omegaDeriv1;
2244 time2 = time1;
2245 time1 = dynamicsHi->data[peakIdx - 1];
2246 peakIdx--;
2247 omegaDeriv1 = gsl_spline_eval_deriv (spline, time1, acc);
2248 }
2249
2250 do
2251 {
2252 timePeak = (time1 + time2) / 2.;
2253 omegaDerivMid = gsl_spline_eval_deriv (spline, timePeak, acc);
2254
2255 if (omegaDerivMid * omegaDeriv1 < 0.0)
2256 {
2257 //omegaDeriv2 = omegaDerivMid;
2258 time2 = timePeak;
2259 }
2260 else
2261 {
2262 omegaDeriv1 = omegaDerivMid;
2263 time1 = timePeak;
2264 }
2265 }
2266 while (time2 - time1 > 1.0e-5);
2267
2268// if (use_tidal == 1)
2269// timePeak = dynamicsHi->data[retLen-1];
2270
2271
2272gsl_spline_free( spline );
2273gsl_interp_accel_free( acc );
2274
2275
2276 //XLALPrintInfo( "Estimation of the peak is now at time %.16e\n", timePeak );
2277
2278
2279 /*
2280 * STEP 5) Calculate NQC correction using hi-sampling data
2281 */
2282
2283 /* Calculate nonspin and amplitude NQC coefficients from fits and interpolation table */
2284 /*switch ( SpinAlignedEOBversion )
2285 {
2286 case 1:
2287 if ( XLALSimIMRGetEOBCalibratedSpinNQC( &nqcCoeffs, 2, 2, eta, a ) == XLAL_FAILURE )
2288 {
2289 XLAL_ERROR( XLAL_EFUNC );
2290 }
2291 break;
2292 case 2:
2293 if ( XLALSimIMRGetEOBCalibratedSpinNQC3D( &nqcCoeffs, 2, 2, eta, a, chiA ) == XLAL_FAILURE )
2294 {
2295 XLAL_ERROR( XLAL_EFUNC );
2296 }
2297 break;
2298 default:
2299 XLALPrintError( "XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1 and v2 are available.\n", __func__);
2300 XLAL_ERROR( XLAL_EINVAL );
2301 break;
2302 } */
2303
2304 /* Calculate the time of amplitude peak. Despite the name, this is in fact the shift in peak time from peak orb freq time */
2305 switch (SpinAlignedEOBversion)
2306 {
2307 case 1:
2308 timewavePeak = XLALSimIMREOBGetNRSpinPeakDeltaT (2, 2, eta, a);
2309 break;
2310 case 2:
2311 timewavePeak = XLALSimIMREOBGetNRSpinPeakDeltaTv2 (2, 2, m1, m2, spin1z, spin2z); // David debug: we need to be using v2 for SpinAlignedEOBversion 2, right?
2312 break;
2313 case 4:
2314 timewavePeak =
2315 XLALSimIMREOBGetNRSpinPeakDeltaTv4 (2, 2, m1, m2, spin1z, spin2z);
2316 break;
2317 default:
2319 ("XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1 and v2 are available.\n",
2320 __func__);
2321 if(tmpValues){
2322 XLALDestroyREAL8Vector (tmpValues);
2323 }
2324 if(sigmaKerr){
2325 XLALDestroyREAL8Vector (sigmaKerr);
2326 }
2327 if(sigmaStar){
2328 XLALDestroyREAL8Vector (sigmaStar);
2329 }
2330 if(values){
2331 XLALDestroyREAL8Vector (values);
2332 }
2333 if(sigReHi){
2334 XLALDestroyREAL8Vector(sigReHi);
2335 }
2336 if(sigImHi){
2337 XLALDestroyREAL8Vector(sigImHi);
2338 }
2339 if(omegaHi){
2340 XLALDestroyREAL8Vector(omegaHi);
2341 }
2342 if(vPhiVecHi){
2343 XLALDestroyREAL8Vector(vPhiVecHi);
2344 }
2345 if(ampNQC){
2346 XLALDestroyREAL8Vector(ampNQC);
2347 }
2348 if(phaseNQC){
2349 XLALDestroyREAL8Vector(phaseNQC);
2350 }
2351 if(hamVHi){
2352 XLALDestroyREAL8Vector(hamVHi);
2353 }
2355 break;
2356 }
2357 if (use_tidal == 1) {
2358 timewavePeak = 0.;
2359 } /* */
2360
2361 /* Evaluating the modes */
2362
2363 /*The for over the modes should start here */
2364 // REAL8 nqcCoeffsMatrix[nModes][10]; //RC: Andrea coded the 2d array in this way. It works in C99 and indeed I don't get any errors when compiling, but I think this should be deprecated, it's better the gsl matrix
2365 gsl_matrix * nqcCoeffsMatrix = gsl_matrix_alloc (nModes, 10);
2366
2367
2368 if(use_hm == 1)
2369 {
2370 //RC for the SEOBNRv4HM model we need to compute again the coefficients for the modes because they are different from those using for computing the flux LALSimIMRSpinEOBFactorizedFlux.
2372 (&hCoeffs, &seobParams, m1, m2, eta, tplspin, chiS, chiA,
2373 SpinAlignedEOBversion) == XLAL_FAILURE)
2374 {
2375 if(tmpValues){
2376 XLALDestroyREAL8Vector (tmpValues);
2377 }
2378 if(sigmaKerr){
2379 XLALDestroyREAL8Vector (sigmaKerr);
2380 }
2381 if(sigmaStar){
2382 XLALDestroyREAL8Vector (sigmaStar);
2383 }
2384 if(values){
2385 XLALDestroyREAL8Vector (values);
2386 }
2387 if(sigReHi){
2388 XLALDestroyREAL8Vector(sigReHi);
2389 }
2390 if(sigImHi){
2391 XLALDestroyREAL8Vector(sigImHi);
2392 }
2393 if(omegaHi){
2394 XLALDestroyREAL8Vector(omegaHi);
2395 }
2396 if(vPhiVecHi){
2397 XLALDestroyREAL8Vector(vPhiVecHi);
2398 }
2399 if(ampNQC){
2400 XLALDestroyREAL8Vector(ampNQC);
2401 }
2402 if(phaseNQC){
2403 XLALDestroyREAL8Vector(phaseNQC);
2404 }
2405 if(hamVHi){
2406 XLALDestroyREAL8Vector(hamVHi);
2407 }
2409 }
2410 if((fabs(m1-m2) == 0) && (chiA == 0)){
2411 //RC: in the case of equal mass equal spins (where odd m modes are 0), the calibration parameter is 0
2412 }
2413 else{
2414 //RC: in addition to the PN coefficient, here we also need to evaluate a spinning pseudo-PN coefficient for the 21 and the 55 mode. These coefficients do not break
2415 //the odd mode's symmetry and for this reason they are 0 if chiS == chiA == 0. This of course hold also for non-spinning configurations.
2416 XLALSimIMREOBCalcCalibCoefficientHigherModes(&hCoeffs, &seobParams,2,1,&phiHi,&rHi,&prHi,
2417 omegaHi,hamVHi,&pPhiHi,timePeak -timewavePeak,m1,m2,chiS,chiA,deltaTHigh / mTScaled);
2418 XLALSimIMREOBCalcCalibCoefficientHigherModes(&hCoeffs, &seobParams,5,5,&phiHi,&rHi,&prHi,
2419 omegaHi,hamVHi,&pPhiHi,timePeak -timewavePeak- 10,m1,m2,chiS,chiA,deltaTHigh / mTScaled);
2420 //RC: The - 10 here is because for the 55 mode the attachment is done at timePeak -timewavePeak- 10. timewavePeak is computed here outside
2421 //the for loop for the modes, for this reason I'm putting the -10 by hand, if it was inside the loop I could have used XLALSimIMREOBGetNRSpinPeakDeltaTv4 (5, 5, m1, m2, spin1z, spin2z)
2422 }
2423 }
2424
2425
2426
2427
2428 hLMAllHi = XLALCreateREAL8Vector((UINT4)2*sigReHi->length*nModes);
2430 memset(hLMAllHi->data, 0, hLMAllHi->length*sizeof (REAL8));
2431for ( UINT4 k = 0; k<nModes; k++) {
2432 modeL = lmModes[k][0];
2433 modeM = lmModes[k][1];
2434#if debugOutput
2435 char filename2[sizeof "saModesXXHi.dat"];
2436 sprintf(filename2,"saModes%01d%01dHi.dat",modeL,modeM);
2437 out = fopen (filename2, "w");
2438#endif
2439 for(i=0; i<retLen; i++){
2440 values->data[0] = rHi.data[i];
2441 values->data[1] = phiHi.data[i];
2442 values->data[2] = prHi.data[i];
2443 values->data[3] = pPhiHi.data[i];
2444 v = cbrt (omegaHi->data[i]);
2445 if (postAdiabaticFlag)
2446 {
2447 status = XLALSimIMRSpinEOBGetSpinFactorizedWaveform_PA(&hLM, values, v, hamVHi->data[i], modeL, modeM, &seobParams,
2448 vPhiVecHi->data[i]);
2449 }
2450 else
2451 {
2452 status = XLALSimIMRSpinEOBGetSpinFactorizedWaveform(&hLM, values, v, hamVHi->data[i], modeL, modeM, &seobParams,
2453 use_optimized_v2_or_v4);
2454 }
2455
2456 if (status == XLAL_FAILURE)
2457 {
2458 if(tmpValues){
2459 XLALDestroyREAL8Vector (tmpValues);
2460 }
2461 if(sigmaKerr){
2462 XLALDestroyREAL8Vector (sigmaKerr);
2463 }
2464 if(sigmaStar){
2465 XLALDestroyREAL8Vector (sigmaStar);
2466 }
2467 if(values){
2468 XLALDestroyREAL8Vector (values);
2469 }
2470 if(sigReHi){
2471 XLALDestroyREAL8Vector(sigReHi);
2472 }
2473 if(sigImHi){
2474 XLALDestroyREAL8Vector(sigImHi);
2475 }
2476 if(omegaHi){
2477 XLALDestroyREAL8Vector(omegaHi);
2478 }
2479 if(vPhiVecHi){
2480 XLALDestroyREAL8Vector(vPhiVecHi);
2481 }
2482 if(ampNQC){
2483 XLALDestroyREAL8Vector(ampNQC);
2484 }
2485 if(phaseNQC){
2486 XLALDestroyREAL8Vector(phaseNQC);
2487 }
2488 if(hamVHi){
2489 XLALDestroyREAL8Vector(hamVHi);
2490 }
2491 if(hLMAllHi){
2492 XLALDestroyREAL8Vector(hLMAllHi);
2493 }
2495 }
2496#if debugOutput
2497 fprintf (out, "%.16e %.16e %.16e\n", timeHi.data[i],
2498 creal (hLM) , cimag (hLM ) );
2499#endif
2500 ampNQC->data[i] = cabs (hLM);
2501 sigReHi->data[i] = (REAL8) (amp0 * creal (hLM));
2502 sigImHi->data[i] = (REAL8) (amp0 * cimag (hLM));
2503 phaseNQC->data[i] = carg (hLM) + phaseCounter * LAL_TWOPI;
2504
2505 if (i && phaseNQC->data[i] > phaseNQC->data[i - 1])
2506 {
2507 phaseCounter--;
2508 phaseNQC->data[i] -= LAL_TWOPI;
2509 }
2510
2511 }
2512#if debugOutput
2513 fclose (out);
2514#endif
2515
2516
2517
2518
2519 if (SpinAlignedEOBversion == 4)
2520 {
2521 if ( use_tidal == 1 && nqcFlag == 2 ) {
2522 nqcCoeffs.a1 = nqcCoeffsInput->data[0];
2523 nqcCoeffs.a2 = nqcCoeffsInput->data[1];
2524 nqcCoeffs.a3 = nqcCoeffsInput->data[2];
2525 nqcCoeffs.a3S = nqcCoeffsInput->data[3];
2526 nqcCoeffs.a4 = nqcCoeffsInput->data[4];
2527 nqcCoeffs.a5 = nqcCoeffsInput->data[5];
2528 nqcCoeffs.b1 = nqcCoeffsInput->data[6];
2529 nqcCoeffs.b2 = nqcCoeffsInput->data[7];
2530 nqcCoeffs.b3 = nqcCoeffsInput->data[8];
2531 nqcCoeffs.b4 = nqcCoeffsInput->data[9];
2532 }
2533 else {
2534 if(eta == 0.25 && chiA == 0 && ( (modeL == 2 && modeM == 1) || (modeL == 3 && modeM == 3)|| (modeL == 5 && modeM == 5) ) ) { //RC:Since the mode is 0 by symmetry, we don't need to compute the NQCs
2535 nqcCoeffs.a1 = 0.;
2536 nqcCoeffs.a2 = 0.;
2537 nqcCoeffs.a3 = 0.;
2538 nqcCoeffs.a3S = 0.;
2539 nqcCoeffs.a4 = 0.;
2540 nqcCoeffs.a5 = 0.;
2541 nqcCoeffs.b1 = 0.;
2542 nqcCoeffs.b2 = 0.;
2543 nqcCoeffs.b3 = 0.;
2544 nqcCoeffs.b4 = 0.;
2545 }
2546 else{
2548 (ampNQC, phaseNQC, &rHi, &prHi, omegaHi, modeL, modeM, timePeak,
2549 deltaTHigh / mTScaled, m1, m2, chiA, chiS, &nqcCoeffs) == XLAL_FAILURE)
2550
2551 {
2552 if(tmpValues){
2553 XLALDestroyREAL8Vector (tmpValues);
2554 }
2555 if(sigmaKerr){
2556 XLALDestroyREAL8Vector (sigmaKerr);
2557 }
2558 if(sigmaStar){
2559 XLALDestroyREAL8Vector (sigmaStar);
2560 }
2561 if(values){
2562 XLALDestroyREAL8Vector (values);
2563 }
2564 if(sigReHi){
2565 XLALDestroyREAL8Vector(sigReHi);
2566 }
2567 if(sigImHi){
2568 XLALDestroyREAL8Vector(sigImHi);
2569 }
2570 if(omegaHi){
2571 XLALDestroyREAL8Vector(omegaHi);
2572 }
2573 if(vPhiVecHi){
2574 XLALDestroyREAL8Vector(vPhiVecHi);
2575 }
2576 if(ampNQC){
2577 XLALDestroyREAL8Vector(ampNQC);
2578 }
2579 if(phaseNQC){
2580 XLALDestroyREAL8Vector(phaseNQC);
2581 }
2582 if(hamVHi){
2583 XLALDestroyREAL8Vector(hamVHi);
2584 }
2585 if(hLMAllHi){
2586 XLALDestroyREAL8Vector(hLMAllHi);
2587 }
2589 }
2590 }
2591 }
2592 }
2593 if ( SpinAlignedEOBversion == 4 && nqcFlag == 1 ) {
2594 nqcCoeffsInput->data[0] = nqcCoeffs.a1;
2595 nqcCoeffsInput->data[1] = nqcCoeffs.a2;
2596 nqcCoeffsInput->data[2] = nqcCoeffs.a3;
2597 nqcCoeffsInput->data[3] = nqcCoeffs.a3S;
2598 nqcCoeffsInput->data[4] = nqcCoeffs.a4;
2599 nqcCoeffsInput->data[5] = nqcCoeffs.a5;
2600 nqcCoeffsInput->data[6] = nqcCoeffs.b1;
2601 nqcCoeffsInput->data[7] = nqcCoeffs.b2;
2602 nqcCoeffsInput->data[8] = nqcCoeffs.b3;
2603 nqcCoeffsInput->data[9] = nqcCoeffs.b4;
2604
2605
2606 // FINISHED COMPUTING NQC. NOW MUST FREE ALLOCATED MEMORY!
2607
2608 XLALDestroyREAL8Vector (tmpValues);
2609 XLALDestroyREAL8Vector (sigmaKerr);
2610 XLALDestroyREAL8Vector (sigmaStar);
2611 XLALDestroyREAL8Vector (values);
2612 XLALDestroyREAL8Vector (ampNQC);
2613 XLALDestroyREAL8Vector (phaseNQC);
2614 XLALDestroyREAL8Vector (sigReVec);
2615 XLALDestroyREAL8Vector (sigImVec);
2616 XLALAdaptiveRungeKuttaFree (integrator);
2617 XLALDestroyREAL8Array (dynamics);
2618 XLALDestroyREAL8Array (dynamicsHi);
2619
2620 if (dynamicstmp)
2621 {
2622 XLALDestroyREAL8Array (dynamicstmp);
2623 }
2624 if (dynamicsHitmp)
2625 {
2626 XLALDestroyREAL8Array (dynamicsHitmp);
2627 }
2628
2629 XLALDestroyREAL8Vector (sigReHi);
2630 XLALDestroyREAL8Vector (sigImHi);
2631 XLALDestroyREAL8Vector (omegaHi);
2632
2633#if debugOutput
2634 printf
2635 ("Tidal point-mass NQC should not be 0 here: %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
2636 nqcCoeffs.a1, nqcCoeffs.a2, nqcCoeffs.a3, nqcCoeffs.a3S, nqcCoeffs.a4,
2637 nqcCoeffs.a5, nqcCoeffs.b1, nqcCoeffs.b2, nqcCoeffs.b3, nqcCoeffs.b4);
2638#endif
2639 return XLAL_SUCCESS;
2640 }
2641 /* Here we store the NQC coefficients for the different modes in some matrices */
2642 gsl_matrix_set(nqcCoeffsMatrix,k,0, nqcCoeffs.a1);
2643 gsl_matrix_set(nqcCoeffsMatrix,k,1, nqcCoeffs.a2);
2644 gsl_matrix_set(nqcCoeffsMatrix,k,2, nqcCoeffs.a3);
2645 gsl_matrix_set(nqcCoeffsMatrix,k,3, nqcCoeffs.a3S);
2646 gsl_matrix_set(nqcCoeffsMatrix,k,4, nqcCoeffs.a4);
2647 gsl_matrix_set(nqcCoeffsMatrix,k,5, nqcCoeffs.a5);
2648 gsl_matrix_set(nqcCoeffsMatrix,k,6, nqcCoeffs.b1);
2649 gsl_matrix_set(nqcCoeffsMatrix,k,7, nqcCoeffs.b2);
2650 gsl_matrix_set(nqcCoeffsMatrix,k,8, nqcCoeffs.b3);
2651 gsl_matrix_set(nqcCoeffsMatrix,k,9, nqcCoeffs.b4);
2652#if debugOutput
2653 printf
2654 ("(%d,%d)-mode NQC should not be 0 here: %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
2655 modeL, modeM, nqcCoeffs.a1, nqcCoeffs.a2, nqcCoeffs.a3, nqcCoeffs.a3S, nqcCoeffs.a4,
2656 nqcCoeffs.a5, nqcCoeffs.b1, nqcCoeffs.b2, nqcCoeffs.b3, nqcCoeffs.b4);
2657 FILE *NQC = NULL;
2658 sprintf(filename2,"NQC%01d%01dHi.dat",modeL,modeM);
2659 NQC = fopen (filename2, "w");
2660 fprintf(NQC, "%.16e \n%.16e \n%.16e \n%.16e \n%.16e\n", nqcCoeffs.a1, nqcCoeffs.a2, nqcCoeffs.a3,nqcCoeffs.b1, nqcCoeffs.b2);
2661 fclose(NQC);
2662#endif
2663
2664
2665/* Apply to the high sampled part */
2666#if debugOutput
2667 char filename[sizeof "saModesXXHiNQC.dat"];
2668 sprintf(filename,"saModes%01d%01dHiNQC.dat",modeL,modeM);
2669 out = fopen (filename, "w");
2670#endif
2671 for (i = 0; i < retLen; i++)
2672 {
2673 values->data[0] = rHi.data[i];
2674 values->data[1] = phiHi.data[i];
2675 values->data[2] = prHi.data[i];
2676 values->data[3] = pPhiHi.data[i];
2677
2679 (&hNQC, values, omegaHi->data[i], &nqcCoeffs) == XLAL_FAILURE)
2680 {
2681 if(tmpValues){
2682 XLALDestroyREAL8Vector (tmpValues);
2683 }
2684 if(sigmaKerr){
2685 XLALDestroyREAL8Vector (sigmaKerr);
2686 }
2687 if(sigmaStar){
2688 XLALDestroyREAL8Vector (sigmaStar);
2689 }
2690 if(values){
2691 XLALDestroyREAL8Vector (values);
2692 }
2693 if(sigReHi){
2694 XLALDestroyREAL8Vector(sigReHi);
2695 }
2696 if(sigImHi){
2697 XLALDestroyREAL8Vector(sigImHi);
2698 }
2699 if(omegaHi){
2700 XLALDestroyREAL8Vector(omegaHi);
2701 }
2702 if(vPhiVecHi){
2703 XLALDestroyREAL8Vector(vPhiVecHi);
2704 }
2705 if(ampNQC){
2706 XLALDestroyREAL8Vector(ampNQC);
2707 }
2708 if(phaseNQC){
2709 XLALDestroyREAL8Vector(phaseNQC);
2710 }
2711 if(hamVHi){
2712 XLALDestroyREAL8Vector(hamVHi);
2713 }
2714 if(hLMAllHi){
2715 XLALDestroyREAL8Vector(hLMAllHi);
2716 }
2718 }
2719 hLM = sigReHi->data[i];
2720 hLM += I * sigImHi->data[i];
2721 hLM *= hNQC;
2722 if ( (lambda2Tidal1 != 0. && omega02Tidal1 != 0.) || (lambda2Tidal2 != 0. && omega02Tidal2 != 0.) ) {
2724 (&hT, values, cbrt(omegaHi->data[i]), 2, 2, &seobParams) )
2725 {
2727 }
2728 hLM += amp0*hT;
2729 }
2730
2731 sigReHi->data[i] = (REAL8) creal (hLM);
2732 sigImHi->data[i] = (REAL8) cimag (hLM);
2733
2734
2735
2736 hLMAllHi->data[2*k*sigReHi->length + i] = sigReHi->data[i];
2737 hLMAllHi->data[(1+2*k)*sigReHi->length + i] = sigImHi->data[i];
2738#if debugOutput
2739 fprintf (out, "%.16e %.16e %.16e %.16e %.16e\n", timeHi.data[i],
2740 creal (hLM) / amp0, cimag (hLM) / amp0,
2741 hLMAllHi->data[2*k*sigReHi->length + i]/ amp0 ,hLMAllHi->data[(1+2*k)*sigReHi->length + i]/ amp0
2742 );
2743#endif
2744
2745 if (SpinAlignedEOBversion==1 || SpinAlignedEOBversion==2) {
2746 sigAmpSqHi = creal (hLM) * creal (hLM) + cimag (hLM) * cimag (hLM);
2747 if (sigAmpSqHi < oldsigAmpSqHi && peakCount == 0 && (i - 1) * deltaTHigh / mTScaled < timePeak-timewavePeak)
2748 {
2749 timewavePeak = (i - 1) * deltaTHigh / mTScaled;
2750 peakCount += 1;
2751 }
2752 oldsigAmpSqHi = sigAmpSqHi;
2753 }
2754 }
2755#if debugOutput
2756 fclose (out);
2757 printf ("NQCs entering hNQC: %f, %f, %f, %f, %f, %f\n", nqcCoeffs.a1,
2758 nqcCoeffs.a2, nqcCoeffs.a3, nqcCoeffs.a3S, nqcCoeffs.a4,
2759 nqcCoeffs.a5);
2760 printf ("NQCs entering hNQC: %f, %f, %f, %f\n", nqcCoeffs.b1, nqcCoeffs.b2,
2761 nqcCoeffs.b3, nqcCoeffs.b4);
2762 printf ("Stas, again: timePeak = %.16f, timewavePeak = %.16f \n", timePeak,
2763 timewavePeak);
2764#endif
2765
2766}
2767
2768
2769
2770
2771/* REMOVE THIS */
2772
2773
2774 if (timewavePeak < 1.0e-16 || peakCount == 0)
2775 {
2776 //printf("YP::warning: could not locate mode peak, use calibrated time shift of amplitude peak instead.\n");
2777 /* NOTE: instead of looking for the actual peak, use the calibrated value, */
2778 /* ignoring the error in using interpolated NQC instead of iterated NQC */
2779 timewavePeak = timePeak - timewavePeak;
2780 }
2781
2782 /*
2783 * STEP 6) Calculate QNM excitation coefficients using hi-sampling data
2784 */
2785
2786 /*out = fopen( "saInspWaveHi.dat", "w" );
2787 for ( i = 0; i < retLen; i++ )
2788 {
2789 fprintf( out, "%.16e %.16e %.16e\n", timeHi.data[i], sigReHi->data[i], sigImHi->data[i] );
2790 }
2791 fclose( out ); */
2792
2793 /* Attach the ringdown at the time of amplitude peak */
2794 REAL8 combSize = 7.5; /* Eq. 34 */
2795 REAL8 chi =
2796 (spin1[2] + spin2[2]) / 2. +
2797 ((spin1[2] - spin2[2]) / 2.) * ((m1 - m2) / (m1 + m2)) / (1. - 2. * eta);
2798
2799 /* Modify the combsize for SEOBNRv2 */
2800 /* If chi1=chi2=0, comb = 11. if chi < 0.8, comb = 12. if chi >= 0.8, comb =
2801 * 13.5 */
2802 //RC: the combsize is not used for the RD attachment for v4, I don't understand why the code enters inside this loop even for v4...
2803 if (SpinAlignedEOBversion == 2 || SpinAlignedEOBversion == 4)
2804 {
2805 combSize = (spin1[2] == 0.
2806 && spin2[2] == 0.) ? 11. : ((eta > 10. / 121.
2807 && chi >= 0.8) ? 8.5 : 12.);
2808 if ((eta > 30. / 31. / 31. && eta <= 10. / 121. && chi >= 0.8)
2809 || (eta <= 30. / 31. / 31. && chi >= 0.8 && chi < 0.9))
2810 combSize = 13.5;
2811 }
2812
2813 REAL8 timeshiftPeak;
2814 timeshiftPeak = timePeak - timewavePeak;
2815 if (SpinAlignedEOBversion == 2 || SpinAlignedEOBversion == 4)
2816 {
2817 timeshiftPeak =
2818 (timePeak - timewavePeak) > 0. ? (timePeak - timewavePeak) : 0.;
2819 }
2820
2821 /*printf("YP::timePeak and timewavePeak: %.16e and %.16e\n",timePeak,timewavePeak);
2822 printf("YP::timeshiftPeak and combSize: %.16e and %.16e\n",timeshiftPeak,combSize);
2823 printf("PK::chi and SpinAlignedEOBversion: %.16e and %u\n\n", chi,SpinAlignedEOBversion); */
2824
2825 REAL8Vector *rdMatchPoint = XLALCreateREAL8Vector (4);
2826 if (!rdMatchPoint)
2827 {
2828 if(tmpValues){
2829 XLALDestroyREAL8Vector (tmpValues);
2830 }
2831 if(sigmaKerr){
2832 XLALDestroyREAL8Vector (sigmaKerr);
2833 }
2834 if(sigmaStar){
2835 XLALDestroyREAL8Vector (sigmaStar);
2836 }
2837 if(values){
2838 XLALDestroyREAL8Vector (values);
2839 }
2840 if(sigReHi){
2841 XLALDestroyREAL8Vector(sigReHi);
2842 }
2843 if(sigImHi){
2844 XLALDestroyREAL8Vector(sigImHi);
2845 }
2846 if(omegaHi){
2847 XLALDestroyREAL8Vector(omegaHi);
2848 }
2849 if(vPhiVecHi){
2850 XLALDestroyREAL8Vector(vPhiVecHi);
2851 }
2852 if(ampNQC){
2853 XLALDestroyREAL8Vector(ampNQC);
2854 }
2855 if(phaseNQC){
2856 XLALDestroyREAL8Vector(phaseNQC);
2857 }
2858 if(hamVHi){
2859 XLALDestroyREAL8Vector(hamVHi);
2860 }
2861 if(hLMAllHi){
2862 XLALDestroyREAL8Vector(hLMAllHi);
2863 }
2865 }
2866
2867 if (combSize > timePeak - timeshiftPeak)
2868 {
2869 XLALPrintError ("The comb size looks to be too big!!!\n");
2870 }
2871
2872 REAL8Vector *OmVec = NULL;
2873 if (use_tidal == 1) {
2874 timeshiftPeak = 0.;
2875 UINT4 indAmax = 0;
2876 REAL8 Anew, Aval = sqrt( sigReHi->data[0]*sigReHi->data[0] +sigImHi->data[0]*sigImHi->data[0] );
2877 for (i = 1; i < (INT4) timeHi.length; i++) {
2878 Anew = sqrt( sigReHi->data[i]*sigReHi->data[i] +sigImHi->data[i]*sigImHi->data[i]);
2879 if ( Aval > Anew ) {
2880 indAmax = i-1;
2881 break;
2882 } else {
2883 indAmax = i;
2884 Aval = Anew;
2885 }
2886 }
2887#if debugOutput
2888 printf("indAmax %d\n",indAmax);
2889#endif
2890
2891 if ( (INT4)indAmax== (INT4) timeHi.length-1 ) {
2892 INT4 peakDet = 0;
2893 REAL8 dAnew, dAval;
2894 REAL8 Avalp = sqrt( sigReHi->data[1]*sigReHi->data[1] +sigImHi->data[1]*sigImHi->data[1] );
2895 REAL8 Avalm = sqrt( sigReHi->data[0]*sigReHi->data[0] +sigImHi->data[0]*sigImHi->data[0] );
2896 dAval= Avalp - Avalm;
2897 INT4 iSkip = (INT4) 1./(deltaTHigh / mTScaled);
2898 for (i=(INT4) timeHi.length/2; i<(INT4) timeHi.length; i=i+iSkip) {
2899 Avalm = sqrt( sigReHi->data[i-1]*sigReHi->data[i-1] +sigImHi->data[i-1]*sigImHi->data[i-1]);
2900 Avalp = sqrt( sigReHi->data[i]*sigReHi->data[i] +sigImHi->data[i]*sigImHi->data[i]);
2901 dAnew = Avalp - Avalm;
2902#if debugOutput
2903 printf("%.16e %.16e %.16e\n", i*deltaTHigh / mTScaled, dAnew, dAval);
2904#endif
2905 if ( peakDet==0) {
2906 if ( dAnew<dAval) peakDet++;
2907 dAval = dAnew;
2908 }
2909 else {
2910 if ( dAnew>dAval ) {
2911 indAmax = i-1;
2912 break;
2913 }
2914 else {
2915 dAval = dAnew;
2916 }
2917 }
2918 }
2919 }
2920#if debugOutput
2921 printf("indAmax %d\n",indAmax);
2922#endif
2923 UINT4 indOmax = 0;
2924 REAL8 dt = timeHi.data[1] - timeHi.data[0];
2925 REAL8 re = sigReHi->data[0], im = sigImHi->data[0];
2926 REAL8 red = ( sigReHi->data[1] - sigReHi->data[0] ) / dt, imd = ( sigImHi->data[1] - sigImHi->data[0] ) / dt;
2927 REAL8 Onew, Oval = - (imd*re - red*im) / (re*re + im*im);
2928
2929 OmVec = XLALCreateREAL8Vector (sigReHi->length);
2930 memset (OmVec->data, 0, OmVec->length * sizeof (REAL8));
2931
2932 for (i = 1; i < (INT4) timeHi.length-1; i++) {
2933 re = sigReHi->data[i];
2934 im = sigImHi->data[i];
2935 red = ( sigReHi->data[i+1] - sigReHi->data[i] ) / dt;
2936 imd = ( sigImHi->data[i+1] - sigImHi->data[i] ) / dt;
2937 Onew = - (imd*re - red*im) / (re*re + im*im);
2938 OmVec->data[i] = Onew;
2939 if ( Onew >= Oval ) {
2940 indOmax = i;
2941 Oval = Onew;
2942 }
2943 }
2944
2945 if ( indAmax>timeHi.length/2 && timeHi.data[indAmax] <= timeHi.data[indOmax] ) {
2946 timePeak = timeHi.data[indAmax] ;
2947 }
2948 else {
2949 timePeak = timeHi.data[indOmax];
2950 }
2951 if ( eobParams.NyquistStop ==1 ) timePeak = timeHi.data[timeHi.length - 1];
2952 }
2953
2954 /* Having located the peak of orbital frequency, we set time and phase of coalescence */
2955 if(!postAdiabaticFlag){
2956 XLALGPSAdd (&tc, -mTScaled * (dynamics->data[hiSRndx] + timePeak));
2957 }
2958
2959
2960 rdMatchPoint->data[0] =
2961 combSize <
2962 timePeak - timeshiftPeak ? timePeak - timeshiftPeak - combSize : 0;
2963 //rdMatchPoint->data[0] = timePeak + 2.0*deltaTHigh;
2964 rdMatchPoint->data[1] = timePeak - timeshiftPeak;
2965 rdMatchPoint->data[2] = dynamicsHi->data[finalIdx];
2966#if debugOutput
2967 printf ("YP::comb range: %f, %f\n", rdMatchPoint->data[0],
2968 rdMatchPoint->data[1]);
2969#endif
2970 rdMatchPoint->data[0] -=
2971 fmod (rdMatchPoint->data[0], deltaTHigh / mTScaled);
2972 rdMatchPoint->data[1] -=
2973 fmod (rdMatchPoint->data[1], deltaTHigh / mTScaled);
2974#if debugOutput
2975 printf("tattach = %.16f\n", rdMatchPoint->data[1]);
2976#endif
2977UINT4 indAmpMax = 0; //RC this variable is only used for SEOBNRv4HM. It stores the index of the attaching point of the 22 mode
2978
2979for ( UINT4 k = 0; k<nModes; k++) {
2980
2981 modeL = lmModes[k][0];
2982 modeM = lmModes[k][1];
2983
2984 //RC: Here I modify the attachment point for the 55 mode, which is tpeak22 -10M and is passed with the variable rdMatchPoint->data[3]
2985 if((modeL == 5)&&(modeM==5)){
2986 rdMatchPoint->data[3] = timePeak - timeshiftPeak-10;
2987 rdMatchPoint->data[3] -= fmod (rdMatchPoint->data[3], deltaTHigh / mTScaled);
2988 }
2989
2990 for ( i=0; i<retLen; i++ ) {
2991 sigReHi->data[i] = hLMAllHi->data[i + 2*k*sigReHi->length];
2992 sigImHi->data[i] = hLMAllHi->data[i + (2*k+1)*sigReHi->length];
2993 }
2994 for ( i=retLen; i<(INT4)sigReHi->length; i++ ) {
2995 sigReHi->data[i] = 0.;
2996 sigImHi->data[i] = 0.;
2997 }
2998
2999 if ( use_tidal == 1 ) {
3000 INT4 kount;
3001 REAL8 dtGeom = deltaTHigh / mTScaled;
3002 REAL8Vector *ampl, *phtmp;
3003 ampl = XLALCreateREAL8Vector (sigReHi->length);
3004 memset (ampl->data, 0, ampl->length * sizeof (REAL8));
3005 phtmp = XLALCreateREAL8Vector (sigReHi->length);
3006 memset (phtmp->data, 0,phtmp->length * sizeof (REAL8));
3007 INT4 iEnd= (INT4)rdMatchPoint->data[1]/dtGeom;
3008 UINT4 iM = iEnd - 1000;
3009 REAL8 omega0 = OmVec->data[iEnd];
3010 REAL8 omegaM = OmVec->data[iM];
3011 REAL8 omegaMdot = (OmVec->data[iM]-OmVec->data[iM-10])/(10*dtGeom);
3012 REAL8 tau = 0.5*LAL_PI/omega0;
3013
3014 for (kount=0; kount<iEnd; kount++){
3015 ampl->data[kount] = sqrt(sigReHi->data[kount]/amp0*sigReHi->data[kount]/amp0 + sigImHi->data[kount]/amp0*sigImHi->data[kount]/amp0)/(1. + exp((kount*dtGeom-rdMatchPoint->data[1]-15)/tau));
3016 phtmp->data[kount] = carg(sigReHi->data[kount] + I * sigImHi->data[kount]);
3017 }
3018 REAL8 amplEnd = sqrt(sigReHi->data[iEnd]/amp0*sigReHi->data[iEnd]/amp0 + sigImHi->data[iEnd]/amp0*sigImHi->data[iEnd]/amp0);
3019 REAL8 amplEndM1 = sqrt(sigReHi->data[iEnd-1]/amp0*sigReHi->data[iEnd-1]/amp0 + sigImHi->data[iEnd-1]/amp0*sigImHi->data[iEnd-1]/amp0);
3020 REAL8 ampldotEnd = (amplEnd-amplEndM1)/dtGeom;
3021 if ( ampldotEnd < 0. ) ampldotEnd = 0.;
3022 for (kount=iEnd;kount<(INT4)(sigReHi->length);kount++){
3023 ampl->data[kount] = (amplEnd + ampldotEnd*(kount - iEnd)*dtGeom)/(1. + exp((kount*dtGeom-rdMatchPoint->data[1]-15)/tau));
3024 }
3025 for (kount=(INT4)iM;kount<(INT4)(sigReHi->length);kount++){
3026 phtmp->data[kount] = phtmp->data[iM] - ( omega0*(kount-(INT4)iM)*dtGeom + (omega0-omegaM)*(omega0-omegaM)/omegaMdot*(exp(-(kount-(INT4)iM)*dtGeom/(omega0-omegaM)*omegaMdot) - 1.) );
3027 }
3028#if debugOutput
3029 FILE *testout = fopen ("test.dat", "w");
3030 for (kount=0;kount<(INT4)(sigReHi->length);kount++){
3031 fprintf(testout, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e\n", kount*dtGeom,ampl->data[kount],phtmp->data[kount],sigReHi->data[kount],sigImHi->data[kount],sqrt(sigReHi->data[kount]/amp0*sigReHi->data[kount]/amp0 + sigImHi->data[kount]/amp0*sigImHi->data[kount]/amp0),carg(sigReHi->data[kount] + I * sigImHi->data[kount]));
3032 }
3033 fclose(testout);
3034#endif
3035 for (kount=0;kount<(INT4)(sigReHi->length);kount++){
3036 sigReHi->data[kount] = amp0*ampl->data[kount]*cos(phtmp->data[kount]);
3037 sigImHi->data[kount] = amp0*ampl->data[kount]*sin(phtmp->data[kount]);
3038 }
3041 /*
3042 if (XLALSimIMREOBTaper (sigReHi, sigImHi, 2, 2,
3043 deltaTHigh, m1, m2, spin1[0],
3044 spin1[1], spin1[2], spin2[0],
3045 spin2[1], spin2[2], &timeHi,
3046 rdMatchPoint,
3047 SpinAlignedEOBapproximant) ==
3048 XLAL_FAILURE)
3049 {
3050 XLAL_ERROR (XLAL_EFUNC);
3051 }
3052 */
3053 }
3054 else {
3055 if (SpinAlignedEOBversion == 1 || SpinAlignedEOBversion == 2)
3056 {
3057 if (XLALSimIMREOBHybridAttachRingdown (sigReHi, sigImHi, 2, 2,
3058 deltaTHigh, m1, m2, spin1[0],
3059 spin1[1], spin1[2], spin2[0],
3060 spin2[1], spin2[2], &timeHi,
3061 rdMatchPoint,
3062 SpinAlignedEOBapproximant) ==
3064 {
3066 }
3067 }
3068 else if (SpinAlignedEOBversion == 4)
3069 {
3071 sigReHi, sigImHi, modeL, modeM,
3072 deltaTHigh, m1, m2,
3073 spin1[0], spin1[1], spin1[2],
3074 spin2[0], spin2[1], spin2[2],
3075 domega220, dtau220,
3076 domega210, dtau210,
3077 domega330, dtau330,
3078 domega440, dtau440,
3079 domega550, dtau550,
3080 TGRflag,
3081 &timeHi,
3082 rdMatchPoint,
3083 SpinAlignedEOBapproximant, &indAmpMax) ==
3085 {
3086 if(tmpValues){
3087 XLALDestroyREAL8Vector (tmpValues);
3088 }
3089 if(sigmaKerr){
3090 XLALDestroyREAL8Vector (sigmaKerr);
3091 }
3092 if(sigmaStar){
3093 XLALDestroyREAL8Vector (sigmaStar);
3094 }
3095 if(values){
3096 XLALDestroyREAL8Vector (values);
3097 }
3098 if(sigReHi){
3099 XLALDestroyREAL8Vector(sigReHi);
3100 }
3101 if(sigImHi){
3102 XLALDestroyREAL8Vector(sigImHi);
3103 }
3104 if(omegaHi){
3105 XLALDestroyREAL8Vector(omegaHi);
3106 }
3107 if(vPhiVecHi){
3108 XLALDestroyREAL8Vector(vPhiVecHi);
3109 }
3110 if(ampNQC){
3111 XLALDestroyREAL8Vector(ampNQC);
3112 }
3113 if(phaseNQC){
3114 XLALDestroyREAL8Vector(phaseNQC);
3115 }
3116 if(hamVHi){
3117 XLALDestroyREAL8Vector(hamVHi);
3118 }
3119 if(hLMAllHi){
3120 XLALDestroyREAL8Vector(hLMAllHi);
3121 }
3123 }
3124
3125 }
3126
3127 }
3128 for ( i=0; i<(INT4)sigReHi->length; i++) {
3129 hLMAllHi->data[2*k*sigReHi->length + i] = sigReHi->data[i];
3130 hLMAllHi->data[(1+2*k)*sigReHi->length + i] = sigImHi->data[i];
3131 }
3132#if debugOutput
3133 char filename[sizeof "saModesXXHiIMR.dat"];
3134 sprintf(filename,"saModes%01d%01dHiIMR.dat",modeL,modeM);
3135 out = fopen (filename, "w");
3136 for ( i=0; i<(INT4)sigReHi->length; i++) {
3137 fprintf (out, "%.16e %.16e %.16e\n", i*deltaTHigh / mTScaled,hLMAllHi->data[2*k*sigReHi->length + i]/amp0,hLMAllHi->data[(1+2*k)*sigReHi->length + i]/amp0);
3138 }
3139 fclose(out);
3140#endif
3141
3142
3143}
3144
3145
3146 /*
3147 * STEP 7) Generate full inspiral waveform using desired sampling frequency
3148 */
3149
3150 if (use_optimized_v2_or_v4)
3151 {
3152 // maybe dynamicstmp and dynamicsHitmp should be called "intermediateDynamics(Hi)" now since they aren't so temporary anymore?
3153 GenerateAmpPhaseFromEOMSoln (retLen_fromOptStep2, dynamicstmp->data,
3154 &seobParams);
3155 /*
3156 * We used dynamics and dynamicsHi to store solution to equations of motion.
3157 * The solution was needed to find, e.g., the time at peak freq (STEP 4).
3158 * At this point, the solution to the EOMs is no longer needed, so we
3159 * now repurpose dynamics and dynamicsHi to store amplitude and phase
3160 * information only.
3161` * This is the most efficient solution, as it frees up unused memory.
3162 */
3163 XLALDestroyREAL8Array (dynamics);
3164 XLALDestroyREAL8Array (dynamicsHi);
3165 dynamics = NULL;
3166 dynamicsHi = NULL;
3167 retLen =
3169 deltaT / mTScaled,
3170 retLen_fromOptStep2,
3171 &dynamics);
3172
3173 ampVec.length = phaseVec.length = retLen;
3174 ampVec.data = dynamics->data + 5 * retLen;
3175 phaseVec.data = dynamics->data + 6 * retLen;
3176
3177 GenerateAmpPhaseFromEOMSoln (retLen_fromOptStep3, dynamicsHitmp->data,
3178 &seobParams);
3179 retLen =
3181 deltaTHigh / mTScaled,
3182 retLen_fromOptStep3,
3183 &dynamicsHi);
3184 }
3185
3186
3187
3188
3189 /* Now create vectors at the correct sample rate, and compile the complete waveform */
3190 if(postAdiabaticFlag && postAdiabaticOutcome == XLAL_SUCCESS){
3191 sigReVec =
3192 XLALCreateREAL8Vector (combinedLenForInterp + ceil (sigReHi->length / resampFac));
3193 sigImVec = XLALCreateREAL8Vector (sigReVec->length);
3194 }
3195 else{
3196 sigReVec =
3197 XLALCreateREAL8Vector (rVec.length + ceil (sigReHi->length / resampFac));
3198 sigImVec = XLALCreateREAL8Vector (sigReVec->length);
3199 }
3200 memset (sigReVec->data, 0, sigReVec->length * sizeof (REAL8));
3201 memset (sigImVec->data, 0, sigImVec->length * sizeof (REAL8));
3202
3203 REAL8Vector *sigReCoorbVec =
3204 XLALCreateREAL8Vector (combinedLenForInterp + ceil (sigReHi->length / resampFac));
3205 REAL8Vector *sigImCoorbVec = XLALCreateREAL8Vector (sigReCoorbVec ->length);
3206
3207 memset (sigReCoorbVec->data, 0, sigReCoorbVec->length * sizeof (REAL8));
3208 memset (sigImCoorbVec->data, 0, sigImCoorbVec->length * sizeof (REAL8));
3209 // PA: the spacing is not regular on the dynamics grid, so must be careful
3210 // to set the correct length with the desired spacing
3211
3212 hLMAll = XLALCreateREAL8Vector((UINT4)2*sigReVec->length*nModes);
3213 memset(hLMAll->data, 0, hLMAll->length*sizeof (REAL8));
3214
3215 UINT4 idx = 0;
3216 /* Generate full inspiral waveform using desired sampling frequency */
3217 if (use_optimized_v2_or_v4)
3218 {
3219 for (i = 0; i < (INT4) rVec.length; i++)
3220 {
3221
3222 hLM = ampVec.data[i] * cexp (I * phaseVec.data[i]);
3223
3224 sigReVec->data[i] = amp0 * creal (hLM);
3225 sigImVec->data[i] = amp0 * cimag (hLM);
3226 hLMAll->data[i] = sigReVec->data[i];
3227 hLMAll->data[sigReVec->length + i] = sigImVec->data[i];
3228 }
3229 }
3230 else
3231 {
3232#if debugOutput
3233 out = fopen ("saDynamics.dat", "w");
3234#endif
3235 hamV = XLALCreateREAL8Vector(rVec.length);
3236 memset(hamV->data, 0., hamV->length*sizeof(REAL8));
3237
3238 omegaVec = XLALCreateREAL8Vector(rVec.length);
3239 memset(omegaVec->data, 0., omegaVec->length*sizeof(REAL8));
3240
3241 vPhiVec = XLALCreateREAL8Vector(rVec.length);
3242 memset(vPhiVec->data, 0., vPhiVec->length*sizeof(REAL8));
3243
3244 if (!omegaVec|| !hamV)
3245 {
3246 if(tmpValues){
3247 XLALDestroyREAL8Vector (tmpValues);
3248 }
3249 if(sigmaKerr){
3250 XLALDestroyREAL8Vector (sigmaKerr);
3251 }
3252 if(sigmaStar){
3253 XLALDestroyREAL8Vector (sigmaStar);
3254 }
3255 if(values){
3256 XLALDestroyREAL8Vector (values);
3257 }
3258 if(sigReHi){
3259 XLALDestroyREAL8Vector(sigReHi);
3260 }
3261 if(sigImHi){
3262 XLALDestroyREAL8Vector(sigImHi);
3263 }
3264 if(omegaHi){
3265 XLALDestroyREAL8Vector(omegaHi);
3266 }
3267 if(vPhiVecHi){
3268 XLALDestroyREAL8Vector(vPhiVecHi);
3269 }
3270 if(ampNQC){
3271 XLALDestroyREAL8Vector(ampNQC);
3272 }
3273 if(phaseNQC){
3274 XLALDestroyREAL8Vector(phaseNQC);
3275 }
3276 if(hamVHi){
3277 XLALDestroyREAL8Vector(hamVHi);
3278 }
3279 if(hLMAllHi){
3280 XLALDestroyREAL8Vector(hLMAllHi);
3281 }
3282 if(sigReVec){
3283 XLALDestroyREAL8Vector(sigReVec);
3284 }
3285 if(sigImVec){
3286 XLALDestroyREAL8Vector(sigImVec);
3287 }
3288 if(hLMAll){
3289 XLALDestroyREAL8Vector(hLMAll);
3290 }
3291 if(vPhiVec)
3292 XLALDestroyREAL8Vector(vPhiVec);
3293
3295 }
3296 for (i = 0; i < (INT4) rVec.length; i++)
3297 {
3298 values->data[0] = rVec.data[i];
3299 values->data[1] = phiVec.data[i];
3300 values->data[2] = prVec.data[i];
3301 values->data[3] = pPhiVec.data[i];
3302 /* Do not need to add an if(use_optimized_v2_or_v4), since this is strictly unoptimized code (see if(use_optimized_v2_or_v4) above) */
3303 if (postAdiabaticFlag){
3304 omegaVec->data[i] = XLALSimIMRSpinAlignedEOBCalcOmegaOptimized (values->data, &seobParams);
3305 vPhiVec->data[i] = XLALSimIMRSpinAlignedEOBNonKeplerCoeffOptimized (values->data, &seobParams);
3306
3307 }
3308 else{
3309 omegaVec->data[i] = XLALSimIMRSpinAlignedEOBCalcOmega (values->data, &seobParams, STEP_SIZE);
3310 }
3311
3312 //
3313
3314#if debugOutput
3315 fprintf (out, "%.16e %.16e %.16e %.16e %.16e %.16e\n", dynamics->data[i],
3316 rVec.data[i], phiVec.data[i], prVec.data[i], pPhiVec.data[i],omegaVec->data[i]);
3317#endif
3318 /* Calculate the value of the Hamiltonian */
3319 cartPosVec.data[0] = values->data[0];
3320 cartMomVec.data[0] = values->data[2];
3321 cartMomVec.data[1] = values->data[3] / values->data[0];
3322
3323 if(postAdiabaticFlag){
3324 hamV->data[i] =
3325 XLALSimIMRSpinEOBHamiltonianOptimized (eta, &cartPosVec, &cartMomVec,
3326 &s1VecOverMtMt, &s2VecOverMtMt,
3327 sigmaKerr, sigmaStar,
3328 seobParams.tortoise, &seobCoeffs);
3329 }
3330 else{
3331 hamV->data[i] =
3332 XLALSimIMRSpinEOBHamiltonian (eta, &cartPosVec, &cartMomVec,
3333 &s1VecOverMtMt, &s2VecOverMtMt,
3334 sigmaKerr, sigmaStar,
3335 seobParams.tortoise, &seobCoeffs);
3336 }
3337 }
3338
3339
3340 // Interpolants for Re/Im parts of coorb modes
3341 UNUSED gsl_interp_accel *acc_re = gsl_interp_accel_alloc();
3342 gsl_spline *spline_re = gsl_spline_alloc(gsl_interp_cspline, rVec.length);
3343 UNUSED gsl_interp_accel *acc_im = gsl_interp_accel_alloc();
3344 gsl_spline *spline_im = gsl_spline_alloc(gsl_interp_cspline, rVec.length);
3345 // Interpolant for orbital phase
3346 UNUSED gsl_interp_accel *acc_orbphase = gsl_interp_accel_alloc();
3347 gsl_spline *spline_orbphase = gsl_spline_alloc(gsl_interp_cspline, rVec.length);
3348 gsl_spline_init(spline_orbphase, tVec.data, phiVec.data, rVec.length);
3349
3350
3351 for ( UINT4 k = 0; k<nModes; k++) {
3352 modeL = lmModes[k][0];
3353 modeM = lmModes[k][1];
3354
3355 nqcCoeffs.a1 = gsl_matrix_get(nqcCoeffsMatrix,k,0);
3356 nqcCoeffs.a2 = gsl_matrix_get(nqcCoeffsMatrix,k,1);
3357 nqcCoeffs.a3 = gsl_matrix_get(nqcCoeffsMatrix,k,2);
3358 nqcCoeffs.a3S = gsl_matrix_get(nqcCoeffsMatrix,k,3);
3359 nqcCoeffs.a4 = gsl_matrix_get(nqcCoeffsMatrix,k,4);
3360 nqcCoeffs.a5 = gsl_matrix_get(nqcCoeffsMatrix,k,5);
3361 nqcCoeffs.b1 = gsl_matrix_get(nqcCoeffsMatrix,k,6);
3362 nqcCoeffs.b2 = gsl_matrix_get(nqcCoeffsMatrix,k,7);
3363 nqcCoeffs.b3 = gsl_matrix_get(nqcCoeffsMatrix,k,8);
3364 nqcCoeffs.b4 = gsl_matrix_get(nqcCoeffsMatrix,k,9);
3365#if debugOutput
3366 printf
3367 ("(%d,%d)-mode NQC should not be 0 here: %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
3368 modeL, modeM, nqcCoeffs.a1, nqcCoeffs.a2, nqcCoeffs.a3, nqcCoeffs.a3S, nqcCoeffs.a4,
3369 nqcCoeffs.a5, nqcCoeffs.b1, nqcCoeffs.b2, nqcCoeffs.b3, nqcCoeffs.b4);
3370#endif
3371 for (i = 0; i < (INT4) rVec.length; i++)
3372 {
3373 values->data[0] = rVec.data[i];
3374 values->data[1] = phiVec.data[i];
3375 values->data[2] = prVec.data[i];
3376 values->data[3] = pPhiVec.data[i];
3377 if(postAdiabaticFlag){
3379 &hLM,
3380 values,
3381 cbrt (omegaVec->data[i]),
3382 hamV->data[i],
3383 modeL,
3384 modeM,
3385 &seobParams,
3386 vPhiVec->data[i]
3387 );
3388 }
3389 else{
3390 status = XLALSimIMRSpinEOBGetSpinFactorizedWaveform(&hLM, values, cbrt (omegaVec->data[i]), hamV->data[i], modeL, modeM, &seobParams, 0 /*use_optimized_v2_or_v4 */ );
3391 }
3392
3393 if ( status == XLAL_FAILURE)
3394 {
3395 if(tmpValues){
3396 XLALDestroyREAL8Vector (tmpValues);
3397 }
3398 if(sigmaKerr){
3399 XLALDestroyREAL8Vector (sigmaKerr);
3400 }
3401 if(sigmaStar){
3402 XLALDestroyREAL8Vector (sigmaStar);
3403 }
3404 if(values){
3405 XLALDestroyREAL8Vector (values);
3406 }
3407 if(sigReHi){
3408 XLALDestroyREAL8Vector(sigReHi);
3409 }
3410 if(sigImHi){
3411 XLALDestroyREAL8Vector(sigImHi);
3412 }
3413 if(omegaHi){
3414 XLALDestroyREAL8Vector(omegaHi);
3415 }
3416 if(vPhiVecHi){
3417 XLALDestroyREAL8Vector(vPhiVecHi);
3418 }
3419 if(ampNQC){
3420 XLALDestroyREAL8Vector(ampNQC);
3421 }
3422 if(phaseNQC){
3423 XLALDestroyREAL8Vector(phaseNQC);
3424 }
3425 if(hamVHi){
3426 XLALDestroyREAL8Vector(hamVHi);
3427 }
3428 if(hLMAllHi){
3429 XLALDestroyREAL8Vector(hLMAllHi);
3430 }
3431 if(sigReVec){
3432 XLALDestroyREAL8Vector(sigReVec);
3433 }
3434 if(sigImVec){
3435 XLALDestroyREAL8Vector(sigImVec);
3436 }
3437 if(hLMAll){
3438 XLALDestroyREAL8Vector(hLMAll);
3439 }
3440 if(vPhiVec)
3441 XLALDestroyREAL8Vector(vPhiVec);
3442
3444 }
3445 hT = 0.;
3446 if ( (lambda2Tidal1 != 0. && omega02Tidal1 != 0.) || (lambda2Tidal2 != 0. && omega02Tidal2 != 0.) ) {
3448 (&hT, values, cbrt (omegaVec->data[i]), 2, 2, &seobParams)
3449 == XLAL_FAILURE)
3450 {
3452 }
3453 }
3454
3455 if (XLALSimIMREOBNonQCCorrection (&hNQC, values, omegaVec->data[i], &nqcCoeffs)
3456 == XLAL_FAILURE)
3457 {
3458 if(tmpValues){
3459 XLALDestroyREAL8Vector (tmpValues);
3460 }
3461 if(sigmaKerr){
3462 XLALDestroyREAL8Vector (sigmaKerr);
3463 }
3464 if(sigmaStar){
3465 XLALDestroyREAL8Vector (sigmaStar);
3466 }
3467 if(values){
3468 XLALDestroyREAL8Vector (values);
3469 }
3470 if(sigReHi){
3471 XLALDestroyREAL8Vector(sigReHi);
3472 }
3473 if(sigImHi){
3474 XLALDestroyREAL8Vector(sigImHi);
3475 }
3476 if(omegaHi){
3477 XLALDestroyREAL8Vector(omegaHi);
3478 }
3479 if(vPhiVecHi){
3480 XLALDestroyREAL8Vector(vPhiVecHi);
3481 }
3482 if(ampNQC){
3483 XLALDestroyREAL8Vector(ampNQC);
3484 }
3485 if(phaseNQC){
3486 XLALDestroyREAL8Vector(phaseNQC);
3487 }
3488 if(hamVHi){
3489 XLALDestroyREAL8Vector(hamVHi);
3490 }
3491 if(hLMAllHi){
3492 XLALDestroyREAL8Vector(hLMAllHi);
3493 }
3494 if(sigReVec){
3495 XLALDestroyREAL8Vector(sigReVec);
3496 }
3497 if(sigImVec){
3498 XLALDestroyREAL8Vector(sigImVec);
3499 }
3500 if(hLMAll){
3501 XLALDestroyREAL8Vector(hLMAll);
3502 }
3504 }
3505
3506 hLM *= hNQC;
3507 hLM += hT;
3508
3509 if (use_tidal==1) {
3510 REAL8 dtGeom = deltaTHigh / mTScaled;
3511 INT4 iEnd= (INT4)rdMatchPoint->data[1]/dtGeom;
3512 REAL8 omega0 = OmVec->data[iEnd];
3513 REAL8 tau = 0.5*LAL_PI/omega0;
3514 REAL8 dtGeomLow = deltaT / mTScaled;
3515 sigReVec->data[i] = amp0 * creal (hLM)/(1. + exp(( i*dtGeomLow - (rdMatchPoint->data[1]+15 + (dynamics->data)[hiSRndx]) )/tau));
3516 sigImVec->data[i] = amp0 * cimag (hLM)/(1. + exp(( i*dtGeomLow - (rdMatchPoint->data[1] +15 + (dynamics->data)[hiSRndx]))/tau));
3517 }
3518 else {
3519 sigReVec->data[i] = amp0 * creal (hLM);
3520 sigImVec->data[i] = amp0 * cimag (hLM);
3521 if(postAdiabaticFlag && postAdiabaticOutcome == XLAL_SUCCESS){
3522 // We need to prepare for interpolation
3523 // We cannot interpolate amplitude and phase directly, because:
3524 // 1. The grid is too sparse and we don't have the unwrapped GW phase
3525 // 2. (2,1) and (5,5) modes can have zeros in the amplitude which
3526 // cause jumps in the phase.
3527 // Thus, we follow the SEOBNRv4HM_ROM paper (https://arxiv.org/pdf/2003.12079.pdf)
3528 // and take out the leading order PN inspiral phasing, interpolate the rest and then transform back.
3529 sigReCoorbVec->data[i] = sigReVec->data[i]*cos(modeM*phiVec.data[i])-sigImVec->data[i]*sin(modeM*phiVec.data[i]);
3530 sigImCoorbVec->data[i] = sigReVec->data[i]*sin(modeM*phiVec.data[i])+sigImVec->data[i]*cos(modeM*phiVec.data[i]);
3531 //printf("i: %d time = %e amp = %e phase = %e\n",i,tVec.data[i],ampVecIn->data[i],phaseVecIn->data[i]);
3532 }
3533 }
3534 if(!postAdiabaticFlag){
3535 hLMAll->data[2*k*sigReVec->length + i] = sigReVec->data[i];
3536 hLMAll->data[(1+2*k)*sigReVec->length + i] = sigImVec->data[i];
3537 }
3538 }
3539 if(postAdiabaticFlag && postAdiabaticOutcome == XLAL_SUCCESS){
3540
3541
3542 gsl_spline_init(spline_re, tVec.data, sigReCoorbVec->data, rVec.length);
3543
3544
3545 gsl_spline_init(spline_im, tVec.data, sigImCoorbVec->data, rVec.length);
3546
3547
3548
3549 REAL8 t_i = 0.0;
3550 REAL8 re_temp = 0.0;
3551 REAL8 im_temp = 0.0;
3552
3553 REAL8 phase_temp = 0.0;
3554 REAL8 re_In = 0.0;
3555 REAL8 im_In = 0.0;
3556 REAL8 cm = 0.0;
3557 REAL8 sm = 0.0;
3558 double x_lo_old = 0, y_lo_old = 0, b_i_old = 0, c_i_old = 0, d_i_old = 0;
3559 double x_lo_old2 = 0, y_lo_old2 = 0, b_i_old2 = 0, c_i_old2 = 0, d_i_old2 = 0;
3560 double x_lo_old3 = 0, y_lo_old3 = 0, b_i_old3 = 0, c_i_old3 = 0, d_i_old3 = 0;
3561 unsigned int index_old = 0, index_old2 = 0, index_old3 = 0;
3562 // printf("Length of rVec is %d\n",rVec.length);
3563 //printf("combinedLenForInterp : %d\n",combinedLenForInterp);
3564 for (i = 0; i < combinedLenForInterp; i++)
3565 {
3566
3567 t_i = i * deltaT / mTScaled;
3568 //printf("%e,%e\n",t_i,tstartHi);
3569 //re_temp = gsl_spline_eval(spline_re, t_i, acc_re);
3570 //im_temp = gsl_spline_eval(spline_im, t_i, acc_im);
3571 //phase_temp = gsl_spline_eval(spline_orbphase, t_i, acc_orbphase);
3572
3573 optimized_gsl_spline_eval_e (spline_re, t_i, acc_re, &re_temp,
3574 &index_old, &x_lo_old, &y_lo_old,
3575 &b_i_old, &c_i_old, &d_i_old);
3576 optimized_gsl_spline_eval_e (spline_im, t_i, acc_im, &im_temp,
3577 &index_old2, &x_lo_old2, &y_lo_old2,
3578 &b_i_old2, &c_i_old2, &d_i_old2);
3579
3580 optimized_gsl_spline_eval_e (spline_orbphase, t_i, acc_orbphase, &phase_temp,
3581 &index_old3, &x_lo_old3, &y_lo_old3,
3582 &b_i_old3, &c_i_old3, &d_i_old3);
3583 cm = cos(modeM * phase_temp);
3584 sm = sin(modeM * phase_temp);
3585
3586 // Reconstruct the intertial frame mode
3587 re_In = re_temp * cm + im_temp * sm;
3588 im_In = -re_temp * sm + im_temp * cm;
3589 hLMAll->data[2 * k * sigReVec->length + i] = re_In;
3590 hLMAll->data[(1 + 2 * k) * sigReVec->length + i] = im_In;
3591 if (t_i > tstartHi && idx == 0)
3592 {
3593 idx = i-1;
3594 }
3595 }
3596 hiSRndx = idx;
3597
3598 }
3599
3600#if outputDebug
3601 fclose (out);
3602 fclose(out2);
3603#endif
3604 }
3605 gsl_spline_free( spline_orbphase);
3606 gsl_interp_accel_free( acc_orbphase );
3607 gsl_spline_free( spline_re);
3608 gsl_interp_accel_free( acc_re );
3609 gsl_spline_free( spline_im);
3610 gsl_interp_accel_free( acc_im );
3611}
3612
3613 if ( OmVec )
3615 if ( omegaVec )
3616 XLALDestroyREAL8Vector(omegaVec);
3617
3618
3619
3620
3621
3622 /*
3623 * STEP 8) Generate full IMR modes -- attaching ringdown to inspiral
3624 */
3625
3626 /* Attach the ringdown part to the inspiral */
3627if(postAdiabaticFlag){
3628 XLALGPSAdd (&tc, -(deltaT*hiSRndx + timePeak*mTScaled));
3629 }
3630for ( UINT4 k = 0; k<nModes; k++) {
3631 for (i = 0; i < (INT4) (sigReHi->length / resampFac); i++)
3632 {
3633 hLMAll->data[2*k*sigReVec->length + i + hiSRndx] = hLMAllHi->data[2*k*sigReHi->length + i*resampFac];
3634 hLMAll->data[(2*k+1)*sigReVec->length + i + hiSRndx] = hLMAllHi->data[(2*k+1)*sigReHi->length + i*resampFac];
3635 }
3636}
3637 // printf("The legnth of sigReVec is %d\n",sigReVec->length);
3638 // printf("The hiSRndx is %d\n",hiSRndx);
3639 // printf("The legnth of sigReHi is %d\n",sigReHi->length);
3640 // printf("The length of hLMAll is %d\n",hLMAll->length);
3641
3642
3643 /* Cut wf if fMin requested by user was high */
3644 INT4 kMin = 0;
3645 if ( fStart != fMin ) {
3646 REAL8 finst;
3647 gsl_spline *splineRe = NULL;
3648 gsl_interp_accel *accRe = NULL;
3649 gsl_spline *splineIm = NULL;
3650 gsl_interp_accel *accIm = NULL;
3651 //RC: since the cut of the waveform is done on the 22 mode, we assign here the 22 mode to sigReVec and sigImVec
3652 for ( i=0; i<(INT4)sigReVec->length; i++) {
3653 sigReVec->data[i] = hLMAll->data[i];
3654 sigImVec->data[i] = hLMAll->data[sigReVec->length + i];
3655 }
3656 REAL8Vector *tmpRe = XLALCreateREAL8Vector(sigReVec->length), *tmpIm = XLALCreateREAL8Vector(sigReVec->length);
3657 for ( i=0; i < (INT4) sigReVec->length; i++) {
3658 tmpRe->data[i] = sigReVec->data[i] / amp0;
3659 tmpIm->data[i] = sigImVec->data[i] / amp0;
3660 }
3661 splineRe = gsl_spline_alloc (gsl_interp_cspline, sigReVec->length);
3662 splineIm = gsl_spline_alloc (gsl_interp_cspline, sigImVec->length);
3663 accRe = gsl_interp_accel_alloc ();
3664 accIm = gsl_interp_accel_alloc ();
3665 REAL8 dRe, dIm;
3666 REAL8Vector *timeList;
3667 timeList = XLALCreateREAL8Vector (sigReVec->length);
3668 for ( i=0; i < (INT4) sigReVec->length; i++) {
3669 timeList->data[i] = i*deltaT/mTScaled;
3670 }
3671 gsl_spline_init (splineRe, timeList->data, tmpRe->data, tmpRe->length);
3672 gsl_spline_init (splineIm, timeList->data, tmpIm->data, tmpIm->length);
3673 REAL8 norm;
3674 for ( i=1; i < (INT4) tmpRe->length - 1; i++) {
3675 norm = tmpRe->data[i]*tmpRe->data[i] + tmpIm->data[i]*tmpIm->data[i];
3676 if ( norm > 0. ) {
3677 dRe = gsl_spline_eval_deriv (splineRe, timeList->data[i], accRe);
3678 dIm = gsl_spline_eval_deriv (splineIm, timeList->data[i], accIm);
3679 finst = (dRe*tmpIm->data[i] - dIm*tmpRe->data[i])/norm;
3680// printf("%.16e %.16e\n", timeList->data[i], finst);
3681 finst = finst/(2.*LAL_PI*mTScaled);
3682// printf("%.16e %.16e %.16e\n", timeList->data[i], finst, fMin);
3683 if ( finst > fMin ) {
3684 kMin = i;
3685 break;
3686 }
3687 }
3688 else {
3689 continue;
3690 }
3691 }
3692 gsl_spline_free( splineRe );
3693 gsl_interp_accel_free( accRe );
3694 gsl_spline_free( splineIm );
3695 gsl_interp_accel_free( accIm );
3696 XLALDestroyREAL8Vector( tmpRe );
3697 XLALDestroyREAL8Vector( tmpIm );
3698 XLALDestroyREAL8Vector(timeList);
3699 }
3700
3701#if debugOutput
3702 for ( UINT4 k = 0; k<nModes; k++) {
3703 modeL = lmModes[k][0];
3704 modeM = lmModes[k][1];
3705 char filename[sizeof "saModesXXIMR.dat"];
3706 sprintf(filename,"saModes%01d%01dIMR.dat",modeL,modeM);
3707 out = fopen (filename, "w");
3708 for ( i=0; i<(INT4)sigReVec->length; i++) {
3709 fprintf (out, "%.16e %.16e %.16e\n", i*deltaT / mTScaled,hLMAll->data[2*k*sigReVec->length + i]/amp0,hLMAll->data[(1+2*k)*sigReVec->length + i]/amp0);
3710 }
3711 fclose(out);
3712 }
3713#endif
3714XLALGPSAdd (&tc, deltaT * (REAL8) kMin);
3715/*
3716 * STEP 9) Generate full IMR hp and hx waveforms
3717 */
3718//RC: this function stops now here and return the array with the modes
3719
3720/*
3721 * STEP 9) Return real and imaginary part of the modes
3722 */
3723 SphHarmTimeSeries *hlms = NULL;
3724 char mode_name[32];
3725
3726for ( UINT4 k = 0; k<nModes; k++) {
3727 modeL = lmModes[k][0];
3728 modeM = lmModes[k][1];
3729 snprintf(mode_name, sizeof(mode_name), "(%d, %d) mode", modeL, modeM);
3730 COMPLEX16TimeSeries *tmp_mode = XLALCreateCOMPLEX16TimeSeries(mode_name, &tc, 0.0,
3731 deltaT, &lalStrainUnit, sigReVec->length - kMin);
3732 for (UINT4 t = kMin; t< (UINT4) sigReVec->length; t++)
3733 {
3734 tmp_mode->data->data[t - kMin] = hLMAll->data[2*k*sigReVec->length + t];
3735 tmp_mode->data->data[t - kMin] += I * hLMAll->data[(2*k+1)*sigReVec->length + t];
3736 }
3737 hlms = XLALSphHarmTimeSeriesAddMode(hlms, tmp_mode, modeL, modeM);
3739 }
3740 /* Point the output pointers to the relevant time series and return */
3741 (*hlmmode) = hlms;
3742
3743 /* Free memory */
3744 XLALDestroyREAL8Vector (tmpValues);
3745 XLALDestroyREAL8Vector (sigmaKerr);
3746 XLALDestroyREAL8Vector (sigmaStar);
3747 XLALDestroyREAL8Vector (values);
3748 XLALDestroyREAL8Vector (rdMatchPoint);
3749 XLALDestroyREAL8Vector (ampNQC);
3750 XLALDestroyREAL8Vector (phaseNQC);
3751 XLALDestroyREAL8Vector (sigReVec);
3752 XLALDestroyREAL8Vector (sigImVec);
3753 XLALDestroyREAL8Vector (sigReCoorbVec);
3754 XLALDestroyREAL8Vector (sigImCoorbVec);
3755 XLALAdaptiveRungeKuttaFree (integrator);
3756 //SM
3757 //XLALDestroyREAL8Array (dynamics);
3758 //XLALDestroyREAL8Array (dynamicsHi);
3759 //SM
3760 gsl_matrix_free (nqcCoeffsMatrix);
3761
3762 if (dynamicstmp)
3763 {
3764 XLALDestroyREAL8Array (dynamicstmp); // DAVIDS: We are done with these now
3765 }
3766 if (dynamicsHitmp)
3767 {
3768 XLALDestroyREAL8Array (dynamicsHitmp); // DAVIDS: Done with these now
3769 }
3770
3771 XLALDestroyREAL8Vector (sigReHi);
3772 XLALDestroyREAL8Vector (sigImHi);
3773 XLALDestroyREAL8Vector (omegaHi);
3774 if ( hLMAllHi )
3775 XLALDestroyREAL8Vector (hLMAllHi);
3776 if ( hLMAll )
3777 XLALDestroyREAL8Vector (hLMAll);
3778 if ( hamV )
3780 if ( hamVHi )
3781 XLALDestroyREAL8Vector (hamVHi);
3782
3783 if (vPhiVec)
3784 XLALDestroyREAL8Vector (vPhiVec);
3785
3786 if (vPhiVecHi)
3787 XLALDestroyREAL8Vector (vPhiVecHi);
3788
3789 if (tVecInterp)
3790 XLALDestroyREAL8Vector(tVecInterp);
3791
3792 if (phiVecInterp)
3793 XLALDestroyREAL8Vector(phiVecInterp);
3794
3795 if (rVecInterp)
3796 XLALDestroyREAL8Vector(rVecInterp);
3797
3798 if (prVecInterp)
3799 XLALDestroyREAL8Vector(prVecInterp);
3800
3801 if (pphiVecInterp)
3802 XLALDestroyREAL8Vector(pphiVecInterp);
3803
3804 //SM
3805 // Copy dynamics to output in the form of a REAL8Vector (required for SWIG wrapping, REAL8Array does not work)
3806 *dynamics_out = XLALCreateREAL8Vector(5 * retLen_out);
3807 *dynamicsHi_out = XLALCreateREAL8Vector(5 * retLenHi_out);
3808 for (i = 0; i < 5*retLen_out; i++) (*dynamics_out)->data[i] = dynamics->data[i];
3809 // We have to add the starting time of the high-sampling dynamics, as the output of the integrator starts with 0
3810 for (i = 0; i < retLenHi_out; i++) (*dynamicsHi_out)->data[i] = tstartHi + dynamicsHi->data[i];
3811 for (i = retLenHi_out; i < 5*retLenHi_out; i++) (*dynamicsHi_out)->data[i] = dynamicsHi->data[i];
3812 XLALDestroyREAL8Array (dynamics);
3813 XLALDestroyREAL8Array (dynamicsHi);
3814 //SM
3815
3816 return XLAL_SUCCESS;
3817 }
3818
3819/**
3820 * This function takes the modes from the function XLALSimIMRSpinAlignedEOBModes and combine them into h+ and hx
3821 */
3822
3823int
3825 REAL8TimeSeries ** hplus,
3826 /**<< OUTPUT, real part of the modes */
3827 REAL8TimeSeries ** hcross,
3828 /**<< OUTPUT, complex part of the modes */
3829 const REAL8 phiC,
3830 /**<< coalescence orbital phase (rad) */
3831 REAL8 deltaT,
3832 /**<< sampling time step */
3833 const REAL8 m1SI,
3834 /**<< mass-1 in SI unit */
3835 const REAL8 m2SI,
3836 /**<< mass-2 in SI unit */
3837 const REAL8 fMin,
3838 /**<< starting frequency of the 22 mode (Hz) */
3839 const REAL8 r,
3840 /**<< distance in SI unit */
3841 const REAL8 inc,
3842 /**<< inclination angle */
3843 const REAL8 spin1z,
3844 /**<< z-component of spin-1, dimensionless */
3845 const REAL8 spin2z,
3846 /**<< z-component of spin-2, dimensionless */
3847 UINT4 SpinAlignedEOBversion,
3848 /**<< 1 for SEOBNRv1, 2 for SEOBNRv2, 4 for SEOBNRv4, 201 for SEOBNRv2T, 401 for SEOBNRv4T, 41 for SEOBNRv4HM */
3849 const REAL8 lambda2Tidal1,
3850 /**<< dimensionless adiabatic quadrupole tidal deformability for body 1 (2/3 k2/C^5) */
3851 const REAL8 lambda2Tidal2,
3852 /**<< dimensionless adiabatic quadrupole tidal deformability for body 2 (2/3 k2/C^5) */
3853 const REAL8 omega02Tidal1,
3854 /**<< quadrupole f-mode angular freq for body 1 m_1*omega_{02,1}*/
3855 const REAL8 omega02Tidal2,
3856 /**<< quadrupole f-mode angular freq for body 2 m_2*omega_{02,2}*/
3857 const REAL8 lambda3Tidal1,
3858 /**<< dimensionless adiabatic octupole tidal deformability for body 1 (2/15 k3/C^7) */
3859 const REAL8 lambda3Tidal2,
3860 /**<< dimensionless adiabatic octupole tidal deformability for body 2 (2/15 k3/C^7) */
3861 const REAL8 omega03Tidal1,
3862 /**<< octupole f-mode angular freq for body 1 m_1*omega_{03,1}*/
3863 const REAL8 omega03Tidal2,
3864 /**<< octupole f-mode angular freq for body 2 m_2*omega_{03,2}*/
3865 const REAL8 quadparam1,
3866 /**<< parameter kappa_1 of the spin-induced quadrupole for body 1, quadrupole is Q_A = -kappa_A m_A^3 chi_A^2 */
3867 const REAL8 quadparam2,
3868 /**<< parameter kappa_2 of the spin-induced quadrupole for body 2, quadrupole is Q_A = -kappa_A m_A^3 chi_A^2 */
3869 REAL8Vector *nqcCoeffsInput,
3870 /**<< Input NQC coeffs */
3871 const INT4 nqcFlag,
3872 /**<< Flag to tell the code to use the NQC coeffs input thorugh nqcCoeffsInput */
3873 LALValue *ModeArray,
3874 /**<< Structure containing the modes to use in the waveform */
3875 LALDict *TGRParams
3876 /**<< dictionary containing parameters for tests of General Relativity */
3877)
3878 {
3879
3880 REAL8 coa_phase = phiC;
3881
3882 SphHarmTimeSeries *hlms = NULL;
3883 //SM
3884 REAL8Vector *dynamics = NULL;
3885 REAL8Vector *dynamicsHi = NULL;
3886 //SM
3887
3888 LALDict *PAParams = XLALCreateDict();
3889
3890 //RC: XLALSimIMRSpinAlignedEOBModes computes the modes and put them into hlm
3891
3893 &hlms, //SM
3894 &dynamics, &dynamicsHi, //SM
3895 deltaT,
3896 m1SI, m2SI,
3897 fMin,
3898 r,
3899 spin1z, spin2z,
3900 SpinAlignedEOBversion,
3901 lambda2Tidal1, lambda2Tidal2,
3902 omega02Tidal1, omega02Tidal2,
3903 lambda3Tidal1, lambda3Tidal2,
3904 omega03Tidal1, omega03Tidal2,
3905 quadparam1, quadparam2,
3906 nqcCoeffsInput, nqcFlag,
3907 PAParams,
3908 TGRParams) == XLAL_FAILURE
3909 ){
3910 if(dynamics) XLALDestroyREAL8Vector(dynamics);
3911 if(dynamicsHi) XLALDestroyREAL8Vector(dynamicsHi);
3913 };
3914
3915 //RC: For SEOBNRv4T we also need to exit from this function when nqcFlag == 1 because when this flag is 1, it is only computing the NQCs and not the wf
3916 if (nqcFlag == 1){
3917 if(hlms)
3919 return XLAL_SUCCESS;
3920 }
3921
3922 //RC: Here we read lenght and epoch of the modes. They are all the same by definition.
3923 INT4 len = hlms->mode->data->length;
3924 LIGOTimeGPS tc = hlms->mode->epoch;
3925
3926 //RC: defining and initializing to 0 the hp and hc vectors
3927 REAL8TimeSeries *hPlusTS =
3928 XLALCreateREAL8TimeSeries ("H_PLUS", &tc, 0.0, deltaT, &lalStrainUnit,
3929 len);
3930 REAL8TimeSeries *hCrossTS =
3931 XLALCreateREAL8TimeSeries ("H_CROSS", &tc, 0.0, deltaT, &lalStrainUnit,
3932 len);
3933 memset( hPlusTS->data->data, 0, hPlusTS->data->length * sizeof(REAL8) );
3934 memset( hCrossTS->data->data, 0, hCrossTS->data->length * sizeof(REAL8) );
3935
3936 //RC: adding all the modes in the SphHarmTimeSeries hlms to hp and hc
3937 SphHarmTimeSeries *hlms_temp = hlms;
3938 while ( hlms_temp ) {
3939 if (XLALSimInspiralModeArrayIsModeActive(ModeArray, hlms_temp->l, hlms_temp->m) == 1){
3940 /*Here we check if the mode generated is in the ModeArray structure
3941 */
3942 //R.C. the angles in the spin-weighted spherical harmonics are set accordingly to the document https://dcc.ligo.org/DocDB/0152/T1800226/003/LAL_GW_Frames.pdf
3943 //for the conventions in master
3944 XLALSimAddMode(hPlusTS, hCrossTS, hlms_temp->mode, inc, LAL_PI/2. - coa_phase, hlms_temp->l, hlms_temp->m, 1);
3945 /*When the function XLALSimAddMode is called with the last argument == 1
3946 *is using both +m and -m modes
3947 */
3948 //printf("Mode (%d,%d) active\n", hlms_temp->l,hlms_temp->m);
3949 }
3950 hlms_temp = hlms_temp->next;
3951 }
3952
3953
3954
3955 /* Point the output pointers to the relevant time series and return */
3956 (*hplus) = hPlusTS;
3957 (*hcross) = hCrossTS;
3958
3959 if(hlms)
3961
3962 XLALDestroyDict(PAParams);
3963
3964 //SM
3965 if(dynamics) XLALDestroyREAL8Vector(dynamics);
3966 if(dynamicsHi) XLALDestroyREAL8Vector(dynamicsHi);
3967 //SM
3968
3969 return XLAL_SUCCESS;
3970 }
3971
3972/** @} */
int XLALDictContains(const LALDict *dict, const char *key)
void XLALDestroyDict(LALDict *dict)
LALDict * XLALCreateDict(void)
int XLALDictInsertUINT4Value(LALDict *dict, const char *key, UINT4 value)
int XLALDictInsertUINT2Value(LALDict *dict, const char *key, UINT2 value)
int XLALDictInsertREAL8Value(LALDict *dict, const char *key, REAL8 value)
UINT2 XLALDictLookupUINT2Value(const LALDict *dict, const char *key)
Module to compute the ring-down waveform as linear combination of quasi-normal-modes decaying wavefor...
static UNUSED INT4 XLALSimIMREOBAttachFitRingdown(REAL8Vector *signal1, REAL8Vector *signal2, const INT4 l, const INT4 m, const REAL8 dt, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1x, const REAL8 spin1y, const REAL8 spin1z, const REAL8 spin2x, const REAL8 spin2y, const REAL8 spin2z, const REAL8 domega220, const REAL8 dtau220, const REAL8 domega210, const REAL8 dtau210, const REAL8 domega330, const REAL8 dtau330, const REAL8 domega440, const REAL8 dtau440, const REAL8 domega550, const REAL8 dtau550, const UINT2 TGRflag, REAL8Vector *timeVec, REAL8Vector *matchrange, Approximant approximant, UINT4 *indAmpMax)
The main function for performing the ringdown attachment for SEOBNRv4 (and beyond) This is the functi...
static UNUSED INT4 XLALSimIMREOBHybridAttachRingdown(REAL8Vector *signal1, REAL8Vector *signal2, const INT4 l, const INT4 m, const REAL8 dt, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1x, const REAL8 spin1y, const REAL8 spin1z, const REAL8 spin2x, const REAL8 spin2y, const REAL8 spin2z, REAL8Vector *timeVec, REAL8Vector *matchrange, Approximant approximant)
The main workhorse function for performing the ringdown attachment for EOB models EOBNRv2 and SEOBNRv...
static UNUSED int XLALSimIMREOBNonQCCorrection(COMPLEX16 *restrict nqc, REAL8Vector *restrict values, const REAL8 omega, EOBNonQCCoeffs *restrict coeffs)
This function calculates the non-quasicircular correction to apply to the waveform.
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakDeltaTv2(INT4 UNUSED l, INT4 UNUSED m, REAL8 UNUSED m1, REAL8 UNUSED m2, REAL8 chi1, REAL8 chi2)
The time difference between the orbital peak and the peak amplitude of the mode in question (currentl...
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakDeltaT(INT4 l, INT4 m, REAL8 UNUSED eta, REAL8 a)
The time difference between the orbital peak and the peak amplitude of the mode in question (currentl...
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakOmega(INT4 UNUSED l, INT4 UNUSED m, REAL8 UNUSED eta, REAL8 a)
Peak frequency predicted by fitting NR results (currently only 2,2 available).
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakOmegav2(INT4 UNUSED l, INT4 UNUSED m, REAL8 UNUSED eta, REAL8 a)
Peak frequency predicted by fitting NR results (currently only 2,2 available).
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakOmegaV5(INT4 modeL, INT4 modeM, REAL8 UNUSED eta, REAL8 a)
Peak frequency predicted by fitting NR results used in SEOBNRv5 The coefficients are in Eq.
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakOmegaV4(INT4 modeL, INT4 modeM, REAL8 UNUSED eta, REAL8 a)
Peak frequency predicted by fitting NR results The coefficients for the (2,2) are in Eq.
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakDeltaTv4(INT4 UNUSED l, INT4 UNUSED m, REAL8 UNUSED m1, REAL8 UNUSED m2, REAL8 UNUSED chi1, REAL8 UNUSED chi2)
The time difference between the orbital peak and the peak amplitude of the mode in question (currentl...
static UNUSED int XLALSimIMRSpinEOBCalculateNQCCoefficientsV4(REAL8Vector *restrict amplitude, REAL8Vector *restrict phase, REAL8Vector *restrict rVec, REAL8Vector *restrict prVec, REAL8Vector *restrict orbOmegaVec, INT4 modeL, INT4 modeM, REAL8 timePeak, REAL8 deltaT, REAL8 m1, REAL8 m2, REAL8 chiA, REAL8 chiS, EOBNonQCCoeffs *restrict coeffs)
This function computes the coefficients a3s, a4, etc.
static UNUSED int XLALSimIMRGetEOBCalibratedSpinNQC(EOBNonQCCoeffs *restrict coeffs, INT4 UNUSED l, INT4 UNUSED m, REAL8 eta, REAL8 a)
More recent versions of the EOB models, such as EOBNRv2 and SEOBNRv1, utilise a non-quasicircular cor...
static UNUSED int XLALSimIMRGetEOBCalibratedSpinNQC3D(EOBNonQCCoeffs *restrict coeffs, INT4 UNUSED l, INT4 UNUSED m, REAL8 m1, REAL8 m2, REAL8 a, REAL8 chiAin)
Function to 3D-interpolate known amplitude NQC coeffcients of spin terms for SEOBNRv2,...
static UNUSED int XLALSimIMREOBComputeNewtonMultipolePrefixes(NewtonMultipolePrefixes *prefix, const REAL8 m1, const REAL8 m2)
Function which computes the various coefficients in the Newtonian multipole.
#define nModes
const UINT4 lmModes[NMODES][2]
#define SEOBNRv4HM
UNUSED REAL8 XLALSimNSNSMergerFreq(TidalEOBParams *tidal1, TidalEOBParams *tidal2)
NR fit to the geometric GW frequency M_{total}omega_{22} of a BNS merger, defined by the time when th...
#define debugOutput
static int UNUSED XLALEOBSpinStopCondition(double UNUSED t, const double values[], double dvalues[], void *funcParams)
#define pSEOBNRv4HM_PA
static int XLALSpinAlignedNSNSStopCondition(double UNUSED t, const double UNUSED values[], double dvalues[], void UNUSED *funcParams)
This function defines the stopping criteria for the tidal EOB model Note that here values[0] = r valu...
static INT4 IntrpolateDynamics(REAL8Vector *tVec, REAL8Vector *rVec, REAL8Vector *phiVec, REAL8Vector *prVec, REAL8Vector *pphiVec, REAL8Vector *values, REAL8 closestTime)
static int XLALSpinAlignedHiSRStopCondition(double UNUSED t, const double UNUSED values[], double dvalues[], void UNUSED *funcParams)
static int XLALSpinAlignedHiSRStopConditionV4(double UNUSED t, const double UNUSED values[], double dvalues[], void UNUSED *funcParams)
static INT4 XLALSetup_EOB__std_mode_array_structure(LALValue *ModeArray, UINT4 SpinAlignedEOBversion)
ModeArray is a structure which allows to select the modes to include in the waveform.
static int XLALEOBSpinAlignedStopCondition(double UNUSED t, const double values[], double dvalues[], void *funcParams)
Stopping condition for the regular resolution EOB orbital evolution – stop when reaching max orbital ...
#define SEOBNRv4HM_PA
static INT4 XLALCheck_EOB_mode_array_structure(LALValue *ModeArray, UINT4 SpinAlignedEOBversion)
ModeArray is a structure which allows to select the modes to include in the waveform.
static UNUSED int SEOBNRv2OptimizedInterpolatorOnlyAmpPhase(REAL8Array *yin, REAL8 tinit, REAL8 deltat, UINT4 num_input_times, REAL8Array **yout)
This function applies the same routines as SEOBNRv2OptimizedInterpolatorNoAmpPhase() above to interpo...
static UNUSED int SEOBNRv2OptimizedInterpolatorNoAmpPhase(REAL8Array *yin, REAL8 tinit, REAL8 deltat, UINT4 num_input_times, REAL8Array **yout)
This function is largely based on/copied from XLALAdaptiveRungeKutta4(), which exists inside the lal/...
static int XLALSpinAlignedHcapDerivative(double t, const REAL8 values[], REAL8 dvalues[], void *funcParams)
static int XLALSpinAlignedHcapDerivativeOptimized(double t, const REAL8 values[], REAL8 dvalues[], void *funcParams)
static int optimized_gsl_spline_eval_e(const gsl_spline *spline, double interptime, gsl_interp_accel *accel, double *output, unsigned int *index_old, double *x_lo_old, double *y_lo_old, double *b_i_old, double *c_i_old, double *d_i_old)
Perform cubic spline interpolation to achieve evenly-sampled data from that input data.
static int XLALSimIMRSpinEOBCalculateSigmaKerr(REAL8Vector *sigmaKerr, REAL8 mass1, REAL8 mass2, REAL8Vector *s1, REAL8Vector *s2)
Function to calculate normalized spin of the deformed-Kerr background in SEOBNRv1.
static int XLALSimIMRSpinEOBCalculateSigmaStar(REAL8Vector *sigmaStar, REAL8 mass1, REAL8 mass2, REAL8Vector *s1, REAL8Vector *s2)
Function to calculate normalized spin of the test particle in SEOBNRv1.
static void GenerateAmpPhaseFromEOMSoln(UINT4 retLen, REAL8 *inputdata, SpinEOBParams *seobParams)
static INT4 XLALSimIMRSpinEOBWaveformTidal(COMPLEX16 *restrict hlm, REAL8Vector *restrict values, const REAL8 v, const INT4 l, const INT4 m, SpinEOBParams *restrict params)
This function calculates tidal correction to the hlm mode factorized-resummed waveform for given dyna...
static UNUSED int XLALSimIMREOBCalcCalibCoefficientHigherModes(FacWaveformCoeffs *const coeffs, SpinEOBParams *restrict UNUSED params, const UINT4 modeL, const UINT4 modeM, REAL8Vector *restrict phaseVec, REAL8Vector *restrict rVec, REAL8Vector *restrict prVec, REAL8Vector *restrict orbOmegaVec, REAL8Vector *restrict HamVec, REAL8Vector *restrict pPhiVec, const REAL8 timePeak, const REAL8 m1, const REAL8 m2, const REAL8 UNUSED chiS, const REAL8 UNUSED chiA, const REAL8 UNUSED deltaT)
This function calculate the calibration parameter for the amplitude of the factorized-resummed wavefo...
static int XLALSimIMREOBCalcSpinFacWaveformCoefficients(FacWaveformCoeffs *const coeffs, SpinEOBParams *restrict params, const REAL8 m1, const REAL8 m2, const REAL8 eta, const REAL8 a, const REAL8 chiS, const REAL8 chiA, const UINT4 SpinAlignedEOBversion)
Spin Factors.
static UNUSED INT4 XLALSimIMRSpinEOBGetSpinFactorizedWaveform(COMPLEX16 *restrict hlm, REAL8Vector *restrict values, const REAL8 v, const REAL8 Hreal, const INT4 l, const INT4 m, SpinEOBParams *restrict params, INT4 use_optimized_v2)
This function calculates hlm mode factorized-resummed waveform for given dynamical variables.
static UNUSED INT4 XLALSimIMRSpinEOBGetSpinFactorizedWaveform_PA(COMPLEX16 *restrict hlm, REAL8Vector *restrict values, const REAL8 v, const REAL8 Hreal, const INT4 l, const INT4 m, SpinEOBParams *restrict params, REAL8 vPhi)
This function calculates hlm mode factorized-resummed waveform for given dynamical variables.
static int XLALSimIMRCalculateSpinEOBHCoeffs(SpinEOBHCoeffs *coeffs, const REAL8 eta, const REAL8 a, const UINT4 SpinAlignedEOBversion)
This function is used to calculate some coefficients which will be used in the spinning EOB Hamiltoni...
static REAL8 XLALSimIMRSpinAlignedEOBCalcOmega(const REAL8 values[], SpinEOBParams *funcParams, REAL8 STEP_SIZE)
Function to calculate the value of omega for the spin-aligned EOB waveform.
static REAL8 XLALSimIMRSpinEOBHamiltonian(const REAL8 eta, REAL8Vector *restrict x, REAL8Vector *restrict p, REAL8Vector *restrict s1Vec, REAL8Vector *restrict s2Vec, REAL8Vector *restrict sigmaKerr, REAL8Vector *restrict sigmaStar, int tortoise, SpinEOBHCoeffs *coeffs)
static const REAL8 STEP_SIZE_CALCOMEGA
UNUSED REAL8 XLALSimIMRSpinEOBHamiltonianOptimized(const REAL8 eta, REAL8Vector *restrict x, REAL8Vector *restrict p, REAL8Vector *restrict s1Vec, REAL8Vector *restrict s2Vec, REAL8Vector *restrict sigmaKerr, REAL8Vector *restrict sigmaStar, INT4 tortoise, SpinEOBHCoeffs *coeffs)
Function to calculate the value of the spinning Hamiltonian for given values of the dynamical variabl...
static REAL8 XLALSimIMRSpinAlignedEOBNonKeplerCoeffOptimized(const REAL8 values[], SpinEOBParams *funcParams)
Function to calculate the non-Keplerian coefficient for the spin-aligned EOB model.
static REAL8 XLALSimIMRSpinAlignedEOBCalcOmegaOptimized(const REAL8 values[], SpinEOBParams *funcParams)
Function to calculate the value of omega for the spin-aligned EOB waveform.
static int XLALSimIMRSpinEOBInitialConditions(REAL8Vector *initConds, const REAL8 mass1, const REAL8 mass2, const REAL8 fMin, const REAL8 inc, const REAL8 spin1[], const REAL8 spin2[], SpinEOBParams *params, INT4 use_optimized_v2)
Main function for calculating the spinning EOB initial conditions, following the quasi-spherical init...
int XLALSimInspiralEOBPostAdiabatic(REAL8Array **dynamics, REAL8 m1, REAL8 m2, REAL8 spin1z, REAL8 spin2z, const REAL8Vector initVals, UINT4 SpinAlignedEOBversion, SpinEOBParams *seobParams, EOBNonQCCoeffs *nqcCoeffs, LALDict *PAParams)
This function generates post-adiabatic inspiral for spin-aligned binary in the SEOB formalism.
static double tau(const double a, const double b, const sysq *system)
Internal function that computes the spin-spin couplings.
LALValue * XLALSimInspiralWaveformParamsLookupModeArray(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalOctupolarFMode1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupDOmega220(LALDict *params)
int XLALSimInspiralWaveformParamsInsertDTau220(LALDict *params, REAL8 value)
int XLALSimInspiralWaveformParamsInsertDOmega440(LALDict *params, REAL8 value)
REAL8 XLALSimInspiralWaveformParamsLookupDTau220(LALDict *params)
int XLALSimInspiralWaveformParamsInsertDTau440(LALDict *params, REAL8 value)
REAL8 XLALSimInspiralWaveformParamsLookupTidalQuadrupolarFMode1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupDOmega550(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupDTau550(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupdQuadMon1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalOctupolarFMode2(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalQuadrupolarFMode2(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalLambda2(LALDict *params)
int XLALSimInspiralWaveformParamsInsertDOmega330(LALDict *params, REAL8 value)
int XLALSimInspiralWaveformParamsInsertDOmega550(LALDict *params, REAL8 value)
int XLALSimInspiralWaveformParamsInsertDTau330(LALDict *params, REAL8 value)
int XLALSimInspiralWaveformParamsInsertDOmega210(LALDict *params, REAL8 value)
REAL8 XLALSimInspiralWaveformParamsLookupDTau330(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupDOmega210(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalLambda1(LALDict *params)
int XLALSimInspiralWaveformParamsInsertDOmega220(LALDict *params, REAL8 value)
REAL8 XLALSimInspiralWaveformParamsLookupDOmega440(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupDTau210(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupDOmega330(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupdQuadMon2(LALDict *params)
int XLALSimInspiralWaveformParamsInsertDTau550(LALDict *params, REAL8 value)
int XLALSimInspiralWaveformParamsInsertDTau210(LALDict *params, REAL8 value)
REAL8 XLALSimInspiralWaveformParamsLookupTidalOctupolarLambda1(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupTidalOctupolarLambda2(LALDict *params)
REAL8 XLALSimInspiralWaveformParamsLookupDTau440(LALDict *params)
void XLALDestroyValue(LALValue *value)
#define fprintf
double dt
Definition: bh_ringdown.c:113
double i
Definition: bh_ringdown.c:118
const double r2
void XLALDestroyREAL8Array(REAL8Array *)
REAL8Array * XLALCreateREAL8ArrayL(UINT4,...)
int XLALAdaptiveRungeKutta4(LALAdaptiveRungeKuttaIntegrator *integrator, void *params, REAL8 *yinit, REAL8 tinit, REAL8 tend, REAL8 deltat, REAL8Array **yout)
void XLALAdaptiveRungeKuttaFree(LALAdaptiveRungeKuttaIntegrator *integrator)
int XLALAdaptiveRungeKutta4NoInterpolate(LALAdaptiveRungeKuttaIntegrator *integrator, void *params, REAL8 *yinit, REAL8 tinit, REAL8 tend, REAL8 deltat_or_h0, REAL8 min_deltat_or_h0, REAL8Array **t_and_yout, INT4 EOBversion)
LALAdaptiveRungeKuttaIntegrator * XLALAdaptiveRungeKutta4InitEighthOrderInstead(int dim, int(*dydt)(double t, const double y[], double dydt[], void *params), int(*stop)(double t, const double y[], double dydt[], void *params), double eps_abs, double eps_rel)
LALAdaptiveRungeKuttaIntegrator * XLALAdaptiveRungeKutta4Init(int dim, int(*dydt)(double t, const double y[], double dydt[], void *params), int(*stop)(double t, const double y[], double dydt[], void *params), double eps_abs, double eps_rel)
#define LAL_MSUN_SI
#define LAL_PI
#define LAL_TWOPI
#define LAL_MTSUN_SI
#define LAL_MRSUN_SI
#define LIGOTIMEGPSZERO
double complex COMPLEX16
double REAL8
uint16_t UINT2
uint32_t UINT4
int32_t INT4
INT4 XLALSimIMREOBGenerateQNMFreqV2(COMPLEX16Vector *modefreqs, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1[3], const REAL8 spin2[3], UINT4 l, INT4 m, UINT4 nmodes, Approximant approximant)
These functions generate the quasinormal mode frequencies for a black hole ringdown.
int XLALSimIMRSpinAlignedEOBModes(SphHarmTimeSeries **hlmmode, REAL8Vector **dynamics_out, REAL8Vector **dynamicsHi_out, REAL8 deltaT, const REAL8 m1SI, const REAL8 m2SI, const REAL8 fMin, const REAL8 r, const REAL8 spin1z, const REAL8 spin2z, UINT4 SpinAlignedEOBversion, const REAL8 lambda2Tidal1, const REAL8 lambda2Tidal2, const REAL8 omega02Tidal1, const REAL8 omega02Tidal2, const REAL8 lambda3Tidal1, const REAL8 lambda3Tidal2, const REAL8 omega03Tidal1, const REAL8 omega03Tidal2, const REAL8 quadparam1, const REAL8 quadparam2, REAL8Vector *nqcCoeffsInput, const INT4 nqcFlag, LALDict *PAParams, LALDict *TGRParams)
This function generates spin-aligned SEOBNRv1,2,2opt,4,4opt,2T,4T,4HM complex modes hlm.
int XLALSimIMRSpinAlignedEOBWaveformAll(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, const REAL8 phiC, REAL8 deltaT, const REAL8 m1SI, const REAL8 m2SI, const REAL8 fMin, const REAL8 r, const REAL8 inc, const REAL8 spin1z, const REAL8 spin2z, UINT4 SpinAlignedEOBversion, const REAL8 lambda2Tidal1, const REAL8 lambda2Tidal2, const REAL8 omega02Tidal1, const REAL8 omega02Tidal2, const REAL8 lambda3Tidal1, const REAL8 lambda3Tidal2, const REAL8 omega03Tidal1, const REAL8 omega03Tidal2, const REAL8 quadparam1, const REAL8 quadparam2, REAL8Vector *nqcCoeffsInput, const INT4 nqcFlag, LALValue *ModeArray, LALDict *TGRParams)
This function takes the modes from the function XLALSimIMRSpinAlignedEOBModes and combine them into h...
int XLALSimIMRSpinAlignedEOBWaveform(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, const REAL8 phiC, REAL8 deltaT, const REAL8 m1SI, const REAL8 m2SI, const REAL8 fMin, const REAL8 r, const REAL8 inc, const REAL8 spin1z, const REAL8 spin2z, UINT4 SpinAlignedEOBversion, LALDict *LALParams)
double XLALSimIMRSpinAlignedEOBPeakFrequency(REAL8 m1SI, REAL8 m2SI, const REAL8 spin1z, const REAL8 spin2z, UINT4 SpinAlignedEOBversion)
This function returns the frequency at which the peak amplitude occurs in SEOBNRv(x)
#define LAL_SIM_L_MAX_MODE_ARRAY
Maximum L spherical harmonic mode that is supported in Mode Array.
Approximant
Enum that specifies the PN approximant to be used in computing the waveform.
@ SEOBNRv2
Spin-aligned EOBNR model v2.
@ SEOBNRv1
Spin-aligned EOBNR model.
@ SEOBNRv4
Spin nonprecessing EOBNR model v4.
int XLALSimInspiralModeArrayIsModeActive(LALValue *modes, unsigned l, int m)
LALValue * XLALSimInspiralModeArrayActivateMode(LALValue *modes, unsigned l, int m)
LALValue * XLALSimInspiralCreateModeArray(void)
Create a LALValue pointer to store the mode array.
int XLALSimAddMode(REAL8TimeSeries *hplus, REAL8TimeSeries *hcross, COMPLEX16TimeSeries *hmode, REAL8 theta, REAL8 phi, int l, int m, int sym)
Multiplies a mode h(l,m) by a spin-2 weighted spherical harmonic to obtain hplus - i hcross,...
SphHarmTimeSeries * XLALSphHarmTimeSeriesAddMode(SphHarmTimeSeries *appended, const COMPLEX16TimeSeries *inmode, UINT4 l, INT4 m)
Prepend a node to a linked list of SphHarmTimeSeries, or create a new head.
void XLALDestroySphHarmTimeSeries(SphHarmTimeSeries *ts)
Delete list from current pointer to the end of the list.
static const INT4 r
static const INT4 a
void XLALDestroyCOMPLEX16TimeSeries(COMPLEX16TimeSeries *series)
COMPLEX16TimeSeries * XLALCreateCOMPLEX16TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalStrainUnit
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
#define XLAL_ERROR(...)
#define XLAL_PRINT_WARNING(...)
#define XLAL_TRY(statement, errnum)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
int int XLALPrintWarning(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_ERANGE
XLAL_EFUNC
XLAL_EERR
XLAL_EDOM
XLAL_EINVAL
XLAL_FAILURE
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
string status
filename
COMPLEX16Sequence * data
COMPLEX16 * data
The coefficients which are used in calculating the non-quasicircular correction to the EOBNRv2 model.
Structure containing all the parameters needed for the EOB waveform.
FacWaveformCoeffs * hCoeffs
NewtonMultipolePrefixes * prefixes
Structure containing the coefficients for calculating the factorized waveform.
TidalEOBParams * tidal2
TidalEOBParams * tidal1
int(* stop)(double t, const double y[], double dydt[], void *params)
Structure containing all the terms of the Newtonian multipole which are constant over the course of t...
UINT4Vector * dimLength
REAL8 * data
REAL8Sequence * data
REAL8 * data
Structure to carry a collection of spherical harmonic modes in COMPLEX16 time series.
struct tagSphHarmTimeSeries * next
next pointer
COMPLEX16TimeSeries * mode
The sequences of sampled data.
INT4 m
Node submode m
UINT4 l
Node mode l
Parameters for the spinning EOB model, used in calculating the Hamiltonian.
TidalEOBParams * tidal1
TidalEOBParams * tidal2
Parameters for the spinning EOB model.
SpinEOBHCoeffs * seobCoeffs
REAL8Vector * sigmaStar
EOBNonQCCoeffs * nqcCoeffs
REAL8Vector * s1Vec
EOBParams * eobParams
REAL8Vector * sigmaKerr
REAL8Vector * s2Vec
Tidal parameters for EOB model of NS: mByM - dimensionless ratio m_{NS}/M lambda2Tidal - dimensionles...
UINT4 * data
Definition: burst.c:245
double deltaT
Definition: unicorn.c:24