LALInspiral 5.0.3.1-eeff03c
LALEOBPPWaveform.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Stas Babak, David Churches, Duncan Brown, David Chin, Jolien Creighton,
3* B.S. Sathyaprakash, Craig Robinson , Thomas Cokelaer, Evan Ochsner
4*
5* This program is free software; you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation; either version 2 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with with program; see the file COPYING. If not, write to the
17* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18* MA 02110-1301 USA
19*/
20
21/**
22 * \author Craig Robinson
23 *
24 * \file
25 *
26 * \brief Functions to generate the EOBNRv2 waveforms, as defined in
27 * Pan et al, arXiv:1106.1021v1 [gr-qc].
28 *
29 * ### Prototypes ###
30 *
31 * <tt>XLALEOBPPWaveform()</tt>
32 * <ul>
33 * <li><tt>signalvec: </tt> Output containing the inspiral waveform.
34 * <li><tt> params:</tt> Input containing binary chirp parameters.
35 * </ul>
36 *
37 * <tt> XLALEOBPPWaveformTemplates() </tt>
38 * <ul>
39 * <li><tt> signalvec1:</tt> Output containing the 0-phase inspiral waveform.
40 * <li><tt> signalvec2:</tt> Output containing the \f$\pi/2\f$-phase inspiral waveform.
41 * <li><tt> params:</tt> Input containing binary chirp parameters.
42 * </ul>
43 *
44 * <tt> XLALEOBPPWaveformForInjection() </tt>
45 * <ul>
46 * <li><tt> waveform: </tt> Coherent GW structure containing output waveform
47 * <li><tt> params: </tt> Input containing inspiral template parameters.
48 * <li><tt> ppnParams </tt> Input containing other necessary parameters.
49 * </ul>
50 */
51
52#include <lal/Units.h>
53#include <lal/LALInspiral.h>
54#include <lal/LALEOBNRv2Waveform.h>
55#include <lal/LALAdaptiveRungeKuttaIntegrator.h>
56#include <lal/FindRoot.h>
57#include <lal/SeqFactories.h>
58#include <lal/NRWaveInject.h>
59
60#include <gsl/gsl_sf_gamma.h>
61
62#define ninty4by3etc 18.687902694437592603 /* (94/3 -41/31*pi*pi) */
63
64static const int EOBNRV2_NUM_MODES_MAX = 5;
65
66typedef struct tagrOfOmegaIn {
67 REAL8 eta, omega;
69
70typedef struct tagPr3In {
71 REAL8 eta, zeta2, omegaS, omega, vr,r,q;
72 EOBACoefficients *aCoeffs;
74} pr3In;
75
76
77static inline REAL8
79
80static inline REAL8
82
83static REAL8
85 const REAL8 r,
86 const REAL8 eta,
87 void *params);
88
89static REAL8
91 REAL8Vector * restrict values,
92 const REAL8 eta,
93 EOBACoefficients *coeffs );
94
95static
97 const double values[],
98 double dvalues[],
99 void *funcParams);
100
101static
103 REAL8 r,
104 REAL8 pr,
105 REAL8 pPhi,
106 EOBACoefficients *aCoeffs );
107
108static
110 const double values[],
111 double dvalues[],
112 void *funcParams);
113
114static
116 const double values[],
117 double dvalues[],
118 void *funcParams);
119
120static
122 EOBACoefficients * restrict coeffs );
123
124static
126 REAL8 eta);
127
128static
130 EOBACoefficients * restrict coeffs );
131
132static
134 const REAL8 r,
135 const REAL8 pr,
136 const REAL8 pp,
137 EOBACoefficients *aCoeffs );
138
139static
141
142static
144 EOBACoefficients * restrict coeffs );
145
146static
148
149static
150REAL8 XLALvrP4PN(const REAL8 r, const REAL8 omega, pr3In *params);
151
152static int
154 REAL4Vector *signalvec1,
155 REAL4Vector *signalvec2,
156 REAL4Vector *h,
157 const REAL8 *phiC,
158 UINT4 *countback,
160 InspiralInit *paramsInit
161 );
162
164 REAL8Vector * restrict values,
165 const REAL8 v,
166 const INT4 l,
167 const INT4 m,
168 EOBParams * restrict params
169 )
170{
171
172 /* Status of function calls */
173 INT4 status;
174 INT4 i;
175
176 REAL8 eta;
177 REAL8 r, pr, pp, Omega, v2, vh, vh3, k, hathatk, eulerlogxabs;
178 REAL8 Hreal, Heff, Slm, deltalm, rholm, rholmPwrl;
179 COMPLEX16 Tlm;
180 COMPLEX16 hNewton;
181 gsl_sf_result lnr1, arg1, z2;
182
183 /* Non-Keplerian velocity */
184 REAL8 vPhi;
185
186 /* Pre-computed coefficients */
187 FacWaveformCoeffs *hCoeffs = params->hCoeffs;
188
189 if ( abs(m) > (INT4) l )
190 {
192 }
193
194
195 eta = params->eta;
196
197 /* Check our eta was sensible */
198 if ( eta > 0.25 )
199 {
200 XLALPrintError("Eta seems to be > 0.25 - this isn't allowed!\n" );
202 }
203 else if ( eta == 0.25 && m % 2 )
204 {
205 /* If m is odd and dM = 0, hLM will be zero */
206 memset( hlm, 0, sizeof( COMPLEX16 ) );
207 return XLAL_SUCCESS;
208 }
209
210 r = values->data[0];
211 pr = values->data[2];
212 pp = values->data[3];
213
214 Heff = XLALEffectiveHamiltonian( eta, r, pr, pp, params->aCoeffs );
215 Hreal = sqrt( 1.0 + 2.0 * eta * ( Heff - 1.0) );
216 v2 = v * v;
217 Omega = v2 * v;
218 vh3 = Hreal * Omega;
219 vh = cbrt(vh3);
220 eulerlogxabs = LAL_GAMMA + log( 2.0 * (REAL8)m * v );
221
222
223 /* Calculate the non-Keplerian velocity */
224 vPhi = nonKeplerianCoefficient( values, eta, params->aCoeffs );
225
226 vPhi = r * cbrt(vPhi);
227 vPhi *= Omega;
228
229 /* Calculate the newtonian multipole */
230 status = XLALCalculateNewtonianMultipole( &hNewton, vPhi * vPhi, vPhi/Omega,
231 values->data[1], (UINT4)l, m, params );
232 if ( status == XLAL_FAILURE )
233 {
235 }
236
237 /* Calculate the source term */
238 if ( ( (l+m)%2 ) == 0)
239 {
240 Slm = Heff;
241 }
242 else
243 {
244 Slm = v * pp;
245 }
246
247 /* Calculate the Tail term */
248 k = m * Omega;
249 hathatk = Hreal * k;
250 XLAL_CALLGSL( status = gsl_sf_lngamma_complex_e( l+1.0, -2.0*hathatk, &lnr1, &arg1 ) );
251 if (status != GSL_SUCCESS)
252 {
253 XLALPrintError("Error in GSL function\n" );
255 }
256 XLAL_CALLGSL( status = gsl_sf_fact_e( l, &z2 ) );
257 if ( status != GSL_SUCCESS)
258 {
259 XLALPrintError("Error in GSL function\n" );
261 }
262 Tlm = cexp( crect( lnr1.val + LAL_PI * hathatk,
263 arg1.val + 2.0 * hathatk * log(4.0*k/sqrt(LAL_E)) ) );
264 Tlm = Tlm / z2.val;
265
266 /* Calculate the residue phase and amplitude terms */
267 switch( l )
268 {
269 case 2:
270 switch( abs(m) )
271 {
272 case 2:
273 deltalm = vh3*(hCoeffs->delta22vh3 + vh3*(hCoeffs->delta22vh6
274 + vh*vh*(hCoeffs->delta22vh8 + hCoeffs->delta22vh9*vh)))
275 + hCoeffs->delta22v5 *v*v2*v2;
276 rholm = 1. + v2*(hCoeffs->rho22v2 + v*(hCoeffs->rho22v3
277 + v*(hCoeffs->rho22v4
278 + v*(hCoeffs->rho22v5 + v*(hCoeffs->rho22v6
279 + hCoeffs->rho22v6l*eulerlogxabs + v*(hCoeffs->rho22v7
280 + v*(hCoeffs->rho22v8 + hCoeffs->rho22v8l*eulerlogxabs
281 + (hCoeffs->rho22v10 + hCoeffs->rho22v10l * eulerlogxabs)*v2)))))));
282 break;
283 case 1:
284 {
285 deltalm = vh3*(hCoeffs->delta21vh3 + vh3*(hCoeffs->delta21vh6
286 + vh*(hCoeffs->delta21vh7 + (hCoeffs->delta21vh9)*vh*vh)))
287 + hCoeffs->delta21v5*v*v2*v2 + hCoeffs->delta21v7*v2*v2*v2*v;
288 rholm = 1. + v*(hCoeffs->rho21v1
289 + v*( hCoeffs->rho21v2 + v*(hCoeffs->rho21v3 + v*(hCoeffs->rho21v4
290 + v*(hCoeffs->rho21v5 + v*(hCoeffs->rho21v6 + hCoeffs->rho21v6l*eulerlogxabs
291 + v*(hCoeffs->rho21v7 + hCoeffs->rho21v7l * eulerlogxabs
292 + v*(hCoeffs->rho21v8 + hCoeffs->rho21v8l * eulerlogxabs
293 + (hCoeffs->rho21v10 + hCoeffs->rho21v10l * eulerlogxabs)*v2))))))));
294 }
295 break;
296 default:
298 break;
299 }
300 break;
301 case 3:
302 switch (m)
303 {
304 case 3:
305 deltalm = vh3*(hCoeffs->delta33vh3 + vh3*(hCoeffs->delta33vh6 + hCoeffs->delta33vh9*vh3))
306 + hCoeffs->delta33v5*v*v2*v2 + hCoeffs->delta33v7*v2*v2*v2*v;
307 rholm = 1. + v2*(hCoeffs->rho33v2 + v*(hCoeffs->rho33v3 + v*(hCoeffs->rho33v4
308 + v*(hCoeffs->rho33v5 + v*(hCoeffs->rho33v6 + hCoeffs->rho33v6l*eulerlogxabs
309 + v*(hCoeffs->rho33v7 + (hCoeffs->rho33v8 + hCoeffs->rho33v8l*eulerlogxabs)*v))))));
310 break;
311 case 2:
312 deltalm = vh3*(hCoeffs->delta32vh3 + vh*(hCoeffs->delta32vh4 + vh*vh*(hCoeffs->delta32vh6
313 + hCoeffs->delta32vh9*vh3)));
314 rholm = 1. + v*(hCoeffs->rho32v
315 + v*(hCoeffs->rho32v2 + v*(hCoeffs->rho32v3 + v*(hCoeffs->rho32v4 + v*(hCoeffs->rho32v5
316 + v*(hCoeffs->rho32v6 + hCoeffs->rho32v6l*eulerlogxabs
317 + (hCoeffs->rho32v8 + hCoeffs->rho32v8l*eulerlogxabs)*v2))))));
318 break;
319 case 1:
320 deltalm = vh3*(hCoeffs->delta31vh3 + vh3*(hCoeffs->delta31vh6
321 + vh*(hCoeffs->delta31vh7 + hCoeffs->delta31vh9*vh*vh)))
322 + hCoeffs->delta31v5*v*v2*v2;
323 rholm = 1. + v2*(hCoeffs->rho31v2 + v*(hCoeffs->rho31v3 + v*(hCoeffs->rho31v4
324 + v*(hCoeffs->rho31v5 + v*(hCoeffs->rho31v6 + hCoeffs->rho31v6l*eulerlogxabs
325 + v*(hCoeffs->rho31v7 + (hCoeffs->rho31v8 + hCoeffs->rho31v8l*eulerlogxabs)*v))))));
326 break;
327 default:
329 break;
330 }
331 break;
332 case 4:
333 switch (m)
334 {
335 case 4:
336
337 deltalm = vh3*(hCoeffs->delta44vh3 + hCoeffs->delta44vh6 *vh3)
338 + hCoeffs->delta44v5*v2*v2*v;
339 rholm = 1. + v2*(hCoeffs->rho44v2
340 + v*( hCoeffs->rho44v3 + v*(hCoeffs->rho44v4
341 + v*(hCoeffs->rho44v5 + (hCoeffs->rho44v6
342 + hCoeffs->rho44v6l*eulerlogxabs)*v))));
343 break;
344 case 3:
345 deltalm = vh3*(hCoeffs->delta43vh3 + vh*(hCoeffs->delta43vh4
346 + hCoeffs->delta43vh6*vh*vh));
347 rholm = 1. + v*(hCoeffs->rho43v
348 + v*(hCoeffs->rho43v2
349 + v2*(hCoeffs->rho43v4 + v*(hCoeffs->rho43v5
350 + (hCoeffs->rho43v6 + hCoeffs->rho43v6l*eulerlogxabs)*v))));
351 break;
352 case 2:
353 deltalm = vh3*(hCoeffs->delta42vh3 + hCoeffs->delta42vh6*vh3);
354 rholm = 1. + v2*(hCoeffs->rho42v2
355 + v*(hCoeffs->rho42v3 + v*(hCoeffs->rho42v4 + v*(hCoeffs->rho42v5
356 + (hCoeffs->rho42v6 + hCoeffs->rho42v6l*eulerlogxabs)*v))));
357 break;
358 case 1:
359 deltalm = vh3*(hCoeffs->delta41vh3 + vh*(hCoeffs->delta41vh4
360 + hCoeffs->delta41vh6*vh*vh));
361 rholm = 1. + v*(hCoeffs->rho41v
362 + v*(hCoeffs->rho41v2
363 + v2*(hCoeffs->rho41v4 + v*(hCoeffs->rho41v5
364 + (hCoeffs->rho41v6 + hCoeffs->rho41v6l*eulerlogxabs)*v))));
365 break;
366 default:
368 break;
369 }
370 break;
371 case 5:
372 switch (m)
373 {
374 case 5:
375 deltalm = hCoeffs->delta55vh3*vh3 + hCoeffs->delta55v5*v2*v2*v;
376 rholm = 1. + v2*( hCoeffs->rho55v2
377 + v*(hCoeffs->rho55v3 + v*(hCoeffs->rho55v4
378 + v*(hCoeffs->rho55v5 + hCoeffs->rho55v6*v))));
379 break;
380 case 4:
381 deltalm = vh3*(hCoeffs->delta54vh3 + hCoeffs->delta54vh4*vh);
382 rholm = 1. + v2*(hCoeffs->rho54v2 + v*(hCoeffs->rho54v3
383 + hCoeffs->rho54v4*v));
384 break;
385 case 3:
386 deltalm = hCoeffs->delta53vh3 * vh3;
387 rholm = 1. + v2*(hCoeffs->rho53v2
388 + v*(hCoeffs->rho53v3 + v*(hCoeffs->rho53v4 + hCoeffs->rho53v5*v)));
389 break;
390 case 2:
391 deltalm = vh3*(hCoeffs->delta52vh3 + hCoeffs->delta52vh4*vh);
392 rholm = 1. + v2*(hCoeffs->rho52v2 + v*(hCoeffs->rho52v3
393 + hCoeffs->rho52v4*v));
394 break;
395 case 1:
396 deltalm = hCoeffs->delta51vh3 * vh3;
397 rholm = 1. + v2*(hCoeffs->rho51v2
398 + v*(hCoeffs->rho51v3 + v*(hCoeffs->rho51v4 + hCoeffs->rho51v5*v)));
399 break;
400 default:
402 break;
403 }
404 break;
405 case 6:
406 switch (m)
407 {
408 case 6:
409 deltalm = hCoeffs->delta66vh3*vh3;
410 rholm = 1. + v2*(hCoeffs->rho66v2 + v*(hCoeffs->rho66v3
411 + hCoeffs->rho66v4*v));
412 break;
413 case 5:
414 deltalm = hCoeffs->delta65vh3*vh3;
415 rholm = 1. + v2*(hCoeffs->rho65v2 + hCoeffs->rho65v3*v);
416 break;
417 case 4:
418 deltalm = hCoeffs->delta64vh3 * vh3;
419 rholm = 1. + v2*(hCoeffs->rho64v2 + v*(hCoeffs->rho64v3
420 + hCoeffs->rho64v4*v));
421 break;
422 case 3:
423 deltalm = hCoeffs->delta63vh3 * vh3;
424 rholm = 1. + v2*(hCoeffs->rho63v2 + hCoeffs->rho63v3*v);
425 break;
426 case 2:
427 deltalm = hCoeffs->delta62vh3 * vh3;
428 rholm = 1. + v2*(hCoeffs->rho62v2 + v*(hCoeffs->rho62v3
429 + hCoeffs->rho62v4 * v));
430 break;
431 case 1:
432 deltalm = hCoeffs->delta61vh3 * vh3;
433 rholm = 1. + v2*(hCoeffs->rho61v2 + hCoeffs->rho61v3*v);
434 break;
435 default:
437 break;
438 }
439 break;
440 case 7:
441 switch (m)
442 {
443 case 7:
444 deltalm = hCoeffs->delta77vh3 * vh3;
445 rholm = 1. + v2*(hCoeffs->rho77v2 + hCoeffs->rho77v3 * v);
446 break;
447 case 6:
448 deltalm = 0.0;
449 rholm = 1. + hCoeffs->rho76v2 * v2;
450 break;
451 case 5:
452 deltalm = hCoeffs->delta75vh3 * vh3;
453 rholm = 1. + v2*(hCoeffs->rho75v2 + hCoeffs->rho75v3*v);
454 break;
455 case 4:
456 deltalm = 0.0;
457 rholm = 1. + hCoeffs->rho74v2 * v2;
458 break;
459 case 3:
460 deltalm = hCoeffs->delta73vh3 *vh3;
461 rholm = 1. + v2*(hCoeffs->rho73v2 + hCoeffs->rho73v3 * v);
462 break;
463 case 2:
464 deltalm = 0.0;
465 rholm = 1. + hCoeffs->rho72v2 * v2;
466 break;
467 case 1:
468 deltalm = hCoeffs->delta71vh3 * vh3;
469 rholm = 1. + v2*(hCoeffs->rho71v2 +hCoeffs->rho71v3 * v);
470 break;
471 default:
473 break;
474 }
475 break;
476 case 8:
477 switch (m)
478 {
479 case 8:
480 deltalm = 0.0;
481 rholm = 1. + hCoeffs->rho88v2 * v2;
482 break;
483 case 7:
484 deltalm = 0.0;
485 rholm = 1. + hCoeffs->rho87v2 * v2;
486 break;
487 case 6:
488 deltalm = 0.0;
489 rholm = 1. + hCoeffs->rho86v2 * v2;
490 break;
491 case 5:
492 deltalm = 0.0;
493 rholm = 1. + hCoeffs->rho85v2 * v2;
494 break;
495 case 4:
496 deltalm = 0.0;
497 rholm = 1. + hCoeffs->rho84v2 * v2;
498 break;
499 case 3:
500 deltalm = 0.0;
501 rholm = 1. + hCoeffs->rho83v2 * v2;
502 break;
503 case 2:
504 deltalm = 0.0;
505 rholm = 1. + hCoeffs->rho82v2 * v2;
506 break;
507 case 1:
508 deltalm = 0.0;
509 rholm = 1. + hCoeffs->rho81v2 * v2;
510 break;
511 default:
513 break;
514 }
515 break;
516 default:
518 break;
519 }
520
521 /* Raise rholm to the lth power */
522 rholmPwrl = 1.0;
523 i = l;
524 while ( i-- )
525 {
526 rholmPwrl *= rholm;
527 }
528
529 *hlm = Tlm * cpolar( 1.0, deltalm) * Slm*rholmPwrl;
530 *hlm = *hlm * hNewton;
531
532 return XLAL_SUCCESS;
533}
534
535static inline
537{
538 return - 5.82827 - 143.486 * eta + 447.045 * eta * eta;
539}
540
541static inline
542REAL8 XLALCalculateA6( const REAL8 UNUSED eta )
543{
544 return 184.0;
545}
546
547
548/**
549 * Function to pre-compute the coefficients in the EOB A potential function
550 */
551
552static
554 EOBACoefficients * const coeffs,
555 const REAL8 eta
556 )
557{
558 REAL8 eta2, eta3;
559 REAL8 a4, a5, a6;
560
561 eta2 = eta*eta;
562 eta3 = eta2 * eta;
563
564 /* Note that the definitions of a5 and a6 DO NOT correspond to those in the paper */
565 /* Therefore we have to multiply the results of our a5 and a6 finctions by eta. */
566
567 a4 = ninty4by3etc * eta;
568 a5 = XLALCalculateA5( eta ) * eta;
569 a6 = XLALCalculateA6( eta ) * eta;
570
571 coeffs->n4 = -64. + 12.*a4 + 4.*a5 + a6 + 64.*eta - 4.*eta2;
572 coeffs->n5 = 32. -4.*a4 - a5 - 24.*eta;
573 coeffs->d0 = 4.*a4*a4 + 4.*a4*a5 + a5*a5 - a4*a6 + 16.*a6
574 + (32.*a4 + 16.*a5 - 8.*a6) * eta + 4.*a4*eta2 + 32.*eta3;
575 coeffs->d1 = 4.*a4*a4 + a4*a5 + 16.*a5 + 8.*a6 + (32.*a4 - 2.*a6)*eta + 32.*eta2 + 8.*eta3;
576 coeffs->d2 = 16.*a4 + 8.*a5 + 4.*a6 + (8.*a4 + 2.*a5)*eta + 32.*eta2;
577 coeffs->d3 = 8.*a4 + 4.*a5 + 2.*a6 + 32.*eta - 8.*eta2;
578 coeffs->d4 = 4.*a4 + 2.*a5 + a6 + 16.*eta - 4.*eta2;
579 coeffs->d5 = 32. - 4.*a4 - a5 - 24. * eta;
580
581 return XLAL_SUCCESS;
582}
583
584static
586 EOBACoefficients * restrict coeffs )
587{
588
589 REAL8 r2, r3, r4, r5;
590 REAL8 NA, DA;
591
592 /* Note that this function uses pre-computed coefficients,
593 * and assumes they have been calculated. Since this is a static function,
594 * so only used here, I assume it is okay to neglect error checking
595 */
596
597 r2 = r*r;
598 r3 = r2 * r;
599 r4 = r2*r2;
600 r5 = r4*r;
601
602
603 NA = r4 * coeffs->n4
604 + r5 * coeffs->n5;
605
606 DA = coeffs->d0
607 + r * coeffs->d1
608 + r2 * coeffs->d2
609 + r3 * coeffs->d3
610 + r4 * coeffs->d4
611 + r5 * coeffs->d5;
612
613 return NA/DA;
614}
615
616
617static
619 EOBACoefficients * restrict coeffs )
620{
621 REAL8 r2, r3, r4, r5;
622
623 REAL8 NA, DA, dNA, dDA, dA;
624
625 r2 = r*r;
626 r3 = r2 * r;
627 r4 = r2*r2;
628 r5 = r4*r;
629
630 NA = r4 * coeffs->n4
631 + r5 * coeffs->n5;
632
633 DA = coeffs->d0
634 + r * coeffs->d1
635 + r2 * coeffs->d2
636 + r3 * coeffs->d3
637 + r4 * coeffs->d4
638 + r5 * coeffs->d5;
639
640 dNA = 4. * coeffs->n4 * r3
641 + 5. * coeffs->n5 * r4;
642
643 dDA = coeffs->d1
644 + 2. * coeffs->d2 * r
645 + 3. * coeffs->d3 * r2
646 + 4. * coeffs->d4 * r3
647 + 5. * coeffs->d5 * r4;
648
649 dA = dNA * DA - dDA * NA;
650
651 return dA / (DA*DA);
652}
653
654static
656 REAL8 eta)
657{
658 REAL8 u, u2, u3;
659
660 u = 1./r;
661 u2 = u*u;
662 u3 = u2*u;
663
664 return 1./(1.+6.*eta*u2+2.*eta*(26.-3.*eta)*u3);
665}
666
667
668/**
669 * Function to calculate the EOB effective Hamiltonian for the
670 * given values of the dynamical variables. The coefficients in the
671 * A potential function should already have been computed.
672 * Note that the pr used here is the tortoise co-ordinate.
673 */
674static
676 const REAL8 r,
677 const REAL8 pr,
678 const REAL8 pp,
679 EOBACoefficients *aCoeffs )
680{
681
682 /* The pr used in here is the tortoise co-ordinate */
683 REAL8 r2, pr2, pp2, z3, eoba;
684
685 r2 = r * r;
686 pr2 = pr * pr;
687 pp2 = pp * pp;
688
689 eoba = XLALCalculateEOBA( r, aCoeffs );
690 z3 = 2. * ( 4. - 3. * eta ) * eta;
691 return sqrt( pr2 + eoba * ( 1. + pp2/r2 + z3*pr2*pr2/r2 ) );
692}
693
694/*-------------------------------------------------------------------*/
695/* pseudo-4PN functions */
696/*-------------------------------------------------------------------*/
697
698REAL8
700 const REAL8 r,
701 EOBACoefficients * restrict coeffs
702 )
703{
704 REAL8 u, u2, A, dA;
705
706 u = 1. / r;
707 u2 = u*u;
708
709 /* Comparing this expression with the old one, I *think* I will need to multiply */
710 /* dA by - r^2. TODO: Check that this should be the case */
711
712 A = XLALCalculateEOBA( r, coeffs );
713 dA = - r*r * XLALCalculateEOBdAdr( r, coeffs );
714 return sqrt(-dA/(2.*u*A + u2 * dA));
715/* why is it called phase? This is initial j!? */
716}
717
718/*-------------------------------------------------------------------*/
719REAL8
721 REAL8 p,
722 void *params
723 )
724{
725 REAL8 pr;
726 REAL8 u, u2, p2, p3, p4, A;
727 REAL8 onebyD, AbyD, Heff, HReal, etahH;
728 REAL8 eta, z3, r, vr, q;
729 pr3In *ak;
730
731 /* TODO: Change this to use tortoise coord */
732
733 ak = (pr3In *) params;
734
735 eta = ak->eta;
736 vr = ak->vr;
737 r = ak->r;
738 q = ak->q;
739
740 p2 = p*p;
741 p3 = p2*p;
742 p4 = p2*p2;
743 u = 1./ r;
744 u2 = u*u;
745 z3 = 2. * (4. - 3. * eta) * eta;
746
747 A = XLALCalculateEOBA( r, ak->aCoeffs );
748 onebyD = 1. / XLALCalculateEOBD( r, eta );
749 AbyD = A * onebyD;
750
751 Heff = sqrt(A*(1. + AbyD * p2 + q*q * u2 + z3 * p4 * u2));
752 HReal = sqrt(1. + 2.*eta*(Heff - 1.)) / eta;
753 etahH = eta*Heff*HReal;
754
755/* This sets pr = dH/dpr - vr, calls rootfinder,
756 gets value of pr s.t. dH/pr = vr */
757 pr = -vr + A*(AbyD*p + 2. * z3 * u2 * p3)/etahH;
758
759 return pr;
760}
761
762
763/*-------------------------------------------------------------------*/
764
765static REAL8
767 const REAL8 r,
768 const REAL8 eta,
769 void *params)
770{
771 REAL8 u, u3, A, dA, omega;
772
773 EOBACoefficients *coeffs;
774 coeffs = (EOBACoefficients *) params;
775
776 u = 1./r;
777 u3 = u*u*u;
778
779 A = XLALCalculateEOBA( r, coeffs );
780 dA = XLALCalculateEOBdAdr( r, coeffs );
781
782 /* Comparing this expression with the old one, I *think* I will need to multiply */
783 /* dA by - r^2. TODO: Check that this should be the case */
784 dA = - r * r * dA;
785
786 omega = sqrt(u3) * sqrt ( -0.5 * dA /(1. + 2.*eta * (A/sqrt(A+0.5 * u*dA)-1.)));
787 return omega;
788}
789
790static REAL8
792 REAL8Vector * restrict values,
793 const REAL8 eta,
794 EOBACoefficients *coeffs )
795{
796
797 REAL8 r = values->data[0];
798 REAL8 pphi = values->data[3];
799
800 REAL8 A = XLALCalculateEOBA( r, coeffs );
801 REAL8 dA = XLALCalculateEOBdAdr( r, coeffs );
802
803 return 2. * (1. + 2. * eta * ( -1. + sqrt( (1. + pphi*pphi/(r*r)) * A ) ) )
804 / ( r*r * dA );
805}
806
807
808/*-------------------------------------------------------------------*/
809
810REAL8
812 REAL8 r,
813 void *params )
814{
815 REAL8 omega1,omega2;
816 pr3In *pr3in;
817
818 if ( !params )
820
821 pr3in = (pr3In *) params;
822
823 omega1 = pr3in->omega;
824 omega2 = omegaofrP4PN(r, pr3in->eta, pr3in->aCoeffs);
825 return ( -omega1 + omega2 );
826}
827
828/*-------------------------------------------------------------------*/
829
830/* Version which uses the factorized flux */
831int
832LALHCapDerivativesP4PN( double UNUSED t,
833 const REAL8 values[],
834 REAL8 dvalues[],
835 void *funcParams
836 )
837{
838
839 EOBParams *params = NULL;
840
841 /* Max l to sum up to in the factorized flux */
842 const INT4 lMax = 8;
843
844 REAL8 eta, omega;
845
846 double r, p, q;
847 REAL8 r2, p2, p4, q2;
848 REAL8 u, u2, u3;
849 REAL8 A, AoverSqrtD, dAdr, Heff, Hreal;
850 REAL8 HeffHreal;
851 REAL8 flux;
852 REAL8 z3;
853
854 /* Factorized flux function takes a REAL8Vector */
855 /* We will wrap our current array for now */
856 REAL8Vector valuesVec;
857
858 params = (EOBParams *) funcParams;
859
860 valuesVec.length = 4;
861 memcpy( &(valuesVec.data), &(values), sizeof(REAL8 *) );
862
863 eta = params->eta;
864
865 z3 = 2. * ( 4. - 3. * eta ) * eta;
866
867 r = values[0];
868 p = values[2];
869 q = values[3];
870
871 u = 1.0 / r;
872 u2 = u * u;
873 u3 = u2 * u;
874 r2 = r * r;
875 p2 = p*p;
876 p4 = p2 * p2;
877 q2 = q * q;
878
879 A = XLALCalculateEOBA(r, params->aCoeffs );
880 dAdr = XLALCalculateEOBdAdr(r, params->aCoeffs );
881 AoverSqrtD = A / sqrt( XLALCalculateEOBD(r, eta) );
882
883 /* Note that Hreal as given here is missing a factor of 1/eta */
884 /* This is because it only enters into the derivatives in */
885 /* the combination eta*Hreal*Heff, so the eta would get */
886 /* cancelled out anyway. */
887
888 Heff = XLALEffectiveHamiltonian( eta, r, p, q, params->aCoeffs );
889 Hreal = sqrt( 1. + 2.*eta*(Heff - 1.) );
890
891 HeffHreal = Heff * Hreal;
892
893 /* rDot */
894 dvalues[0] = AoverSqrtD * u2 * p * (r2 + 2. * p2 * z3 * A ) / HeffHreal;
895
896 /* sDot */
897 dvalues[1] = omega = q * A * u2 / HeffHreal;
898
899 /* Note that the only field of dvalues used in the flux is dvalues->data[1] */
900 /* which we have already calculated. */
901 flux = XLALInspiralFactorizedFlux( &valuesVec, omega, params, lMax );
902
903 /* pDot */
904 dvalues[2] = 0.5 * AoverSqrtD * u3 * ( 2.0 * ( q2 + p4 * z3) * A
905 - r * ( q2 + r2 + p4 * z3 ) * dAdr ) / HeffHreal
906 - (p / q) * (flux / (eta * omega));
907
908 /* qDot */
909 dvalues[3] = - flux / (eta * omega);
910
911 /* Let the integrator know via the return code if the derivative is nan */
912 if ( isnan( dvalues[0] ) || isnan( dvalues[1] ) || isnan( dvalues[2] ) || isnan( dvalues[3] ) )
913 {
914 return 1;
915 }
916
917 return GSL_SUCCESS;
918}
919
920/* Function for calculating only omega */
921static
923 REAL8 r,
924 REAL8 pr,
925 REAL8 pPhi,
926 EOBACoefficients *aCoeffs )
927{
928
929 REAL8 A, Heff, Hreal, HeffHreal;
930
931 A = XLALCalculateEOBA( r, aCoeffs );
932 Heff = XLALEffectiveHamiltonian( eta, r, pr, pPhi, aCoeffs );
933 Hreal = sqrt( 1. + 2.*eta*(Heff - 1.) );
934
935 HeffHreal = Heff * Hreal;
936 return pPhi * A / (HeffHreal*r*r);
937}
938
939/**
940 * Function which will calculate the stopping condition for the
941 * initial sampling rate
942 */
943static int
945 const double UNUSED values[],
946 double dvalues[],
947 void *funcParams
948 )
949{
950
951 EOBParams *params = (EOBParams *)funcParams;
952 double omega = dvalues[1];
953
954 if ( omega < params->omega )
955 {
956 return 1;
957 }
958
959 params->omega = omega;
960 return GSL_SUCCESS;
961}
962
963/**
964 * Function which will calculate the stopping condition for the
965 * higher sampling rate
966 */
967static int
969 const double values[],
970 double dvalues[],
971 void UNUSED *funcParams
972 )
973{
974 EOBParams *params = (EOBParams *)funcParams;
975 REAL8 rstop;
976 if ( params->eta > 0.1 )
977 {
978 rstop = 1.25 - params->eta;
979 }
980 else
981 {
982 rstop = 2.1 - 10.0 * params->eta;
983 }
984
985 if ( values[0] <= rstop || isnan(dvalues[3]) || isnan(dvalues[2]) || isnan(dvalues[1]) || isnan(dvalues[0]) )
986 {
987 return 1;
988 }
989 return 0;
990}
991
992/*-------------------------------------------------------------------*/
994 const REAL8 omega,
995 pr3In *params )
996{
997 REAL8 A, dAdr, d2Adr2, dA, d2A, NA, DA, dDA, dNA, d2DA, d2NA;
998 REAL8 r2, r3, r4, r5, u, u2, v, x1;
999 REAL8 eta, FDIS;
1000 REAL8 twoUAPlusu2dA;
1001
1002 EOBACoefficients *aCoeffs = params->aCoeffs;
1003
1004 eta = params->eta;
1005 r2 = r*r;
1006 r3 = r2*r;
1007 r4 = r2*r2;
1008 r5 = r2*r3;
1009
1010 u = 1./ r;
1011
1012 u2 = u*u;
1013
1014 NA = r4 * aCoeffs->n4
1015 + r5 * aCoeffs->n5;
1016
1017 DA = aCoeffs->d0
1018 + r * aCoeffs->d1
1019 + r2 * aCoeffs->d2
1020 + r3 * aCoeffs->d3
1021 + r4 * aCoeffs->d4
1022 + r5 * aCoeffs->d5;
1023
1024 dNA = 4. * aCoeffs->n4 * r3
1025 + 5. * aCoeffs->n5 * r4;
1026
1027 dDA = aCoeffs->d1
1028 + 2. * aCoeffs->d2 * r
1029 + 3. * aCoeffs->d3 * r2
1030 + 4. * aCoeffs->d4 * r3
1031 + 5. * aCoeffs->d5 * r4;
1032
1033 d2NA = 12. * aCoeffs->n4 * r2
1034 + 20. * aCoeffs->n5 * r3;
1035
1036 d2DA = 2. * aCoeffs->d2
1037 + 6. * aCoeffs->d3 * r
1038 + 12. * aCoeffs->d4 * r2
1039 + 20. * aCoeffs->d5 * r3;
1040
1041 A = NA/DA;
1042 dAdr = ( dNA * DA - dDA * NA ) / (DA*DA);
1043 d2Adr2 = (d2NA*DA - d2DA*NA - 2.*dDA*DA*dAdr)/(DA*DA);
1044
1045 /* The next derivatives are with respect to u, not r */
1046
1047 dA = - r2 * dAdr;
1048 d2A = r4 * d2Adr2 + 2.*r3 * dAdr;
1049
1050 v = cbrt(omega);
1051 FDIS = -params->in3copy.flux(v, params->in3copy.coeffs)/(eta*omega);
1052
1053 twoUAPlusu2dA = 2.* u * A + u2 * dA;
1054 x1 = -r2 * sqrt (-dA * twoUAPlusu2dA * twoUAPlusu2dA * twoUAPlusu2dA )
1055 / (2.* u * dA * dA + A*dA - u * A * d2A);
1056 return (FDIS * x1);
1057}
1058
1059static REAL8
1061{
1062
1063 switch ( l )
1064 {
1065 case 2:
1066 switch ( m )
1067 {
1068 case 2:
1069 return 5.;
1070 break;
1071 case 1:
1072 return 8.;
1073 break;
1074 default:
1076 break;
1077 }
1078 break;
1079 case 3:
1080 if ( m == 3 )
1081 {
1082 return 12.;
1083 }
1084 else
1085 {
1087 }
1088 break;
1089 case 4:
1090 if ( m == 4 )
1091 {
1092 return 9.;
1093 }
1094 else
1095 {
1097 }
1098 break;
1099 case 5:
1100 if ( m == 5 )
1101 {
1102 return 8.;
1103 }
1104 else
1105 {
1107 }
1108 break;
1109 default:
1111 break;
1112 }
1113
1114 /* It should not be possible to get to this point */
1115 /* Put an return path here to avoid compiler warningd */
1116 XLALPrintError( "We shouldn't ever reach this point!\n" );
1118
1119}
1120
1121/*-------------------------------------------------------------------*/
1122
1123int
1125 REAL4Vector *signalvec,
1127 )
1128{
1129 XLAL_PRINT_DEPRECATION_WARNING("lalsimulation/XLALSimIMREOBNRv2AllModes or lalsimulation/XLALSimIMREOBNRv2DominantMode");
1130 XLALPrintWarning( "WARNING: The lalinspiral version of EOBNRv2 and EOBNRv2HM are not reviewed or maintained and will be removed in the future. The lalsimulation versions of these waveforms should be used.\n" );
1131
1132 UINT4 count;
1133 InspiralInit paramsInit;
1134
1135 if ( !signalvec )
1136 {
1138 }
1139 if ( !signalvec->data )
1140 {
1142 }
1143 if ( !params )
1144 {
1146 }
1147 if ( params->nStartPad < 0 || params->nEndPad < 0 )
1148 {
1149 XLALPrintError( "nStartPad and nEndPad must be >= 0.\n");
1151 }
1152 if ( params->fLower <= 0. )
1153 {
1154 XLALPrintError( "fLower must be > 0.\n");
1156 }
1157 if ( params->tSampling <= 0. )
1158 {
1159 XLALPrintError( "tSampling must be > 0.\n");
1161 }
1162 if ( params->totalMass <= 0. )
1163 {
1164 XLALPrintError( "totalMass must be > 0.\n");
1166 }
1167
1168 if ( XLALInspiralSetup( &(paramsInit.ak), params) == XLAL_FAILURE )
1169 {
1171 }
1172
1173 if ( XLALInspiralChooseModel( &(paramsInit.func),
1174 &(paramsInit.ak), params ) == XLAL_FAILURE )
1175 {
1177 }
1178
1179 memset(signalvec->data, 0, signalvec->length * sizeof( REAL4 ));
1180
1181 /* Call the engine function */
1182 if ( XLALEOBPPWaveformEngine( signalvec, NULL, NULL, NULL,
1183 &count, params, &paramsInit) == XLAL_FAILURE )
1184 {
1186 }
1187
1188 return XLAL_SUCCESS;
1189}
1190
1191
1192int
1194 REAL4Vector *signalvec1,
1195 REAL4Vector *signalvec2,
1197 )
1198{
1199 UINT4 count;
1200
1201 InspiralInit paramsInit;
1202
1203 if ( !signalvec1 )
1204 {
1206 }
1207 if ( !signalvec2 )
1208 {
1210 }
1211 if ( !signalvec1->data )
1212 {
1214 }
1215 if ( !signalvec2->data )
1216 {
1218 }
1219 if ( !params )
1220 {
1222 }
1223 if ( params->nStartPad < 0 || params->nEndPad < 0 )
1224 {
1225 XLALPrintError( "nStartPad and nEndPad must be >= 0.\n");
1227 }
1228 if ( params->fLower <= 0. )
1229 {
1230 XLALPrintError( "fLower must be > 0.\n");
1232 }
1233 if ( params->tSampling <= 0. )
1234 {
1235 XLALPrintError( "tSampling must be > 0.\n");
1237 }
1238 if ( params->totalMass <= 0. )
1239 {
1240 XLALPrintError( "totalMass must be > 0.\n");
1242 }
1243
1244 if ( XLALInspiralSetup( &(paramsInit.ak), params) == XLAL_FAILURE )
1245 {
1247 }
1248
1249 if ( XLALInspiralChooseModel( &(paramsInit.func),
1250 &(paramsInit.ak), params ) == XLAL_FAILURE )
1251 {
1253 }
1254
1255 memset(signalvec1->data, 0, signalvec1->length * sizeof( REAL4 ));
1256 memset(signalvec2->data, 0, signalvec2->length * sizeof( REAL4 ));
1257
1258 /* Call the engine function */
1259 if ( XLALEOBPPWaveformEngine( signalvec1, signalvec2, NULL, NULL,
1260 &count, params, &paramsInit) == XLAL_FAILURE )
1261 {
1263 }
1264
1265 return XLAL_SUCCESS;
1266}
1267
1268
1269/*=========================================================*/
1270/*======INJECTION =========================================*/
1271/*=========================================================*/
1272
1273
1274int
1276 CoherentGW *waveform,
1278 PPNParamStruc *ppnParams
1279 )
1280{
1281 UINT4 count, i;
1282
1283 REAL4Vector *h=NULL;/* pointers to generated polarization data */
1284
1285 REAL8 phiC;/* phase at coalescence */
1286 InspiralInit paramsInit;
1287
1288 /* Make sure parameter and waveform structures exist. */
1289 if ( !params )
1291
1292 if ( !waveform )
1294
1295 /* Make sure waveform fields don't exist. */
1296 if ( waveform->a )
1297 {
1298 XLALPrintError( "Pointer for waveform->a exists. Was expecting NULL.\n" );
1300 }
1301 if ( waveform->h )
1302 {
1303 XLALPrintError( "Pointer for waveform->h exists. Was expecting NULL.\n" );
1305 }
1306 if ( waveform->f )
1307 {
1308 XLALPrintError( "Pointer for waveform->f exists. Was expecting NULL.\n" );
1310 }
1311 if ( waveform->phi )
1312 {
1313 XLALPrintError( "Pointer for waveform->phi exists. Was expecting NULL.\n" );
1315 }
1316 if ( waveform->shift )
1317 {
1318 XLALPrintError( "Pointer for waveform->shift exists. Was expecting NULL.\n" );
1320 }
1321
1322 params->ampOrder = (LALPNOrder) 0;
1323 XLALPrintWarning( "WARNING: Amp Order has been reset to %d\n", params->ampOrder);
1324
1325 /* Compute some parameters*/
1326 if( XLALInspiralInit( params, &paramsInit) == XLAL_FAILURE )
1327 {
1329 }
1330
1331 if (paramsInit.nbins==0)
1332 {
1333 XLALPrintWarning( "Waveform is of zero length!!\n" );
1334 return XLAL_SUCCESS;
1335 }
1336 /* Now we can allocate memory and vector for coherentGW structure*/
1337 if ( (h = XLALCreateREAL4Vector(2*paramsInit.nbins)) == NULL )
1338 {
1340 }
1341
1342 phiC = ppnParams->phi;
1343
1344 /* By default the waveform is empty */
1345 memset(h->data, 0, 2 * paramsInit.nbins * sizeof(REAL4));
1346
1347 /* Call the engine function */
1348 params->startPhase = ppnParams->phi;
1349 if( XLALEOBPPWaveformEngine( NULL, NULL, h,
1350 &phiC, &count, params, &paramsInit) == XLAL_FAILURE )
1351 {
1354 }
1355
1356 /* Check an empty waveform hasn't been returned */
1357 for (i = 0; i < h->length; i++)
1358 {
1359 if (h->data[i] != 0.0) break;
1360 if (i == h->length - 1)
1361 {
1363 XLALPrintError( "An empty waveform has been generated!\n" );
1365 }
1366 }
1367
1368 /* Allocate the waveform structures. */
1369 if ( ( waveform->h = (REAL4TimeVectorSeries *)
1370 LALMalloc( sizeof(REAL4TimeVectorSeries) ) ) == NULL )
1371 {
1374 }
1375 memset( waveform->h, 0, sizeof(REAL4TimeVectorSeries) );
1376
1377 if ( (waveform->h->data = XLALCreateREAL4VectorSequence( count, 2 )) == NULL )
1378 {
1379 LALFree( waveform->h );
1382 }
1383
1384
1385 memcpy(waveform->h->data->data , h->data, 2*count*(sizeof(REAL4)));
1386
1387 waveform->h->deltaT = 1./params->tSampling;
1388
1389 waveform->h->sampleUnits = lalStrainUnit;
1390 waveform->position = ppnParams->position;
1391 waveform->psi = ppnParams->psi;
1392
1393 snprintf( waveform->h->name,
1394 LALNameLength, "EOB inspiral polarizations");
1395
1396 /* --- fill some output ---*/
1397 /* Note that dfdt used to be set here. It has no relevance */
1398 /* to this code, and was in fact probably wrong. */
1399 /* However, certain codes use it to check for sampling issues */
1400 /* so if things fail, we may need to do something. */
1401 ppnParams->tc = (double)(count-1) / params->tSampling ;
1402 ppnParams->length = count;
1403 ppnParams->fStop = params->fFinal;
1405 ppnParams->termDescription = GENERATEPPNINSPIRALH_MSGEFSTOP;
1406
1407 ppnParams->fStart = ppnParams->fStartIn;
1408
1409 /* --- free memory --- */
1410
1412
1413 return XLAL_SUCCESS;
1414}
1415
1416/* Engine function for generating waveform
1417 Craig Robinson 15/07/05 */
1418static int
1420 REAL4Vector *signalvec1,
1421 REAL4Vector *signalvec2,
1422 REAL4Vector *h,
1423 const REAL8 *phiC,
1424 UINT4 *countback,
1426 InspiralInit *paramsInit
1427 )
1428{
1429
1430
1431 UINT4 count, nn=4, length = 0, hiSRndx=0;
1432
1433 REAL4Vector *sig1, *sig2, *freq;
1434 REAL8Vector rVec, phiVec, prVec, pPhiVec;
1435 REAL8Vector rVecHi, phiVecHi, prVecHi, pPhiVecHi, tVecHi;
1436
1437 REAL8 eta, m, r, s, p, q, dt, t, v, omega, f, ampl0;
1438 REAL8 omegaOld;
1439
1440 void *funcParams;
1441
1442 REAL8Vector *values, *dvalues;
1444
1445 /* Variables for the integrator */
1446 LALAdaptiveRungeKuttaIntegrator *integrator = NULL;
1447 REAL8Array *dynamics = NULL;
1448 REAL8Array *dynamicsHi = NULL;
1449 INT4 retLen;
1450 REAL8 tMax;
1451
1452 pr3In pr3in;
1453 expnCoeffs ak;
1454 expnFunc func;
1455 DFindRootIn rootIn2, rootIn3;
1456
1457 /* Stuff for pre-computed EOB values */
1458 EOBParams eobParams;
1459 EOBACoefficients aCoeffs;
1460 FacWaveformCoeffs hCoeffs;
1461 NewtonMultipolePrefixes prefixes;
1462
1463 REAL8 (*rOfOmegaFunc)(REAL8, void *); /* Function to be used in root finding later */
1464
1465 /* Variables to allow the waveform to be generated */
1466 /* from a specific fLower */
1467 REAL8 /*sInit,*/ sSub = 0.0; /* Initial phase, and phase to subtract */
1468
1469 REAL8 rmin = 20; /* Smallest value of r at which to generate the waveform */
1470 COMPLEX16 MultSphHarmP; /* Spin-weighted spherical harmonics */
1471 COMPLEX16 MultSphHarmM; /* Spin-weighted spherical harmonics */
1472 COMPLEX16 hLM; /* Factorized waveform */
1473 COMPLEX16 hNQC; /* Non-quasicircular correction */
1474 REAL4 x1, x2;
1475 UINT4 i, j, k, modeL;
1476 INT4 modeM;
1477 INT4 nModes; /* number of modes required */
1478 REAL4 inclination; /* binary inclination */
1479 REAL4 coa_phase; /* binary coalescence phase */
1480 REAL8 y_1, y_2, z_1, z_2; /* (2,2) and (2,-2) spherical harmonics needed in (h+,hx) */
1481
1482
1483 /* Used for EOBNR */
1484 COMPLEX8Vector *modefreqs;
1485 UINT4 resampFac;
1486 UINT4 resampPwr; /* Power of 2 for resampling */
1487 REAL8 resampEstimate;
1488
1489 /* For checking XLAL return codes */
1490 INT4 xlalStatus;
1491
1492 /* Variables used in injection */
1493 REAL8 unitHz;
1494
1495 /* Accuracy of root finding algorithms */
1496 const REAL8 xacc = 1.0e-12;
1497
1498 /* Accuracies of adaptive Runge-Kutta integrator */
1499 const REAL8 EPS_ABS = 1.0e-12;
1500 const REAL8 EPS_REL = 1.0e-10;
1501
1502 REAL8 tStepBack; /* We need to step back 6M to attach ringdown */
1503 UINT4 nStepBack; /* Num points to step back */
1504
1505 /* Stuff at higher sample rate */
1506 REAL4Vector *sig1Hi, *sig2Hi, *freqHi;
1507 REAL8Vector *phseHi, *omegaHi;
1508 UINT4 lengthHiSR;
1509
1510 /* Used in the calculation of the non-quasicircular correctlon */
1511 REAL8Vector *ampNQC, *q1, *q2, *q3, *p1, *p2;
1512 EOBNonQCCoeffs nqcCoeffs;
1513
1514 /* Inidices of the ringdown matching points */
1515 /* peakIdx is the index where omega is a maximum */
1516 /* finalIdx is the index of the last point before the */
1517 /* integration breaks */
1518 /* startIdx is the index at which the waveform crosses fLower */
1519 REAL8Vector *rdMatchPoint;
1520 UINT4 peakIdx = 0;
1521 UINT4 finalIdx = 0;
1522 UINT4 startIdx = 0;
1523 /* Counter used in unwrapping the waveform phase for NQC correction */
1524 INT4 phaseCounter;
1525
1526 /* The list of available modes */
1527 const INT4 lmModes[5][2] = {{2, 2},
1528 {2, 1},
1529 {3, 3},
1530 {4, 4},
1531 {5, 5}};
1532
1533 INT4 currentMode;
1534
1535 ak = paramsInit->ak;
1536 func = paramsInit->func;
1537
1538 /* Check order is consistent */
1539 if ( params->order != LAL_PNORDER_PSEUDO_FOUR )
1540 {
1541 XLALPrintError( "Order must be LAL_PNORDER_PSEUDO_FOUR for approximant EOBNRv2.\n" );
1543 }
1544
1545 /* Since h contains both plus and cross, it is twice the length of the vectors */
1546 if (signalvec1) length = signalvec1->length; else if (h) length = h->length / 2;
1547
1548 /* Allocate some memory */
1549 values = XLALCreateREAL8Vector( nn );
1550 dvalues = XLALCreateREAL8Vector( nn );
1551
1552 if ( !values || !dvalues )
1553 {
1554 XLALDestroyREAL8Vector( values );
1555 XLALDestroyREAL8Vector( dvalues );
1557 }
1558
1559 /* Set dt to sampling interval specified by user */
1560 dt =1./params->tSampling;
1561 eta = ak.eta;
1562 m = ak.totalmass;
1563
1564 /* The maximum allowed time is determined by the length of the vectors */
1565 tMax = length * dt;
1566
1567 /* only used in injection case */
1568 unitHz = m*(REAL8)LAL_PI;
1569
1570 /* Set the amplitude depending on whether the distance is given */
1571 if ( params->distance > 0.0 )
1572 ampl0 = params->totalMass * LAL_MRSUN_SI/params->distance;
1573 else
1574 ampl0 = params->signalAmplitude;
1575
1576 /* Check we get a sensible answer */
1577 if ( ampl0 == 0.0 )
1578 {
1579 XLALPrintWarning( "Generating waveform of zero amplitude!!\n" );
1580 }
1581
1582 /* Set the number of modes depending on whether the user wants higher order modes */
1583 if ( params->approximant == EOBNRv2 )
1584 {
1585 nModes = 1;
1586 }
1587 else if ( params->approximant == EOBNRv2HM )
1588 {
1590 }
1591 else
1592 {
1593 XLALPrintError( "Unsupported approximant\n" );
1595 }
1596
1597 /* Check that the 220 QNM freq. is less than the Nyquist freq. */
1598 /* Get QNM frequencies */
1599 modefreqs = XLALCreateCOMPLEX8Vector( 3 );
1600 xlalStatus = XLALGenerateQNMFreqV2( modefreqs, params, 2, 2, 3 );
1601 if ( xlalStatus != XLAL_SUCCESS )
1602 {
1603 XLALDestroyCOMPLEX8Vector( modefreqs );
1605 }
1606
1607 /* If Nyquist freq. < 220 QNM freq., exit */
1608 /* Note that we cancelled a factor of 2 occuring on both sides */
1609 if ( params->tSampling < crealf(modefreqs->data[0]) / LAL_PI )
1610 {
1611 XLALDestroyCOMPLEX8Vector( modefreqs );
1612 XLALPrintError( "Ringdown freq greater than Nyquist freq. "
1613 "Increase sample rate or consider using EOB approximant.\n" );
1615 }
1616
1617 /* Calculate the time we will need to step back for ringdown */
1618 tStepBack = 20.0 * params->totalMass * LAL_MTSUN_SI;
1619 nStepBack = ceil( tStepBack * params->tSampling );
1620
1621 /* Set up structures for pre-computed EOB coefficients */
1622 memset( &eobParams, 0, sizeof(eobParams) );
1623 eobParams.eta = eta;
1624 eobParams.m1 = params->mass1;
1625 eobParams.m2 = params->mass2;
1626 eobParams.aCoeffs = &aCoeffs;
1627 eobParams.hCoeffs = &hCoeffs;
1628 eobParams.nqcCoeffs = &nqcCoeffs;
1629 eobParams.prefixes = &prefixes;
1630
1631 if ( XLALCalculateEOBACoefficients( &aCoeffs, eta ) == XLAL_FAILURE )
1632 {
1634 }
1635
1636 if ( XLALCalcFacWaveformCoefficients( &hCoeffs, eta) == XLAL_FAILURE )
1637 {
1639 }
1640
1641 if ( XLALComputeNewtonMultipolePrefixes( &prefixes, eobParams.m1, eobParams.m2 )
1642 == XLAL_FAILURE )
1643 {
1645 }
1646
1647 /* For the dynamics, we need to use preliminary calculated versions */
1648 /*of the NQC coefficients for the (2,2) mode. We calculate them here. */
1649 if ( XLALGetCalibratedNQCCoeffs( &nqcCoeffs, 2, 2, eta ) == XLAL_FAILURE )
1650 {
1652 }
1653
1654 /* Calculate the resample factor for attaching the ringdown */
1655 /* We want it to be a power of 2 */
1656 /* Of course, we only want to do this if the required SR > current SR... */
1657 /* The form chosen for the resampleEstimate will essentially set */
1658 /* deltaT = M / 20. ( or less taking into account the power of 2 stuff */
1659 resampEstimate = 20. / ( params->totalMass * LAL_MTSUN_SI * params->tSampling );
1660 resampFac = 1;
1661
1662 if ( resampEstimate > 1 )
1663 {
1664 resampPwr = (UINT4)ceil(log2(resampEstimate));
1665 while ( resampPwr-- )
1666 {
1667 resampFac *= 2u;
1668 }
1669 }
1670
1671 /* The length of the vectors at the higher sample rate will be */
1672 /* the step back time plus the ringdown */
1673 lengthHiSR = ( nStepBack + (UINT4)(20.0 / cimagf(modefreqs->data[0]) / dt) ) * resampFac;
1674
1675 /* Double it for good measure */
1676 lengthHiSR *= 2;
1677
1678 /* We are now done with the ringdown modes - destroy them here */
1679 XLALDestroyCOMPLEX8Vector( modefreqs );
1680 modefreqs = NULL;
1681
1682 /* Find the initial velocity given the lower frequency */
1683 f = params->fLower;
1684 omega = f * LAL_PI * m;
1685 v = cbrt( omega );
1686
1687 /* Then the initial phase */
1688 s = params->startPhase / 2.;
1689 /*sInit = s;*/
1690
1691 /* initial r as a function of omega - where to start evolution */
1692 rootIn3.xacc = xacc;
1693 rootIn2.xmax = 1000.;
1694 rootIn2.xmin = 3.;
1695 pr3in.eta = eta;
1696 pr3in.omegaS = params->OmegaS;
1697 pr3in.zeta2 = params->Zeta2;
1698 pr3in.aCoeffs = &aCoeffs;
1699
1700 /* We will be changing the starting r if it is less than rmin */
1701 /* Therefore, we should reset pr3in.omega later if necessary. */
1702 /* For now we need it so that we can see what the initial r is. */
1703
1704 pr3in.omega = omega;
1705 in3.totalmass = ak.totalmass;
1706 in3.dEnergy = func.dEnergy;
1707 in3.flux = func.flux;
1708 in3.coeffs = &ak;
1709 in3.nqcCoeffs = &nqcCoeffs;
1710
1711 rOfOmegaFunc = XLALrOfOmegaP4PN;
1712 funcParams = (void *) &pr3in;
1713 r = XLALDBisectionFindRoot( rOfOmegaFunc, rootIn2.xmin,
1714 rootIn2.xmax, xacc, funcParams);
1715 if ( XLAL_IS_REAL8_FAIL_NAN( r ) )
1716 {
1718 }
1719
1720 /* We want the waveform to generate from a point which won't cause */
1721 /* problems with the initial conditions. Therefore we force the code */
1722 /* to start at least at r = rmin (in units of M). */
1723
1724 r = (r<rmin) ? rmin : r;
1725
1726 rootIn3.xmax = 5;
1727 rootIn3.xmin = -10;
1728 pr3in.in3copy = in3;
1729 pr3in.r = r;
1730
1731 /* Now that r is changed recompute omega corresponding */
1732 /* to that r and only then compute initial pr and pphi */
1733
1734 omega = omegaofrP4PN( r, eta, &aCoeffs );
1735 pr3in.omega = omega;
1736 q = XLALpphiInitP4PN(r, &aCoeffs );
1737 /* first we compute vr (we need coeef->Fp6) */
1738 pr3in.q = q;
1739 funcParams = (void *) &pr3in;
1740 pr3in.vr = XLALvrP4PN(r, omega, (void *) &pr3in);
1741 /* then we compute the initial value of p */
1742 p = XLALDBisectionFindRoot( XLALprInitP4PN, rootIn3.xmin, rootIn3.xmax, xacc, funcParams);
1743 if ( XLAL_IS_REAL8_FAIL_NAN( p ) )
1744 {
1746 }
1747 /* We need to change P to be the tortoise co-ordinate */
1748 /* TODO: Change prInit to calculate this directly */
1749 p = p * XLALCalculateEOBA(r, &aCoeffs);
1750 p = p / sqrt( XLALCalculateEOBD( r, eta ) );
1751
1752 values->data[0] = r;
1753 values->data[1] = s;
1754 values->data[2] = p;
1755 values->data[3] = q;
1756
1757 /* Allocate memory for temporary arrays */
1758 sig1 = XLALCreateREAL4Vector ( length );
1759 sig2 = XLALCreateREAL4Vector ( length );
1760 freq = XLALCreateREAL4Vector ( length );
1761
1762 if ( !sig1 || !sig2 || !freq )
1763 {
1764 if ( sig1 ) XLALDestroyREAL4Vector( sig1 );
1765 if ( sig2 ) XLALDestroyREAL4Vector( sig2 );
1766 if ( freq ) XLALDestroyREAL4Vector( freq );
1767 XLALDestroyREAL8Vector( values );
1768 XLALDestroyREAL8Vector( dvalues );
1770 }
1771
1772 memset(sig1->data, 0, sig1->length * sizeof( REAL4 ));
1773 memset(sig2->data, 0, sig2->length * sizeof( REAL4 ));
1774 memset(freq->data, 0, freq->length * sizeof( REAL4 ));
1775
1776 /* And their higher sample rate counterparts */
1777 /* Allocate memory for temporary arrays */
1778 sig1Hi = XLALCreateREAL4Vector ( lengthHiSR );
1779 sig2Hi = XLALCreateREAL4Vector ( lengthHiSR );
1780 freqHi = XLALCreateREAL4Vector ( lengthHiSR );
1781 phseHi = XLALCreateREAL8Vector ( lengthHiSR );
1782 omegaHi = XLALCreateREAL8Vector ( lengthHiSR );
1783
1784 /* Allocate NQC vectors */
1785 ampNQC = XLALCreateREAL8Vector ( lengthHiSR );
1786 q1 = XLALCreateREAL8Vector ( lengthHiSR );
1787 q2 = XLALCreateREAL8Vector ( lengthHiSR );
1788 q3 = XLALCreateREAL8Vector ( lengthHiSR );
1789 p1 = XLALCreateREAL8Vector ( lengthHiSR );
1790 p2 = XLALCreateREAL8Vector ( lengthHiSR );
1791
1792 if ( !sig1Hi || !sig2Hi || !freqHi || !phseHi )
1793 {
1794 if ( sig1 ) XLALDestroyREAL4Vector( sig1 );
1795 if ( sig2 ) XLALDestroyREAL4Vector( sig2 );
1796 if ( freq ) XLALDestroyREAL4Vector( freq );
1797 XLALDestroyREAL8Vector( values );
1798 XLALDestroyREAL8Vector( dvalues );
1800 }
1801
1802 memset(sig1Hi->data, 0, sig1Hi->length * sizeof( REAL4 ));
1803 memset(sig2Hi->data, 0, sig2Hi->length * sizeof( REAL4 ));
1804 memset(freqHi->data, 0, freqHi->length * sizeof( REAL4 ));
1805 memset(phseHi->data, 0, phseHi->length * sizeof( REAL8 ));
1806 memset(omegaHi->data, 0, omegaHi->length * sizeof( REAL8 ));
1807 memset(ampNQC->data, 0, ampNQC->length * sizeof( REAL8 ));
1808 memset(q1->data, 0, q1->length * sizeof( REAL8 ));
1809 memset(q2->data, 0, q2->length * sizeof( REAL8 ));
1810 memset(q3->data, 0, q3->length * sizeof( REAL8 ));
1811 memset(p1->data, 0, p1->length * sizeof( REAL8 ));
1812 memset(p2->data, 0, p2->length * sizeof( REAL8 ));
1813
1814 /* Initialize the GSL integrator */
1815 if (!(integrator = XLALAdaptiveRungeKutta4Init(nn, LALHCapDerivativesP4PN, XLALFirstStoppingCondition, EPS_ABS, EPS_REL)))
1816 {
1817 XLALDestroyREAL4Vector( sig1 );
1818 XLALDestroyREAL4Vector( sig2 );
1819 XLALDestroyREAL4Vector( freq );
1820 XLALDestroyREAL8Vector( values );
1821 XLALDestroyREAL8Vector( dvalues );
1823 }
1824
1825 integrator->stopontestonly = 1;
1826 integrator->retries = 1;
1827
1828 count = 0;
1829 if (h || signalvec2)
1830 params->nStartPad = 0; /* must be zero for templates and injection */
1831
1832 count = params->nStartPad;
1833
1834 /* Use the new adaptive integrator */
1835 /* TODO: Implement error checking */
1836 retLen = XLALAdaptiveRungeKutta4( integrator, &eobParams, values->data, 0., tMax/m, dt/m, &dynamics );
1837
1838 /* We should have integrated to the peak of the frequency by now */
1839 hiSRndx = retLen - nStepBack;
1840
1841 /* Set up the vectors, and re-initialize everything for the high sample rate */
1842 rVec.length = phiVec.length = prVec.length = pPhiVec.length = retLen;
1843 rVec.data = dynamics->data+retLen;
1844 phiVec.data = dynamics->data+2*retLen;
1845 prVec.data = dynamics->data+3*retLen;
1846 pPhiVec.data = dynamics->data+4*retLen;
1847
1848 /* It is not easy to define an exact coalescence phase for this model */
1849 /* Therefore we will just choose it to be the point where the peak was */
1850 /* estimated to be here */
1851 if ( phiC )
1852 {
1853 sSub = phiVec.data[retLen - 1] - (*phiC)/2.;
1854 }
1855
1856 dt = dt/(REAL8)resampFac;
1857 values->data[0] = rVec.data[hiSRndx];
1858 values->data[1] = phiVec.data[hiSRndx];
1859 values->data[2] = prVec.data[hiSRndx];
1860 values->data[3] = pPhiVec.data[hiSRndx];
1861
1862 /* We want to use a different stopping criterion for the higher sample rate */
1863 integrator->stop = XLALHighSRStoppingCondition;
1864
1865 retLen = XLALAdaptiveRungeKutta4( integrator, &eobParams, values->data,
1866 0, (lengthHiSR-1)*dt/m, dt/m, &dynamicsHi );
1867
1868 rVecHi.length = phiVecHi.length = prVecHi.length = pPhiVecHi.length = tVecHi.length = retLen;
1869 rVecHi.data = dynamicsHi->data+retLen;
1870 phiVecHi.data = dynamicsHi->data+2*retLen;
1871 prVecHi.data = dynamicsHi->data+3*retLen;
1872 pPhiVecHi.data = dynamicsHi->data+4*retLen;
1873 tVecHi.data = dynamicsHi->data;
1874
1875 /* We are now finished with the adaptive RK, so we can free its resources */
1876 XLALAdaptiveRungeKuttaFree( integrator );
1877 integrator = NULL;
1878
1879 /* Now we have the dynamics, we tweak the factorized coefficients for the waveform */
1880 if ( XLALModifyFacWaveformCoefficients( &hCoeffs, eta) == XLAL_FAILURE )
1881 {
1883 }
1884
1885 /* We can now start calculating things for NQCs, and hiSR waveform */
1886 omegaOld = 0.0;
1887
1888 for ( currentMode = 0; currentMode < nModes; currentMode++ )
1889 {
1890 count = params->nStartPad;
1891
1892 modeL = lmModes[currentMode][0];
1893 modeM = lmModes[currentMode][1];
1894
1895 /* If we have an equal mass system, some modes will be zero */
1896 if ( eta == 0.25 && modeM % 2 )
1897 {
1898 continue;
1899 }
1900
1901 phaseCounter = 0;
1902 for ( i=0; i < (UINT4)retLen; i++ )
1903 {
1904 omega = XLALCalculateOmega( eta, rVecHi.data[i], prVecHi.data[i], pPhiVecHi.data[i], &aCoeffs );
1905 omegaHi->data[i] = omega;
1906 /* For now we re-populate values - there may be a better way to do this */
1907 values->data[0] = r = rVecHi.data[i];
1908 values->data[1] = s = phiVecHi.data[i] - sSub;
1909 values->data[2] = p = prVecHi.data[i];
1910 values->data[3] = q = pPhiVecHi.data[i];
1911
1912 v = cbrt( omega );
1913
1914 xlalStatus = XLALGetFactorizedWaveform( &hLM, values, v, modeL, modeM, &eobParams );
1915
1916 ampNQC->data[i] = cabs( hLM );
1917 sig1Hi->data[i] = (REAL4) ampl0 * creal(hLM);
1918 sig2Hi->data[i] = (REAL4) ampl0 * cimag(hLM);
1919 phseHi->data[i] = carg( hLM ) + phaseCounter * LAL_TWOPI;
1920 if ( i && phseHi->data[i] > phseHi->data[i-1] )
1921 {
1922 phaseCounter--;
1923 phseHi->data[i] -= LAL_TWOPI;
1924 }
1925 q1->data[i] = p*p / (r*r*omega*omega);
1926 q2->data[i] = q1->data[i] / r;
1927 q3->data[i] = q2->data[i] / sqrt(r);
1928 p1->data[i] = p / ( r*omega );
1929 p2->data[i] = p1->data[i] * p*p;
1930
1931 if ( omega <= omegaOld && !peakIdx )
1932 {
1933 peakIdx = i-1;
1934 }
1935 omegaOld = omega;
1936 }
1937 finalIdx = retLen - 1;
1938
1939 /* Stuff to find the actual peak time */
1940 gsl_spline *spline = NULL;
1941 gsl_interp_accel *acc = NULL;
1942 REAL8 omegaDeriv1;
1943 REAL8 time1, time2;
1944 REAL8 timePeak, omegaDerivMid;
1945
1946 spline = gsl_spline_alloc( gsl_interp_cspline, retLen );
1947 acc = gsl_interp_accel_alloc();
1948
1949 time1 = dynamicsHi->data[peakIdx];
1950
1951 gsl_spline_init( spline, dynamicsHi->data, omegaHi->data, retLen );
1952 omegaDeriv1 = gsl_spline_eval_deriv( spline, time1, acc );
1953 if ( omegaDeriv1 > 0. )
1954 {
1955 time2 = dynamicsHi->data[peakIdx+1];
1956 }
1957 else
1958 {
1959 time2 = time1;
1960 time1 = dynamicsHi->data[peakIdx-1];
1961 peakIdx--;
1962 omegaDeriv1 = gsl_spline_eval_deriv( spline, time1, acc );
1963 }
1964
1965 do
1966 {
1967 timePeak = ( time1 + time2 ) / 2.;
1968 omegaDerivMid = gsl_spline_eval_deriv( spline, timePeak, acc );
1969
1970 if ( omegaDerivMid * omegaDeriv1 < 0.0 )
1971 {
1972 time2 = timePeak;
1973 }
1974 else
1975 {
1976 omegaDeriv1 = omegaDerivMid;
1977 time1 = timePeak;
1978 }
1979 }
1980 while ( time2 - time1 > 1.0e-5 );
1981
1982 gsl_spline_free( spline );
1983 gsl_interp_accel_free( acc );
1984
1985 XLALPrintInfo( "Estimation of the peak is now at time %e\n", timePeak );
1986
1987 /* Calculate the NQC correction */
1988 XLALCalculateNQCCoefficients( ampNQC, phseHi, q1,q2,q3,p1,p2, modeL, modeM, timePeak, dt/m, eta, &nqcCoeffs );
1989
1990 /* We can now calculate the waveform */
1991 i = 0;
1992
1993 /* Find the point where we reach the low frequency cutoff */
1994 REAL8 lfCut = f * LAL_PI*m;
1995
1996 while ( i < hiSRndx )
1997 {
1998 omega = XLALCalculateOmega( eta, rVec.data[i], prVec.data[i], pPhiVec.data[i], &aCoeffs );
1999 if ( omega > lfCut || fabs( omega - lfCut ) < 1.0e-5 )
2000 {
2001 break;
2002 }
2003 i++;
2004 }
2005
2006 if ( i == hiSRndx )
2007 {
2008 XLALPrintError( "We don't seem to have crossed the low frequency cut-off\n" );
2010 }
2011
2012 startIdx = i;
2013
2014 /* Set the coalescence time */
2015 t = m * (dynamics->data[hiSRndx] + dynamicsHi->data[peakIdx] - dynamics->data[startIdx]);
2016
2017 /* Now create the (low-sampled) part of the waveform */
2018 while ( i < hiSRndx )
2019 {
2020 omega = XLALCalculateOmega( eta, rVec.data[i], prVec.data[i], pPhiVec.data[i], &aCoeffs );
2021 /* For now we re-populate values - there may be a better way to do this */
2022 values->data[0] = r = rVec.data[i];
2023 values->data[1] = s = phiVec.data[i] - sSub;
2024 values->data[2] = p = prVec.data[i];
2025 values->data[3] = q = pPhiVec.data[i];
2026
2027 v = cbrt( omega );
2028
2029 xlalStatus = XLALGetFactorizedWaveform( &hLM, values, v, modeL, modeM, &eobParams );
2030
2031 xlalStatus = XLALEOBNonQCCorrection( &hNQC, values, omega, &nqcCoeffs );
2032 hLM = hNQC * hLM;
2033
2034 sig1->data[count] = (REAL4) ampl0 * creal(hLM);
2035 sig2->data[count] = (REAL4) ampl0 * cimag(hLM);
2036
2037 count++;
2038 i++;
2039 }
2040
2041 /* Now apply the NQC correction to the high sample part */
2042 for ( i = 0; i <= finalIdx; i++ )
2043 {
2044 omega = XLALCalculateOmega( eta, rVecHi.data[i], prVecHi.data[i], pPhiVecHi.data[i], &aCoeffs );
2045
2046 /* For now we re-populate values - there may be a better way to do this */
2047 values->data[0] = r = rVecHi.data[i];
2048 values->data[1] = s = phiVecHi.data[i] - sSub;
2049 values->data[2] = p = prVecHi.data[i];
2050 values->data[3] = q = pPhiVecHi.data[i];
2051
2052 xlalStatus = XLALEOBNonQCCorrection( &hNQC, values, omega, &nqcCoeffs );
2053
2054 hLM = crect( sig1Hi->data[i], sig2Hi->data[i] );
2055
2056 hLM = hNQC * hLM;
2057 sig1Hi->data[i] = (REAL4) creal(hLM);
2058 sig2Hi->data[i] = (REAL4) cimag(hLM);
2059 }
2060
2061
2062 /*----------------------------------------------------------------------*/
2063 /* Record the final cutoff frequency of BD Waveforms for record keeping */
2064 /* ---------------------------------------------------------------------*/
2065 params->vFinal = v;
2066 if (signalvec1 && !signalvec2) params->tC = t;
2067
2068 /* For now we just set fFinal to Nyquist */
2069 /* This is a hack to get the filtering code to work properly */
2070 params->fFinal = params->tSampling/2.;
2071
2072 /*--------------------------------------------------------------
2073 * Attach the ringdown waveform to the end of inspiral
2074 -------------------------------------------------------------*/
2075 REAL8 tmpSamplingRate = params->tSampling;
2076 params->tSampling *= resampFac;
2077
2078 rdMatchPoint = XLALCreateREAL8Vector( 3 );
2079
2080 /* Check the first matching point is sensible */
2081 if ( ceil( tStepBack * params->tSampling / 2.0 ) > peakIdx )
2082 {
2083 XLALPrintError( "Invalid index for first ringdown matching point.\n" );
2085 }
2086
2087 REAL8 combSize = GetRingdownAttachCombSize( modeL, modeM );
2088 REAL8 nrPeakDeltaT = XLALGetNRPeakDeltaT( modeL, modeM, eta );
2089
2090 if ( combSize > timePeak )
2091 {
2092 XLALPrintWarning( "Comb size not as big as it should be\n" );
2093 }
2094 rdMatchPoint->data[0] = combSize < timePeak + nrPeakDeltaT ? timePeak + nrPeakDeltaT - combSize : 0;
2095 rdMatchPoint->data[1] = timePeak + nrPeakDeltaT;
2096 rdMatchPoint->data[2] = dynamicsHi->data[finalIdx];
2097
2098 xlalStatus = XLALInspiralHybridAttachRingdownWave(sig1Hi, sig2Hi,
2099 modeL, modeM, &tVecHi, rdMatchPoint, params);
2100 if (xlalStatus != XLAL_SUCCESS )
2101 {
2102 XLALDestroyREAL4Vector( sig1 );
2103 XLALDestroyREAL4Vector( sig2 );
2104 XLALDestroyREAL4Vector( freq );
2106 }
2107 XLALDestroyREAL8Vector( rdMatchPoint );
2108 params->tSampling = tmpSamplingRate;
2109
2110 for(j=0; j<sig1Hi->length; j+=resampFac)
2111 {
2112 sig1->data[count] = sig1Hi->data[j];
2113 sig2->data[count] = sig2Hi->data[j];
2114 freq->data[count] = freqHi->data[j];
2115 if (sig1->data[count] == 0)
2116 {
2117 break;
2118 }
2119 count++;
2120 }
2121 *countback = count;
2122
2123 /*-------------------------------------------------------------------
2124 * Compute the spherical harmonics required for constructing (h+,hx).
2125 * We are going to choose coa_phase to be zero. This perhaps should be
2126 * made compatible with the wave CoherentGW handles the phase at
2127 * coalecence. I have no idea how I (i.e., Sathya) might be able to
2128 * do this for EOBNR as there is no such thing as "phase at merger".
2129 -------------------------------------------------------------------*/
2130 inclination = (REAL4)params->inclination;
2131 coa_phase = 0.;
2132 /* -----------------------------------------------------------------
2133 * Attaching the (2,2) Spherical Harmonic
2134 * need some error checking
2135 *----------------------------------------*/
2136 xlalStatus = XLALSphHarm( &MultSphHarmP, modeL, modeM, inclination, coa_phase );
2137 if (xlalStatus != XLAL_SUCCESS )
2138 {
2139 XLALDestroyREAL4Vector( sig1 );
2140 XLALDestroyREAL4Vector( sig2 );
2141 XLALDestroyREAL4Vector( freq );
2143 }
2144
2145 modeM = -modeM;
2146 xlalStatus = XLALSphHarm( &MultSphHarmM, modeL, modeM, inclination, coa_phase );
2147 if (xlalStatus != XLAL_SUCCESS )
2148 {
2149 XLALDestroyREAL4Vector( sig1 );
2150 XLALDestroyREAL4Vector( sig2 );
2151 XLALDestroyREAL4Vector( freq );
2153 }
2154
2155 if ( modeL % 2 ) /* odd modeL gives a minus sign to negative m modes */
2156 {
2157 MultSphHarmM = - MultSphHarmM;
2158 }
2159 y_1 = creal(MultSphHarmP) + creal(MultSphHarmM);
2160 y_2 = cimag(MultSphHarmM) - cimag(MultSphHarmP);
2161 z_1 = - cimag(MultSphHarmM) - cimag(MultSphHarmP);
2162 z_2 = creal(MultSphHarmM) - creal(MultSphHarmP);
2163
2164 /* Next, compute h+ and hx from hLM, hLM*, YLM, YL-M */
2165 for ( i = 0; i < sig1->length; i++)
2166 {
2167 freq->data[i] /= unitHz;
2168 x1 = sig1->data[i];
2169 x2 = sig2->data[i];
2170 sig1->data[i] = (x1 * y_1) + (x2 * y_2);
2171 sig2->data[i] = (x1 * z_1) + (x2 * z_2);
2172 }
2173
2174 /*------------------------------------------------------
2175 * If required by the user copy other data sets to the
2176 * relevant arrays
2177 ------------------------------------------------------*/
2178 if (h)
2179 {
2180 for(i = 0; i < length; i++)
2181 {
2182 j = 2*i;
2183 k = j+1;
2184 h->data[j] += sig1->data[i];
2185 h->data[k] += sig2->data[i];
2186 }
2187 }
2188 /*
2189 if (signalvec1) memcpy(signalvec1->data , sig1->data, length * (sizeof(REAL4)));
2190 if (signalvec2) memcpy(signalvec2->data , sig2->data, length * (sizeof(REAL4)));
2191 */
2192 if (signalvec1)
2193 {
2194 for ( i = 0; i < length; i++ )
2195 {
2196 signalvec1->data[i] += sig1->data[i];
2197 }
2198 }
2199 if (signalvec2)
2200 {
2201 for ( i = 0; i < length; i++ )
2202 {
2203 signalvec2->data[i] += sig2->data[i];
2204 }
2205 }
2206 } /* End loop over modes */
2207
2208 /* Clean up */
2209 XLALDestroyREAL8Vector( values );
2210 XLALDestroyREAL8Vector( dvalues );
2211 XLALDestroyREAL8Array( dynamics );
2212 XLALDestroyREAL8Array( dynamicsHi );
2213 XLALDestroyREAL4Vector ( sig1 );
2214 XLALDestroyREAL4Vector ( sig2 );
2215 XLALDestroyREAL4Vector ( freq );
2216 XLALDestroyREAL4Vector ( sig1Hi );
2217 XLALDestroyREAL4Vector ( sig2Hi );
2218 XLALDestroyREAL4Vector ( freqHi );
2219 XLALDestroyREAL8Vector ( phseHi );
2220 XLALDestroyREAL8Vector ( omegaHi );
2221 XLALDestroyREAL8Vector( ampNQC );
2227
2228 return XLAL_SUCCESS;
2229}
int XLALCalculateNQCCoefficients(REAL8Vector *restrict amplitude, REAL8Vector *restrict phase, REAL8Vector *restrict q1, REAL8Vector *restrict q2, REAL8Vector *restrict q3, REAL8Vector *restrict p1, REAL8Vector *restrict p2, INT4 l, INT4 m, REAL8 timePeak, REAL8 deltaT, REAL8 eta, EOBNonQCCoeffs *restrict coeffs)
int XLALEOBNonQCCorrection(COMPLEX16 *restrict nqc, REAL8Vector *restrict values, const REAL8 omega, EOBNonQCCoeffs *restrict coeffs)
static REAL8 XLALrOfOmegaP4PN(REAL8 r, void *params)
int XLALEOBPPWaveformForInjection(CoherentGW *waveform, InspiralTemplate *params, PPNParamStruc *ppnParams)
static REAL8 XLALprInitP4PN(REAL8 p, void *params)
static REAL8 XLALCalculateEOBdAdr(const REAL8 r, EOBACoefficients *restrict coeffs)
static int LALHCapDerivativesP4PN(double t, const double values[], double dvalues[], void *funcParams)
static int XLALFirstStoppingCondition(double t, const double values[], double dvalues[], void *funcParams)
static REAL8 omegaofrP4PN(const REAL8 r, const REAL8 eta, void *params)
INT4 XLALGetFactorizedWaveform(COMPLEX16 *restrict hlm, REAL8Vector *restrict values, const REAL8 v, const INT4 l, const INT4 m, EOBParams *restrict params)
static REAL8 XLALEffectiveHamiltonian(const REAL8 eta, const REAL8 r, const REAL8 pr, const REAL8 pp, EOBACoefficients *aCoeffs)
Function to calculate the EOB effective Hamiltonian for the given values of the dynamical variables.
static const int EOBNRV2_NUM_MODES_MAX
static REAL8 XLALCalculateA6(REAL8 eta)
int XLALEOBPPWaveformTemplates(REAL4Vector *signalvec1, REAL4Vector *signalvec2, InspiralTemplate *params)
static REAL8 XLALvrP4PN(const REAL8 r, const REAL8 omega, pr3In *params)
static int XLALCalculateEOBACoefficients(EOBACoefficients *const coeffs, const REAL8 eta)
Function to pre-compute the coefficients in the EOB A potential function.
static REAL8 GetRingdownAttachCombSize(INT4 l, INT4 m)
static REAL8 XLALCalculateA5(REAL8 eta)
static REAL8 XLALpphiInitP4PN(const REAL8 r, EOBACoefficients *restrict coeffs)
static int XLALHighSRStoppingCondition(double t, const double values[], double dvalues[], void *funcParams)
static int XLALEOBPPWaveformEngine(REAL4Vector *signalvec1, REAL4Vector *signalvec2, REAL4Vector *h, const REAL8 *phiC, UINT4 *countback, InspiralTemplate *params, InspiralInit *paramsInit)
static REAL8 XLALCalculateOmega(REAL8 eta, REAL8 r, REAL8 pr, REAL8 pPhi, EOBACoefficients *aCoeffs)
int XLALEOBPPWaveform(REAL4Vector *signalvec, InspiralTemplate *params)
static REAL8 XLALCalculateEOBD(REAL8 r, REAL8 eta)
static REAL8 nonKeplerianCoefficient(REAL8Vector *restrict values, const REAL8 eta, EOBACoefficients *coeffs)
static REAL8 XLALCalculateEOBA(const REAL8 r, EOBACoefficients *restrict coeffs)
#define ninty4by3etc
INT4 XLALGenerateQNMFreqV2(COMPLEX8Vector *modefreqs, InspiralTemplate *params, UINT4 l, UINT4 m, UINT4 nmodes)
As with the above function, this generates the quasinormal mode frequencies for a black hole ringdown...
int XLALInspiralSetup(expnCoeffs *ak, InspiralTemplate *params)
int XLALInspiralInit(InspiralTemplate *params, InspiralInit *paramsInit)
int XLALInspiralChooseModel(expnFunc *func, expnCoeffs *ak, InspiralTemplate *params)
INT4 XLALInspiralHybridAttachRingdownWave(REAL4Vector *signalvec1, REAL4Vector *signalvec2, INT4 l, INT4 m, REAL8Vector *timeVec, REAL8Vector *matchrange, InspiralTemplate *params)
#define LALMalloc(n)
#define LALFree(p)
#define nModes
const UINT4 lmModes[NMODES][2]
REAL8 Hreal
#define XLAL_CALLGSL(statement)
int s
int l
double i
const double pp
const double pp2
const double pr
const double u
const double a4
const double u3
const double r2
const double u2
void XLALDestroyREAL8Array(REAL8Array *)
REAL4VectorSequence * XLALCreateREAL4VectorSequence(UINT4 length, UINT4 veclen)
REAL8 XLALDBisectionFindRoot(REAL8(*y)(REAL8, void *), REAL8 xmin, REAL8 xmax, REAL8 xacc, void *params)
#define GENERATEPPNINSPIRALH_EFSTOP
Reached requested termination frequency.
int XLALAdaptiveRungeKutta4(LALAdaptiveRungeKuttaIntegrator *integrator, void *params, REAL8 *yinit, REAL8 tinit, REAL8 tend, REAL8 deltat, REAL8Array **yout)
void XLALAdaptiveRungeKuttaFree(LALAdaptiveRungeKuttaIntegrator *integrator)
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_E
#define LAL_PI
#define LAL_TWOPI
#define LAL_MTSUN_SI
#define LAL_GAMMA
#define LAL_MRSUN_SI
#define crect(re, im)
#define cpolar(r, th)
double complex COMPLEX16
double REAL8
uint32_t UINT4
int32_t INT4
float REAL4
LALNameLength
int XLALModifyFacWaveformCoefficients(FacWaveformCoeffs *const coeffs, const REAL8 eta)
REAL8 XLALGetNRPeakDeltaT(INT4 l, INT4 m, REAL8 eta)
More recent versions of the EOB model, such as EOBNR_v2, utilise a non-quasicircular correction to br...
int XLALCalculateNewtonianMultipole(COMPLEX16 *multipole, REAL8 x, REAL8 r, REAL8 phi, UINT4 l, INT4 m, EOBParams *params)
int XLALGetCalibratedNQCCoeffs(EOBNonQCCoeffs *coeffs, INT4 l, INT4 m, REAL8 eta)
For the 2,2 mode, there are fits available for the NQC coefficients.
int XLALCalcFacWaveformCoefficients(FacWaveformCoeffs *const coeffs, const REAL8 eta)
The functions contained within this file pre-compute the various coefficients which are required for ...
REAL8 XLALInspiralFactorizedFlux(REAL8Vector *values, const REAL8 omega, EOBParams *ak, const INT4 lMax)
Function to compute the factorized flux as uses in the new EOBNR_PP model. Flux function given by Phy...
int XLALComputeNewtonMultipolePrefixes(NewtonMultipolePrefixes *prefix, const REAL8 m1, const REAL8 m2)
LALPNOrder
EOBNRv2HM
EOBNRv2
LAL_PNORDER_PSEUDO_FOUR
static const INT4 r
static const INT4 m
static const INT4 q
INT4 XLALSphHarm(COMPLEX16 *out, UINT4 L, INT4 M, REAL4 theta, REAL4 phi)
const LALUnit lalStrainUnit
REAL4Vector * XLALCreateREAL4Vector(UINT4 length)
void XLALDestroyREAL4Vector(REAL4Vector *vector)
COMPLEX8Vector * XLALCreateCOMPLEX8Vector(UINT4 length)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
void XLALDestroyCOMPLEX8Vector(COMPLEX8Vector *vector)
#define XLAL_ERROR_REAL8(...)
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_ERROR(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
int int XLALPrintWarning(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_PRINT_DEPRECATION_WARNING(replacement)
#define XLAL_IS_REAL8_FAIL_NAN(val)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_EINVAL
XLAL_EFAILED
XLAL_FAILURE
p
COMPLEX8 * data
REAL4TimeSeries * shift
SkyPosition position
REAL4TimeVectorSeries * a
REAL8TimeSeries * phi
REAL4TimeVectorSeries * h
REAL4TimeSeries * f
EOBNonQCCoeffs * nqcCoeffs
FacWaveformCoeffs * hCoeffs
NewtonMultipolePrefixes * prefixes
EOBACoefficients * aCoeffs
Structure used as an input to compute the derivatives needed in solving the phasing formula when the ...
Definition: LALInspiral.h:607
EnergyFunction * dEnergy
Definition: LALInspiral.h:609
FluxFunction * flux
Definition: LALInspiral.h:610
EOBNonQCCoeffs * nqcCoeffs
Definition: LALInspiral.h:612
expnCoeffs * coeffs
Definition: LALInspiral.h:611
expnFunc func
Definition: LALInspiral.h:680
expnCoeffs ak
Definition: LALInspiral.h:679
The inspiral waveform parameter structure containing information about the waveform to be generated.
Definition: LALInspiral.h:205
int(* stop)(double t, const double y[], double dydt[], void *params)
This structure stores the parameters for constructing a restricted post-Newtonian waveform.
const CHAR * termDescription
The termination code description (above)
INT4 termCode
The termination condition (above) that stopped computation of the waveform.
REAL4 phi
The phase at coalescence (or arbitrary reference phase for a post -Newtonian approximation),...
REAL4 psi
polarization angle (radians)
REAL4 fStart
The actual starting frequency of the waveform, in Hz (normally close but not identical to fStartIn)
SkyPosition position
location of source on sky
UINT4 length
The length of the generated waveform.
REAL4 fStop
The frequency at the termination of the waveform, in Hz.
REAL8 tc
The time from the start of the waveform to coalescence (in the point-mass approximation),...
REAL4 fStartIn
The requested starting frequency of the waveform, in Hz.
CHAR name[LALNameLength]
REAL4VectorSequence * data
REAL4 * data
REAL8 * data
REAL8 * data
This structure contains various post-Newtonian and P-approximant expansion coefficients; the meanings...
Definition: LALInspiral.h:399
REAL8 totalmass
Definition: LALInspiral.h:474
Structure to hold the pointers to the generic functions defined above.
Definition: LALInspiral.h:546
EnergyFunction * dEnergy
Definition: LALInspiral.h:547
FluxFunction * flux
Definition: LALInspiral.h:548
double inclination
double distance
REAL8 vr
EOBACoefficients * aCoeffs
REAL8 eta
REAL8 omega