forked from Shallyn/pyWaveformGenerator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpBHRingdown.c
4233 lines (4061 loc) · 284 KB
/
pBHRingdown.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* Writer: Xiaolin.liu
*
* This module contains basic functions for calculation.
* Functions list:
* Kernel:
* 20xx.xx.xx, LOC
**/
#include "pBHRingdown.h"
#include "myLog.h"
#include <gsl/gsl_vector.h>
#include <gsl/gsl_multiroots.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_interp.h>
#include <gsl/gsl_spline.h>
#define EOB_RD_EFOLDS 20.0
/* Search for index at which the maximum of the amplitude occurs */
static INT XLALSimFindIndexMaxAmpli( UINT * indAmax, REAL8Vector * timeVec, REAL8Vector * ampWave, REAL8 * valAmax, REAL8 tofAmax )
{
if ( indAmax == NULL || timeVec == NULL || ampWave == NULL || valAmax == NULL )
{
return CEV_FAILURE;
}
INT debugSB = 0;
*indAmax = 0;
INT found = 0;
UINT i;
for ( i = 0; i < timeVec->length - 1; i++)
{
if (timeVec->data[i] == tofAmax)
{
found = 1;
*indAmax = i;
*valAmax = ampWave->data[i];
}
}
if (found == 0)
{
return CEV_FAILURE;
}
else {
// if (debugSB) {
// printf(" found maximum times: %f, %f \n", timeVec->data[*indAmax], tofAmax );
// }
return CEV_SUCCESS;
}
}
REAL8 XLALSimRadiusKerrISCO ( REAL8 a )
{
REAL8 z1, z2;
if ( 1. - a * a < 0. || 1. + a < 0. || 1. - a < 0. )
{
PRINT_LOG_INFO(LOG_CRITICAL, "Arguments of pow and sqrt functions should be nonnegative!");
return REAL8_FAIL_NAN;
}
z1 = 1. + pow(1. - a * a, 1. / 3.) * (pow(1. + a, 1. / 3.) + pow(1. - a, 1. / 3.));
z2 = sqrt(3. * a * a + z1 * z1);
if ( (3. - z1) * (3. + z1 + 2. * z2) < 0. )
{
PRINT_LOG_INFO(LOG_CRITICAL, "Arguments of pow and sqrt functions should be nonnegative!");
return REAL8_FAIL_NAN;
}
return 3. + z2 - (a < 0. ? -1. : 1.) * sqrt((3. - z1) * (3. + z1 + 2. * z2));
}
REAL8 XLALSimEnergyKerrISCO ( REAL8 rISCO )
{
if ( 1. - 2. / (3. * rISCO) < 0. ) {
PRINT_LOG_INFO(LOG_CRITICAL, "Arguments of pow and sqrt functions should be nonnegative!");
return REAL8_FAIL_NAN;
}
return sqrt(1. - 2. / (3. * rISCO));
}
REAL8 XLALSimAngMomKerrISCO ( REAL8 rISCO )
{
if ( 3. * rISCO - 2. < 0. )
{
PRINT_LOG_INFO(LOG_CRITICAL, "Arguments of pow and sqrt functions should be nonnegative!");
return REAL8_FAIL_NAN;
}
return 2. / (3. * sqrt(3.)) * (1. + 2. * sqrt(3. * rISCO - 2.));
}
/**
* Computes the final mass and spin of the black hole resulting from merger.
* They are given by fittings of NR simulations results. Specifically,
* for EOBNR, Table I of Buonanno et al. PRD76, 104049;
* for EOBNRv2 and EOBNRv2HM, Eqs. 29a and 29b of Pan et al. PRD84, 124052;
* for SEOBNRv1, SEOBNRv2, Eq. 8 of Tichy and Marronetti PRD78, 081501 and
* Eqs. 1 and 3 of Barausse and Rezzolla ApJ704, L40. Complemented by https://dcc.ligo.org/T1400476.
* For SEOBNRv4P: i) the final mass comes from Eq(3) in https://dcc.ligo.org/T1400476, but
* we use q<=1; ii) the final spin comes from Eq(13-16) for Hofmann et al,
* https://iopscience.iop.org/article/10.3847/2041-8205/825/2/L19/meta [arxiv:1605.01938]
*/
INT XLALSimIMREOBFinalMassSpinPrec(
REAL8 *finalMass, /**<< OUTPUT, the final mass (scaled by original total mass) */
REAL8 *finalSpin, /**<< OUTPUT, the final spin (scaled by final mass) */
const REAL8 mass1, /**<< The mass of the 1st component of the system */
const REAL8 mass2, /**<< The mass of the 2nd component of the system */
const REAL8 spin1[3], /**<< The spin of the 1st object; only needed for spin waveforms */
const REAL8 spin2[3] /**<< The spin of the 2nd object; only needed for spin waveforms */
)
{
INT approximant = 4;
REAL8 LISCO,csi,aeff, a_tot_prec,fitpart,alpha,beta,gamma,epsilon_beta,epsilon_gamma;
REAL8 epsilon_alpha;
static const REAL8 root9ovr8minus1 = -0.057190958417936644;
static const REAL8 root12 = 3.4641016151377544;
/* Constants used for the spinning EOB model */
static const REAL8 p0 = 0.04826;
static const REAL8 p1 = 0.01559;
static const REAL8 p2 = 0.00485;
static const REAL8 t0 = -2.8904;
static const REAL8 t2 = -3.5171;
static const REAL8 t3 = 2.5763;
static const REAL8 s4 = -0.1229;
static const REAL8 s5 = 0.4537;
static const REAL8 s9 = 2.763032781169752;
static const REAL8 s8 = -2.6081232221537394;
static const REAL8 s7 = 1.2657111864932808;
static const REAL8 s6 = -0.7835007857591175;
static const REAL8 s5v2 = -0.3264724801557159;
static const REAL8 s4v2 = -0.27506210736300474;
static const REAL8 t0v2 = -2.649826989941522;
static const REAL8 t3v2 = 3.910637513328723;
// static const REAL8 t2v2 = 16.* (-0.17958273605461628 - 0.015625*t3v2);
static const REAL8 t2v2 = -3.850983155206041;
static const REAL8 k00 = -5.977230835551017; // Solving Eq.(11) of https://arxiv.org/pdf/1605.01938v2.pdf
static const REAL8 k01 = 3.39221;
static const REAL8 k02 = 4.48865;
static const REAL8 k03 = -5.77101;
static const REAL8 k04 = -13.0459;
static const REAL8 k10 = 35.1278;
static const REAL8 k11 = -72.9336;
static const REAL8 k12 = -86.0036;
static const REAL8 k13 = 93.7371;
static const REAL8 k14 = 200.975;
static const REAL8 k20 = - 146.822;
static const REAL8 k21 = 387.184;
static const REAL8 k22 = 447.009;
static const REAL8 k23 = -467.383;
static const REAL8 k24 = -884.339;
static const REAL8 k30 = 223.911;
static const REAL8 k31 = -648.502;
static const REAL8 k32 = -697.177;
static const REAL8 k33 = 753.738;
static const REAL8 k34 = 1166.89;
INT4 debugout=0;
REAL8 totalMass;
REAL8 eta, eta2, eta3;
REAL8 a1, a2, chiS, q;
REAL8 z1, z2, rISCO, eISCO, atl, tmpVar;
REAL8 cosa, cosb, cosg, a1a2norm, a1a2L, lnorm;
REAL8 q2,chi1, chi2, theta1, theta2, phi1, phi2, swapvar;
/* get a local copy of the intrinsic parameters */
totalMass = mass1 + mass2;
eta = mass1 * mass2 / (totalMass*totalMass);
eta2 = eta * eta;
eta3 = eta2 * eta;
//XLAL_PRINT_INFO("Approximant: %d\n",approximant);
#if 0
switch ( approximant )
{
case EOBNRv2:
case EOBNRv2HM:
eta3 = eta2 * eta;
/* Final mass and spin given by Eqs. 29a and 29b of Pan et al. PRD84, 124052 */
*finalMass = 1. + root9ovr8minus1 * eta - 0.4333 * eta2 - 0.4392 * eta3;
*finalSpin = root12 * eta - 3.871 * eta2 + 4.028 * eta3;
break;
case EOBNR:
/* Final mass and spin given by Table I of Buonanno et al. PRD76, 104049 */
*finalMass = 1 - 0.057191 * eta - 0.498 * eta2;
*finalSpin = 3.464102 * eta - 2.9 * eta2;
break;
case SEOBNRv2:
/* See page 3 of the dcc document T1400476-v3, quantities MFinal and aFinal, for expressions below. */
a1 = spin1[2];
a2 = spin2[2];
q = mass1 / mass2;
atl = ( a1 + a2 /q/q) / (1.+1./q)/(1.+ 1./q);
tmpVar = ( a1 + a2 /q/q) / (1.+1./q/q);
z1 = 1. + pow( 1.-atl*atl, 1./3.) * ( pow( 1.+atl, 1./3. ) + pow( 1.-atl, 1./3. ) );
z2 = sqrt( 3.*atl*atl + z1*z1 );
rISCO = 3. + z2 - ( atl<0. ? -1. : 1. ) * sqrt( (3.-z1) * (3.+z1+2.*z2) );
eISCO = sqrt( 1. - 2./(3.*rISCO) );
*finalMass = 1. - ( (1.-eISCO)*eta
+ 16.*eta*eta*( 0.00258 - 0.0773/(1./((1.+1/q/q)/(1.+1/q)/(1.+1/q))*atl-1.6939) - 0.25*(1.-eISCO)) );
*finalSpin = tmpVar + tmpVar*eta*( s9*eta*tmpVar*tmpVar + s8*eta*eta*tmpVar + s7*eta*tmpVar
+ s6*tmpVar*tmpVar + s4v2*tmpVar + s5v2*eta + t0v2)
+ eta*( 2.*sqrt(3.) + t2v2*eta + t3v2 *eta*eta );
break;
case SEOBNRv1:
/* Final mass/spin comes from Eq. 8 of Tichy and Marronetti PRD78, 081501
and from Eqs. 1 and 3 of Barausse and Rezzolla ApJ704, L40 */
a1 = spin1[2];
a2 = spin2[2];
chiS = 0.5 * ( a1 + a2 );
q = mass1 / mass2;
*finalMass = 1. - p0 + 2.*p1 * chiS + 4.*p2*chiS*chiS;
*finalMass = 1. + (0.9515 - 1.0)*4.*eta - 0.013*16.*eta2*(a1+a2);
tmpVar = ( a1 + a2 /q/q) / ( 1. + 1/q/q);
*finalSpin = tmpVar + tmpVar * eta * (s4 * tmpVar + s5 * eta + t0 ) + eta * (2. * sqrt(3.) + t2*eta + t3*eta*eta );
break;
case SEOBNRv3_opt:
case SEOBNRv3:
// Precessing spins (Barausse & Rezzolla 2009, Eqs (6-10))
chi1 = sqrt( spin1[0]*spin1[0] + spin1[1]*spin1[1] + spin1[2]*spin1[2] );
chi2 = sqrt( spin2[0]*spin2[0] + spin2[1]*spin2[1] + spin2[2]*spin2[2] );
if ( chi1 < 1.0e-15 )
{ theta1 = 0.; }
else
{ theta1 = acos( spin1[2] / chi1 ); }
if ( chi2 < 1.0e-15 )
{ theta2 = 0.; }
else
{ theta2 = acos( spin2[2] / chi2 ); }
phi1 = atan2( spin1[1], spin1[0] );
phi2 = atan2( spin2[1], spin2[0] );
if ( mass1 > mass2 )
{
q = mass2 / mass1;
}
else
{
q = mass1 / mass2;
swapvar = chi1; chi1 = chi2; chi2 = swapvar;
swapvar = theta1; theta1 = theta2; theta2 = swapvar;
swapvar = phi1; phi1 = phi2; phi2 = swapvar;
}
q2 = q * q;
/* Stas: this is v2 appraoch applied to s1.J s2.J az z-components of spin1/2*/
q = mass1 / mass2;
a1 = spin1[2];
a2 = spin2[2];
atl = ( a1 + a2 /q/q) / (1.+1./q)/(1.+ 1./q);
tmpVar = ( a1 + a2 /q/q) / (1.+1./q/q);
z1 = 1. + pow( 1.-atl*atl, 1./3.) * ( pow( 1.+atl, 1./3. ) + pow( 1.-atl, 1./3. ) );
z2 = sqrt( 3.*atl*atl + z1*z1 );
rISCO = 3. + z2 - ( atl<0. ? -1. : 1. ) * sqrt( (3.-z1) * (3.+z1+2.*z2) );
eISCO = sqrt( 1. - 2./(3.*rISCO) );
*finalMass = 1. - ( (1.-eISCO)*eta
+ 16.*eta*eta*( 0.00258 - 0.0773/(1./((1.+1/q/q)/(1.+1/q)/(1.+1/q))*atl-1.6939) - 0.25*(1.-eISCO)) );
*finalSpin = tmpVar + tmpVar*eta*( s9*eta*tmpVar*tmpVar + s8*eta*eta*tmpVar + s7*eta*tmpVar
+ s6*tmpVar*tmpVar + s4v2*tmpVar + s5v2*eta + t0v2)
+ eta*( 2.*sqrt(3.) + t2v2*eta + t3v2 *eta*eta );
break;
case SEOBNRv4P:
case SEOBNRv4PHM:
#endif
/* Depending on which mass is larger, compute q. Note that below
we always use the convention that q=mass2/mass1<=1. Thus for
us, internally mass1 is always the primary. */
q = mass2 / mass1;
a1 = spin1[2];
a2 = spin2[2];
if (mass1 < mass2)
{
q = mass1 / mass2;
// We need to flip the spins as well, because spin1 should be primary,
// and spin2 should be secondary.
swapvar = a2;
a2 = a1;
a1 = swapvar;
}
/* This comes from SEOBNRv4 in XLALSimIMREOBFinalMassSpin. Note that
we have swapped conventions for q! */
REAL8 OnePlusQ = 1. + q;
atl = (a1 + a2 * q * q) / (OnePlusQ * OnePlusQ);
rISCO = XLALSimRadiusKerrISCO(atl);
eISCO = XLALSimEnergyKerrISCO(rISCO);
/* See page 3 of the dcc document T1400476-v3, quantity MFinal, for expression below.
Note that in this reference it was assumed that q>=1*/
*finalMass = 1. - ((1. - eISCO) * eta + 16. * eta * eta * (0.00258 - 0.0773 / (1. / ((1. + q * q) / (OnePlusQ * OnePlusQ)) * atl - 1.6939) - 0.25 * (1. - eISCO)));
// Final spin fit for precessing spins (Hofmann et al, 2015)
chi1 = sqrt(spin1[0] * spin1[0] + spin1[1] * spin1[1] + spin1[2] * spin1[2]);
chi2 = sqrt(spin2[0] * spin2[0] + spin2[1] * spin2[1] + spin2[2] * spin2[2]);
alpha = 0.0; // Angle between the 2 spins
beta = 0.0; // The angle between spin1 and Newtonian orbital angular momentum
gamma = 0.0; // The angle between spin2 and Newtonian orbital angular momentum
if (chi1 > 1e-6)
{
beta = acos(spin1[2] / chi1);
}
if (chi2 > 1e-6)
{
gamma = acos(spin2[2] / chi2);
}
// Dot product between the 2 spins
REAL8 tmp = spin1[0] * spin2[0] + spin1[1] * spin2[1] + spin1[2] * spin2[2];
// alpha only makes sense if both spins are non-zero
if (chi1 > 1e-4 && chi2 > 1e-4)
{
tmp /= chi1;
tmp /= chi2;
if (tmp > 1. && tmp <= 1. + 1e-4)
tmp = 1.;
if (tmp < -1. && tmp >= -1. - 1e-4)
tmp = -1.;
alpha = acos(tmp);
}
// See below Eq(18) in Hofmann et al 2015.
epsilon_beta = 0.024;
epsilon_gamma = 0.024;
// Eq(18) in Hofmann et al, 2015.
beta = beta + epsilon_beta * sin(beta);
gamma = gamma + epsilon_gamma * sin(gamma);
// If mass2 > mass1 we need to swap things.
// Since alpha is the angle between the spins it is not affected.
if (mass2 > mass1)
{
swapvar = gamma;
gamma = beta;
beta = swapvar;
swapvar = chi2;
chi2 = chi1;
chi1 = swapvar;
}
/* Final spin expressions from Hofmann et al, 2015. */
// See Table I for the n_M=3, n_J=4 fit and expression for aeff below.
csi = 0.474046; //This is $\xi$ in the paper.
// Eq(14) in Hofmann et al.
a_tot_prec = (chi1 * cos(beta) + chi2 * cos(gamma) * q * q) / ((1.0 + q) * (1.0 + q));
// Eq(15) in Hofmann et al.
aeff = a_tot_prec + csi * eta * (chi1 * cos(beta) + chi2 * cos(gamma));
// These are standard Kerr expressions for quantities at ISCO. See e.g
// Bardeen et al. 1972, ApJ 178 347, Hofmann et al 2015, Eqs(2-6)
rISCO = XLALSimRadiusKerrISCO(aeff);
eISCO = XLALSimEnergyKerrISCO(rISCO);
LISCO = XLALSimAngMomKerrISCO(rISCO);
/* The k00, k01, ... coefficients are defined in LALSimBlackHoleRingdown.h */
REAL8 eta4 = eta * eta3;
if (fabs(aeff) > 0.)
{
REAL8 aeff2 = aeff * aeff;
REAL8 aeff3 = aeff * aeff2;
REAL8 aeff4 = aeff * aeff3;
fitpart = k00 * eta + k01 * aeff * eta + k02 * aeff2 * eta + k03 * aeff3 * eta + k04 * aeff4 * eta +
k10 * eta2 + k11 * aeff * eta2 + k12 * aeff2 * eta2 + k13 * aeff3 * eta2 + k14 * aeff4 * eta2 +
k20 * eta3 + k21 * aeff * eta3 + k22 * aeff2 * eta3 + k23 * aeff3 * eta3 + k24 * aeff4 * eta3 +
k30 * eta4 + k31 * aeff * eta4 + k32 * aeff2 * eta4 + k33 * aeff3 * eta4 + k34 * aeff4 * eta4;
}
else
{
// If there is no effective spin, use a simpler expression.
fitpart = k00 * eta + k10 * eta2 + k20 * eta3 + k30 * eta4;
}
// Eq(13) in Hofmann et al.
REAL8 ell_norm = fabs(LISCO - 2 * a_tot_prec * (eISCO - 1.0) + fitpart);
// Next 2 equations are combined to get Eq(16) in Hofmann et al.
REAL8 prefactor = 1. / ((1 + q) * (1 + q));
REAL8 inside_sqrt = pow(chi1, 2) + pow(chi2, 2) * pow(q, 4) + 2 * chi1 * chi2 * pow(q, 2) * cos(alpha) +
2 * (chi1 * cos(beta) + chi2 * pow(q, 2) * cos(gamma)) * ell_norm * q + pow(ell_norm, 2) * pow(q, 2);
// Guard against NANs inside the fit
if (inside_sqrt < 0)
{
PRINT_LOG_INFO(LOG_WARNING, "in the final spin fit, argument of sqrt was negative. Truncating the spin to 0.");
inside_sqrt = 0.0;
}
*finalSpin = prefactor * sqrt(inside_sqrt);
// If somehow we have gone above the Kerr limit, don't.
if (*finalSpin > 1)
{
*finalSpin = 1 - 1e-6;
}
#if 0
break; // End of SEOBNRv4P
default:
XLALPrintError("XLAL Error %s - Unsupported approximant.\n", __func__);
XLAL_ERROR(XLAL_EINVAL);
}
#endif
//XLAL_PRINT_INFO( "Final mass = %e, Final spin = %e\n", *finalMass, *finalSpin );
return CEV_SUCCESS;
}
#define LMax 6
#define MMax 6
static REAL8 XLALCalculateRDAmplitudeCoefficient1( UINT modeL, UINT modeM, REAL8 eta, REAL8 chi){
REAL8 A1coeff00[LMax][MMax]={{0}};
REAL8 A1coeff01[LMax][MMax]={{0}};
REAL8 A1coeff02[LMax][MMax]={{0}};
REAL8 A1coeff10[LMax][MMax]={{0}};
REAL8 A1coeff11[LMax][MMax]={{0}};
REAL8 A1coeff20[LMax][MMax]={{0}};
REAL8 A1coeff21[LMax][MMax]={{0}};
REAL8 A1coeff31[LMax][MMax]={{0}};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Fit coefficients that enter amplitude of the RD signal for SEOBNRv4 and SEOBNRv4HM*/
/* Eq. (54) of https://dcc.ligo.org/T1600383 for SEOBNRv4 and 22 mode SEOBNRv4HM*/
/* Eqs. (C1, C3, C5, C7) of https://arxiv.org/pdf/1803.10701.pdf for SEOBNRv4HM*/
A1coeff00[2][2] = 0.0830664;
A1coeff01[2][2] = -0.0196758;
A1coeff02[2][2] = -0.0136459;
A1coeff10[2][2] = 0.0612892;
A1coeff11[2][2] = 0.00146142;
A1coeff20[2][2] = -0.0893454;
A1coeff00[2][1] = 0.07780330893915006;
A1coeff01[2][1] = -0.05070638166864379;
A1coeff10[2][1] = 0.24091006920322164;
A1coeff11[2][1] = 0.38582622780596576;
A1coeff20[2][1] = -0.7456327888190485;
A1coeff21[2][1] = -0.9695534075470388;
A1coeff00[3][3] = 0.07638733045623343;
A1coeff01[3][3] = -0.030993441267953236;
A1coeff10[3][3] = 0.2543447497371546;
A1coeff11[3][3] = 0.2516879591102584;
A1coeff20[3][3] = -1.0892686061231245;
A1coeff21[3][3] = -0.7980907313033606;
A1coeff00[4][4] = -0.06392710223439678;
A1coeff01[4][4] = -0.03646167590514318;
A1coeff10[4][4] = 0.345195277237925;
A1coeff11[4][4] = 1.2777441574118558;
A1coeff20[4][4] = -1.764352185878576;
A1coeff21[4][4] = -14.825262897834696;
A1coeff31[4][4] = 40.67135475479875;
A1coeff00[5][5] = -0.06704614393611373;
A1coeff01[5][5] = 0.021905949257025503;
A1coeff10[5][5] = -0.24754936787743445;
A1coeff11[5][5] = -0.0943771022698497;
A1coeff20[5][5] = 0.7588042862093705;
A1coeff21[5][5] = 0.4357768883690394;
return A1coeff00[modeL][modeM] + A1coeff01[modeL][modeM] * chi + A1coeff02[modeL][modeM] * chi * chi + A1coeff10[modeL][modeM] * eta +
A1coeff11[modeL][modeM] * eta * chi + A1coeff20[modeL][modeM] * eta * eta + A1coeff21[modeL][modeM]*eta*eta*chi + A1coeff31[modeL][modeM]*eta*eta*eta*chi;
}
static REAL8 XLALCalculateRDAmplitudeCoefficient2( UINT modeL, UINT modeM, REAL8 eta, REAL8 chi){
REAL8 A2coeff00[LMax][MMax]={{0}};
REAL8 A2coeff01[LMax][MMax]={{0}};
REAL8 A2coeff10[LMax][MMax]={{0}};
REAL8 A2coeff11[LMax][MMax]={{0}};
REAL8 A2coeff20[LMax][MMax]={{0}};
REAL8 A2coeff21[LMax][MMax]={{0}};
REAL8 A2coeff31[LMax][MMax]={{0}};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Fit coefficients that enter amplitude of the RD signal of SEOBNRv4 and SEOBNRv4HM*/
/* Eq. (55) of https://dcc.ligo.org/T1600383 for SEOBNRv4 and 22 mode SEOBNRv4HM*/
/* Eqs. (C1, C3, C5, C7) of https://arxiv.org/pdf/1803.10701.pdf for SEOBNRv4HM*/
A2coeff00[2][2] = -0.623953;
A2coeff01[2][2] = -0.371365;
A2coeff10[2][2] = 1.39777;
A2coeff11[2][2] = 2.40203;
A2coeff20[2][2] = -1.82173;
A2coeff21[2][2] = -5.25339;
A2coeff00[2][1] = -1.2451852641667298;
A2coeff01[2][1] = -1.195786238319961;
A2coeff10[2][1] = 6.134202504312409;
A2coeff11[2][1] = 15.66696619631313;
A2coeff20[2][1] = -14.67251127485556;
A2coeff21[2][1] = -44.41982201432511;
A2coeff00[3][3] = -0.8325292359346013;
A2coeff01[3][3] = -0.598880303198448;
A2coeff10[3][3] = 2.767989795032018;
A2coeff11[3][3] = 5.904371617277156;
A2coeff20[3][3] = -7.028151926115957;
A2coeff21[3][3] = -18.232606706124482;
A2coeff00[4][4] = 0.7813275473485185;
A2coeff01[4][4] = 0.8094706044462984;
A2coeff10[4][4] = -5.18689829943586;
A2coeff11[4][4] = -5.38343327318501;
A2coeff20[4][4] = 14.026415859369477;
A2coeff21[4][4] = 0.1051625997942299;
A2coeff31[4][4] = 46.978434956814006;
A2coeff00[5][5] = 1.6763424265367357;
A2coeff01[5][5] = 0.4925695499534606;
A2coeff10[5][5] = -5.604559311983177;
A2coeff11[5][5] = -6.209095657439377;
A2coeff20[5][5] = 16.751319143123386;
A2coeff21[5][5] = 16.778452555342554;
return A2coeff00[modeL][modeM] + A2coeff01[modeL][modeM] * chi + A2coeff10[modeL][modeM] * eta +
A2coeff11[modeL][modeM] * eta * chi + A2coeff20[modeL][modeM] * eta * eta + A2coeff21[modeL][modeM] * eta * eta * chi + A2coeff31[modeL][modeM]*eta*eta*eta*chi;
}
static REAL8 XLALCalculateRDPhaseCoefficient1( UINT modeL, UINT modeM, REAL8 eta, REAL8 chi){
REAL8 P1coeff00[LMax][MMax]={{0}};
REAL8 P1coeff01[LMax][MMax]={{0}};
REAL8 P1coeff02[LMax][MMax]={{0}};
REAL8 P1coeff10[LMax][MMax]={{0}};
REAL8 P1coeff11[LMax][MMax]={{0}};
REAL8 P1coeff20[LMax][MMax]={{0}};
REAL8 P1coeff21[LMax][MMax]={{0}};
REAL8 P1coeff31[LMax][MMax]={{0}};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Fit coefficients that enter the phase of the RD signal of SEOBNRv4 and SEOBNRv4HM*/
/* Eq. (62) of https://dcc.ligo.org/T1600383 for SEOBNRv4 and 22 mode SEOBNRv4HM*/
/* Eqs. (C9, C11, C13, C15) of https://arxiv.org/pdf/1803.10701.pdf for SEOBNRv4HM*/
P1coeff00[2][2] = 0.147584;
P1coeff01[2][2] = 0.00779176;
P1coeff02[2][2] = -0.0244358;
P1coeff10[2][2] = 0.263456;
P1coeff11[2][2] = -0.120853;
P1coeff20[2][2] = -0.808987;
P1coeff00[2][1] = 0.15601401627613815;
P1coeff01[2][1] = 0.10219957917717622;
P1coeff10[2][1] = 0.023346852452720928;
P1coeff11[2][1] = -0.9435308286367039;
P1coeff20[2][1] = 0.15326558178697175;
P1coeff21[2][1] = 1.7979082057513565;
P1coeff00[3][3] = 0.11085299117493969;
P1coeff01[3][3] = 0.018959099261813613;
P1coeff10[3][3] = 0.9999800463662053;
P1coeff11[3][3] = -0.729149797691242;
P1coeff20[3][3] = -3.3983315694441125;
P1coeff21[3][3] = 2.5192011762934037;
P1coeff00[4][4] = 0.11498976343440313;
P1coeff01[4][4] = 0.008389519706605305;
P1coeff10[4][4] = 1.6126522800609633;
P1coeff11[4][4] = -0.8069979888526699;
P1coeff20[4][4] = -6.255895564079467;
P1coeff21[4][4] = 7.595651881827078;
P1coeff31[4][4] = -19.32367406125053;
P1coeff00[5][5] = 0.16465380962882128;
P1coeff01[5][5] = -0.026574817803812007;
P1coeff10[5][5] = -0.19184523794508765;
P1coeff11[5][5] = -0.05519618962738479;
P1coeff20[5][5] = 0.33328424135336965;
P1coeff21[5][5] = 0.3194274548351241;
return P1coeff00[modeL][modeM] + P1coeff01[modeL][modeM] * chi + P1coeff02[modeL][modeM] * chi * chi + P1coeff10[modeL][modeM] * eta +
P1coeff11[modeL][modeM] * eta * chi + P1coeff20[modeL][modeM] * eta * eta + P1coeff21[modeL][modeM]*eta*eta*chi + P1coeff31[modeL][modeM]*eta*eta*eta*chi;
}
static REAL8 XLALCalculateRDPhaseCoefficient2( UINT modeL, UINT modeM, REAL8 eta, REAL8 chi){
REAL8 P2coeff00[LMax][MMax]={{0}};
REAL8 P2coeff01[LMax][MMax]={{0}};
REAL8 P2coeff02[LMax][MMax]={{0}};
REAL8 P2coeff12[LMax][MMax]={{0}};
REAL8 P2coeff10[LMax][MMax]={{0}};
REAL8 P2coeff11[LMax][MMax]={{0}};
REAL8 P2coeff20[LMax][MMax]={{0}};
REAL8 P2coeff21[LMax][MMax]={{0}};
REAL8 P2coeff31[LMax][MMax]={{0}};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Fit coefficients that enter the phase of the RD signal of SEOBNRv4 and SEOBNRv4HM*/
/* Eq. (63) of https://dcc.ligo.org/T1600383 for SEOBNRv4 and 22 mode SEOBNRv4HM*/
/* Eqs. (C10, C12, C14, C16) of https://arxiv.org/pdf/1803.10701.pdf for SEOBNRv4HM*/
P2coeff00[2][2] = 2.46654;
P2coeff01[2][2] = 3.13067;
P2coeff02[2][2] = 0.581626;
P2coeff10[2][2] = -6.99396;
P2coeff11[2][2] = -9.61861;
P2coeff20[2][2] = 17.5646;
P2coeff00[2][1] = 2.7886287922318105;
P2coeff01[2][1] = 4.29290053494256;
P2coeff10[2][1] = -0.8145406685320334;
P2coeff11[2][1] = -15.93796979597706;
P2coeff20[2][1] = 5.549338798935832;
P2coeff21[2][1] = 12.649775582333442;
P2coeff02[2][1] = 2.5582321247274726;
P2coeff12[2][1] = -10.232928498772893;
P2coeff00[3][3] = 2.7825237371542735;
P2coeff01[3][3] = 2.8796835808075003;
P2coeff10[3][3] = -7.844741660437831;
P2coeff11[3][3] = -34.7670039322078;
P2coeff20[3][3] = 27.181024362399302;
P2coeff21[3][3] = 127.13948436435182;
P2coeff00[4][4] = 3.111817347262856;
P2coeff01[4][4] = 5.399341180960216;
P2coeff10[4][4] = 15.885333959709488;
P2coeff11[4][4] = -87.92421137153823;
P2coeff20[4][4] = -79.64931908155609;
P2coeff21[4][4] = 657.7156442271963;
P2coeff31[4][4] = -1555.2968529739226;
P2coeff02[4][4] = 2.3832321567874686;
P2coeff12[4][4] = -9.532928476043567;
P2coeff00[5][5] = 11.102447263357977;
P2coeff01[5][5] = 6.015112119742853;
P2coeff10[5][5] = -58.605776859097084;
P2coeff11[5][5] = -81.68032025902797;
P2coeff20[5][5] = 176.60643662729498;
P2coeff21[5][5] = 266.47345742836745;
return P2coeff00[modeL][modeM] + P2coeff01[modeL][modeM] * chi + P2coeff02[modeL][modeM] * chi * chi + P2coeff12[modeL][modeM] * chi * chi * eta + P2coeff10[modeL][modeM] * eta +
P2coeff11[modeL][modeM] * eta * chi + P2coeff20[modeL][modeM] * eta * eta + P2coeff21[modeL][modeM]*eta*eta*chi + P2coeff31[modeL][modeM]*eta*eta*eta*chi;
}
INT XLALSimIMREOBAttachFitRingdown(
REAL8Vector * signal1, /**<< OUTPUT, Real of inspiral waveform to which we attach ringdown */
REAL8Vector * signal2, /**<< OUTPUT, Imag of inspiral waveform to which we attach ringdown */
const INT l, /**<< Current mode l */
const INT m, /**<< Current mode m */
const REAL8 dt, /**<< Sample time step (in seconds) */
const REAL8 mass1, /**<< First component mass (in Solar masses) */
const REAL8 mass2, /**<< Second component mass (in Solar masses) */
const REAL8 spin1x, /**<<The spin of the first object; */
const REAL8 spin1y, /**<<The spin of the first object; */
const REAL8 spin1z, /**<<The spin of the first object; */
const REAL8 spin2x, /**<<The spin of the second object; */
const REAL8 spin2y, /**<<The spin of the second object; */
const REAL8 spin2z, /**<<The spin of the second object; */
const REAL8 finalM, /**<<The spin of the final BH; */
const REAL8 finalS, /**<< The magnitude of the final spin */
REAL8Vector * timeVec, /**<< Vector containing the time values */
REAL8Vector * matchrange,
/**<< Time values chosen as points for performing comb matching */
UINT * indAmpMax /**<<This is used only for SEOBNRv4HM, it is needed to remember the attaching point of the 22 mode */
)
{
if ( mass1 <= 0. || mass2 <= 0.
|| fabs(spin1x) > 1. || fabs(spin1y) > 1. || fabs(spin1z) > 1.
|| fabs(spin2x) > 1. || fabs(spin2y) > 1. || fabs(spin2z) > 1.
|| spin1x*spin1x + spin1y*spin1y + spin1z*spin1z > 1.
|| spin2x*spin2x + spin2y*spin2y + spin2z*spin2z > 1.
)
{
PRINT_LOG_INFO(LOG_CRITICAL, "Input parameters are illegal.");
PRINT_LOG_INFO(LOG_DEBUG, "Input params: spin1x = %g, spin1y = %g, spin1z = %g, s1 = %g", spin1x, spin1y, spin1z, spin1x*spin1x + spin1y*spin1y + spin1z*spin1z);
PRINT_LOG_INFO(LOG_DEBUG, "Input params: spin2x = %g, spin2y = %g, spin2z = %g, s2 = %g", spin2x, spin2y, spin2z, spin2x*spin2x + spin2y*spin2y + spin2z*spin2z);
PRINT_LOG_INFO(LOG_DEBUG, "Input params: mass1 = %g, mass2 = %g", mass1, mass2);
return CEV_FAILURE;
}
INT debugSB = 0, failed = 0;
UINT i;
INT4 phasecount;
REAL8Vector *ampWave = NULL;
REAL8Vector *phWave = NULL;
REAL8Vector *rdtime = NULL;
REAL8Vector *ampRD = NULL;
REAL8Vector *phRD = NULL;
COMPLEX16Vector *modefreqs = NULL;
COMPLEX16Vector *modefreqs22 = NULL; //RC: we use this variable to compute the damping time of the 22 mode which will be used to set the lenght of the ringdown for all the modes
ampWave = CreateREAL8Vector(signal1->length);
phWave = CreateREAL8Vector(signal1->length);
REAL8 mtot = mass1 + mass2;
REAL8 eta = mass1 * mass2 / (mtot * mtot);
/* Here I assume that the spins were properly projected (is precessing) and only spin1z, spin2z
* are relevant, if not we need to add extra function to define what we call chi1, chi2 */
REAL8 chi1 = spin1z;
REAL8 chi2 = spin2z;
//REAL8 spin1[3] = { spin1x, spin1y, spin1z };
//REAL8 spin2[3] = { spin2x, spin2y, spin2z };
// Approximant appr;
// appr = approximant;
gsl_spline *spline0 = NULL;
gsl_interp_accel *acc0 = NULL;
// if (debugSB) {
// printf("RDfit: we use spin1 %f, spin2 %f, and it should be dimensionless [-1,1] \n", chi1, chi2);
// printf("We use approximant = %d \n", appr);
// }
REAL8 chi = 0.5 * (chi1 + chi2) + 0.5 * (chi1 - chi2) * (mass1 - mass2)/(mass1 + mass2) / (1.0 - 2.0 * eta);
/*********************************************************************************************/
/* QNMs of the remnant */
/*********************************************************************************************/
/* Getting QNMs */
modefreqs = CreateCOMPLEX16Vector(1);
if (XLALSimIMREOBGenerateQNMFreqV2FromFinalPrec(modefreqs, mass1, mass2, finalM, finalS , l, m, 1) == CEV_FAILURE)
{
PRINT_LOG_INFO(LOG_CRITICAL, "failure in XLALSimIMREOBGenerateQNMFreqV2FromFinalPrec");
failed = 1;
goto QUIT;
}
//RC: we use this variable to compute the damping time of the 22 mode which will be used to set the lenght of the ringdown for all the modes
modefreqs22 = CreateCOMPLEX16Vector(1);
if (XLALSimIMREOBGenerateQNMFreqV2FromFinalPrec(modefreqs22, mass1, mass2, finalM, finalS, 2, 2, 1) == CEV_FAILURE)
{
PRINT_LOG_INFO(LOG_CRITICAL, "failure in XLALSimIMREOBGenerateQNMFreqV2FromFinalPrec");
failed = 1;
goto QUIT;
}
/* Least-damped QNM */
COMPLEX16 sigmalm0;
sigmalm0 = (-cimag(modefreqs->data[0]) - I * creal(modefreqs->data[0])) * (mtot * CST_MTSUN_SI);
// sigmalm0 = -0.08119703120243188 - I*0.5040714995216017;
// if (debugSB) {
// printf("Mode %d %d \n",l, m);
// printf("matchpoints are: %.16f, %.16f, %.16f \n", matchrange->data[0], matchrange->data[1], matchrange->data[2]);
// printf("the 0-overtone is: %.16f + i %.16f \n", creal(sigmalm0), cimag(sigmalm0));
// }
/*********************************************************************************************/
/* Prepare inspiral signal */
/* This is needed to guarantee continuity with RD signal */
/*********************************************************************************************/
/* Compute amplitude and the unwrapped phase of the inspiral */
phasecount = 0;
for (i = 0; i < signal1->length; i++)
{
ampWave->data[i] = 0.0;
phWave->data[i] = 0.0;
}
REAL8 prev, now, corph;
prev = atan2(signal2->data[0], signal1->data[0]);
phWave->data[0] = prev;
for (i = 0; i < timeVec->length; i++)
{
ampWave->data[i] = sqrt(signal1->data[i] * signal1->data[i] + signal2->data[i] * signal2->data[i]);
now = atan2(signal2->data[i], signal1->data[i]);
if (i > 0)
{
/* Unwrapping */
corph = now - prev;
corph = corph > CST_PI ? corph - CST_2PI : (corph < -CST_PI ? corph + CST_2PI : corph);
phWave->data[i] = phWave->data[i - 1] + corph;
prev = now;
}
//phWave->data[i] = now;
}
FILE *fout = NULL;
// if (debugSB) {
// char filename2[sizeof "CheckStasAmplPhaseXX.dat"];
// sprintf(filename2,"CheckStasAmplPhase%01d%01d.dat",l,m);
// fout = fopen(filename2, "w");
// printf("Check the length: time %d, signal %d \n", timeVec->length, signal1->length);
// for (i = 0; i < timeVec->length; i++) {
// fprintf(fout, "%f %.16e %.16e %.16e %.16e \n", timeVec->data[i], ampWave->data[i], phWave->data[i], signal1->data[i], signal2->data[i]);
// }
// fclose(fout);
// }
/* Search for index at which the maximum of the amplitude occurs */
REAL8 valAmax = ampWave->data[0];
REAL8 valdAmax = 0;
REAL8 tofAmax = matchrange->data[1];
UINT indAmax;
if (l == 5 && m==5)
{
tofAmax = matchrange->data[3];
}
//RC we should find this only for the mode 22, for the other one the attaching point is the same, with the exception of the 55
//For the 55 mode we need to find tpeak22 -10M, which in that case is fed as matchrange->data[1]
if((l == 2 && m == 2) || (l == 5 && m == 5))
{
if ( XLALSimFindIndexMaxAmpli( &indAmax, timeVec, ampWave, &valAmax, tofAmax ) == CEV_FAILURE )
{
PRINT_LOG_INFO(LOG_CRITICAL, "Time of maximum amplitude is not found .");
failed = 1;
goto QUIT;
}
*indAmpMax = indAmax;
//RC for the 55 mode we also need to find the derivative at the attachment point, since we are not making the attachment
//at the peak of the mode where the derivative is zero
if(l == 5 && m == 5)
{
spline0 = gsl_spline_alloc (gsl_interp_cspline, timeVec->length);
acc0 = gsl_interp_accel_alloc ();
gsl_spline_init (spline0, timeVec->data, ampWave->data, timeVec->length);
gsl_interp_accel_reset (acc0);
valdAmax = gsl_spline_eval_deriv (spline0, tofAmax, acc0);
}
}
else
{
indAmax = *indAmpMax;
valAmax = ampWave->data[indAmax]; //For the modes different from 22, this IS NOT the value of the maximum of the amplitude of the mode, but is the value of the amplitude at the peak of the 22 mode
//RC: for the SEOBNRv4HM model we need to compute also the derivative at the attaching point. This is not zero because we are attaching the HMs not at the paek of the lm mode, but at the peak of the 22 mode
spline0 = gsl_spline_alloc (gsl_interp_cspline, timeVec->length);
acc0 = gsl_interp_accel_alloc ();
gsl_spline_init (spline0, timeVec->data, ampWave->data, timeVec->length);
gsl_interp_accel_reset (acc0);
valdAmax = gsl_spline_eval_deriv (spline0, tofAmax, acc0);
// valAmax = 0.019835031225903733*AMP0;
// valdAmax = 0.00020163171965464758*AMP0;
}
// if (debugSB) {
// printf("Check: The maximum of amplitude is %.16e found at t=%f, index = %d (out of %d) \n", valAmax, tofAmax, indAmax, timeVec->length);
// printf("Amp@Attachment = %.16f \n", valAmax);
// printf("dAmp@Attachment = %.16f \n", valdAmax);
// FILE *indMax = NULL;
// char filename2[sizeof "indexMaxXXHi.dat"];
// sprintf(filename2,"indexMax%01d%01dHi.dat",l,m);
// indMax = fopen (filename2, "w");
// fprintf(indMax, "%d \n",indAmax);
// fclose(indMax);
// }
/*********************************************************************************************/
/* Constant coefficients entering RD fitting formulas */
/*********************************************************************************************/
/* Computing fit coefficients that enter amplitude and phase of the RD signal */
/* Numeircal constants are defined at the top of this file */
/* Eq. (28) of https://dcc.ligo.org/T1600383 */
REAL8 ampcf1;
// ampcf1 = A1coeff00[l][m] + A1coeff01[l][m] * chi + A1coeff02[l][m] * chi * chi + A1coeff10[l][m] * eta + A1coeff11[l][m] * eta * chi + A1coeff20[l][m] * eta * eta;
ampcf1 = XLALCalculateRDAmplitudeCoefficient1(l, m, eta, chi);
//ampcf1 = 0.08953902308302486;
// if(debugSB){
// printf("ampcf1 = %.16f \n", ampcf1);
// }
/* Eq. (29) of https://dcc.ligo.org/T1600383 */
REAL8 ampcf2;
// ampcf2 = A2coeff00[l][m] + A2coeff01[l][m] * chi + A2coeff10[l][m] * eta + A2coeff11[l][m] * eta * chi + A2coeff20[l][m] * eta * eta + A2coeff21[l][m] * eta * eta * chi;
ampcf2 = XLALCalculateRDAmplitudeCoefficient2(l, m, eta, chi);
//ampcf2 = -0.506368869538912;
// if(debugSB){
// printf("ampcf2 = %.16f \n", ampcf2);
// }
// printf("creal(sigma220), 2.*ampcf1*tanh(ampcf2) = %.16e %.16e\n",1./creal(sigma220), 2.*ampcf1*tanh(ampcf2));
/* Eqs. (31)-(32) of https://dcc.ligo.org/T1600383 */
if( l == 2 && m == 2)
{
if (creal(sigmalm0) > 2. * ampcf1 * tanh(ampcf2))
{
ampcf1 = creal(sigmalm0) / (2. * tanh(ampcf2));
}
}
/* Eq. (36) of https://dcc.ligo.org/T1600383 */
REAL8 phasecf1;
// phasecf1 = P1coeff00[l][m] + P1coeff01[l][m] * chi + P1coeff02[l][m] * chi * chi + P1coeff10[l][m] * eta + P1coeff11[l][m] * eta * chi + P1coeff20[l][m] * eta * eta;
phasecf1 = XLALCalculateRDPhaseCoefficient1(l, m, eta, chi);
// if(debugSB){
// printf("phasecf1 = %.16f \n", phasecf1);
// }
/* Eq. (37) of https://dcc.ligo.org/T1600383 */
REAL8 phasecf2;
// phasecf2 = P2coeff00[l][m] + P2coeff01[l][m] * chi + P2coeff02[l][m] * chi * chi + P2coeff10[l][m] * eta + P2coeff11[l][m] * eta * chi + P2coeff20[l][m] * eta * eta;
phasecf2 = XLALCalculateRDPhaseCoefficient2(l, m, eta, chi);
// if(debugSB){
// printf("phasecf2 = %.16f \n", phasecf2);
// }
// print_debug("(%d,%d):sigmalm0:(%.16e,%.16e),amp:(%.16e,%.16e),phase:(%.16e,%.16e)\n",
// l, m, creal(sigmalm0), cimag(sigmalm0), ampcf1, ampcf2, phasecf1, phasecf2);
/*********************************************************************************************/
/* RD fitting formulas */
/*********************************************************************************************/
/* Ringdown signal length: 10 times the decay time of the n=0 mode */
UINT Nrdwave = (INT4) (EOB_RD_EFOLDS / cimag(modefreqs22->data[0]) / dt);
//printf("Stas Nrdwave %d, dt = %f", Nrdwave, dt);
REAL8 dtM = dt / (mtot * CST_MTSUN_SI); // go to geometric units
rdtime = CreateREAL8Vector(Nrdwave);
for (i = 0; i < Nrdwave; i++)
{
rdtime->data[i] = i * dtM; // this time for RD and it starts with 0
}
REAL8 tcons = 0.; //attachment point relative to peak; possibility for non zero values not fully implemented
/* Rescalings to guarantee continuity with inspiral */
REAL8 Arescaledtcons = valAmax * exp(-creal(sigmalm0) * tcons) / eta;
REAL8 dtArescaledtcons = (valdAmax - creal(sigmalm0) * valAmax) * exp(-creal(sigmalm0) * tcons) / eta; // valdAmax = 0 - assumes extermum (max) of peak amplitude //RC: valdAmax = 0 for 22 mode
REAL8 ampcc1 = dtArescaledtcons * pow(cosh(ampcf2), 2) / ampcf1;
REAL8 ampcc2 = (Arescaledtcons * ampcf1 - dtArescaledtcons * cosh(ampcf2) * sinh(ampcf2)) / ampcf1;
// print_debug("(%d,%d):Arescaledtcons=%.16e\n\tdtArescaledtcons=%.16e\n\tampcc1=%.16e\n\tampcc2=%.16e\n",
// l,m, Arescaledtcons,dtArescaledtcons,ampcc1,ampcc2);
ampRD = CreateREAL8Vector(Nrdwave);
phRD = CreateREAL8Vector(Nrdwave);
/* Construct RD amplitude */
/* Eqs. (22)-(23) of https://dcc.ligo.org/T1600383 */
for (i = 0; i < Nrdwave; i++)
{
ampRD->data[i] = eta * exp(creal(sigmalm0) * rdtime->data[i]) * (ampcc1 * tanh(ampcf1 * rdtime->data[i] + ampcf2) + ampcc2);
}
// if (debugSB) {
// char filename[sizeof "StasAmpRD_fullXX.dat"];
// sprintf(filename,"StasAmpRD_full%01d%01d.dat",l,m);
// fout = fopen (filename, "w");
// // for (i = 0; i < indAmax; i++) {
// // fprintf(fout, "%.16e %.16e \n", timeVec->data[i], ampWave->data[i]/AMP0);
// // }
// for (i = 1; i < Nrdwave; i++) {
// fprintf(fout, "%.16e %.16e \n", rdtime->data[i] + tofAmax*0, ampRD->data[i]);
// }
// fclose(fout);
// }
/* Construct RD phase */
REAL8 omegarescaledtcons = (phWave->data[indAmax] - phWave->data[indAmax - 1]) / dtM - cimag(sigmalm0);
// omegarescaledtcons = -0.2354501785436996 - cimag(sigmalm0); 21 mode
// omegarescaledtcons = -0.6076660197512114 - cimag(sigmalm0); 33 mode
// omegarescaledtcons = -0.8063013198270685 - cimag(sigmalm0); 44 mode
// omegarescaledtcons = -0.7813933465833801 - cimag(sigmalm0); 55 mode
// if(debugSB){
// printf("omega0 = %.16f\n", phWave->data[0]);
// printf("omega0fit = %.16f, omega0numder = %.16f \n", XLALSimIMREOBGetNRSpinPeakOmegaV4 (l, m, eta, chi), (phWave->data[indAmax] - phWave->data[indAmax - 1]) / dtM);
// }
REAL8 phasecc1 = omegarescaledtcons * (phasecf2 + 1.0) / phasecf2 / phasecf1;
REAL8 phi0 = phWave->data[indAmax];
// print_debug("(%d,%d):dtM = %.16e, omegarescaledtcons = %.16e, phasecc1 = %.16e\n",
// l,m,dtM,omegarescaledtcons,phasecc1);
// phi0 = -165.37581501842033; 21 mode
// phi0 = -486.98433862793974; 33 mode
// phi0 = -651.2335864724689; 44 mode
// phi0 = -805.2637568966843; 55 mode
// if(debugSB){
// printf("phi_0 = %.16f \n", phi0);
// }
REAL8 logargnum, logargden;
/* Eq. (33)-(34) of https://dcc.ligo.org/T1600383 */
for (i = 0; i < Nrdwave; i++)
{
logargnum = 1. + phasecf2 * exp(-phasecf1 * rdtime->data[i]);
logargden = 1. + phasecf2;
phRD->data[i] = phi0 - phasecc1 * log(logargnum / logargden) + cimag(sigmalm0) * rdtime->data[i];
}
// if (debugSB) {
// char filename[sizeof "StasPhRD_fullXX.dat"];
// sprintf(filename,"StasPhRD_full%01d%01d.dat",l,m);
// fout = fopen (filename, "w");
// // for (i = 0; i < indAmax; i++) {
// // fprintf(fout, "%.16e %.16e \n", timeVec->data[i], phWave->data[i]);
// // }
// for (i = 1; i < Nrdwave; i++) {
// fprintf(fout, "%.16e %.16e \n", rdtime->data[i] + tofAmax*0, phRD->data[i]);
// }
// fclose(fout);
// // Compute the frequency of the ful signal
// UINT4 totSz = indAmax + Nrdwave;
// REAL8Vector *PhFull;
// PhFull = XLALCreateREAL8Vector(totSz);
// REAL8Vector *tFull;
// tFull = XLALCreateREAL8Vector(totSz);
// REAL8Vector *frFull;
// frFull = XLALCreateREAL8Vector(totSz);
// for (i = 0; i < indAmax; i++) {
// tFull->data[i] = timeVec->data[i];
// PhFull->data[i] = phWave->data[i];
// }
// for (i = 0; i < Nrdwave; i++) {
// tFull->data[i + indAmax] = rdtime->data[i] + tofAmax;