LALSimulation  5.4.0.1-fe68b98
LALSimIMRSpinPrecEOB.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2011 Craig Robinson, Enrico Barausse, Yi Pan,
3 * 2014 Prayush Kumar, Stas Babak, Andrea Taracchini (Precessing EOB)
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 #ifndef _LALSIMIMRSPINPRECEOB_C
21 #define _LALSIMIMRSPINPRECEOB_C
22 /**
23  * @addtogroup LALSimIMRSpinPrecEOB_c
24  *
25  * @author Craig Robinson, Yi Pan, Prayush Kumar, Stas Babak, Andrea Taracchini
26  *
27  * \brief Functions for producing SEOBNRv3 waveforms for
28  * precessing binaries of spinning compact objects, as described
29  * in Pan et al. ( PRD 89, 084006 (2014) ) == YPP.
30  */
31 
32 #include <math.h>
33 #include <complex.h>
34 #include <lal/LALSimInspiral.h>
35 #include <lal/LALSimIMR.h>
36 #include <lal/Date.h>
37 #include <lal/TimeSeries.h>
38 #include <lal/Units.h>
39 #include <lal/LALAdaptiveRungeKuttaIntegrator.h>
40 #include <lal/SphericalHarmonics.h>
41 #include <gsl/gsl_sf_gamma.h>
42 #include <gsl/gsl_integration.h>
43 #include "LALSimIMREOBNRv2.h"
44 #include "LALSimIMRSpinEOB.h"
45 #include "LALSimInspiralPrecess.h"
47 #include "LALSimFindAttachTime.h"
48 #include <lal/VectorOps.h>
49 
50 /* Include all the static function files we need */
66 
67 /* Begin OPTv3 */
71 /* End OPTv3 */
72 
73 #define debugOutput 0
74 
75 #ifdef __GNUC__
76 #define UNUSED __attribute__ ((unused))
77 #else
78 #define UNUSED
79 #endif
80 
81 #define FREE_EVERYTHING \
82 if ( hlmPTS != NULL ) \
83 XLALDestroySphHarmTimeSeries(hlmPTS); \
84 if ( hIMRlmJTS != NULL ) \
85 XLALDestroySphHarmTimeSeries(hIMRlmJTS); \
86 if ( hIMRlmITS != NULL ) \
87 XLALDestroySphHarmTimeSeries(hIMRlmITS); \
88 \
89 if ( dynamics != NULL ) \
90 XLALDestroyREAL8Array( dynamics ); \
91 if ( dynamicsV2 != NULL ) \
92 XLALDestroyREAL8Array( dynamicsV2 ); \
93 if ( dynamicsV2Hi != NULL ) \
94 XLALDestroyREAL8Array( dynamicsV2Hi ); \
95 if ( dynamicsHi != NULL ) \
96 XLALDestroyREAL8Array( dynamicsHi ); \
97 \
98 XLALDestroyREAL8Vector( valuesV2 ); \
99 XLALDestroyREAL8Vector( values ); \
100 XLALDestroyREAL8Vector( dvalues ); \
101 \
102 XLALDestroyREAL8Vector( sigmaStar ); \
103 XLALDestroyREAL8Vector( sigmaKerr ); \
104 \
105 XLALDestroyREAL8Vector( rdMatchPoint ); \
106 \
107 XLALDestroyREAL8Vector( Alpha ); \
108 XLALDestroyREAL8Vector( Beta ); \
109 XLALDestroyREAL8Vector( Gamma ); \
110 XLALDestroyREAL8Vector( AlphaHi ); \
111 XLALDestroyREAL8Vector( BetaHi ); \
112 XLALDestroyREAL8Vector( GammaHi ); \
113 \
114 XLALDestroyREAL8Vector( sigReHi ); \
115 XLALDestroyREAL8Vector( sigImHi ); \
116 \
117 XLALDestroyREAL8TimeSeries(alphaI2PTS); \
118 XLALDestroyREAL8TimeSeries(betaI2PTS); \
119 XLALDestroyREAL8TimeSeries(gammaI2PTS); \
120 \
121 XLALDestroyREAL8TimeSeries(alphaI2PTSHi); \
122 XLALDestroyREAL8TimeSeries(betaI2PTSHi); \
123 XLALDestroyREAL8TimeSeries(gammaI2PTSHi); \
124 \
125 XLALDestroyREAL8TimeSeries(alphaP2JTS); \
126 XLALDestroyREAL8TimeSeries(betaP2JTS); \
127 XLALDestroyREAL8TimeSeries(gammaP2JTS); \
128 \
129 XLALDestroyREAL8TimeSeries(alphaP2JTSHi); \
130 XLALDestroyREAL8TimeSeries(betaP2JTSHi); \
131 XLALDestroyREAL8TimeSeries(gammaP2JTSHi); \
132 \
133 XLALDestroyREAL8TimeSeries(alpI); \
134 XLALDestroyREAL8TimeSeries(betI); \
135 XLALDestroyREAL8TimeSeries(gamI); \
136 \
137 XLALDestroyCOMPLEX16TimeSeries(h22TS); \
138 XLALDestroyCOMPLEX16TimeSeries(h21TS); \
139 XLALDestroyCOMPLEX16TimeSeries(h20TS); \
140 XLALDestroyCOMPLEX16TimeSeries(h2m1TS); \
141 XLALDestroyCOMPLEX16TimeSeries(h2m2TS); \
142 \
143 XLALDestroyCOMPLEX16TimeSeries(h22TSHi); \
144 XLALDestroyCOMPLEX16TimeSeries(h21TSHi); \
145 XLALDestroyCOMPLEX16TimeSeries(h20TSHi); \
146 XLALDestroyCOMPLEX16TimeSeries(h2m1TSHi); \
147 XLALDestroyCOMPLEX16TimeSeries(h2m2TSHi); \
148 \
149 XLALDestroyCOMPLEX16TimeSeries(hIMRJTS); \
150 XLALDestroyCOMPLEX16TimeSeries(hIMRJTSHi); \
151 \
152 XLALAdaptiveRungeKuttaFree(integrator); \
153 \
154 XLALDestroyREAL8TimeSeries(hPlusTS); \
155 XLALDestroyREAL8TimeSeries(hCrossTS);
156 
157 
158 #define FREE_SPHHARM \
159 XLALDestroyREAL8Vector( tlist ); \
160 XLALDestroyREAL8Vector( tlistHi ); \
161 XLALDestroyREAL8Vector( timeJFull ); \
162 XLALDestroyREAL8Vector( timeIFull ); \
163 XLALDestroyREAL8Vector( tlistRDPatch ); \
164 XLALDestroyREAL8Vector( tlistRDPatchHi );
165 
166 #define PRINT_PARAMS do { \
167 XLALPrintError("--approximant SEOBNRv3 --f-min %.16e --m1 %.16e --m2 %.16e --spin1x %.16e --spin1y %.16e --spin1z %.16e --spin2x %.16e --spin2y %.16e --spin2z %.16e --inclination %.16e --distance %.16e --phiRef %.16e --sample-rate %.16e\n",\
168  fMin, m1SI/LAL_MSUN_SI, m2SI/LAL_MSUN_SI, INspin1x, INspin1y, INspin1z, INspin2x, INspin2y, INspin2z, inc, r/(1e6 * LAL_PC_SI), phiC, 1./deltaT);\
169 } while(0);
170 
171 /**
172  * Stopping conditions for dynamics integration for SEOBNRv3
173  */
174 UNUSED static int
176  const double values[],
177  double dvalues[],
178  void UNUSED *funcParams
179  )
180 {
181  int debugPK = 0; int debugPKverbose = 0;
182  INT4 i;
183  SpinEOBParams UNUSED *params = (SpinEOBParams *)funcParams;
184 
185  REAL8 r2, pDotr = 0;
186  REAL8 p[3], r[3], pdotVec[3], rdotVec[3];
187  REAL8 omega, omega_xyz[3], L[3], dLdt1[3], dLdt2[3];
188 
189  memcpy( r, values, 3*sizeof(REAL8));
190  memcpy( p, values+3, 3*sizeof(REAL8));
191  memcpy( rdotVec, dvalues, 3*sizeof(REAL8));
192  memcpy( pdotVec, dvalues+3, 3*sizeof(REAL8));
193 
194  r2 = inner_product(r,r);
195  cross_product( values, dvalues, omega_xyz );
196  omega = sqrt(inner_product( omega_xyz, omega_xyz )) / r2;
197  pDotr = inner_product( p, r ) / sqrt(r2);
198  if (debugPK){ XLAL_PRINT_INFO("XLALEOBSpinPrecStopConditionBasedOnPR:: r = %e %e\n", sqrt(r2), omega);}
199  if (debugPK){ XLAL_PRINT_INFO("XLALEOBSpinPrecStopConditionBasedOnPR:: values = %e %e %e %e %e %e\n", values[6], values[7], values[8], values[9], values[10], values[11]);}
200  if (debugPK){ XLAL_PRINT_INFO("XLALEOBSpinPrecStopConditionBasedOnPR:: dvalues = %e %e %e %e %e %e\n",dvalues[6], dvalues[7], dvalues[8], dvalues[9], dvalues[10], dvalues[11]);}
201  REAL8 rdot;
202  // this is d(r)/dt obtained by differentiating r2 (see above)
203  rdot = inner_product(rdotVec, r) / sqrt(r2);
204  // This is d/dt(pDotr) see pDotr above.
205  double prDot = - inner_product( p, r )*rdot/r2
206  + inner_product( pdotVec, r )/sqrt(r2)
207  + inner_product( rdotVec, p )/sqrt(r2);
208 
209  cross_product( r, pdotVec, dLdt1 );
210  cross_product( rdotVec, p, dLdt2 );
211  cross_product( r, p, L );
212 
213  /* ********************************************************** */
214  /* ******* Different termination conditions Follow ******** */
215  /* ********************************************************** */
216 
217  /* Terminate if any derivative is Nan */
218  for( i = 0; i < 12; i++ )
219  {
220  if( isnan(dvalues[i]) || isnan(values[i]) )
221  {
222  if(debugPK){XLAL_PRINT_INFO("\n isnan reached. r2 = %f\n", r2); fflush(NULL); }
223  XLALPrintError( "XLAL Error - %s: nan reached at r2 = %f \n", __func__, r2);
225 
226  return 1;
227  }
228  }
229 
230  /* ********************************************************** */
231  /* ******* Unphysical orbital conditions ******** */
232  /* ********************************************************** */
233  /* Terminate if p_r points outwards */
234  if ( r2 < 16 && pDotr >= 0 )
235  {
236  if(debugPK){
237  XLAL_PRINT_INFO("\n Integration stopping, p_r pointing outwards -- out-spiraling!\n");
238  fflush(NULL);
239  }
240  return 1;
241  }
242 
243  /* Terminate if rdot is >0 (OUTspiraling) for separation <4M */
244  if ( r2 < 16 && rdot >= 0 )
245  {
246  if(debugPK){
247  XLAL_PRINT_INFO("\n Integration stopping, dr/dt>0 -- out-spiraling!\n");
248  fflush(NULL);
249  }
250  return 1;
251  }
252 
253  /* Terminate if dp_R/dt > 0, i.e. radial momentum is increasing for separation <2M */
254  if(r2 < 4. && prDot > 0. )
255  {
256  if(debugPK){
257  XLAL_PRINT_INFO("\n Integration stopping as prDot = %lf at r = %lf\n",
258  prDot, sqrt(r2));
259  fflush(NULL);
260  }
261  return 1;
262  }
263 
264  if(r2 < 16. && ( sqrt(values[3]*values[3] + values[4]*values[4] + values[5]*values[5]) > 10. )) {
265  if(debugPK)XLAL_PRINT_INFO("\n Integration stopping |pvec|> 10\n");
266  fflush(NULL);
267  return 1;
268  }
269 
270  if(r2 < 16. && ( sqrt(values[3]*values[3] + values[4]*values[4] + values[5]*values[5]) < 1.e-10 )) {
271  if(debugPK)XLAL_PRINT_INFO("\n Integration stopping |pvec|<1e-10\n");
272  fflush(NULL);
273  return 1;
274  }
275 
276  /* **************************************************************** */
277  /* Omega related */
278  /* **************************************************************** */
279  /* Terminate when omega reaches peak, and separation is < 4M */
280  if ( r2 < 16. && omega < params->eobParams->omega )
281  params->eobParams->omegaPeaked = 1;
282 
283  /* If omega has gone through a second extremum, break */
284  if ( r2 < 4. && params->eobParams->omegaPeaked == 1
285  && omega > params->eobParams->omega )
286  {
287  if(debugPK) {
288  XLAL_PRINT_INFO("\n Integration stopping, omega reached second extremum\n");
289  fflush(NULL);
290  }
291  return 1;
292  }
293 
294  /* If Momega did not evolve above 0.01 even though r < 4 or omega<0.14 for r<2, break */
295  if((r2 < 16. && omega < 0.04) || (r2 < 4. && omega < 0.14 && params->eobParams->omegaPeaked == 1 ) )
296  {
297  if(debugPK){
298  XLAL_PRINT_INFO("\n Integration stopping for omega below threshold, omega=%f at r = %f\n", omega, sqrt(r2));
299  fflush(NULL);
300  }
301  return 1;
302  }
303 
304  if(r2 < 16. && omega > 1. )
305  {
306  if(debugPK){
307  XLAL_PRINT_INFO("\n Integration stopping, omega>1 at r = %f\n", sqrt(r2));
308  fflush(NULL);
309  }
310  return 1;
311  }
312  params->eobParams->omega = omega;
313 
314  /* **************************************************************** */
315  /* related to Numerical values of x/p/derivatives */
316  /* **************************************************************** */
317 
318  /* If momentum derivatives are too large numerically, break */
319  if ( r2 < 25 && (fabs(dvalues[3]) > 10 || fabs(dvalues[4]) > 10 || fabs(dvalues[5]) > 10) )
320  {
321  if(debugPK){
322  XLAL_PRINT_INFO("\n Integration stopping, dpdt > 10 -- too large!\n");
323  fflush(NULL);}
324  return 1;
325  }
326 
327  /* If p_\Phi is too large numerically, break */
328  if( r2 < 16. && values[5] > 10 )
329  {
330  if(debugPK){
331  XLAL_PRINT_INFO("Integration stopping, Pphi > 10 now\n\n");
332  fflush(NULL);
333  }
334  return 1;
335  }
336  /* If rdot inclreases, break */
337  if ( r2 < 9. && rdot>params->prev_dr ) {
338  if(debugPK){
339  XLAL_PRINT_INFO("\n Integration stopping, dr/dt increasing!\n");
340  fflush(NULL);
341  }
342  params->prev_dr=rdot;
343  return 1;
344  }
345  params->prev_dr=rdot;
346 
347  /* **************************************************************** */
348  /* Last resort conditions */
349  /* **************************************************************** */
350 
351  /* Very verbose output */
352  if(debugPKverbose && r2 < 16.) {
353  XLAL_PRINT_INFO("%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
354  t, values[0], values[1], values[2], values[3], values[4], values[5],
355  values[6], values[7], values[8], values[9], values[10], values[11],
356  values[12], values[13], omega);
357  }
358 
359  return GSL_SUCCESS;
360 }
361 
362 
363 /**
364  * Stopping condition for the regular resolution SEOBNRv1/2 orbital evolution
365  * -- stop when reaching max orbital frequency in strong field.
366  * At each test,
367  * if omega starts to decrease, return 1 to stop evolution;
368  * if not, update omega with current value and return GSL_SUCCESS to continue evolution.
369  */
370 static int
371 XLALEOBSpinPrecAlignedStopCondition(double UNUSED t, /**< UNUSED */
372  const double values[], /**< dynamical variable values */
373  double dvalues[], /**< dynamical variable time derivative values */
374  void *funcParams /**< physical parameters */
375  )
376 {
377  int debugPK = 0;
378  REAL8 omega, r;
379  SpinEOBParams *params = (SpinEOBParams *)funcParams;
380 
381  r = values[0];
382  omega = dvalues[1];
383  if (debugPK){ XLAL_PRINT_INFO("XLALEOBSpinPrecAlignedStopCondition:: r = %e\n", r);}
384 
385  if ( r < 6. && omega < params->eobParams->omega )
386  {
387  return 1;
388  }
389 
390  params->eobParams->omega = omega;
391  return GSL_SUCCESS;
392 }
393 
394 /**
395  * Stopping condition for the high resolution SEOBNRv1/2 orbital evolution
396  * -- stop when reaching a minimum radius 0.3M out of the EOB horizon (Eqs. 9b, 37)
397  * or when getting nan in any of the four ODE equations
398  * At each test,
399  * if conditions met, return 1 to stop evolution;
400  * if not, return GSL_SUCCESS to continue evolution.
401  */
402 static int
403 XLALSpinPrecAlignedHiSRStopCondition(double UNUSED t, /**< UNUSED */
404  const double UNUSED values[], /**< dynamical variable values */
405  double dvalues[], /**< dynamical variable time derivative values */
406  void UNUSED *funcParams /**< physical parameters */
407  )
408 {
409  int debugPK = 0;
410  if (debugPK){
411  XLAL_PRINT_INFO("XLALSpinPrecAlignedHiSRStopCondition:: r = %e\n", values[0]);
412  XLAL_PRINT_INFO("values[0], values[1], values[2], values[3], dvalues[0], dvalues[1], dvalues[2], dvalues[3] = %e %e %e %e %e %e %e %e\n", values[0], values[1], values[2], values[3], dvalues[0], dvalues[1], dvalues[2], dvalues[3]);
413  }
414 
415  if ( dvalues[0] >= 0. || dvalues[2] >= 0. || isnan( dvalues[3] ) || isnan (dvalues[2]) || isnan (dvalues[1]) || isnan (dvalues[0]) )
416  {
417  return 1;
418  }
419  return GSL_SUCCESS;
420 }
421 
422 /**
423  * Optimized routine for calculating coefficients for the v3 Hamiltonian.
424  */
426 
427  SEOBHCoeffConstants CoeffConsts;
428 
429  REAL8 c20 = 1.712;
430  REAL8 c21 = -1.803949138004582;
431  REAL8 c22 = -39.77229225266885;
432  REAL8 c23 = 103.16588921239249;
433 
434  /*
435  coeffsb3 = 0.;
436  coeffsbb3 = 0.;
437  */
438 
439  REAL8 coeffsKK = c20 + c21*eta + c22*eta*eta + c23*eta*eta*eta;
440  REAL8 m1PlusEtaKK = -1. + eta*coeffsKK;
441 
442  #include "seobnrv3_opt_exactderivs/SEOBNRv3_opt_coeffs-kC-parsedfinal.c.generated"
443  CoeffConsts.a0k2 = kC0;
444  CoeffConsts.a1k2 = kC1;
445  CoeffConsts.a0k3 = kC2;
446  CoeffConsts.a1k3 = kC3;
447  CoeffConsts.a0k4 = kC4;
448  CoeffConsts.a1k4 = kC5;
449  CoeffConsts.a2k4 = kC6;
450  CoeffConsts.a0k5 = kC7;
451  CoeffConsts.a1k5 = kC8;
452  CoeffConsts.a2k5 = kC9;
453 
454  return CoeffConsts;
455 }
456 
457 /**
458  * Standard interface for SEOBNRv3 waveform generator: calls XLALSimIMRSpinEOBWaveformAll
459  */
461  REAL8TimeSeries **hplus, /**<< OUTPUT, +-polarization waveform */
462  REAL8TimeSeries **hcross, /**<< OUTPUT, x-polarization waveform */
463  const REAL8 phiC, /**<< coalescence orbital phase (rad) */
464  const REAL8 deltaT, /**<< sampling time step */
465  const REAL8 m1SI_in, /**<< mass-1 in SI unit (kg) */
466  const REAL8 m2SI_in, /**<< mass-2 in SI unit (kg) 8*/
467  const REAL8 fMin, /**<< starting frequency (Hz) */
468  const REAL8 r, /**<< luminosity distance in SI unit (m) */
469  const REAL8 inc, /**<< inclination angle */
470  const REAL8 INspin1[], /**<< spin1 */
471  const REAL8 INspin2[], /**<< spin2 */
472  const UINT4 PrecEOBversion /**<< Precessing EOB waveform generator model */
473  )
474 
475 {
476  int ret;
477  REAL8Vector *dynamicsHi = NULL;
478  REAL8Vector *AttachPars = NULL;
479  /** This time series contains harmonics in precessing (P) frame, no RD, for the end of the signal (high samling part)*/
480  SphHarmTimeSeries *hlmPTSHi = NULL;
481  /** This stores harmonics in J-frame, no RD, for the end of the signal (high sampling part) */
482  SphHarmTimeSeries *hlmPTSout = NULL;
483  /** Stores harmonics in J-frame with RD, for the end of the signal (high samling part) */
484  SphHarmTimeSeries *hIMRlmJTSHi = NULL;
485  /** stores harmonics of the full waveform in I-frame */
486  SphHarmTimeSeries *hIMR = NULL;
487 
488  REAL8 m1SI = m1SI_in;
489  REAL8 m2SI = m2SI_in;
490 
491  // Loop around waveform generation and perturb masses if it returns NULL pointers
492  bool generation_OK = false;
493  int i = 0;
494  int n_try = 5;
495  REAL8 pert = 1.0 + 1e-12;
496  while (!generation_OK && (i < n_try)) {
497  ret = XLALSimIMRSpinEOBWaveformAll(hplus, hcross, &dynamicsHi, &hlmPTSout, &hlmPTSHi, &hIMRlmJTSHi, &hIMR, &AttachPars,
498  phiC, deltaT, m1SI, m2SI, fMin, r, inc, INspin1[0], INspin1[1], INspin1[2], INspin2[0], INspin2[1], INspin2[2], PrecEOBversion);
499  if (ret == XLAL_SUCCESS) {
500  if (*hplus == NULL || *hcross == NULL || (*hplus)->data == NULL || (*hcross)->data == NULL){
501  XLALPrintWarning("Houston-2/3, we've got a problem SOS, SOS, SOS, the waveform generator returns NULL!!!... m1 = %.18e, m2 = %.18e, fMin = %.18e, inclination = %.18e, spin1 = {%.18e, %.18e, %.18e}, spin2 = {%.18e, %.18e, %.18e} \n",
502  m1SI/LAL_MSUN_SI, m2SI/LAL_MSUN_SI, (double)fMin, (double)inc, INspin1[0], INspin1[1], INspin1[2], INspin2[0], INspin2[1], INspin2[2]);
503  XLALPrintWarning("We will perturb the masses by a small amount and retry in next iteration (%d of %d).\n", i, n_try);
504  m1SI *= pert;
505  m2SI /= pert;
506  }
507  else{
508  generation_OK = true;
509  }
510  }
511  else{
512  //If we failed, don't try agin
513  break;
514  }
515  i++;
516  }
517  if(ret!=XLAL_SUCCESS){
518  // Something has gone wrong, just propogate it upward
519  XLAL_ERROR(ret);
520  }
521  else if (!generation_OK && ret==XLAL_SUCCESS) {
522  // We know that waveform generator gave NULL pointers. Die in a specific way.
523  XLALPrintWarning("We have called XLALSimIMRSpinEOBWaveformAll %d times with perturbed masses, now we give up.\n", n_try);
525  }
526 
527  if(dynamicsHi)
528  XLALDestroyREAL8Vector( dynamicsHi );
529  if(AttachPars)
530  XLALDestroyREAL8Vector( AttachPars );
531  if(hlmPTSout)
532  XLALDestroySphHarmTimeSeries(hlmPTSout);
533  if(hlmPTSHi)
535  if(hIMRlmJTSHi)
536  XLALDestroySphHarmTimeSeries(hIMRlmJTSHi);
537  if(hIMR)
539  return ret;
540 }
541 
542 /**
543  * This function generates precessing spinning SEOBNRv3 waveforms h+ and hx.
544  * Currently, only h2m harmonics will be generated.
545  *
546  * Input conventions:
547  * Cartesian coordinate system: initial \f$\vec{L}_N\f$ is in the xz plane, rotated away from
548  * the z-axis by an angle inc
549  * phiC : in radians
550  * deltaT : in SI units (s)
551  * m1SI, m2SI : in SI units (kg)
552  * fMin : in SI units (Hz)
553  * r : in SI units (m)
554  * inc : in radians
555  * INspin{1,2}: in dimensionless units of m{1,2}^2
556  *
557  * Evolution conventions:
558  * values[0-2]: r vector in units of total mass
559  * values[3-5]: pstar vector in units of reduced mass
560  * values[6-8]: S1 vector in units of (total mass)^2
561  * values[9-11]: S2 vector in units of (total mass)^2
562  * values[12-13]: phases (carrier and precession (Thomas)) in rads
563  *
564  * Note that when the initial opening angles of the spins w.r.t. the initial Newtonian
565  * angular momentum are small, the aligned-spin SEOBNRv2 dynamics is used.
566  * However, the waveforms are then generated according the the SEOBNRv3 model:
567  * for example, they include the (2,1) mode.
568  *
569  * STEP 0) Prepare parameters, including pre-computed coefficients
570  * for EOB Hamiltonian, flux and waveform
571  * STEP 1) Solve for initial conditions
572  * STEP 2) Evolve EOB trajectory both at low and high sampling rate
573  * STEP 3) Compute Euler angles to go from initial inertial frame to
574  * precessing frame
575  * STEP 4) Locate merger point and at that time calculate J, chi and kappa,
576  * and construct final J frame
577  * STEP 5) Generate quasi-nonprecessing waveforms in precessing frame
578  * STEP 6) Rotate quasi-nonprecessing waveforms from precessing to final-J-frame
579  * STEP 7) Attach ringdown to final-J-frame modes
580  * STEP 8) Rotate modes from final final-J-frame to initial inertial frame
581  * STEP 9) Compute h+, hx
582  */
584  REAL8TimeSeries **hplus, /**<< output: hplus GW polarization */
585  REAL8TimeSeries **hcross, /**<< output: hcross GW polarization */
586  REAL8Vector **dynHi, /**<< Here we store and return the seob dynamics for high sampling (end of inspiral) */
587  SphHarmTimeSeries **hlmPTSoutput, /**<< Here we store and return the PWave (high sampling) */
588  SphHarmTimeSeries **hlmPTSHiOutput, /**<< Here we store and return the JWave (high sampling) */
589  SphHarmTimeSeries **hIMRlmJTSHiOutput, /**<< Here we store and return the JWaveIMR (high sampling) */
590  SphHarmTimeSeries **hIMRoutput, /**<< Here we store and return the IWave (full) */
591  REAL8Vector **AttachPars, /**<< Parameters of RD attachment: */
592  const REAL8 phiC, /**<< intitial orbital phase */
593  const REAL8 deltaT, /**<< sampling time step */
594  const REAL8 m1SI, /**<< mass of first object in SI */
595  const REAL8 m2SI, /**<< mass of second object in SI */
596  const REAL8 fMin, /**<< fMin */
597  const REAL8 r, /**<< luminosity distance in SI */
598  const REAL8 inc, /**<< inclination */
599  const REAL8 INspin1x, /**<< spin1 x-component */
600  const REAL8 INspin1y, /**<< spin1 y-component */
601  const REAL8 INspin1z, /**<< spin1 z-component */
602  const REAL8 INspin2x, /**<< spin2 x-component */
603  const REAL8 INspin2y, /**<< spin2 y-component */
604  const REAL8 INspin2z, /**<< spin2 z-component */
605  const UINT4 PrecEOBversion /**<< Precessing EOB waveform generator model */
606  )
607 
608 {
609  REAL8 INspin1[3], INspin2[3];
610  INspin1[0] = INspin1x;
611  INspin1[1] = INspin1y;
612  INspin1[2] = INspin1z;
613  INspin2[0] = INspin2x;
614  INspin2[1] = INspin2y;
615  INspin2[2] = INspin2z;
616 
617  INT4 debugPK = 0, debugCustomIC = 0, debugNoNQC = 0;
618  INT4 debugRD = 0;
619  FILE *out = NULL;
620  INT4 i=0;
621  INT4 k=0;
622  UINT4 j=0;
624  //REAL8 coa_phase_offset = 0;
625 
626  REAL8Vector *AttachParams = NULL;
627 
628  /* SEOBNRv3_opt selection code */
629  Approximant spinEOBApproximant = SEOBNRv3;
630  INT4 use_optimized = 0;
631  if ( PrecEOBversion == 300 || PrecEOBversion == 304 ) { spinEOBApproximant = SEOBNRv3_opt; use_optimized = 1; }
632 
633  /* The underlying aligned-spin EOB model is hard-coded here */
634  INT4 SpinAlignedEOBversion = 2;
635 
636  /* Vector to store the initial spins */
637  //REAL8 spin1[3] = {0,0,0}, spin2[3] = {0,0,0}, InitLhat[3] = {sin(inc),0.,cos(inc)};
638  REAL8 spin1[3] = {0,0,0}, spin2[3] = {0,0,0}, InitLhat[3] = {0.0,0.0,1.0};
639  // FIXME
640  memcpy( spin1, INspin1, 3*sizeof(REAL8));
641  memcpy( spin2, INspin2, 3*sizeof(REAL8));
642 
643  /* Check the initial misalignment of component spins, w.r.t. the z-axis
644  * theta{1,2}Ini measure the angle w.r.t. the orbital ang. momentum
645  * */
646  REAL8 theta1Ini = 0, theta2Ini = 0;
647  REAL8 spin1Norm = -1, spin2Norm = -1;
648  spin1Norm = sqrt( INspin1[0]*INspin1[0] + INspin1[1]*INspin1[1] + INspin1[2]*INspin1[2] );
649  spin2Norm = sqrt( INspin2[0]*INspin2[0] + INspin2[1]*INspin2[1] + INspin2[2]*INspin2[2] );
650  if ( INspin1[0] == 0. && INspin1[1] == 0. && INspin1[2] == 0. ) {
651  spin1Norm = 0.;
652  }
653  if ( INspin2[0] == 0. && INspin2[1] == 0. && INspin2[2] == 0. ) {
654  spin2Norm = 0.;
655  }
656 
657  /** NOTE: if the spin magnitude is less than 1.e-5 we put them explicitely to zero! */
658  if (spin1Norm <= 1.0e-5) {INspin1[0]=0.;INspin1[1]=0.;INspin1[2]=0.;}
659  if (spin2Norm <= 1.0e-5) {INspin2[0]=0.;INspin2[1]=0.;INspin2[2]=0.;}
660  REAL8 acosarg1 = 0, acosarg2 = 0;
661  if( spin1Norm > 1.0e-5){
662  acosarg1 = (InitLhat[0]*INspin1[0] + InitLhat[1]*INspin1[1] + InitLhat[2]*INspin1[2])/ spin1Norm ;
663  if (acosarg1 > 1.) {
664  theta1Ini = 0.;
665  }
666  else if (acosarg1 < -1.) {
667  theta1Ini = LAL_PI;
668  }
669  else {
670  theta1Ini = acos( acosarg1 );
671  }
672  }
673 
674  if( spin2Norm > 1.0e-5){
675  acosarg2 = (InitLhat[0]*INspin2[0] + InitLhat[1]*INspin2[1] + InitLhat[2]*INspin2[2])/ spin2Norm ;
676  if (acosarg2 > 1.) {
677  theta2Ini = 0.;
678  }
679  else if (acosarg2 < -1.) {
680  theta2Ini = LAL_PI;
681  }
682  else {
683  theta2Ini = acos( acosarg2 );
684  }
685  }
686 
687  /** If the misalignment angle of spins with orbital angular momentum is less than <1.e-4 we treat them as aligned for evolution of the
688  * orbital dynamics */
689  REAL8 EPS_ALIGN = 1.0e-4, incA = inc;
690  bool SpinsAlmostAligned = ( fabs(theta1Ini) <= EPS_ALIGN || fabs(theta1Ini) >= LAL_PI - EPS_ALIGN) && ( fabs(theta2Ini) <= EPS_ALIGN || fabs(theta2Ini) >= LAL_PI - EPS_ALIGN);
691  if ( SpinsAlmostAligned ) {
692  XLAL_PRINT_INFO("Both spins are almost aligned/antialigned to initial LNhat: we use V2 dynamics\n");
693  if (debugPK) {
694  XLAL_PRINT_INFO("spin1Norm spin2Norm %e %e\n", spin1Norm, spin2Norm);
695  }
696  spin1[0] = 0.;
697  spin1[1] = 0.;
698  spin1[2] = spin1Norm*copysign(1., cos(theta1Ini));
699  spin2[0] = 0.;
700  spin2[1] = 0.;
701  spin2[2] = spin2Norm*copysign(1., cos(theta2Ini));
702  incA = 0.;
703 
704  use_optimized = 0;
705  }
706 
707  if ( debugPK ) {
708  XLAL_PRINT_INFO( "InitLhat = {%3.10f, %3.10f, %3.10f}\n",
709  InitLhat[0], InitLhat[1], InitLhat[2] );
710 
711  XLAL_PRINT_INFO( "theta1Ini, theta2Ini = %3.10f, %3.10f\n", theta1Ini, theta2Ini );
712  XLAL_PRINT_INFO( "INspin1 = {%3.10f, %3.10f, %3.10f}\n",
713  INspin1[0], INspin1[1], INspin1[2] );
714  XLAL_PRINT_INFO( "INspin2 = {%3.10f, %3.10f, %3.10f}\n",
715  INspin2[0], INspin2[1], INspin2[2] );
716  XLAL_PRINT_INFO( "spin1 = {%3.10f, %3.10f, %3.10f}\n", spin1[0], spin1[1], spin1[2] );
717  XLAL_PRINT_INFO( "spin2 = {%3.10f, %3.10f, %3.10f}\n", spin2[0], spin2[1], spin2[2] );
718  }
719 
720  /* *******************************************************************/
721  /* ********************** Memory Allocation **************************/
722  /* *******************************************************************/
723 
724  /* Allocate the values vector to contain the ICs */
725  /* Throughout the code, there are 12 dynamical variables: */
726  /* values[0-2] is x (Cartesian tortoise separation vector) */
727  /* values[3-5] is p (Cartesian momentum) */
728  /* values[6-8] is spin of body 1 */
729  /* values[9-11] is spin of body 2 */
730  /* Two additional orbital quantities are evolved */
731  /* values[12] is orbital phase */
732  /* values[13] is alpha dot cos(inclination) */
733  REAL8Vector *values = NULL;
734  if ( !(values = XLALCreateREAL8Vector( 14 )) )
735  {
736  XLALPrintError("Failed to allocate REAL8Vector values!\n");
739  }
740  memset( values->data, 0, values->length * sizeof( REAL8 ));
741 
742  /* Vector to contain derivatives of ICs */
743  REAL8Vector *dvalues = NULL;
744  if ( !(dvalues = XLALCreateREAL8Vector( 14 )) )
745  {
746  XLALDestroyREAL8Vector( values );
747  XLALPrintError("Failed to allocate REAL8Vector dvalues!\n");
750  }
751  REAL8 rdotvec[3] = {0,0,0};
752 
753  /* EOB spin vectors used in the Hamiltonian */
754  REAL8 a = 0, tplspin = 0;
755  REAL8 chiS = 0, chiA = 0;
756  REAL8 spinNQC = 0;
757  REAL8Vector *sigmaStar = NULL;
758  REAL8Vector *sigmaKerr = NULL;
759  if ( !(sigmaStar = XLALCreateREAL8Vector( 3 )) )
760  {
761  XLALDestroyREAL8Vector( sigmaStar );
762  XLALDestroyREAL8Vector( values );
763  XLALDestroyREAL8Vector( dvalues );
764  XLALPrintError("Failed to allocate REAL8Vector sigmaStar!\n");
767  }
768  if ( !(sigmaKerr = XLALCreateREAL8Vector( 3 )) )
769  {
770  XLALDestroyREAL8Vector( sigmaStar );
771  XLALDestroyREAL8Vector( values );
772  XLALDestroyREAL8Vector( dvalues );
773  XLALPrintError("Failed to allocate REAL8Vector sigmaKerr!\n");
776  }
777 
778  /* Spins not scaled by the mass */
779  REAL8 mSpin1[3] = {0,0,0}, mSpin2[3] = {0,0,0};
780 
781  /* Wrapper spin vectors used to calculate sigmas */
782  REAL8Vector s1Vec, s1VecOverMtMt;
783  REAL8Vector s2Vec, s2VecOverMtMt;
784  /* In s1Data and s2Data will store chi_i * m_i^2 in geomtric units */
785  /* In s1DataNorm and s2DataNorm will store chi_i * m_i^2/M^2 */
786  REAL8 s1Data[3] = {0,0,0}, s2Data[3] = {0,0,0},
787  s1DataNorm[3] = {0,0,0}, s2DataNorm[3] = {0,0,0};
788 
789  /* Parameters of the system */
790  REAL8 m1 = 0, m2 = 0, mTotal = 0, eta = 0, mTScaled = 0;
791  REAL8 amp0 = 0;
792 
793  /* Dynamics of the system */
794  REAL8Vector tVec, phiDMod, phiMod;
795  REAL8Vector posVecx, posVecy, posVecz, momVecx, momVecy, momVecz;
796  REAL8Vector s1Vecx, s1Vecy, s1Vecz, s2Vecx, s2Vecy, s2Vecz;
797  REAL8 omega = 0, v = 0, ham = 0;
798 
799  /* OPTV3 BEGIN */
800  posVecx.data = posVecy.data = posVecz.data = phiMod.data = phiDMod.data = tVec.data = NULL;
801  s1Vecx.data = s1Vecy.data = s1Vecz.data = s2Vecx.data = s2Vecy.data = s2Vecz.data = momVecx.data = momVecy.data = momVecz.data = NULL;
802 
803  REAL8Vector posVecxEOMv, posVecyEOMv, posVeczEOMv, tVecEOMv; /* OPTV3: Dynamics for sparse ODE solution */
804  REAL8Vector * posVecxEOM = &posVecxEOMv, * posVecyEOM = &posVecyEOMv, /* OPTV3: Pointers to Dynamics Vectors */
805  * posVeczEOM = &posVeczEOMv, * tVecEOM = &tVecEOMv;
806 
807  posVecxEOMv.data = posVecyEOMv.data = posVeczEOMv.data = tVecEOMv.data = NULL;
808  posVecxEOMv.length = posVecyEOMv.length = posVeczEOMv.length = tVecEOMv.length = 0; /* OPTV3: Initialize to avoid GCC warnings like "‘posVecyEOMv.length’ may be used uninitialized in this function" */
809  /* OPTV3 END */
810 
811  /* Cartesian vectors needed to calculate Hamiltonian */
812  REAL8Vector cartPosVec, cartMomVec;
813  REAL8 cartPosData[3] = {0,0,0}, cartMomData[3] = {0,0,0};
814  REAL8 rcrossrdotNorm = 0, rvec[3] = {0,0,0}, rcrossrdot[3] = {0,0,0};
815  REAL8 pvec[3] = {0,0,0}, rcrossp[3] = {0,0,0};//, rcrosspMag = 0;
816  REAL8 s1dotLN = 0, s2dotLN = 0;
817 
818  /* Polar vectors needed for waveform modes calculation */
819  REAL8Vector polarDynamics;
820  REAL8 polData[4] = {0,0,0,0};
821 
822  /* Signal mode */
823  COMPLEX16 hLM = 0.0 + 0.0*j;
824 
825  /* Non-quasicircular correction */
826  COMPLEX16 hNQC = 0.0 + 0.0*j;
827  EOBNonQCCoeffs nqcCoeffs;
828  memset( &nqcCoeffs, 0, sizeof( nqcCoeffs ) );
829 
830  /* Ringdown freq used to check the sample rate */
831  COMPLEX16Vector modefreqVec;
832  COMPLEX16 modeFreq;
833 
834  /* Spin-weighted spherical harmonics */
835  COMPLEX16 Y22 = 0.0 + 0.0j, Y2m2 = 0.0 + 0.0j, Y21 = 0.0 + 0.0j, Y2m1 = 0.0 + 0.0j;
836  COMPLEX16 Y20 = 0.0 + 0.0j;
837  /* (2,2) and (2,-2) spherical harmonics needed in (h+,hx) */
838 
839  /*Parameters for the portion of the orbit we integrate at high sampling rate*/
840  REAL8 deltaTHigh = 0, resampEstimate = 0;
841  UINT4 resampFac = 0, resampPwr = 0;
842 
843  /* How far will we have to step back to attach the ringdown? */
844  REAL8 tStepBack = 0, HiSRstart = 0;
845  INT4 nStepBack = 0;
846  UINT4 hiSRndx = 0;
847 
848  /* Dynamics and details of the high sample rate part used to attach the
849  * ringdown */
850  REAL8Vector timeHi, phiDModHi, phiModHi;
851  REAL8Vector posVecxHi, posVecyHi, posVeczHi, momVecxHi, momVecyHi, momVeczHi;
852  REAL8Vector s1VecxHi, s1VecyHi, s1VeczHi, s2VecxHi, s2VecyHi, s2VeczHi;
853  REAL8Vector *sigReHi = NULL, *sigImHi = NULL;
854 
855 
856  /* Set up structures and calculate necessary PN parameters */
857  /* SpinEOBParams contains:
858  EOBParams *eobParams; // see below
859  SpinEOBHCoeffs *seobCoeffs; // see below
860  EOBNonQCCoeffs *nqcCoeffs; // see below
861  REAL8Vector *s1Vec; // spin1
862  REAL8Vector *s2Vec; // spin2
863  REAL8Vector *sigmaStar; // Eq. 5.3 of Barausse and Buonanno PRD 81, 084024 (2010)
864  REAL8Vector *sigmaKerr; // Eq. 5.2 of Barausse and Buonanno PRD 81, 084024 (2010)
865  REAL8 a; // |sigmaKerr|
866  REAL8 chi1; // spin1.LNhat/m1^2
867  REAL8 chi2; // spin2.LNhat/m2^2
868  REAL8 prev_dr; // stores dr/dt for stopping condition purposes
869  int alignedSpins; // flag to indicate whther the binary is precessing or not
870  int tortoise; // flag to switch on/off tortoise coordinates when calling Hamiltonian
871  int ignoreflux; // flag to switch off radiation reaction when calling the ODEs via XLALSpinPrecHcapNumericalDerivative or as XLALSpinPrecHcapExactDerivative
872  */
873  SpinEOBParams seobParams;
874  /* SpinEOBHCoeffs contains:
875  double KK; // nonspinning calibration in Hamiltonian (for SEOBNRv2: 1.712 − 1.804eta − 39:77eta^2 + 103.2eta^3)
876  double k0; // Delta_i coefficients in the Delta_u potential Eq. 8 of PRD 86, 024011 (2012) and https://dcc.ligo.org/T1400476
877  double k1;
878  double k2;
879  double k3;
880  double k4;
881  double k5;
882  double k5l;
883  double b3; // omega_{fd}^1 frame dragging parameter in Hamiltonian (unused)
884  double bb3; // omega_{fd}^2 frame dragging parameter in Hamiltonian (unused)
885  double d1; // spin-orbit calibration in Hamiltonian for SEOBNRv1
886  double d1v2; // spin-orbit calibration in Hamiltonian for SEOBNRv1
887  double dheffSS; // spin-spin calibration in Hamiltonian for SEOBNRv1
888  double dheffSSv2; // spin-spin calibration in Hamiltonian for SEOBNRv1
889  UINT4 SpinAlignedEOBversion;
890  int updateHCoeffs;
891  */
892  SpinEOBHCoeffs seobCoeffs;
893  /* EOBParams contains parameters common to nonspin and spin EOBNR models,
894  including mass ratio, masses, pre-computed coefficients for potential, flux and waveforms,
895  NQC coefficients and Newtonian multiple prefixes */
896  EOBParams eobParams;
897  /*FacWaveformCoeffscontaining the coefficients for calculating the factorized waveform.
898  The coefficients are precomputed in the function XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients */
899  FacWaveformCoeffs hCoeffs;
900  /* NewtonMultipolePrefixes contains all the terms of the Newtonian multipole which
901  are constant over the course of the evolution, and can therefore be
902  pre-computed. They are stored in a two-dimensional array, which is
903  indexed as values[l][m]. This is filled by XLALSimIMREOBComputeNewtonMultipolePrefixes */
904  NewtonMultipolePrefixes prefixes;
905 
906  memset( &seobParams, 0, sizeof(seobParams) );
907  memset( &seobCoeffs, 0, sizeof(seobCoeffs) );
908  memset( &eobParams, 0, sizeof(eobParams) );
909  memset( &hCoeffs, 0, sizeof( hCoeffs ) );
910  memset( &prefixes, 0, sizeof( prefixes ) );
911 
912  REAL8TimeSeries *alphaI2PTS = NULL, *betaI2PTS = NULL, *gammaI2PTS = NULL, *alphaP2JTS = NULL, *betaP2JTS = NULL, *gammaP2JTS = NULL;
913  REAL8TimeSeries *alphaI2PTSHi = NULL, *betaI2PTSHi = NULL, *gammaI2PTSHi = NULL, *alphaP2JTSHi = NULL, *betaP2JTSHi = NULL, *gammaP2JTSHi = NULL;
914  COMPLEX16TimeSeries *h22TS = NULL, *h21TS = NULL, *h20TS = NULL, *h2m1TS = NULL, *h2m2TS = NULL;
915  COMPLEX16TimeSeries *h22TSHi = NULL, *h21TSHi = NULL, *h20TSHi = NULL, *h2m1TSHi = NULL, *h2m2TSHi = NULL;
916 
917  COMPLEX16TimeSeries *hIMRJTSHi = NULL;
918  COMPLEX16TimeSeries *h22PTSHi = NULL;
919  COMPLEX16TimeSeries *h21PTSHi = NULL;
920  COMPLEX16TimeSeries *h20PTSHi = NULL;
921  COMPLEX16TimeSeries *h2m1PTSHi = NULL;
922  COMPLEX16TimeSeries *h2m2PTSHi = NULL;
923 
924  COMPLEX16TimeSeries *h22JTSHi = NULL;
925  COMPLEX16TimeSeries *h21JTSHi = NULL;
926  COMPLEX16TimeSeries *h20JTSHi = NULL;
927  COMPLEX16TimeSeries *h2m1JTSHi = NULL;
928  COMPLEX16TimeSeries *h2m2JTSHi = NULL;
929  COMPLEX16TimeSeries *hJTSHi = NULL;
930 
931  COMPLEX16TimeSeries *hIMR22JTSHi = NULL;
932  COMPLEX16TimeSeries *hIMR21JTSHi = NULL;
933  COMPLEX16TimeSeries *hIMR20JTSHi = NULL;
934  COMPLEX16TimeSeries *hIMR2m1JTSHi = NULL;
935  COMPLEX16TimeSeries *hIMR2m2JTSHi = NULL;
936 
937  COMPLEX16TimeSeries *hIMRJTS2mHi = NULL;
938  COMPLEX16TimeSeries *hIMR22ITS = NULL;
939  COMPLEX16TimeSeries *hIMR21ITS = NULL;
940  COMPLEX16TimeSeries *hIMR20ITS = NULL;
941  COMPLEX16TimeSeries *hIMR2m1ITS = NULL;
942  COMPLEX16TimeSeries *hIMR2m2ITS = NULL;
943  REAL8TimeSeries *alpI = NULL, *betI = NULL, *gamI = NULL;
944 
945  COMPLEX16TimeSeries *h22PTS = NULL;
946  COMPLEX16TimeSeries *h21PTS = NULL;
947  COMPLEX16TimeSeries *h20PTS = NULL;
948  COMPLEX16TimeSeries *h2m1PTS = NULL;
949  COMPLEX16TimeSeries *h2m2PTS = NULL;
950 
951  COMPLEX16TimeSeries *h22JTS = NULL;
952  COMPLEX16TimeSeries *h21JTS = NULL;
953  COMPLEX16TimeSeries *h20JTS = NULL;
954  COMPLEX16TimeSeries *h2m1JTS = NULL;
955  COMPLEX16TimeSeries *h2m2JTS = NULL;
956 
957  COMPLEX16TimeSeries *hJTS = NULL;
958 
959  COMPLEX16TimeSeries *hIMR22JTS = NULL;
960  COMPLEX16TimeSeries *hIMR21JTS = NULL;
961  COMPLEX16TimeSeries *hIMR20JTS = NULL;
962  COMPLEX16TimeSeries *hIMR2m1JTS = NULL;
963  COMPLEX16TimeSeries *hIMR2m2JTS = NULL;
964  REAL8TimeSeries *hPlusTS = NULL;
965  REAL8TimeSeries *hCrossTS = NULL;
966  COMPLEX16TimeSeries *hIMRJTS = NULL;
967 
968 
969  /* Miscellaneous memory for Ringdown attachment */
970  REAL8 tPeakOmega = 0, tAttach = 0, combSize = 0,/*longCombSize,*/ deltaNQC =0;
971  REAL8 sh = 0;
972  REAL8 magR = 0, Lx = 0, Ly = 0, Lz = 0, magL = 0, magJ = 0, /* magR not in SEOBNRv3_opt */
973  LNhx = 0, LNhy = 0, LNhz = 0, magLN =0, Jx = 0, Jy = 0, Jz = 0;
974  REAL8 aI2P = 0, bI2P = 0, gI2P = 0; /* These variables not in SEOBNRv3_opt */
975  REAL8 aP2J = 0, bP2J = 0, gP2J = 0;
976  REAL8 chi1J= 0, chi2J= 0, chiJ = 0;
977  REAL8 chi1L= 0.0, chi2L = 0.0, chiL = 0.0;
978  REAL8 kappaJL = 0;
979  REAL8 JLN = 0.0;
980  REAL8 JframeEx[3] = {0,0,0}, JframeEy[3] = {0,0,0}, JframeEz[3] = {0,0,0};
981 
982  /* Variables for the integrator */
983  LALAdaptiveRungeKuttaIntegrator *integrator = NULL;
984  REAL8Array *dynamics = NULL;
985  REAL8Array *dynamicsHi = NULL;
986  REAL8Array *dynamicsV2 = NULL;
987  REAL8Array *dynamicsV2Hi = NULL;
988  REAL8Array *dynamicsEOMLo = NULL; //OPTV3: For Sparse Amp/Phase Calcualtion
989  REAL8Array *dynamicsEOMHi = NULL;
990  INT4 retLenEOMLow = 0, retLenEOMHi = 0;
991  INT4 retLen = 0, retLenLow = 0, retLenHi = 0; /* retLen not used in SEOBNRv3_opt */
992  INT4 retLenRDPatchHi= 0, retLenRDPatchLow = 0;
993 
994 
995  /* Interpolation spline */
996  gsl_spline *spline = NULL;
997  gsl_interp_accel *acc = NULL;
998 
999  /* Accuracies of adaptive Runge-Kutta integrator */
1000  /* Note that this accuracies are lower than those used in SEOBNRv2: they allow reasonable runtimes for precessing systems */
1001  /* These accuracies can be adjusted according to desired accuracy and runtime */
1002  REAL8 EPS_ABS = 1.0e-8;
1003  const REAL8 EPS_REL = 1.0e-8;
1004 
1005  /* Relax abs accuracy in case of highly symmetric case that would otherwise slow down significantly */
1006  if (sqrt((INspin1[0] + INspin2[0])*(INspin1[0] + INspin2[0]) + (INspin1[1] + INspin2[1])*(INspin1[1] + INspin2[1])) < 1.0e-10 && !SpinsAlmostAligned && !use_optimized)
1007  {
1008  if (debugPK) XLAL_PRINT_INFO("EPS_ABS is decreased!\n");
1009  EPS_ABS = 1.0e-4;
1010  }
1011 
1012  /* Memory for the calculation of the alpha(t) and beta(t) angles */
1013  REAL8Vector *Alpha = NULL, *Beta = NULL, *Gamma = NULL;
1014  REAL8Vector *AlphaHi = NULL, *BetaHi = NULL, *GammaHi = NULL;
1015  /* Memory to help with rotation of dynamics */
1016  REAL8 JExnorm = 0;
1017  SphHarmTimeSeries *hlmPTS = NULL;
1018  SphHarmTimeSeries *hIMRlmJTS = NULL;
1019  REAL8Sequence *tlist = NULL;
1020  REAL8Sequence *tlistRDPatch = NULL;
1021 
1022  SphHarmTimeSeries *hlmPTSHi = NULL;
1023  SphHarmTimeSeries *hlmPTSout = NULL;
1024  SphHarmTimeSeries *hIMRlmJTSHi = NULL;
1025 
1026  REAL8Sequence *tlistHi = NULL;
1027  REAL8Sequence *tlistRDPatchHi = NULL;
1028  REAL8Sequence *timeJFull = NULL;
1029  REAL8Sequence *timeIFull = NULL;
1030 
1031  /* Memory for ringdown attachment */
1032  REAL8Vector *rdMatchPoint = XLALCreateREAL8Vector( 3 );
1033  if ( !rdMatchPoint )
1034  {
1035  XLALPrintError("Failed to allocate REAL8Vector rdMatchPoint!\n");
1036  PRINT_PARAMS
1038  }
1039  REAL8 alJtoI = 0, betJtoI = 0, gamJtoI = 0;
1040  SphHarmTimeSeries *hIMRlmITS = NULL;
1041  COMPLEX16 x11 = 0.0 + 0.0j;
1042 
1043  /* *******************************************************************/
1044  /* ********************** Memory Initialization **********************/
1045  /* *******************************************************************/
1046 
1047  /* Initialize mass parameters */
1048  m1 = m1SI / LAL_MSUN_SI;
1049  m2 = m2SI / LAL_MSUN_SI;
1050  mTotal = m1 + m2;
1051  mTScaled = mTotal * LAL_MTSUN_SI;
1052  eta = m1 * m2 / (mTotal*mTotal);
1053 
1054  if (eta > 0.25){
1055  m2=m1;
1056  eta = 0.25;
1057  }
1058 
1059  /* Initialize amplitude scaling parameter */
1060  amp0 = mTotal * LAL_MRSUN_SI / r;
1061 
1062  /**
1063  * OPTV3: Define the SpinEOBH coefficients constants of Hamiltonian spin
1064  * derivative calculation.
1065  */
1066  SEOBHCoeffConstants seobCoeffConsts;
1067  if(use_optimized) seobCoeffConsts = XLALEOBSpinPrecCalcSEOBHCoeffConstants(eta);
1068 
1069  if (debugPK) {
1070  XLAL_PRINT_INFO("Stas, here is the passes functions\n");
1071  XLAL_PRINT_INFO("Inputs: m1 = %.16e, m2 = %.16e, fMin = %.16e, inclination = %.16e\n",
1072  m1, m2, (double) fMin, (double) inc );
1073  XLAL_PRINT_INFO("Mtotal = %.16e, eta = %.16e \n", mTotal, eta);
1074  XLAL_PRINT_INFO("Inputs: spin1 = {%.16e, %.16e, %.16e}\n",
1075  spin1[0], spin1[1], spin1[2]);
1076  XLAL_PRINT_INFO("Inputs: spin2 = {%.16e, %.16e, %.16e}\n",
1077  spin2[0], spin2[1], spin2[2]);
1078  }
1079 
1080  /* Calculate the time we will need to step back for ringdown */
1081  /* Stepping back 150M in time is very conservative: the attachment point usually lies in the last 20M of the trajectory */
1082  tStepBack = 150. * mTScaled;
1083  nStepBack = ceil( tStepBack / deltaT );
1084 
1085  /* Calculate the resample factor for attaching the ringdown */
1086  /* We want it to be a power of 2 */
1087  /* If deltaT > Mtot/50, reduce deltaT by the smallest power of two for which*/
1088  /* deltaT < Mtot/50 */
1089  resampEstimate = 50. * deltaT / mTScaled;
1090  resampFac = 1;
1091  if ( resampEstimate > 1. ) {
1092  resampPwr = (UINT4)ceil( log2( resampEstimate ) );
1093  while( resampPwr-- ) { resampFac *= 2u; }
1094  }
1095 
1096  /* Wrapper spin vectors used to calculate sigmas */
1097  /* Note: spin{1,2} have INspin{1,2} (\chi vectors) at this point */
1098  s1Vec.length = s2Vec.length = 3;
1099  s1Vec.data = s1Data;
1100  s2Vec.data = s2Data;
1101 
1102  s1VecOverMtMt.length = s2VecOverMtMt.length = 3;
1103  s1VecOverMtMt.data = s1DataNorm;
1104  s2VecOverMtMt.data = s2DataNorm;
1105 
1106  for( i = 0; i < 3; i++ )
1107  {
1108  s1Vec.data[i] = mSpin1[i] = spin1[i] * m1 * m1;
1109  s2Vec.data[i] = mSpin2[i] = spin2[i] * m2 * m2;
1110  s1VecOverMtMt.data[i] = s1Vec.data[i] / mTotal / mTotal;
1111  s2VecOverMtMt.data[i] = s2Vec.data[i] / mTotal / mTotal;
1112  }
1113 
1114  if (debugPK){
1115  XLAL_PRINT_INFO("Stas, here is the passes functions\n");
1116  XLAL_PRINT_INFO("Inputs: m1 = %.16e, m2 = %.16e, fMin = %.16e, inclination = %.16e\n",
1117  m1, m2, (double) fMin, (double) inc );
1118  XLAL_PRINT_INFO("Inputs: spin1 = {%.16e, %.16e, %.16e}\n",
1119  spin1[0], spin1[1], spin1[2]);
1120  XLAL_PRINT_INFO("Inputs: spin2 = {%.16e, %.16e, %.16e}\n",
1121  spin2[0], spin2[1], spin2[2]);
1122  XLAL_PRINT_INFO("Inputs: s1V = {%.16e, %.16e, %.16e}\n",
1123  s1Vec.data[0], s1Vec.data[1], s1Vec.data[2]);
1124  XLAL_PRINT_INFO("Inputs: s2V = {%.16e, %.16e, %.16e}\n",
1125  s2Vec.data[0], s2Vec.data[1], s2Vec.data[2]);
1126  }
1127 
1128 /* *********************************************************************************
1129  * *********************************************************************************
1130  * STEP 0) Prepare parameters, including pre-computed coefficients
1131  * for EOB Hamiltonian, flux and waveform
1132  * *********************************************************************************
1133  * ********************************************************************************* */
1134  /* ************************************************* */
1135  /* Populate the initial structures */
1136  /* ************************************************* */
1137  /* Spin parameters */
1139  sigmaStar, m1, m2, &s1Vec, &s2Vec ) == XLAL_FAILURE )
1140  {
1141  XLALDestroyREAL8Vector( sigmaKerr );
1142  XLALDestroyREAL8Vector( sigmaStar );
1143  XLALDestroyREAL8Vector( values );
1144  XLALDestroyREAL8Vector( dvalues );
1145  XLALDestroyREAL8Vector( rdMatchPoint );
1146  XLALPrintError("XLALSimIMRSpinEOBCalculateSigmaStar failed!\n");
1147  PRINT_PARAMS
1148  XLAL_ERROR( XLAL_EDOM );
1149  }
1151  sigmaKerr, m1, m2, &s1Vec, &s2Vec ) == XLAL_FAILURE )
1152  {
1153  XLALDestroyREAL8Vector( sigmaKerr );
1154  XLALDestroyREAL8Vector( sigmaStar );
1155  XLALDestroyREAL8Vector( values );
1156  XLALDestroyREAL8Vector( dvalues );
1157  XLALDestroyREAL8Vector( rdMatchPoint );
1158  XLALPrintError("XLALSimIMRSpinEOBCalculateSigmaKerr failed!\n");
1159  PRINT_PARAMS
1160  XLAL_ERROR( XLAL_EDOM );
1161  }
1162 
1163  if (use_optimized) {
1164  seobParams.seobApproximant = SEOBNRv3_opt;
1165  }
1166  /* Calculate the value of a, that is magnitude of Eq. 31 in PRD 86, 024011 (2012) */
1167  seobParams.a = a = sqrt( inner_product(sigmaKerr->data, sigmaKerr->data) );
1168  seobParams.s1Vec = &s1VecOverMtMt;
1169  seobParams.s2Vec = &s2VecOverMtMt;
1170 
1171  if (debugPK){
1172  XLAL_PRINT_INFO("Inputs: sigma = {%.16e, %.16e, %.16e}\n",
1173  sigmaKerr->data[0], sigmaKerr->data[1], sigmaKerr->data[2]);
1174  XLAL_PRINT_INFO("Inputs: star = {%.16e, %.16e, %.16e}\n",
1175  sigmaStar->data[0], sigmaStar->data[1], sigmaStar->data[2]);
1176  XLAL_PRINT_INFO("Inputs: a = %.16e\n", a);
1177  fflush(NULL);
1178  }
1179 
1180  if ( !(AttachParams = XLALCreateREAL8Vector( 5 )) )
1181  {
1182  XLALDestroyREAL8Vector( sigmaKerr );
1183  XLALDestroyREAL8Vector( sigmaStar );
1184  XLALDestroyREAL8Vector( values );
1185  XLALDestroyREAL8Vector( dvalues );
1186  XLALDestroyREAL8Vector( rdMatchPoint );
1187  XLALPrintError("Failed to allocate REAL8Vector AttachParams!\n");
1188  PRINT_PARAMS
1190  }
1191  *AttachPars = AttachParams;
1192 
1193  /* Cartesian vectors needed to calculate Hamiltonian */
1194  if (!use_optimized) {
1195  cartPosVec.length = cartMomVec.length = 3;
1196  cartPosVec.data = cartPosData;
1197  cartMomVec.data = cartMomData;
1198  memset( cartPosData, 0, sizeof( cartPosData ) );
1199  memset( cartMomData, 0, sizeof( cartMomData ) );
1200  }
1201 
1202  /* ************************************************* */
1203  /* Waveform parameter structures */
1204  /* ************************************************* */
1205  /* Spin-EOB parameters */
1206  seobParams.alignedSpins = 0;
1207  seobParams.tortoise = 1;
1208  seobParams.ignoreflux = 0;
1209  seobParams.sigmaStar = sigmaStar;
1210  seobParams.sigmaKerr = sigmaKerr;
1211  seobParams.seobCoeffs = &seobCoeffs;
1212  if(use_optimized){ seobParams.seobCoeffConsts = &seobCoeffConsts; }
1213  seobParams.eobParams = &eobParams;
1214  seobParams.nqcCoeffs = &nqcCoeffs;
1215  /* Non-Spin-EOB parameters */
1216  eobParams.hCoeffs = &hCoeffs;
1217  eobParams.prefixes = &prefixes;
1218  seobCoeffs.SpinAlignedEOBversion = SpinAlignedEOBversion;
1219  eobParams.m1 = m1;
1220  eobParams.m2 = m2;
1221  eobParams.eta = eta;
1222 
1223  TidalEOBParams tidal1, tidal2;
1224  tidal1.mByM = m1SI / (m1SI + m2SI);
1225  tidal1.lambda2Tidal = 0.;
1226  tidal1.omega02Tidal = 0.;
1227  tidal1.lambda3Tidal = 0.;
1228  tidal1.omega03Tidal = 0.;
1229 
1230  tidal2.mByM = m2SI / (m1SI + m2SI);
1231  tidal2.lambda2Tidal = 0.;
1232  tidal2.omega02Tidal = 0.;
1233  tidal2.lambda3Tidal = 0.;
1234  tidal2.omega03Tidal = 0.;
1235 
1236  seobCoeffs.tidal1 = &tidal1;
1237  seobCoeffs.tidal2 = &tidal2;
1238 
1239  hCoeffs.tidal1 = &tidal1;
1240  hCoeffs.tidal2 = &tidal2;
1241 
1242  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs( &seobCoeffs, eta, a,
1243  SpinAlignedEOBversion ) == XLAL_FAILURE ) /* This function returns XLAL_SUCCESS or calls XLAL_ERROR( XLAL_EINVAL ) */
1244  {
1245  XLALDestroyREAL8Vector( sigmaKerr );
1246  XLALDestroyREAL8Vector( sigmaStar );
1247  XLALDestroyREAL8Vector( values );
1248  XLALDestroyREAL8Vector( dvalues );
1249  XLALDestroyREAL8Vector( rdMatchPoint );
1250  XLALPrintError("XLALSimIMRCalculateSpinPrecEOBHCoeffs failed!\n");
1251  PRINT_PARAMS
1253  }
1254 
1255  /* Pre-compute the coefficients for the Newtonian factor of hLM
1256  Eq. A1 of PRD 86, 024011 (2012) */
1257  if ( XLALSimIMREOBComputeNewtonMultipolePrefixes( &prefixes, eobParams.m1,
1258  eobParams.m2 ) == XLAL_FAILURE )
1259  {
1260  XLALDestroyREAL8Vector( sigmaKerr );
1261  XLALDestroyREAL8Vector( sigmaStar );
1262  XLALDestroyREAL8Vector( values );
1263  XLALDestroyREAL8Vector( dvalues );
1264  XLALDestroyREAL8Vector( rdMatchPoint );
1265  XLALPrintError("XLALSimIMREOBComputeNewtonMultipolePrefixes failed!\n");
1266  PRINT_PARAMS
1267  XLAL_ERROR( XLAL_EDOM );
1268  }
1269 
1270 /* *********************************************************************************
1271  * *********************************************************************************
1272  * STEP 1) Solve for initial conditions, according to Sec. IV A of
1273  * PRD 74, 104005 (2006)
1274  * *********************************************************************************
1275  * ********************************************************************************* */
1276  if( debugPK )
1277  {
1278  XLAL_PRINT_INFO("Calling the XLALSimIMRSpinEOBInitialConditionsPrec function!\n");
1280  "Inputs: m1 = %.16e, m2 = %.16e, fMin = %.16e, inclination = %.16e\n",
1281  m1, m2, (double) fMin, (double) inc );
1282  XLAL_PRINT_INFO("Inputs: mSpin1 = {%.16e, %.16e, %.16e}\n",
1283  mSpin1[0], mSpin1[1], mSpin1[2]);
1284  XLAL_PRINT_INFO("Inputs: mSpin2 = {%.16e, %.16e, %.16e}\n",
1285  mSpin2[0], mSpin2[1], mSpin2[2]);
1286  fflush(NULL);
1287  }
1288 
1289  //values = XLALCreateREAL8Vector( 14 );
1290  REAL8 incl_temp = 0.0; // !!!! For comparison with C++ and NR we need inc = 0 for initial conditions
1291 
1292  //incl_temp = inc; //FIXME
1293  /* The initial condition construction is based on PRD 74, 104005 (2006) */
1294  /* If the initial spin opening angles are small, then use SEOBNRv2 (aligned-spin) dyamics */
1295  int failure_flag=0;
1296  if ( SpinsAlmostAligned ) {
1297  seobParams.alignedSpins = 1;
1298  seobParams.chi1 = copysign( spin1Norm, cos(theta1Ini) );
1299  seobParams.chi2 = copysign( spin2Norm, cos(theta2Ini) );
1300  chiS = 0.5*(seobParams.chi1 + seobParams.chi2);
1301  chiA = 0.5*(seobParams.chi1 - seobParams.chi2);
1302  tplspin = (1.-2.*eta) * chiS + (m1 - m2)/(m1 + m2) * chiA;
1303  if ( XLALSimIMREOBCalcSpinFacWaveformCoefficients( seobParams.eobParams->hCoeffs, &seobParams, m1, m2, eta, tplspin, chiS, chiA, SpinAlignedEOBversion ) == XLAL_FAILURE ) /* This function returns XLAL_SUCCESS or calls XLAL_ERROR( XLAL_EINVAL ) */
1304  {
1305  failure_flag = 1;
1306  XLALPrintError("XLALSimIMREOBCalcSpinFacWaveformCoefficients failed!\n");
1307  }
1308 
1309  if ( XLALSimIMRSpinEOBInitialConditions( values, m1, m2, fMin, incA, mSpin1, mSpin2, &seobParams, use_optimized ) == XLAL_FAILURE ) /* This function returns XLAL_SUCCESS or calls XLAL_ERROR with XLAL_EINVAL, XLAL_ENOMEM, or XLAL_EMAXITER */
1310  {
1311  failure_flag = 1;
1312  XLALPrintError("XLALSimIMRSpinEOBInitialConditions failed!\n");
1313  }
1314  seobParams.alignedSpins = 0;
1315  }
1316  else {
1317  /* This function returns XLAL_SUCCESS or calls XLAL_ERROR with XLAL_EINVAL, XLAL_ENOMEM, or XLAL_EMAXITER */
1318  if ( XLALSimIMRSpinEOBInitialConditionsPrec( values, m1, m2, fMin, incl_temp, mSpin1, mSpin2, &seobParams, use_optimized ) == XLAL_FAILURE )
1319  {
1320  failure_flag = 1;
1321  XLALPrintError("XLALSimIMRSpinEOBInitialConditionsPrec failed!\n");
1322  }
1323 
1324  if(failure_flag){
1325  XLALDestroyREAL8Vector( sigmaKerr );
1326  XLALDestroyREAL8Vector( sigmaStar );
1327  XLALDestroyREAL8Vector( values );
1328  XLALDestroyREAL8Vector( dvalues );
1329  XLALDestroyREAL8Vector( rdMatchPoint );
1330  PRINT_PARAMS
1332  }
1333  }
1334  /* Initial phases */
1335  values->data[12] = 0.;
1336  values->data[13] = 0.;
1337 
1338  if(debugCustomIC) {
1339  /* Hardcode initial conditions for debugging purposes here */
1340  values->data[0]= 15.4898001256;
1341  values->data[1]= 0.;
1342  values->data[2]= -4.272074867808132e-19;
1343  values->data[3]= -0.0009339635043526475;
1344  values->data[4]= 0.2802596444562164;
1345  values->data[5]= -0.0001262371378125648;
1346  values->data[6]= 0.03950299224160406;
1347  values->data[7]= 0.1033495061350166;
1348  values->data[8]= 0.02382287037711037;
1349  values->data[9]= 0.07463668902857602;
1350  values->data[10]= 0.001769731591445356;
1351  values->data[11]= 0.04303525354405329;
1352  }
1353 
1354  if(debugPK)
1355  {
1356  XLAL_PRINT_INFO("Setting up initial conditions, returned values are:\n");
1357  for( j=0; j < values->length; j++)
1358  XLAL_PRINT_INFO("%.16le\n", values->data[j]);
1359  }
1360 
1361  if(debugPK)XLAL_PRINT_INFO("\nReached the point where LN is to be calculated\n");
1362 
1363  memset( dvalues->data, 0, 14 * sizeof(REAL8) );
1364  failure_flag = 0;
1365  if (use_optimized) failure_flag = XLALSpinPrecHcapRvecDerivative_exact( 0, values->data, dvalues->data, (void*) &seobParams);
1366  else failure_flag = XLALSpinPrecHcapRvecDerivative( 0, values->data, dvalues->data, (void*) &seobParams);
1367  if(failure_flag == XLAL_FAILURE )
1368  {
1369  XLALDestroyREAL8Vector( sigmaKerr );
1370  XLALDestroyREAL8Vector( sigmaStar );
1371  XLALDestroyREAL8Vector( values );
1372  XLALDestroyREAL8Vector( dvalues );
1373  XLALDestroyREAL8Vector( rdMatchPoint );
1374  XLALPrintError("XLALSpinPrecHcapRvecDerivative failed!\n");
1375  PRINT_PARAMS
1376  XLAL_ERROR( XLAL_EDOM );
1377  }
1378 
1379  if(debugPK)XLAL_PRINT_INFO("\nCalculated Rdot\n");
1380 
1381  /* Calculate r cross rDot */
1382  memcpy( rdotvec, dvalues->data, 3*sizeof(REAL8) );
1383  memcpy( rvec, values->data, 3*sizeof(REAL8) );
1384  memcpy( pvec, values->data+3,3*sizeof(REAL8) );
1385 
1386  cross_product( rvec, rdotvec, rcrossrdot );
1387  rcrossrdotNorm = sqrt(inner_product( rcrossrdot, rcrossrdot ));
1388  for( i = 0; i < 3; i++ ) { rcrossrdot[i] /= rcrossrdotNorm; }
1389 
1390 /* Calculate the values of chiS and chiA, as given in Eq. 17 of
1391  * PRD 89, 084006 (2014) */
1392  s1dotLN = inner_product( spin1, rcrossrdot );
1393  s2dotLN = inner_product( spin2, rcrossrdot );
1394 
1395 ///* An alternative is to project the spins onto L = rXp */
1396 // cross_product( rvec, pvec, rcrossp );
1397 // rcrosspMag = sqrt(inner_product(rcrossp, rcrossp));
1398 // for( i = 0; i < 3; i++ ) { rcrossp[i] /= rcrosspMag; }
1399 //
1400 // s1dotL = inner_product( spin1, rcrossrdot );
1401 // s2dotL = inner_product( spin2, rcrossrdot );
1402 
1403  if(debugPK) {
1404  XLAL_PRINT_INFO("rXp = %3.10f %3.10f %3.10f\n", rcrossp[0], rcrossp[1], rcrossp[2]);
1405  XLAL_PRINT_INFO("rXrdot = %3.10f %3.10f %3.10f\n", rcrossrdot[0], rcrossrdot[1], rcrossrdot[2]);
1406  fflush(NULL);
1407  }
1408 
1409  chiS = 0.5 * (s1dotLN + s2dotLN);
1410  chiA = 0.5 * (s1dotLN - s2dotLN);
1411 
1412  /* Compute the test-particle limit spin of the deformed-Kerr background: (S1+S2).LNhat/Mtot^2 */
1413  switch ( SpinAlignedEOBversion )
1414  {
1415  case 1:
1416  /* See below Eq. 17 of PRD 86, 041011 (2012) */
1417  tplspin = 0.0;
1418  break;
1419  case 2:
1420  /* See below Eq. 4 of PRD 89, 061502(R) (2014)*/
1421  tplspin = (1.-2.*eta) * chiS + (m1 - m2)/(m1 + m2) * chiA;
1422  break;
1423  default:
1424  XLALPrintError( "XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1 and v2 are available.\n", __func__);
1425  XLALDestroyREAL8Vector( sigmaKerr );
1426  XLALDestroyREAL8Vector( sigmaStar );
1427  XLALDestroyREAL8Vector( values );
1428  XLALDestroyREAL8Vector( dvalues );
1429  XLALDestroyREAL8Vector( rdMatchPoint );
1430  PRINT_PARAMS
1432  break;
1433  }
1434 
1435  /* ************************************************* */
1436  /* Populate the Waveform initial structures */
1437  /* ************************************************* */
1438  /* Pre-compute the non-spinning and spinning coefficients for hLM factors */
1439  if( debugPK ) {
1440  XLAL_PRINT_INFO("tplspin = %.12e, chiS = %.12e, chiA = %.12e\n", tplspin, chiS, chiA);
1441  fflush(NULL);
1442  }
1443 
1444  if ( XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients( eobParams.hCoeffs, m1, m2, eta,
1445  tplspin, chiS, chiA, 3 ) == XLAL_FAILURE ) /* This function returns XLAL_SUCCESS or calls XLAL_ERROR( XLAL_EINVAL ) */
1446  {
1447  XLALDestroyREAL8Vector( sigmaKerr );
1448  XLALDestroyREAL8Vector( sigmaStar );
1449  XLALDestroyREAL8Vector( values );
1450  XLALDestroyREAL8Vector( dvalues );
1451  XLALDestroyREAL8Vector( rdMatchPoint );
1452  XLALPrintError("XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients failed!\n");
1453  PRINT_PARAMS
1455  }
1456 
1457  /* ************************************************* */
1458  /* Compute the coefficients for the NQC Corrections */
1459  /* ************************************************* */
1460  /* See below Eq. 4 of PRD 89, 061502(R) (2014)*/
1461  spinNQC = (1.-2.*eta) * chiS + (m1 - m2)/(m1 + m2) * chiA;
1462 
1463  /* Check if initial frequency is too high: we choose an initial minimum separation
1464  * of 10M as a compromise between reliability of initial conditions and length
1465  * of the waveform */
1466  REAL8 NRPeakOmega22 = XLALSimIMREOBGetNRSpinPeakOmegav2(2, 2, eta, spinNQC) / mTScaled;
1467  REAL8 freqMinRad = pow(10.0, -1.5)/(LAL_PI*mTScaled);
1468  REAL8 signOfa = copysign(1., spinNQC);
1469  REAL8 spn2 = spinNQC*spinNQC;
1470  /* Kerr ISCO radius from Eq. 2.21 of Astrophysical Journal, Vol. 178, pp. 347-370 (1972) */
1471  REAL8 Z1 = 1.0 + pow(1.0 - spn2, 1./3.)*(pow(1.0+spinNQC, 1./3.) + pow(1.0-spinNQC, 1./3.) );
1472  REAL8 Z2 = sqrt(3.0*spn2 + Z1*Z1);
1473  REAL8 rISCO = 3.0 + Z2 - signOfa*sqrt( (3.-Z1)*(3.+Z1 + 2.*Z2));
1474  REAL8 fISCO = pow(rISCO, -1.5)/(LAL_PI*mTScaled);
1475 
1476  if (debugPK){
1477  XLAL_PRINT_INFO("Stas - spin = %4.10f \n", spinNQC);
1478  XLAL_PRINT_INFO("Stas - NRPeakOmega22 = %4.10f, %4.10f \n", XLALSimIMREOBGetNRSpinPeakOmegav2(2, 2, eta, spinNQC) / mTotal, XLALSimIMREOBGetNRSpinPeakOmegav2(2, 2, eta, spinNQC));
1479  XLAL_PRINT_INFO("Stas ---- check for fmin NRPeakOmega22 = %4.10f, freqMinRad = %4.10f \n", NRPeakOmega22, freqMinRad);
1480  XLAL_PRINT_INFO("Stas -- minf freq is min( %4.10f, %4.10f )\n", NRPeakOmega22*0.1, freqMinRad);
1481  XLAL_PRINT_INFO("Stas -- initial radius (apr) %4.10f \n", pow(LAL_PI*fMin*mTScaled,-2./3.) );
1482  XLAL_PRINT_INFO("Stas -- omega_orb_0 = %4.10f \n", rcrossrdotNorm/inner_product( rvec, rvec )/mTScaled);
1483  XLAL_PRINT_INFO("Stas -- rISCO = %4.10f , freq_ISCO = %4.10f \n", rISCO, fISCO);
1484 
1485  }
1486 
1487  /* Check if initial frequency is too high: we choose an initial minimum separation
1488  * of 10M as a compromise between reliability of initial conditions ans length
1489  * of the waveform. We use Newtonian Kepler's law */
1490  if (pow(LAL_PI*fMin*mTScaled,-2./3.) < 10.0)
1491  {
1492  XLAL_PRINT_WARNING("Waveform generation may fail due to high starting frequency. The starting frequency corresponds to a small initial radius of %.2fM. We recommend a lower starting frequency that corresponds to an estimated starting radius > 10M.", pow(LAL_PI*fMin*mTScaled,-2.0/3.0));
1493  }
1494  if (fMin > freqMinRad){
1495  XLALPrintError("XLAL Error - %s: Intitial frequency is too high, the limit is %4.10f \n", __func__, freqMinRad);
1496  XLALDestroyREAL8Vector( sigmaKerr );
1497  XLALDestroyREAL8Vector( sigmaStar );
1498  XLALDestroyREAL8Vector( values );
1499  XLALDestroyREAL8Vector( dvalues );
1500  XLALDestroyREAL8Vector( rdMatchPoint );
1501  PRINT_PARAMS
1502  XLAL_ERROR (XLAL_EDOM );
1503  }
1504 
1505  switch ( SpinAlignedEOBversion )
1506  {
1507  case 1:
1508  if(debugPK)XLAL_PRINT_INFO("\t NQC: spin used = %.12e\n", spinNQC);
1509  XLALSimIMRGetEOBCalibratedSpinNQC( &nqcCoeffs, 2, 2, eta, spinNQC );
1510  break;
1511  case 2:
1512  if(debugPK)XLAL_PRINT_INFO("\t NQC: spins used = %.12e, %.12e\n", spinNQC, chiA);
1513  XLALSimIMRGetEOBCalibratedSpinNQC3D( &nqcCoeffs, 2, 2, m1, m2, spinNQC, chiA );
1514  break;
1515  default:
1516  XLALPrintError( "XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1 and v2 are available.\n", __func__);
1517  XLALDestroyREAL8Vector( sigmaKerr );
1518  XLALDestroyREAL8Vector( sigmaStar );
1519  XLALDestroyREAL8Vector( values );
1520  XLALDestroyREAL8Vector( dvalues );
1521  XLALDestroyREAL8Vector( rdMatchPoint );
1522  PRINT_PARAMS
1524  break;
1525  }
1526 
1527  /* NQC coeffs can be put to zero for debugging here */
1528  if (debugNoNQC) {
1529  nqcCoeffs.a1 = nqcCoeffs.a2 = nqcCoeffs.a3 = nqcCoeffs.a3S = nqcCoeffs.a4 =
1530  nqcCoeffs.a5 = nqcCoeffs.b1 = nqcCoeffs.b2 = nqcCoeffs.b3 = nqcCoeffs.b4 =
1531  0;
1532  }
1533 
1534  if ( debugPK )
1535  {
1536  /* Print out all NQC coefficients */
1537  XLAL_PRINT_INFO(" NQC: a1 = %.16e, a2 = %.16e,\n a3 = %.16e, a3S = %.16e,\n a4 = %.16e, a5 = %.16e\n b1 = %.16e, b2 = %.16e,\n b3 = %.16e, b4 = %.16e\n",
1538  nqcCoeffs.a1, nqcCoeffs.a2, nqcCoeffs.a3,
1539  nqcCoeffs.a3S, nqcCoeffs.a4, nqcCoeffs.a5,
1540  nqcCoeffs.b1, nqcCoeffs.b2, nqcCoeffs.b3, nqcCoeffs.b4 );
1541 
1542  /* Print out all mass parameters */
1543  XLAL_PRINT_INFO("m1SI = %lf, m2SI = %lf, m1 = %lf, m2 = %lf\n",
1544  (double) m1SI, (double) m2SI, (double) m1, (double) m2 );
1545  XLAL_PRINT_INFO("mTotal = %lf, mTScaled = %lf, eta = %lf\n",
1546  (double) mTotal, (double) mTScaled, (double) eta );
1547  /* Print out all spin parameters */
1548  XLAL_PRINT_INFO("spin1 = {%lf,%lf,%lf}, spin2 = {%lf,%lf,%lf}\n",
1549  (double) spin1[0], (double) spin1[1], (double) spin1[2],
1550  (double) spin2[0], (double) spin2[1], (double) spin2[2]);
1551  XLAL_PRINT_INFO("mSpin1 = {%lf,%lf,%lf}, mSpin2 = {%lf,%lf,%lf}\n",
1552  (double) mSpin1[0], (double) mSpin1[1], (double) mSpin1[2],
1553  (double) mSpin2[0], (double) mSpin2[1], (double) mSpin2[2]);
1554 
1555  XLAL_PRINT_INFO("sigmaStar = {%lf,%lf,%lf}, sigmaKerr = {%lf,%lf,%lf}\n",
1556  (double) sigmaStar->data[0], (double) sigmaStar->data[1],
1557  (double) sigmaStar->data[2], (double) sigmaKerr->data[0],
1558  (double) sigmaKerr->data[1], (double) sigmaKerr->data[2]);
1559  XLAL_PRINT_INFO("a = %lf, tplspin = %lf, chiS = %lf, chiA = %lf\n",
1560  (double) a, (double) tplspin, (double) chiS, (double) chiA);
1561  XLAL_PRINT_INFO("s1Vec = {%lf,%lf,%lf}, s2Vec = {%lf,%lf,%lf}\n",
1562  (double) seobParams.s1Vec->data[0], (double) seobParams.s1Vec->data[1],
1563  (double) seobParams.s1Vec->data[2], (double) seobParams.s2Vec->data[0],
1564  (double) seobParams.s2Vec->data[1], (double) seobParams.s2Vec->data[2]);
1565  XLAL_PRINT_INFO("a is used to compute Hamiltonian coefficients,\n tplspin and chiS and chiA for the multipole coefficients\n");
1566 
1567  XLAL_PRINT_INFO("s1VecOverM = {%.12e,%.12e,%.12e}\n", (double) s1VecOverMtMt.data[0],
1568  (double) s1VecOverMtMt.data[1], (double) s1VecOverMtMt.data[2]);
1569  XLAL_PRINT_INFO("s2VecOverM = {%.12e,%.12e,%.12e}\n", (double) s2VecOverMtMt.data[0],
1570  (double) s2VecOverMtMt.data[1], (double) s2VecOverMtMt.data[2]);
1571 
1572  double StasS1 = sqrt(spin1[0]*spin1[0] + spin1[1]*spin1[1] +spin1[2]*spin1[2]);
1573  double StasS2 = sqrt(spin2[0]*spin2[0] + spin2[1]*spin2[1] +spin2[2]*spin2[2]);
1574  XLAL_PRINT_INFO("Stas: amplitude of spin1 = %.16e, amplitude of spin2 = %.16e, theta1 = %.16e , theta2 = %.16e, phi1 = %.16e, phi2 = %.16e \n",
1575  StasS1, StasS2, acos(spin1[2]/StasS1)/LAL_PI, acos(spin2[2]/StasS2)/LAL_PI,
1576  atan2(spin1[1], spin1[0])/LAL_PI, atan2(spin2[1], spin2[0])/LAL_PI );
1577  fflush(NULL);
1578  }
1579 
1580 /* *********************************************************************************
1581  * *********************************************************************************
1582  * STEP 2) Evolve EOB trajectory both at low and high sampling rate
1583  * *********************************************************************************
1584  * ********************************************************************************* */
1585  /* Low Sampling-rate integration */
1586  /* Initialize the GSL integrator */
1587  REAL8Vector *valuesV2 = NULL;
1588  if ( !(valuesV2 = XLALCreateREAL8Vector( 4 )) )
1589  {
1590  XLALDestroyREAL8Vector( sigmaKerr );
1591  XLALDestroyREAL8Vector( sigmaStar );
1592  XLALDestroyREAL8Vector( values );
1593  XLALDestroyREAL8Vector( dvalues );
1594  XLALDestroyREAL8Vector( rdMatchPoint );
1595  XLALPrintError("Failed to allocate REAL8Vector valuesV2!\n");
1596  PRINT_PARAMS
1598  }
1599  memset( valuesV2->data, 0, valuesV2->length * sizeof( REAL8 ));
1600  const INT8 v3_Hamiltonian_variables = 14; /* Number of variables in v3 Hamiltonian. */
1601  /* If spins are almost aligned with LNhat, use SEOBNRv2 dynamics */
1602  if ( SpinsAlmostAligned ) {
1603  /* In SEOBNRv2 the dynamical variables are r, phi, p_r^*, p_phi */
1604  valuesV2->data[0] = values->data[0];
1605  valuesV2->data[1] = 0.;
1606  valuesV2->data[2] = values->data[3];
1607  valuesV2->data[3] = values->data[0] * values->data[4];
1608 
1609  seobParams.alignedSpins = 1;
1610  seobParams.chi1 = spin1Norm*copysign(1., cos(theta1Ini));
1611  seobParams.chi2 = spin2Norm*copysign(1., cos(theta2Ini));
1612 
1614 
1615  seobParams.alignedSpins = 0;
1616  } else {
1617  if (use_optimized && PrecEOBversion == 300) {
1619  } else if (use_optimized && PrecEOBversion == 304) {
1620  integrator = XLALAdaptiveRungeKutta4Init(v3_Hamiltonian_variables, XLALSpinPrecHcapExactDerivative, XLALEOBSpinPrecStopConditionBasedOnPR, EPS_ABS, EPS_REL);
1621  } else {
1622  integrator = XLALAdaptiveRungeKutta4Init(v3_Hamiltonian_variables, XLALSpinPrecHcapNumericalDerivative, XLALEOBSpinPrecStopConditionBasedOnPR, EPS_ABS, EPS_REL);
1623  }
1624  }
1625 
1626  if (!integrator){
1627  XLALDestroyREAL8Vector( sigmaKerr );
1628  XLALDestroyREAL8Vector( sigmaStar );
1629  XLALDestroyREAL8Vector( values );
1630  XLALDestroyREAL8Vector( dvalues );
1631  XLALDestroyREAL8Vector( rdMatchPoint );
1632  XLALDestroyREAL8Vector( valuesV2 );
1633  XLALPrintError("XLALAdaptiveRungeKutta4Init failed!\n");
1634  PRINT_PARAMS
1635  XLAL_ERROR( XLAL_EDOM );
1636  }
1637 
1638  /* Ensure that integration stops ONLY when the stopping condition is True */
1639  integrator->stopontestonly = 1;
1640  /* When this option is set to 0, the integration can be exceeddingly slow for spin-aligned systems */
1641  integrator->retries = 1;
1642 
1643  if( debugPK ){
1644  XLAL_PRINT_INFO("\n r = {%f,%f,%f}\n",
1645  values->data[0], values->data[1], values->data[2]);
1646  fflush(NULL);
1647  }
1648 
1649  if(debugPK) { XLAL_PRINT_INFO("\n\n BEGINNING THE EVOLUTION\n\n"); fflush(NULL); }
1650 
1651  REAL8Vector rVec, phiVec, prVec, pPhiVec;
1652  rVec.length = phiVec.length = prVec.length = pPhiVec.length = 0;
1653  rVec.data = 0; phiVec.data = 0; prVec.data = 0; pPhiVec.data = 0;
1654  /* Call the integrator */
1655  /* If spins are almost aligned with LNhat, use SEOBNRv2 dynamics */
1656  if ( SpinsAlmostAligned ) {
1657  seobParams.alignedSpins = 1;
1658  seobParams.chi1 = spin1Norm*copysign(1.,cos(theta1Ini));
1659  seobParams.chi2 = spin2Norm*copysign(1.,cos(theta2Ini));
1660 
1661  retLen = XLALAdaptiveRungeKutta4( integrator, &seobParams, valuesV2->data, 0., 20./mTScaled, deltaT/mTScaled, &dynamicsV2 );
1662  retLenLow = retLen;
1663 
1664 
1665  seobParams.alignedSpins = 0;
1666  if ( retLenLow == XLAL_FAILURE )
1667  {
1668  XLALDestroyREAL8Vector( sigmaKerr );
1669  XLALDestroyREAL8Vector( sigmaStar );
1670  XLALDestroyREAL8Vector( values );
1671  XLALDestroyREAL8Vector( dvalues );
1672  XLALDestroyREAL8Vector( rdMatchPoint );
1673  XLALDestroyREAL8Vector( valuesV2 );
1674  if (dynamicsV2 != NULL){
1675  XLALDestroyREAL8Array( dynamicsV2 );
1676  }
1677  XLALPrintError("XLALAdaptiveRungeKutta4 failed!\n");
1678  PRINT_PARAMS
1680  }
1681  tVec.length=rVec.length = phiVec.length = prVec.length = pPhiVec.length = retLenLow;
1682  tVec.data = dynamicsV2->data;
1683  rVec.data = dynamicsV2->data+retLenLow;
1684  phiVec.data = dynamicsV2->data+2*retLenLow;
1685  prVec.data = dynamicsV2->data+3*retLenLow;
1686  pPhiVec.data = dynamicsV2->data+4*retLenLow;
1687  dynamics = XLALCreateREAL8ArrayL( 2, 15, (UINT4)retLenLow );
1688 
1689  for (i = 0; i < retLenLow; i++) {
1690  dynamics->data[i] = tVec.data[i];
1691  dynamics->data[retLenLow + i] = rVec.data[i]*cos(phiVec.data[i]);
1692  dynamics->data[2*retLenLow + i] = rVec.data[i]*sin(phiVec.data[i]);
1693  dynamics->data[3*retLenLow + i] = 0.;
1694  dynamics->data[4*retLenLow + i] = prVec.data[i]*cos(phiVec.data[i]) - pPhiVec.data[i]/rVec.data[i]*sin(phiVec.data[i]);
1695  dynamics->data[5*retLenLow + i] = prVec.data[i]*sin(phiVec.data[i]) + pPhiVec.data[i]/rVec.data[i]*cos(phiVec.data[i]);
1696  dynamics->data[6*retLenLow + i] = 0.;
1697  dynamics->data[7*retLenLow + i] = 0.;
1698  dynamics->data[8*retLenLow + i] = 0.;
1699  dynamics->data[9*retLenLow + i] = spin1[2]*(m1*m1/mTotal/mTotal);
1700  dynamics->data[10*retLenLow + i] = 0.;
1701  dynamics->data[11*retLenLow + i] = 0.;
1702  dynamics->data[12*retLenLow + i] = spin2[2]*(m2*m2/mTotal/mTotal);
1703  dynamics->data[13*retLenLow + i]= phiVec.data[i];
1704  dynamics->data[14*retLenLow + i]= 0.;
1705  }
1706 
1707  } else {
1708  if(use_optimized){
1709  retLenEOMLow = XLALAdaptiveRungeKuttaDenseandSparseOutput(integrator, &seobParams, values->data, 0., 20./mTScaled, deltaT/mTScaled, &dynamicsEOMLo, &dynamics);
1710  if ( retLenEOMLow == XLAL_FAILURE )
1711  {
1712  XLALPrintError("XLALAdaptiveRungeKuttaDenseandSparseOutput failed!\n");
1713  PRINT_PARAMS
1715  }
1716 
1717  retLenLow = (int)(dynamicsEOMLo->data[retLenEOMLow-1] / (deltaT/mTScaled))+ 1;
1718 
1719  posVecxEOMv.length = posVecyEOMv.length = posVeczEOMv.length = tVecEOMv.length = retLenEOMLow;
1720  posVecxEOM->data = dynamicsEOMLo->data+retLenEOMLow;
1721  posVecyEOM->data = dynamicsEOMLo->data+2*retLenEOMLow;
1722  posVeczEOM->data = dynamicsEOMLo->data+3*retLenEOMLow;
1723  tVecEOM->data = dynamicsEOMLo->data;
1724  }else{
1725  retLen = XLALAdaptiveRungeKutta4( integrator, &seobParams, values->data,
1726  0., 20./mTScaled, deltaT/mTScaled, &dynamics );
1727  retLenLow = retLen;
1728  if ( retLenLow == XLAL_FAILURE )
1729  {
1730  XLALPrintError("XLALAdaptiveRungeKutta4 failed!\n");
1731  PRINT_PARAMS
1733  }
1734  }
1735 
1736  tVec.length = retLenLow;
1737  tVec.data = dynamics->data;
1738  }
1739 
1740  if (!use_optimized) {
1741  /* This is common to all un-optimized cases, even when we use SEOBNRv2 dynamics */
1742  posVecx.data = dynamics->data+retLenLow;
1743  posVecy.data = dynamics->data+2*retLenLow;
1744  posVecz.data = dynamics->data+3*retLenLow;
1745  momVecx.data = dynamics->data+4*retLenLow;
1746  momVecy.data = dynamics->data+5*retLenLow;
1747  momVecz.data = dynamics->data+6*retLenLow;
1748  s1Vecx.data = dynamics->data+7*retLenLow;
1749  s1Vecy.data = dynamics->data+8*retLenLow;
1750  s1Vecz.data = dynamics->data+9*retLenLow;
1751  s2Vecx.data = dynamics->data+10*retLenLow;
1752  s2Vecy.data = dynamics->data+11*retLenLow;
1753  s2Vecz.data = dynamics->data+12*retLenLow;
1754  phiDMod.data= dynamics->data+13*retLenLow;
1755  phiMod.data = dynamics->data+14*retLenLow;
1756  }
1757  if(debugPK) { XLAL_PRINT_INFO("\n\n FINISHED THE EVOLUTION\n\n"); fflush(NULL); }
1758 
1759  if (debugPK) {
1760  /* Write the dynamics to file */
1761  out = fopen( "seobDynamics.dat", "w" );
1762  for ( i = 0; i < retLenLow; i++ )
1763  {
1764  //YP: output orbital phase and phase modulation separately, instead of their sum
1765  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
1766  tVec.data[i],
1767  posVecx.data[i], posVecy.data[i], posVecz.data[i],
1768  momVecx.data[i], momVecy.data[i], momVecz.data[i],
1769  s1Vecx.data[i], s1Vecy.data[i], s1Vecz.data[i],
1770  s2Vecx.data[i], s2Vecy.data[i], s2Vecz.data[i],
1771  phiDMod.data[i], phiMod.data[i] );
1772  }
1773  fclose( out );
1774 
1775  XLAL_PRINT_INFO("AT We are here %d %d\n",retLenLow, nStepBack);
1776  fflush(NULL);
1777  }
1778 
1779  /* High Sampling-rate integration */
1780  /* Stepback by 150M wrt the ending time of the low-sampling-rate trajecotry */
1781  /* If 150M of step back > actual time of evolution, step back 50% of that */
1782  if (tStepBack > retLenLow*deltaT)
1783  {
1784  tStepBack = 0.5*retLenLow*deltaT;
1785  nStepBack = ceil( tStepBack / deltaT );
1786  }
1787 
1788  /* Step back in time by tStepBack and volve EOB trajectory again
1789  * using high sampling rate. */
1790  hiSRndx = retLenLow - nStepBack;
1791  deltaTHigh = deltaT / (REAL8)resampFac;
1792  HiSRstart = tVec.data[hiSRndx];
1793 
1794  if (debugPK) {
1795  XLAL_PRINT_INFO("AT We are here %d\n",nStepBack);
1796  XLAL_PRINT_INFO("Stas: start HighSR at %.16e \n", HiSRstart);
1797  XLAL_PRINT_INFO( "Stepping back %d points - we expect %d points at high SR\n", nStepBack, nStepBack*resampFac );
1798  fflush(NULL);
1799  }
1800 
1801  /* Copy over the dynamics at "hiSRndx" over as "initial values" */
1802  if (!use_optimized) {
1803  values->data[0] = posVecx.data[hiSRndx];
1804  values->data[1] = posVecy.data[hiSRndx];
1805  values->data[2] = posVecz.data[hiSRndx];
1806  values->data[3] = momVecx.data[hiSRndx];
1807  values->data[4] = momVecy.data[hiSRndx];
1808  values->data[5] = momVecz.data[hiSRndx];
1809  values->data[6] = s1Vecx.data[hiSRndx];
1810  values->data[7] = s1Vecy.data[hiSRndx];
1811  values->data[8] = s1Vecz.data[hiSRndx];
1812  values->data[9] = s2Vecx.data[hiSRndx];
1813  values->data[10]= s2Vecy.data[hiSRndx];
1814  values->data[11]= s2Vecz.data[hiSRndx];
1815  values->data[12]= phiDMod.data[hiSRndx];
1816  values->data[13]= phiMod.data[hiSRndx];
1817  }
1818 
1819  if (use_optimized) {
1820  for( i=1; i<=14; i++) /*OPTV3 cleans up the above mess*/
1821  values->data[i-1] = dynamics->data[i*retLenLow+hiSRndx];
1822  }
1823 
1824  if (debugPK){
1825  XLAL_PRINT_INFO( "Commencing high SR integration.. From: \n" );
1826  for( i=0; i<12; i++)XLAL_PRINT_INFO("%.16e\n", values->data[i]);
1827  fflush(NULL);
1828  }
1829  seobParams.prev_dr=0.;
1830  /* For HiSR evolution, we stop whenver XLALEOBSpinPrecStopConditionBasedOnPR is triggered */
1832 
1833  REAL8Vector rVecHi, phiVecHi, prVecHi, pPhiVecHi;
1834  rVecHi.length = phiVecHi.length = prVecHi.length = pPhiVecHi.length = 0;
1835  rVecHi.data = 0; phiVecHi.data = 0; prVecHi.data = 0; pPhiVecHi.data = 0;
1836 
1837  /** If spins are aligned/antialigned with LNhat to within 1e-4 rads, then use SEOBNRv2 dynamics */
1838  if ( SpinsAlmostAligned ) {
1839  seobParams.alignedSpins = 1;
1840  seobParams.chi1 = spin1Norm*copysign(1., cos(theta1Ini));
1841  seobParams.chi2 = spin2Norm*copysign(1.,cos(theta2Ini));
1842 
1843  valuesV2->data[0] = rVec.data[hiSRndx];
1844  valuesV2->data[1] = phiVec.data[hiSRndx];
1845  valuesV2->data[2] = prVec.data[hiSRndx];
1846  valuesV2->data[3] = pPhiVec.data[hiSRndx];
1847  if (debugPK) {XLAL_PRINT_INFO("Start high SR integration at: valuesV2->data[0], valuesV2->data[1], valuesV2->data[2], valuesV2->data[3] %e %e %e %e\n", valuesV2->data[0], valuesV2->data[1], valuesV2->data[2], valuesV2->data[3]);}
1848 
1850  retLen = XLALAdaptiveRungeKutta4( integrator, &seobParams, valuesV2->data, 0., tStepBack/mTScaled, deltaTHigh/mTScaled, &dynamicsV2Hi );
1851  retLenHi = retLen;
1852 
1853  seobParams.alignedSpins = 0;
1854 
1855  if ( retLenHi == XLAL_FAILURE )
1856  {
1857  XLALDestroyREAL8Vector( sigmaKerr );
1858  XLALDestroyREAL8Vector( sigmaStar );
1859  XLALDestroyREAL8Vector( values );
1860  XLALDestroyREAL8Vector( dvalues );
1861  XLALDestroyREAL8Vector( rdMatchPoint );
1862  XLALDestroyREAL8Vector( valuesV2 );
1863  if (dynamicsV2 != NULL){
1864  XLALDestroyREAL8Array( dynamicsV2 );
1865  }
1866  if (dynamicsV2Hi != NULL){
1867  XLALDestroyREAL8Array( dynamicsV2Hi );
1868  }
1869  XLALPrintError("XLALAdaptiveRungeKutta4 failed!\n");
1870  PRINT_PARAMS
1872  }
1873  timeHi.length = phiVecHi.length = prVecHi.length = pPhiVecHi.length = retLenHi;
1874  timeHi.data = dynamicsV2Hi->data;
1875  rVecHi.data = dynamicsV2Hi->data+retLenHi;
1876  phiVecHi.data = dynamicsV2Hi->data+2*retLenHi;
1877  prVecHi.data = dynamicsV2Hi->data+3*retLenHi;
1878  pPhiVecHi.data = dynamicsV2Hi->data+4*retLenHi;
1879  dynamicsHi = XLALCreateREAL8ArrayL( 2, 15, (UINT4)retLenHi );
1880 
1881  for (i = 0; i < retLenHi; i++) {
1882  dynamicsHi->data[i] = timeHi.data[i];
1883  dynamicsHi->data[retLenHi + i] = rVecHi.data[i]*cos(phiVecHi.data[i]);
1884  dynamicsHi->data[2*retLenHi + i] = rVecHi.data[i]*sin(phiVecHi.data[i]);
1885  dynamicsHi->data[3*retLenHi + i] = 0.;
1886  dynamicsHi->data[4*retLenHi + i] = prVecHi.data[i]*cos(phiVecHi.data[i]) - pPhiVecHi.data[i]/rVecHi.data[i]*sin(phiVecHi.data[i]);
1887  dynamicsHi->data[5*retLenHi + i] = prVecHi.data[i]*sin(phiVecHi.data[i]) + pPhiVecHi.data[i]/rVecHi.data[i]*cos(phiVecHi.data[i]);
1888  dynamicsHi->data[6*retLenHi + i] = 0.;
1889  dynamicsHi->data[7*retLenHi + i] = 0.;
1890  dynamicsHi->data[8*retLenHi + i] = 0.;
1891  dynamicsHi->data[9*retLenHi + i] = spin1[2]*(m1*m1/mTotal/mTotal);
1892  dynamicsHi->data[10*retLenHi + i] = 0.;
1893  dynamicsHi->data[11*retLenHi + i] = 0.;
1894  dynamicsHi->data[12*retLenHi + i] = spin2[2]*(m2*m2/mTotal/mTotal);
1895  dynamicsHi->data[13*retLenHi + i] = phiVecHi.data[i];
1896  dynamicsHi->data[14*retLenHi + i] = 0.;
1897  }
1898 
1899  retLenHi = retLen;
1900 
1901  }else{
1902  if(use_optimized) {
1903  retLenEOMHi = XLALAdaptiveRungeKuttaDenseandSparseOutput(integrator, &seobParams, values->data, 0., 20./mTScaled, deltaTHigh/mTScaled, &dynamicsEOMHi, &dynamicsHi);
1904  retLenHi = (int)(dynamicsEOMHi->data[retLenEOMHi-1] / (deltaTHigh/mTScaled))+ 1;
1905  } else {
1906  retLen = XLALAdaptiveRungeKutta4( integrator, &seobParams, values->data, 0., tStepBack/mTScaled, deltaTHigh/mTScaled, &dynamicsHi );
1907  retLenHi = retLen;
1908  }
1909 
1910  if ( retLenHi == XLAL_FAILURE ) {
1911  XLALDestroyREAL8Vector( sigmaKerr );
1912  XLALDestroyREAL8Vector( sigmaStar );
1913  XLALDestroyREAL8Vector( values );
1914  XLALDestroyREAL8Vector( dvalues );
1915  XLALDestroyREAL8Vector( rdMatchPoint );
1916  XLALDestroyREAL8Vector( valuesV2 );
1917  if (dynamicsV2 != NULL){
1918  XLALDestroyREAL8Array( dynamicsV2 );
1919  }
1920  if (dynamicsV2Hi != NULL){
1921  XLALDestroyREAL8Array( dynamicsV2Hi );
1922  }
1923  if (dynamics != NULL){
1924  XLALDestroyREAL8Array( dynamics );
1925  }
1926  if (dynamicsHi != NULL){
1927  XLALDestroyREAL8Array( dynamicsHi );
1928  }
1929  XLALPrintError("XLALAdaptiveRungeKutta4 failed!\n");
1930  PRINT_PARAMS
1932  }
1933  timeHi.length = retLenHi;
1934  timeHi.data = dynamicsHi->data;
1935  }
1936  if(debugPK){XLAL_PRINT_INFO("retLenHi = %d\n", retLenHi);}
1937  posVecxHi.length = posVecyHi.length = posVeczHi.length =
1938  momVecxHi.length = momVecyHi.length = momVeczHi.length =
1939  s1VecxHi.length = s1VecyHi.length = s1VeczHi.length =
1940  s2VecxHi.length = s2VecyHi.length = s2VeczHi.length =
1941  phiDModHi.length = phiModHi.length = retLenHi;
1942 
1943  /* This is common to all cases, even when we use SEOBNRv2 dynamics */
1944  posVecxHi.data = dynamicsHi->data+retLenHi;
1945  posVecyHi.data = dynamicsHi->data+2*retLenHi;
1946  posVeczHi.data = dynamicsHi->data+3*retLenHi;
1947  momVecxHi.data = dynamicsHi->data+4*retLenHi;
1948  momVecyHi.data = dynamicsHi->data+5*retLenHi;
1949  momVeczHi.data = dynamicsHi->data+6*retLenHi;
1950  s1VecxHi.data = dynamicsHi->data+7*retLenHi;
1951  s1VecyHi.data = dynamicsHi->data+8*retLenHi;
1952  s1VeczHi.data = dynamicsHi->data+9*retLenHi;
1953  s2VecxHi.data = dynamicsHi->data+10*retLenHi;
1954  s2VecyHi.data = dynamicsHi->data+11*retLenHi;
1955  s2VeczHi.data = dynamicsHi->data+12*retLenHi;
1956  phiDModHi.data= dynamicsHi->data+13*retLenHi;
1957  phiModHi.data = dynamicsHi->data+14*retLenHi;
1958 
1959 
1960  if(debugPK) { XLAL_PRINT_INFO( "Finished high SR integration... \n" ); fflush(NULL); }
1961 
1962  if (debugPK){
1963  out = fopen( "seobDynamicsHi.dat", "w" );
1964  for ( i = 0; i < retLenHi; i++ )
1965  {
1966  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
1967  timeHi.data[i],
1968  posVecxHi.data[i], posVecyHi.data[i], posVeczHi.data[i],
1969  momVecxHi.data[i], momVecyHi.data[i], momVeczHi.data[i],
1970  s1VecxHi.data[i], s1VecyHi.data[i], s1VeczHi.data[i],
1971  s2VecxHi.data[i], s2VecyHi.data[i], s2VeczHi.data[i],
1972  phiDModHi.data[i], phiModHi.data[i] );
1973  }
1974  fclose( out );
1975  }
1976 
1977 /* *********************************************************************************
1978  * *********************************************************************************
1979  * STEP 3) Compute Euler angles to go from initial inertial frame to
1980  * precessing frame: Eqs. 19-20 of PRD 89, 084006 (2014)
1981 * *********************************************************************************
1982 * **********************************************************************************/
1983 /* Interpolate trajectories to compute L_N (t) in order to get alpha(t) and
1984  * beta(t). */
1985  INT4 phaseCounterA = 0, phaseCounterB = 0;
1986  if (use_optimized) {
1987  Alpha = XLALCreateREAL8Vector( retLenEOMLow );
1988  Beta = XLALCreateREAL8Vector( retLenEOMLow );
1989  Gamma = XLALCreateREAL8Vector( retLenEOMLow );
1990  EulerAnglesI2P(Alpha, Beta, Gamma, &phaseCounterA, &phaseCounterB, *tVecEOM, *posVecxEOM, *posVecyEOM, *posVeczEOM, retLenEOMLow, 0., 0.5*LAL_PI, 0, 1);
1991  } else {
1992  Alpha = XLALCreateREAL8Vector( retLenLow );
1993  Beta = XLALCreateREAL8Vector( retLenLow );
1994  Gamma = XLALCreateREAL8Vector( retLenLow );
1995  EulerAnglesI2P(Alpha, Beta, Gamma, &phaseCounterA, &phaseCounterB, tVec, posVecx, posVecy, posVecz, retLenLow, 0., 0.5*LAL_PI, 0, 0);
1996  }
1997  if (debugPK){
1998  XLAL_PRINT_INFO("Writing Alpha and Beta angle timeseries at low SR to alphaANDbeta.dat\n" );
1999  fflush(NULL);
2000  out = fopen( "alphaANDbeta.dat","w");
2001  for( i = 0; i < retLenLow; i++ ) {
2002  fprintf( out, "%.16e %.16e %.16e\n", tVec.data[i], Alpha->data[i], Beta->data[i]);
2003  }
2004  fclose(out);
2005 
2006  XLAL_PRINT_INFO("Writing Gamma angle timeseries at low SR to gamma.dat\n");
2007  fflush(NULL);
2008  out = fopen( "gamma.dat","w");
2009  for( i = 0; i < retLenLow; i++ ) {
2010  fprintf( out, "%.16e %.16e\n", tVec.data[i], Gamma->data[i]);
2011  }
2012  fclose(out);
2013  }
2014 
2015  AlphaHi = XLALCreateREAL8Vector( retLenHi );
2016  BetaHi = XLALCreateREAL8Vector( retLenHi );
2017  GammaHi = XLALCreateREAL8Vector( retLenHi );
2018 
2019  if (use_optimized) {
2020  REAL8 alphaHiSRndx; //OPTV3: Alpha at time dynamics->data[hiSRndx]
2021  REAL8 gammaHiSRndx; //OPTV3: Gamma at time dynamics->data[hiSRndx]
2022 
2023  REAL8 precEulerresult = 0, precEulererror = 0;
2024  gsl_integration_workspace * precEulerw = gsl_integration_workspace_alloc (1000);
2025  gsl_function precEulerF;
2026  PrecEulerAnglesIntegration precEulerparams;
2027 
2028  /* OPTV3: Since the angles are now solved for sparsely,
2029  * we must get alpha and gamma at hiSRndx, in another way */
2030 
2031  gsl_interp_accel *alpha_acc = gsl_interp_accel_alloc();
2032  gsl_spline *alpha_spline = gsl_spline_alloc( gsl_interp_cspline, retLenEOMLow );
2033  gsl_spline_init( alpha_spline, dynamicsEOMLo->data, Alpha->data, retLenEOMLow );
2034 
2035  gsl_interp_accel *beta_acc = gsl_interp_accel_alloc();
2036  gsl_spline *beta_spline = gsl_spline_alloc( gsl_interp_cspline, retLenEOMLow );
2037  gsl_spline_init( beta_spline, dynamicsEOMLo->data, Beta->data, retLenEOMLow );
2038 
2039  precEulerparams.alpha_spline = alpha_spline;
2040  precEulerparams.alpha_acc = alpha_acc;
2041  precEulerparams.beta_spline = beta_spline;
2042  precEulerparams.beta_acc = beta_acc;
2043 
2044  precEulerF.function = &f_alphadotcosi;
2045  precEulerF.params = &precEulerparams;
2046 
2047  /* OPTV3: Each gamma value is calculated using the one before it, so we find the nearest time below t[hiSRndx]*/
2048  int hiSRndxEOMf=retLenEOMLow-1;
2049  for (;dynamicsEOMLo->data[hiSRndxEOMf] > dynamics->data[hiSRndx]; hiSRndxEOMf--);
2050 
2051  /* OPTV3: Now use it to get Gamma at t[hiSRndx]*/
2052  gsl_integration_qags (&precEulerF, dynamicsEOMLo->data[hiSRndxEOMf], dynamics->data[hiSRndx], 1e-9, 1e-9, 1000, precEulerw, &precEulerresult, &precEulererror);
2053  gammaHiSRndx = Gamma->data[hiSRndxEOMf]+precEulerresult;
2054  alphaHiSRndx = gsl_spline_eval(alpha_spline,tVec.data[hiSRndx],alpha_acc);
2055  gsl_spline_free(alpha_spline);
2056  gsl_interp_accel_free(alpha_acc);
2057  gsl_spline_free(beta_spline);
2058  gsl_interp_accel_free(beta_acc);
2059  gsl_integration_workspace_free(precEulerw);
2060 
2061  EulerAnglesI2P(AlphaHi, BetaHi, GammaHi, &phaseCounterA, &phaseCounterB, timeHi, posVecxHi, posVecyHi, posVeczHi, retLenHi, alphaHiSRndx, gammaHiSRndx, 1, 1);
2062  } else {
2063  EulerAnglesI2P(AlphaHi, BetaHi, GammaHi, &phaseCounterA, &phaseCounterB, timeHi, posVecxHi, posVecyHi, posVeczHi, retLenHi, Alpha->data[hiSRndx], Gamma->data[hiSRndx], 1, 0);
2064  }
2065 
2066  if (debugPK){
2067  XLAL_PRINT_INFO("Writing Alpha and Beta angle timeseries at high SR to alphaANDbetaHi.dat\n" );
2068  fflush(NULL);
2069  out = fopen( "alphaANDbetaHi.dat","w");
2070  for( i = 0; i < retLenHi; i++ ) {
2071  fprintf( out, "%.16e %.16e %.16e\n", tVec.data[hiSRndx] + timeHi.data[i], AlphaHi->data[i], BetaHi->data[i]);
2072  }
2073  fclose(out);
2074 
2075  XLAL_PRINT_INFO("Writing Gamma angle timeseries at high SR to gammaHi.dat\n");
2076  fflush(NULL);
2077  out = fopen( "gammaHi.dat","w");
2078  for( i = 0; i < retLenHi; i++ ) {
2079  fprintf( out, "%.16e %.16e\n", tVec.data[hiSRndx] + timeHi.data[i], GammaHi->data[i]);
2080  }
2081  fclose(out);
2082  }
2083 
2084  /* Compute leading QNM to determine how long the ringdown will be */
2085  modefreqVec.length = 1;
2086  modefreqVec.data = &modeFreq;
2087 
2088  if ( XLALSimIMREOBGenerateQNMFreqV2Prec( &modefreqVec, m1, m2, spin1, spin2, 2, 2, 1, spinEOBApproximant ) == XLAL_FAILURE ) /* This function returns XLAL_SUCCESS or calls XLAL_ERROR( XLAL_EINVAL ). Internally, it calls XLALSimIMREOBFinalMassSpinPrec which has the same behavior */ {
2090  FREE_SPHHARM
2091  XLALPrintError("XLALSimIMREOBGenerateQNMFreqV2Prec failed!\n");
2092  PRINT_PARAMS
2094  }
2095 
2096  retLenRDPatchHi= (UINT4)ceil( 40 / ( cimag(modeFreq) * deltaTHigh ));
2097  retLenRDPatchLow = (UINT4)ceil( 40 / ( cimag(modeFreq) * deltaT ));
2098 
2099 /* *********************************************************************************
2100  * *********************************************************************************
2101  * STEP 4) Locate merger point and at that time calculate J, chi and kappa,
2102  * and construct final J frame
2103  * *********************************************************************************
2104  * **********************************************************************************/
2105  /* Locate merger point */
2106  // Find tAmpMax to determin the tAttachment
2107  REAL8Vector *radiusVec = NULL;
2108  if ( !(radiusVec = XLALCreateREAL8Vector( retLenHi )) ) {
2110  FREE_SPHHARM
2111  XLALPrintError("Failed to allocate REAL8Vector radiusVec!\n");
2112  PRINT_PARAMS
2114  }
2115 
2116  for ( i = 0; i < retLenHi; i++ )
2117  {
2118  for ( j = 0; j < 3; j++ )
2119  {
2120  values->data[j] = dynamicsHi->data[(j+1)*retLenHi + i];
2121  }
2122  radiusVec->data[i] = sqrt(values->data[0]*values->data[0] + values->data[1]*values->data[1] + values->data[2]*values->data[2]);
2123  }
2124 
2125 
2126  int foundPeakOmega = 0;
2127  if (debugPK) {
2128  XLAL_PRINT_INFO("Stas searching for maxima in omega .... \n");
2129  }
2130  REAL8 tMaxOmega;
2131  tPeakOmega = XLALSimLocateOmegaTime(dynamicsHi, values->length, retLenHi, seobParams, seobCoeffs, m1, m2, radiusVec, &foundPeakOmega, &tMaxOmega, use_optimized);
2132 
2133  if(tPeakOmega == 0.0 || foundPeakOmega==0){
2134  if (debugPK){
2135  XLAL_PRINT_INFO("maximum of omega and A(r) is not found, looking for amplitude maximum\n");
2136  }
2137  }
2138  else{
2139  if (debugPK){
2140  XLAL_PRINT_INFO("The omega-related time is found and it's %f \n", tPeakOmega);
2141  }
2142  }
2143  if(debugPK) {
2144  XLAL_PRINT_INFO( "Estimation of the peak is now at time %.16e, %.16e \n",
2145  tPeakOmega, tPeakOmega+HiSRstart);
2146  fflush(NULL);
2147  }
2148 
2149 
2150  /* Calculate J at merger */
2151  spline = gsl_spline_alloc( gsl_interp_cspline, retLenHi );
2152  acc = gsl_interp_accel_alloc();
2153 
2154  /* Obtain the dynamics at the time where Omega = d\phi/dt peaks */
2155  for ( j = 0; j < values->length; j++ )
2156  {
2157  gsl_spline_init( spline,
2158  dynamicsHi->data, dynamicsHi->data+(j+1)*retLenHi, retLenHi );
2159  values->data[j] = gsl_spline_eval( spline, tPeakOmega, acc );
2160  }
2161  gsl_spline_free(spline);
2162  gsl_interp_accel_free(acc);
2163 
2164  /* Get the phase offset required to ensure that the orbital phase = phiC at
2165  * tPeakOmega */
2166  //coa_phase_offset = values->data[12] - phiC;
2167 
2168  /* Calculate dr/dt */
2169  memset( dvalues->data, 0, 14*sizeof(dvalues->data[0]));
2170 
2171  failure_flag=0;
2172  if (use_optimized) failure_flag = XLALSpinPrecHcapRvecDerivative_exact( 0, values->data, dvalues->data, &seobParams);
2173  else failure_flag = XLALSpinPrecHcapRvecDerivative( 0, values->data, dvalues->data, &seobParams);
2174  if(failure_flag != XLAL_SUCCESS )
2175  {
2176  XLAL_PRINT_INFO( " Calculation of dr/dt at t = tPeakOmega \n");
2178  FREE_SPHHARM
2179  XLALPrintError("XLALSpinPrecHcapRvecDerivative failed!\n");
2180  PRINT_PARAMS
2181  XLAL_ERROR( XLAL_EDOM );
2182  }
2183 
2184  /* Calculate Omega = r x dr/dt */
2185  memcpy( rdotvec, dvalues->data, 3*sizeof(REAL8));
2186  memcpy( rvec, values->data, 3*sizeof(REAL8));
2187  memcpy( pvec, values->data+3,3*sizeof(REAL8));
2188  cross_product( rvec, rdotvec, rcrossrdot );
2189  cross_product( rvec, pvec, rcrossp );
2190  /* Calculate L at OmegaPeak */
2191  Lx = rcrossp[0]; Ly = rcrossp[1]; Lz = rcrossp[2];
2192  magL = sqrt(inner_product(rcrossp, rcrossp));
2193  /* Calculate J at OmegaPeak */
2194  Jx = eta*Lx + values->data[6] + values->data[9];
2195  Jy = eta*Ly + values->data[7] + values->data[10];
2196  Jz = eta*Lz + values->data[8] + values->data[11];
2197  magJ = sqrt( Jx*Jx + Jy*Jy + Jz*Jz );
2198 
2199  if(debugPK){
2200  XLAL_PRINT_INFO("J at merger: %e, %e, %e (mag = %e)\n", Jx, Jy, Jz, magJ);
2201  fflush(NULL);
2202  }
2203 
2204  /* Calculate chi and kappa at merger: Eq. 26 and 27 of PRD 89, 084006 (2014).
2205  Here we project the spins onto J */
2206  chi1J = values->data[6]*Jx + values->data[7] *Jy + values->data[8] *Jz;
2207  chi2J = values->data[9]*Jx + values->data[10]*Jy + values->data[11]*Jz;
2208  chi1J/= magJ*m1*m1/mTotal/mTotal;
2209  chi2J/= magJ*m2*m2/mTotal/mTotal;
2210  chiJ = (chi1J+chi2J)/2. + (chi1J-chi2J)/2.*((m1-m2)/(m1+m2))/(1. - 2.*eta);
2211  kappaJL = (Lx*Jx + Ly*Jy + Lz*Jz) / magL / magJ;
2212  magLN = sqrt(inner_product(rcrossrdot, rcrossrdot));
2213  JLN = (Jx*rcrossrdot[0] + Jy*rcrossrdot[1] + Jz*rcrossrdot[2])/magLN/magJ;
2214  // Stas: here is the second option which we will use: projection of the spin on
2215  // L at l.r. projection on J doesn't work for anti-aligned system
2216  chi1L = values->data[6]*Lx + values->data[7] *Ly + values->data[8] *Lz;
2217  chi2L = values->data[9]*Lx + values->data[10]*Ly + values->data[11]*Lz;
2218  chi1L /= magL*m1*m1/mTotal/mTotal;
2219  chi2L /= magL*m2*m2/mTotal/mTotal;
2220  chiL = (chi1L+chi2L)/2. + (chi1L-chi2L)/2.*((m1-m2)/(m1+m2))/(1. - 2.*eta);
2221 
2222 
2223  if(debugPK) {
2224  XLAL_PRINT_INFO("chi1J,chi2J,chiJ = %3.10f %3.10f %3.10f\n", chi1J,chi2J,chiJ); fflush(NULL); fflush(NULL);
2225  XLAL_PRINT_INFO("chi1L,chi2L,chiL = %3.10f %3.10f %3.10f\n", chi1L,chi2L,chiL); fflush(NULL); fflush(NULL);
2226  XLAL_PRINT_INFO("J.L = %4.11f \n", kappaJL); fflush(NULL);
2227  XLAL_PRINT_INFO("J.LN = %4.11f \n", JLN);
2228  XLAL_PRINT_INFO("L.LN = %4.11f \n", (Lx*rcrossrdot[0] + Ly*rcrossrdot[1] + Lz*rcrossrdot[2])/magL/magLN);
2229  }
2230 
2231 
2232  sh = 0.0;
2233  /* Calculate combsize and deltaNQC */
2234  switch ( SpinAlignedEOBversion )
2235  {
2236  /* Eqs. 33-34 of PRD 86, 024011 (2012) */
2237  case 1:
2238  combSize = 7.5;
2239  deltaNQC = XLALSimIMREOBGetNRSpinPeakDeltaT(2, 2, eta, chiJ);
2240  if ( debugPK ) {
2241  XLAL_PRINT_INFO("v1 RD prescriptions are used! %3.10f %3.10f\n",
2242  combSize, deltaNQC);
2243  fflush(NULL);
2244  }
2245  break;
2246  /* The following if's are documented in sections "DeltaNQC" and "PseudoQNM prescriptions" of https://dcc.ligo.org/T1400476 */
2247  case 2:
2248  combSize = 12.;
2249  if ( chi1L == 0. && chi2L == 0. ) combSize = 11.;
2250  if (chiL >= 0.8 && eta >30.0/(31.*31) && eta <10.0/121.) combSize = 13.5;
2251  if (chiL >= 0.9 && eta < 30./(31.*31.)) combSize = 12.0;
2252  if (chiL >= 0.8 && eta > 10./121.) combSize = 8.5;
2253  deltaNQC = XLALSimIMREOBGetNRSpinPeakDeltaTv2(2, 2, m1, m2, chi1L, chi2L );
2254  if ( debugPK ) {
2255  XLAL_PRINT_INFO("v2 RD prescriptions are used! %3.10f %3.10f\n",
2256  combSize, deltaNQC);
2257  fflush(NULL);
2258  }
2259  break;
2260  default:
2261  XLALPrintError( "XLAL Error - %s: wrong SpinAlignedEOBversion value, must be 1 or 2!\n", __func__ );
2263  FREE_SPHHARM
2264  PRINT_PARAMS
2266  break;
2267  }
2268 
2269 
2270  /* NOTE: tAttach is further modified by small shift "sh" computed and applied in XLALSimIMREOBHybridAttachRingdownPrec !!!
2271  Manually choose tAttach here */
2272  tAttach = tPeakOmega - deltaNQC;
2273 
2274  /* tPeakOmega is initialized to 0 by default, so even when found is false, tPeakOmega has numerical value */
2275  if ( ! foundPeakOmega ){
2276  tAttach = tPeakOmega;
2277  }
2278 
2279  if (debugPK){
2280  XLAL_PRINT_INFO("tPeakOmega - deltaNQC, tPeakOmega, deltaNQC %e %e %e\n", tPeakOmega - deltaNQC + HiSRstart, tPeakOmega + HiSRstart, deltaNQC);
2281  XLAL_PRINT_INFO("For RD: DeltaNQC = %3.10f, comb = %3.10f \n", deltaNQC, combSize);
2282  XLAL_PRINT_INFO("NOTE! that additional shift (sh) is computed and added in XLALSimIMREOBHybridAttachRingdownPrec\n");
2283  fflush(NULL);
2284  }
2285 
2286  /* Manually choose combSize */
2287  //combSize = 40.0;
2288 
2289  /* Construct J-frame */
2290  JframeEz[0] = Jx / magJ;
2291  JframeEz[1] = Jy / magJ;
2292  JframeEz[2] = Jz / magJ;
2293 
2294  if ( fabs(1.+ JframeEz[2]) <= 1.0e-13 )
2295  { JframeEx[0] = -1.; JframeEx[1] = 0.; JframeEx[2] = 0.; } // anti-aligned
2296  //{ JframeEx[0] = 0.0; JframeEx[1] = -1.0; JframeEx[2] = 0.; } // anti-aligned
2297  else {
2298  if ( fabs(1. - JframeEz[2]) <= 1.0e-13 )
2299  //{ JframeEx[0] = 1.; JframeEx[1] = 0.; JframeEx[2] = 0.; } // aligned
2300  { JframeEx[0] = 1.0; JframeEx[1] = 0.0; JframeEx[2] = 0.; } // aligned
2301  else {
2302  JframeEx[0] = JframeEz[1];
2303  JframeEx[1] = -JframeEz[0];
2304  JframeEx[2] = 0.;
2305  }
2306  }
2307 
2308  JExnorm = sqrt(JframeEx[0]*JframeEx[0] + JframeEx[1]*JframeEx[1]);
2309 
2310  JframeEx[0] /= JExnorm;
2311  JframeEx[1] /= JExnorm;
2312  JframeEy[0] = JframeEz[1]*JframeEx[2] - JframeEz[2]*JframeEx[1];
2313  JframeEy[1] = JframeEz[2]*JframeEx[0] - JframeEz[0]*JframeEx[2];
2314  JframeEy[2] = JframeEz[0]*JframeEx[1] - JframeEz[1]*JframeEx[0];
2315 
2316 
2317  if(debugPK) {
2318  XLAL_PRINT_INFO("J-frameEx = [%.16e\t%.16e\t%.16e]\n", JframeEx[0], JframeEx[1], JframeEx[2]);XLAL_PRINT_INFO("J-frameEy = [%.16e\t%.16e\t%.16e]\n", JframeEy[0], JframeEy[1], JframeEy[2]);
2319  XLAL_PRINT_INFO("J-frameEz = [%.16e\t%.16e\t%.16e]\n", JframeEz[0], JframeEz[1], JframeEz[2]);fflush(NULL);
2320  }
2321 
2322 /* *********************************************************************************
2323  * *********************************************************************************
2324  * STEP 5) Generate quasi-nonprecessing waveforms in precessing frame
2325  * *********************************************************************************
2326  * **********************************************************************************/
2327  /* these three variables hVec, hVecEOM, and hVecEOMData are only used in v3opt but are used in multiple conditional sections so must be declared here*/
2328  REAL8Array * hVec = NULL;
2329  /* these two variables tMaxAmp and tAmpMax are used in both later on and need to be declared here outside the conditionals */
2330  REAL8 tMaxAmp;
2331  double tAmpMax;
2332  if (use_optimized) {
2333  // START OPTIMIZED CODE CHUNK
2334  REAL8Vector *hVecEOM = NULL;
2335  if ( !(hVecEOM = XLALCreateREAL8Vector( 3*retLenEOMLow ) ) )
2336  {
2337  XLALPrintError("Failed to allocate REAL8Vector hVecEOM!\n");
2338  PRINT_PARAMS
2340  }
2341 
2342  h22TSHi = XLALCreateCOMPLEX16TimeSeries( "H_22", &tc, 0.0, deltaTHigh, &lalStrainUnit, retLenHi );
2343  h21TSHi = XLALCreateCOMPLEX16TimeSeries( "H_21", &tc, 0.0, deltaTHigh, &lalStrainUnit, retLenHi );
2344  h20TSHi = XLALCreateCOMPLEX16TimeSeries( "H_20", &tc, 0.0, deltaTHigh, &lalStrainUnit, retLenHi );
2345  h2m1TSHi = XLALCreateCOMPLEX16TimeSeries( "H_2m1", &tc, 0.0, deltaTHigh, &lalStrainUnit, retLenHi );
2346  h2m2TSHi = XLALCreateCOMPLEX16TimeSeries( "H_2m2", &tc, 0.0, deltaTHigh, &lalStrainUnit, retLenHi );
2347 
2348  /* OPTV3: Spherical Harmonic calculation moved to here */
2349  Y22 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, 2 );
2350  Y2m2 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, -2 );
2351  Y21 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, 1 );
2352  Y2m1 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, -1 );
2353  Y20 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, 0 );
2354  COMPLEX16 Y[5]={Y2m2,Y2m1,Y20,Y21,Y22};
2355 
2356  /* OPTV3: Generate the low and high sampling waveforms. */
2357  XLALEOBSpinPrecGenerateHplusHcrossTSFromEOMSoln(hVecEOM,retLenEOMLow,Alpha,Beta,Gamma,JframeEx,JframeEy,JframeEz,Y,dynamicsEOMLo,&seobParams);
2358  XLALEOBSpinPrecGenerateHTSModesFromEOMSoln(h2m2TSHi->data->data,h2m1TSHi->data->data,h20TSHi->data->data,h21TSHi->data->data,h22TSHi->data->data,retLenHi,dynamicsHi,&seobParams);
2359 
2360  //OPTV3: Interpolate the WF solutions to the desired times
2361  SEOBNRv3OptimizedInterpolatorGeneral(hVecEOM->data,0., deltaT/mTScaled, retLenEOMLow, &hVec,2);
2362 
2363  if ( !(tlist = XLALCreateREAL8Vector( retLenLow ))
2364  || !(tlistRDPatch = XLALCreateREAL8Vector( retLenLow + retLenRDPatchLow )) )
2365  {
2366  XLALPrintError("Failed to allocate REAL8Vector tlistRDPatch!\n");
2367  PRINT_PARAMS
2369  }
2370  memset( tlistRDPatch->data, 0, tlistRDPatch->length * sizeof( REAL8 ));
2371  for ( i = 0; i < retLenLow; i++ ){
2372  tlist->data[i] = i * deltaT/mTScaled;
2373  tlistRDPatch->data[i] = i * deltaT/mTScaled;
2374  }
2375  if( hVecEOM != NULL ) XLALDestroyREAL8Vector( hVecEOM );
2376  if( tlist != NULL ) XLALDestroyREAL8Vector( tlist );
2377  // END OPTIMIZED CODE CHUNK
2378  } else {
2379  // START UNOPTIMIZED CODE CHUNK
2380  /* Create time-series containers for euler angles and hlm harmonics */
2381  if ( !(alphaI2PTS = XLALCreateREAL8TimeSeries( "alphaI2P", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(betaI2PTS = XLALCreateREAL8TimeSeries( "betaI2P", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(gammaI2PTS = XLALCreateREAL8TimeSeries( "gammaI2P", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(alphaP2JTS = XLALCreateREAL8TimeSeries( "alphaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(betaP2JTS = XLALCreateREAL8TimeSeries( "betaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(gammaP2JTS = XLALCreateREAL8TimeSeries( "gammaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) ) {
2383  FREE_SPHHARM
2384  XLALPrintError("Failed to allocate alphaI2PTS or betaI2PTS or gammaI2PTS or alphaP2JTS or betaP2JTS or gammaP2JTS!\n");
2385  PRINT_PARAMS
2387  }
2388 
2389  if ( !(h22TS = XLALCreateCOMPLEX16TimeSeries( "H_22", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(h21TS = XLALCreateCOMPLEX16TimeSeries( "H_21", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(h20TS = XLALCreateCOMPLEX16TimeSeries( "H_20", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(h2m1TS = XLALCreateCOMPLEX16TimeSeries( "H_2m1", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow )) + !(h2m2TS = XLALCreateCOMPLEX16TimeSeries( "H_2m2", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow ))) {
2391  FREE_SPHHARM
2392  XLALPrintError("Failed to allocate h22TS or h21TS or h20TS or h2m1TS or h2m2TS!\n");
2393  PRINT_PARAMS
2395  }
2396 
2397  hIMRJTS = XLALCreateCOMPLEX16TimeSeries( "HIMRJ",
2398  &tc, 0.0, deltaT, &lalStrainUnit, retLenLow + retLenRDPatchLow );
2399 
2400 
2401  if ( !(tlist = XLALCreateREAL8Vector( retLenLow ))
2402  || !(tlistRDPatch = XLALCreateREAL8Vector( retLenLow + retLenRDPatchLow )) )
2403  {
2404  XLALPrintError("Failed to allocate REAL8Vector tlistRDPatch!\n");
2405  PRINT_PARAMS
2407  }
2408  } // END UNOPTIMIZED CODE CHUNK (straight from LALSuite master, Nov 14, 2016.)
2409  // START OPTIMIZED & UNOPTIMIZED CODE CHUNK
2410  // timeJFullHi will be a copy of tlistRDPatchHi which will be returned together with J-frame modes
2411  if ( !(timeJFull = XLALCreateREAL8Vector( retLenLow + retLenRDPatchLow )) )
2412  {
2413  XLALPrintError("Failed to allocate REAL8Vector timeJFull!\n");
2414  PRINT_PARAMS
2416  }
2417  // timeIFullHi will be a copy of tlistRDPatchHi which will be returned together with I-frame modes
2418  if ( !(timeIFull = XLALCreateREAL8Vector( retLenLow + retLenRDPatchLow )) )
2419  {
2420  XLALPrintError("Failed to allocate REAL8Vector timeIFull!\n");
2421  PRINT_PARAMS
2423  }
2424  // END OPTIMIZED & UNOPTIMIZED CODE CHUNK
2425  if (!use_optimized) {
2426  // START UNOPTIMIZED CODE CHUNK (straight from LALSuite master, Nov 14, 2016.)
2427  memset( tlist->data, 0, tlist->length * sizeof( REAL8 ));
2428  memset( tlistRDPatch->data, 0, tlistRDPatch->length * sizeof( REAL8 ));
2429  memset( timeJFull->data, 0, timeJFull->length * sizeof( REAL8 ));
2430  memset( timeIFull->data, 0, timeIFull->length * sizeof( REAL8 ));
2431  for ( i = 0; i < retLenLow; i++ )
2432  {
2433  tlist->data[i] = i * deltaT/mTScaled;
2434  tlistRDPatch->data[i] = i * deltaT/mTScaled;
2435  }
2436  for ( i = retLenLow; i < retLenLow + retLenRDPatchLow; i++ )
2437  {
2438  tlistRDPatch->data[i] = i * deltaT/mTScaled;
2439  }
2440  // END UNOPTIMIZED CODE CHUNK (straight from LALSuite master, Nov 14, 2016.)
2441  }
2442 
2443  if (use_optimized) {
2444  // START OPTIMIZED CODE CHUNK
2445  /* Main loop for quasi-nonprecessing waveform generation -- HIGH SR */
2446  if (!(alphaP2JTSHi = XLALCreateREAL8TimeSeries( "alphaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(betaP2JTSHi = XLALCreateREAL8TimeSeries( "betaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(gammaP2JTSHi = XLALCreateREAL8TimeSeries( "gammaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) )
2447  {
2449  XLALDestroyREAL8Vector( tlistHi );
2450  XLALDestroyREAL8Vector( timeJFull );
2451  XLALDestroyREAL8Vector( timeIFull );
2452  XLALDestroyREAL8Vector( tlistRDPatch );
2453  XLALDestroyREAL8Vector( tlistRDPatchHi );
2454  XLALPrintError("Failed to allocate alphaI2PTSHi or betaI2PTSHi or gammaI2PTSHi or alphaP2JTSHi or betaP2JTSHi or gammaP2JTSHi!\n");
2455  PRINT_PARAMS
2457  }
2458  if ( !(tlistHi = XLALCreateREAL8Vector( retLenHi )) || !(tlistRDPatchHi = XLALCreateREAL8Vector( retLenHi + retLenRDPatchHi)) ){
2459  XLALPrintError("Failed to allocate REAL8Vector tlistHi!\n");
2460  PRINT_PARAMS
2462  }
2463 
2464  for ( i = retLenLow; i < retLenLow + retLenRDPatchLow; i++ ){
2465  tlistRDPatch->data[i] = i * deltaT/mTScaled;
2466  }
2467 
2468  memset( tlistHi->data, 0, tlistHi->length * sizeof( REAL8 ));
2469  memset( tlistRDPatchHi->data, 0, tlistRDPatchHi->length * sizeof( REAL8 ));
2470  for ( i = 0; i < retLenHi; i++ ){
2471  tlistHi->data[i] = i * deltaTHigh/mTScaled + HiSRstart;
2472  tlistRDPatchHi->data[i] = i * deltaTHigh/mTScaled + HiSRstart;
2473  }
2474  for ( i = retLenHi; i < retLenHi + retLenRDPatchHi; i++ ){
2475  tlistRDPatchHi->data[i] = i * deltaTHigh/mTScaled + HiSRstart;
2476  }
2477 
2478  for( i=0; i<retLenHi; i++){ //OPTV3: Calculate P2J angles across time
2479  for ( j = 0; j < values->length; j++ )
2480  values->data[j] = dynamicsHi->data[(j+1)*retLenHi + i];
2481  /* Calculate dr/dt */
2482  memset( dvalues->data, 0, 14*sizeof(dvalues->data[0]));
2483  if( XLALSpinPrecHcapRvecDerivative_exact( 0, values->data, dvalues->data, &seobParams) != XLAL_SUCCESS )
2484  {
2485  XLAL_PRINT_INFO( " Calculation of dr/dt at t = tPeakOmega \n");
2487  XLALDestroyREAL8Vector( tlistHi );
2488  XLALDestroyREAL8Vector( timeJFull );
2489  XLALDestroyREAL8Vector( timeIFull );
2490  XLALDestroyREAL8Vector( tlistRDPatch );
2491  XLALDestroyREAL8Vector( tlistRDPatchHi );
2492  XLALPrintError("XLALSpinPrecHcapRvecDerivative_exact failed!\n");
2493  PRINT_PARAMS
2494  XLAL_ERROR( XLAL_EDOM );
2495  }
2496  rvec[0] = posVecxHi.data[i];
2497  rvec[1] = posVecyHi.data[i];
2498  rvec[2] = posVeczHi.data[i];
2499  cross_product( rvec, dvalues->data, rcrossrdot );
2500  magLN = sqrt(inner_product(rcrossrdot, rcrossrdot));
2501  LNhx = rcrossrdot[0] / magLN;
2502  LNhy = rcrossrdot[1] / magLN;
2503  LNhz = rcrossrdot[2] / magLN;
2504 
2505  /*Rounding LNhz creates the possible issue of causing the input for the acos() call in EulerAnglesP2J
2506  to be out of the [-1,1] interval required by the function, so it has been commented out.
2507  The other two rounding statements are being removed because they do not appear in the current version
2508  of the unoptimized code. -Tom Adams*/
2509  // if (fabs(LNhx) < 1.e-7)
2510  // LNhx = 0.0;
2511  // if (fabs(LNhy) < 1.e-7)
2512  // LNhy = 0.0;
2513  // if (fabs(LNhz-1.0) < 1.e-7)
2514  // LNhz = 1.0;
2515 
2516  EulerAnglesP2J(&aP2J,&bP2J,&gP2J,AlphaHi->data[i],BetaHi->data[i], GammaHi->data[i], LNhx, LNhy, LNhz, JframeEx, JframeEy, JframeEz );
2517  alphaP2JTSHi->data->data[i]=-aP2J;
2518  betaP2JTSHi->data->data[i]=bP2J;
2519  gammaP2JTSHi->data->data[i]=-gP2J;
2520 
2521  }
2522 
2523  /* Add quasi-nonprecessing spherical harmonic modes to the SphHarmTimeSeries structure */
2524  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h22TSHi, 2, 2 );
2525  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h21TSHi, 2, 1 );
2526  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h20TSHi, 2, 0 );
2527  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h2m1TSHi, 2, -1 );
2528  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h2m2TSHi, 2, -2 );
2529  XLALSphHarmTimeSeriesSetTData( hlmPTSHi, tlistHi );
2530 
2531  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h22TSHi, 2, 2 );
2532  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h21TSHi, 2, 1 );
2533  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h20TSHi, 2, 0 );
2534  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h2m1TSHi, 2, -1 );
2535  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h2m2TSHi, 2, -2 );
2536  *hlmPTSoutput = hlmPTSout;
2537 
2538  h22PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 2 );
2539  h21PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 1 );
2540  h20PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 0 );
2541  h2m1PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, -1);
2542  h2m2PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, -2);
2543 
2544  hIMRJTSHi = XLALCreateCOMPLEX16TimeSeries(
2545  "HIMRJHi", &tc, 0.0, deltaTHigh, &lalStrainUnit, retLenHi + retLenRDPatchHi);
2546 
2547  if (debugPK){
2548  XLAL_PRINT_INFO("YP: SphHarmTS structures populated for HIgh SR.\n");
2549 
2550  out = fopen( "PWavesHi.dat", "w" );
2551  for ( i = 0; i < retLenHi; i++ )
2552  {
2553  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
2554  i*deltaTHigh/mTScaled + HiSRstart, creal(h22PTSHi->data->data[i]),
2555  cimag(h22PTSHi->data->data[i]),
2556  creal(h21PTSHi->data->data[i]), cimag(h21PTSHi->data->data[i]),
2557  creal(h20PTSHi->data->data[i]), cimag(h20PTSHi->data->data[i]),
2558  creal(h2m1PTSHi->data->data[i]), cimag(h2m1PTSHi->data->data[i]),
2559  creal(h2m2PTSHi->data->data[i]), cimag(h2m2PTSHi->data->data[i]));
2560  }
2561  fclose( out );
2562  XLAL_PRINT_INFO("YP: P-frame waveforms written to file for High SR.\n");
2563  fflush(NULL);
2564  }
2565 
2566  int foundAmp = 0;
2567  tAmpMax = XLALSimLocateAmplTime(&timeHi, h22PTSHi->data, radiusVec, &foundAmp, &tMaxAmp);
2568 
2569  if(foundAmp==0){
2570  if (debugPK){
2571  XLAL_PRINT_INFO("maximum of Amplitude or dot{Ampl} are not found \n");
2572  }
2573  }else{
2574  if (debugPK){
2575  XLAL_PRINT_INFO("The Amplitude-related time is found and it's %f \n", tAmpMax);
2576  }
2577  }
2578 
2579  if( foundAmp==0 && foundPeakOmega == 0){
2580  if (debugPK){
2581  XLALPrintError("Houston, we've got a problem SOS, SOS, SOS, cannot find the RD attachment point... m1 = %.16e, m2 = %.16e, fMin = %.16e, inclination = %.16e, Mtotal = %.16e, eta = %.16e, spin1 = {%.16e, %.16e, %.16e}, spin2 = {%.16e, %.16e, %.16e} \n",
2582  m1, m2, (double)fMin, (double)inc, mTotal, eta, spin1[0], spin1[1], spin1[2], spin2[0], spin2[1], spin2[2]);
2583  }
2584 
2585  tAttach = tAttach -2.0;
2586  //FREE_EVERYTHING
2587  //XLALDestroyREAL8Vector( timeJFull );
2588  //XLALDestroyREAL8Vector( timeIFull );
2589  //XLALDestroyREAL8Vector( tlistRDPatch );
2590  //XLALDestroyREAL8Vector( tlistRDPatchHi );
2591  //XLAL_ERROR( XLAL_EINVAL );
2592  }
2593 
2594  if (tAmpMax < tAttach){
2595  if (debugPK){
2596  XLAL_PRINT_INFO("Stas the attachment time will be modified from %f to %f \n", tAttach, tAmpMax);
2597  }
2598  tAttach = tAmpMax;
2599  }
2600 
2601  if (debugPK){
2602  XLAL_PRINT_INFO("Stas: the final decision on the attachment time is %f \n", tAttach);
2603  }
2604 
2605  // END OPTIMIZED CODE CHUNK
2606  } else {
2607  // START UNOPTIMIZED CODE CHUNK (straight from LALSuite master, Nov 14, 2016). CONTINUES ALL THE WAY TO START OF STEP 6!
2608  /* Main loop for quasi-nonprecessing waveform generation */
2609  // Generating modes for coarsely sampled portion
2610  //FILE *out2 = fopen("Lframe.dat", "w"); //FIXME
2611  if(debugPK){
2612  XLAL_PRINT_INFO("Generating precessing-frame modes for coarse dynamics\n");
2613  fflush(NULL);
2614  out = fopen( "rotDynamics.dat", "w" );
2615  }
2616 
2617  for ( i = 0; i < retLenLow; i++ )
2618  {
2619  for ( j = 0; j < values->length; j++ )
2620  {
2621  values->data[j] = dynamics->data[(j+1)*retLenLow + i];
2622  }
2623 
2624  /* Calculate dr/dt */
2625  memset( dvalues->data, 0, 14*sizeof(dvalues->data[0]));
2626  if( XLALSpinPrecHcapRvecDerivative( 0, values->data, dvalues->data,
2627  &seobParams) != XLAL_SUCCESS )
2628  {
2629  XLAL_PRINT_INFO( " Calculation of dr/dt at t = tPeakOmega \n");
2631  FREE_SPHHARM
2632  XLALPrintError("XLALSpinPrecHcapRvecDerivative failed!\n");
2633  PRINT_PARAMS
2634  XLAL_ERROR( XLAL_EDOM );
2635  }
2636 
2637  /* Calculate omega */
2638  memcpy( rdotvec, dvalues->data, 3*sizeof(REAL8));
2639  rvec[0] = posVecx.data[i]; rvec[1] = posVecy.data[i];
2640  rvec[2] = posVecz.data[i];
2641  cross_product( rvec, rdotvec, rcrossrdot );
2642  magR = sqrt(inner_product(rvec, rvec));
2643  omega = sqrt(inner_product(rcrossrdot, rcrossrdot)) / (magR*magR);
2644  v = cbrt( omega );
2645 
2646  /* Cartesian vectors needed to calculate Hamiltonian */
2647  cartPosVec.length = cartMomVec.length = 3;
2648  cartPosVec.data = cartPosData;
2649  cartMomVec.data = cartMomData;
2650  memset( cartPosData, 0, sizeof( cartPosData ) );
2651  memset( cartMomData, 0, sizeof( cartMomData ) );
2652 
2653  LNhx = rcrossrdot[0];
2654  LNhy = rcrossrdot[1];
2655  LNhz = rcrossrdot[2];
2656  magLN = sqrt(LNhx*LNhx + LNhy*LNhy + LNhz*LNhz);
2657  LNhx = LNhx / magLN;
2658  LNhy = LNhy / magLN;
2659  LNhz = LNhz / magLN;
2660 
2661  /* this one is defined w.r.t. L not LN*/
2662  aI2P = Alpha->data[i];
2663  bI2P = Beta->data[i];
2664  gI2P = Gamma->data[i];
2665 
2666  //if (debugPK){
2667  //REAL8 LframeEx[3] = {0,0,0}, LframeEy[3] = {0,0,0}, LframeEz[3] = {0,0,0};
2668  //LframeEx[0] = cos(aI2P)*cos(bI2P)*cos(gI2P) - sin(aI2P)*sin(gI2P);
2669  // LframeEx[1] = sin(aI2P)*cos(bI2P)*cos(gI2P) + cos(aI2P)*sin(gI2P);
2670  //LframeEx[2] = -sin(bI2P)*cos(gI2P);
2671  //LframeEy[0] = -cos(aI2P)*cos(bI2P)*sin(gI2P) - sin(aI2P)*cos(gI2P);
2672  //LframeEy[1] = -sin(aI2P)*cos(bI2P)*sin(gI2P) + cos(aI2P)*cos(gI2P);
2673  //LframeEy[2] = sin(bI2P)*sin(gI2P);
2674  //LframeEz[0] = LNhx;
2675  //LframeEz[1] = LNhy;
2676  //LframeEz[2] = LNhz;
2677 
2678  //fprintf(out2, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e \n",
2679  // i*deltaT/mTScaled, LframeEx[0], LframeEx[1], LframeEx[2], LframeEy[0], LframeEy[1],
2680  // LframeEy[2], LframeEz[0], LframeEz[1], LframeEz[2]);
2681 
2682  //}
2683 
2684  EulerAnglesP2J(&aP2J, &bP2J, &gP2J, aI2P, bI2P, gI2P, LNhx, LNhy, LNhz, JframeEx, JframeEy, JframeEz);
2685 
2686  /** Euler angles to go from precessing to J-frame. Note that we follow in this code passive rotation Z-Y-Z and notations
2687  * of Arun et al. arXiv 0810.5336, however the Wiegner D-matrix and mode rotation coded up in LAL for active rotation
2688  * We make the angle transformation here in order to match two conventions */
2689  alphaI2PTS->data->data[i] = -aI2P;
2690  betaI2PTS->data->data[i] = bI2P;
2691  gammaI2PTS->data->data[i] = -gI2P;
2692  alphaP2JTS->data->data[i] = -aP2J;
2693  betaP2JTS->data->data[i] = bP2J;
2694  gammaP2JTS->data->data[i] = -gP2J;
2695 
2696 
2697  /* Calculate the value of the Hamiltonian */
2698  memcpy( cartPosVec.data, values->data, 3*sizeof(REAL8) );
2699  memcpy( cartMomVec.data, values->data+3, 3*sizeof(REAL8) );
2700 
2701  /* Update Hamiltonian coefficients as per |Skerr| */
2702  s1Vec.data = s1Data;
2703  s2Vec.data = s2Data;
2704 
2705  s1VecOverMtMt.data = s1DataNorm;
2706  s2VecOverMtMt.data = s2DataNorm;
2707  for( k = 0; k < 3; k++ )
2708  {
2709  s1VecOverMtMt.data[k] = values->data[k+6];
2710  s2VecOverMtMt.data[k] = values->data[k+9];
2711  s1Vec.data[k] = s1VecOverMtMt.data[k] * mTotal * mTotal;
2712  s2Vec.data[k] = s2VecOverMtMt.data[k] * mTotal * mTotal;
2713  }
2714 
2715  seobParams.s1Vec = &s1VecOverMtMt;
2716  seobParams.s2Vec = &s2VecOverMtMt;
2717 
2718  XLALSimIMRSpinEOBCalculateSigmaStar( sigmaStar, m1, m2, &s1Vec, &s2Vec );
2719  XLALSimIMRSpinEOBCalculateSigmaKerr( sigmaKerr, m1, m2, &s1Vec, &s2Vec );
2720 
2721  seobParams.a = a = sqrt(inner_product(sigmaKerr->data, sigmaKerr->data));
2722 
2723  rcrossrdot[0] = LNhx;
2724  rcrossrdot[1] = LNhy;
2725  rcrossrdot[2] = LNhz;
2726  /* Eq. 16 of PRD 89, 084006 (2014): it's S_{1,2}/m_{1,2}^2.LNhat */
2727  s1dotLN = inner_product(s1Vec.data, rcrossrdot) / (m1*m1);
2728  s2dotLN = inner_product(s2Vec.data, rcrossrdot) / (m2*m2);
2729 
2730  chiS = 0.5 * (s1dotLN + s2dotLN);
2731  chiA = 0.5 * (s1dotLN - s2dotLN);
2732 
2733  switch ( SpinAlignedEOBversion )
2734  {
2735  case 1:
2736  /* See below Eq. 17 of PRD 86, 041011 (2012) */
2737  tplspin = 0.0;
2738  break;
2739  case 2:
2740  /* See below Eq. 4 of PRD 89, 061502(R) (2014)*/
2741  tplspin = (1.-2.*eta) * chiS + (m1 - m2)/(m1 + m2) * chiA;
2742  break;
2743  default:
2744  XLALPrintError( "XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1 and v2 are available.\n", __func__);
2746  FREE_SPHHARM
2748  break;
2749  }
2750 
2751  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs( &seobCoeffs, eta, a,
2752  SpinAlignedEOBversion ) == XLAL_FAILURE )
2753  XLAL_PRINT_INFO("\nSomething went wrong evaluating XLALSimIMRCalculateSpinPrecEOBHCoeffs in step %d of coarse dynamics\n",
2754  i );
2755 
2756  /* Update hlm coefficients */
2757  if ( XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients( eobParams.hCoeffs, m1, m2, eta,
2758  tplspin, chiS, chiA, 3 ) == XLAL_FAILURE ) /* This function returns XLAL_SUCCESS or calls XLAL_ERROR( XLAL_EINVAL ) */
2759  {
2760  XLAL_PRINT_INFO("\nSomething went wrong evaluating XLALSimIMRCalculateSpinPrecEOBHCoeffs in step %d of coarse dynamics\n",
2761  i );
2762  XLALPrintError("XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients failed!\n");
2763  PRINT_PARAMS
2765  }
2766 
2767  ham = XLALSimIMRSpinPrecEOBHamiltonian( eta, &cartPosVec, &cartMomVec,
2768  &s1VecOverMtMt, &s2VecOverMtMt,
2769  sigmaKerr, sigmaStar, seobParams.tortoise, &seobCoeffs );
2770 
2771  /* Calculate the polar data */
2772  polarDynamics.length = 4;
2773  polarDynamics.data = polData;
2774 
2775  /* Calculate the orbital angular momentum */
2776  cross_product( values->data, values->data+3, rcrossp );
2777  magL = sqrt(inner_product(rcrossp, rcrossp));
2778 
2779  polarDynamics.data[0] = sqrt(inner_product(values->data, values->data));
2780  polarDynamics.data[1] = phiMod.data[i] + phiDMod.data[i];
2781  polarDynamics.data[2] = inner_product(values->data, values->data+3) / polarDynamics.data[0];
2782  polarDynamics.data[3] = magL;
2783 
2785  &polarDynamics, values, v, ham, 2, 2, &seobParams ) == XLAL_FAILURE )
2786  {
2788  FREE_SPHHARM
2789  XLALPrintError("XLALSimIMRSpinEOBGetPrecSpinFactorizedWaveform failed!\n");
2790  PRINT_PARAMS
2791  XLAL_ERROR( XLAL_EDOM );
2792  }
2794  values, omega, &nqcCoeffs ) == XLAL_FAILURE )
2795  {
2797  FREE_SPHHARM
2798  XLALPrintError("XLALSimIMRSpinEOBNonQCCorrection failed!\n");
2799  PRINT_PARAMS
2800  XLAL_ERROR( XLAL_EDOM );
2801  }
2802  hLM *= hNQC;
2803  h22TS->data->data[i] = hLM;
2804  h2m2TS->data->data[i] = conj(hLM);
2805 
2806  if (debugPK) {
2807  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e ",
2808  i*deltaT/mTScaled, aI2P, bI2P, gI2P, aP2J, bP2J, gP2J );
2809  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
2810  polData[0], polData[1], polData[2], polData[3], ham, v,
2811  creal(hLM), cimag(hLM), creal(hLM/hNQC), cimag(hLM/hNQC) );
2812  fflush(NULL);
2813  }
2814 
2816  &polarDynamics, values, v, ham, 2, 1, &seobParams ) == XLAL_FAILURE )
2817  {
2819  FREE_SPHHARM
2820  XLALPrintError("XLALSimIMRSpinEOBGetPrecSpinFactorizedWaveform failed!\n");
2821  PRINT_PARAMS
2822  XLAL_ERROR( XLAL_EDOM );
2823  }
2824  h21TS->data->data[i] = hLM;
2825  h2m1TS->data->data[i] = conj(hLM);
2826  h20TS->data->data[i] = 0.0;
2827  }
2828  if(debugPK) {
2829  fclose( out );
2830  //fclose( out2 );
2831  XLAL_PRINT_INFO("YP: quasi-nonprecessing modes generated.\n"); fflush(NULL);
2832  }
2833 
2834  /* Add quasi-nonprecessing spherical harmonic modes to the SphHarmTimeSeries structure */
2835  hlmPTS = XLALSphHarmTimeSeriesAddMode( hlmPTS, h22TS, 2, 2 );
2836  hlmPTS = XLALSphHarmTimeSeriesAddMode( hlmPTS, h21TS, 2, 1 );
2837  hlmPTS = XLALSphHarmTimeSeriesAddMode( hlmPTS, h20TS, 2, 0 );
2838  hlmPTS = XLALSphHarmTimeSeriesAddMode( hlmPTS, h2m1TS, 2, -1 );
2839  hlmPTS = XLALSphHarmTimeSeriesAddMode( hlmPTS, h2m2TS, 2, -2 );
2840  XLALSphHarmTimeSeriesSetTData( hlmPTS, tlist );
2841 
2842  h22PTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, 2 );
2843  h21PTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, 1 );
2844  h20PTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, 0 );
2845  h2m1PTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, -1);
2846  h2m2PTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, -2);
2847 
2848  /* Write waveforms in precessing frame */
2849  if (debugPK) {
2850  XLAL_PRINT_INFO("YP: SphHarmTS structures populated.\n"); fflush(NULL);
2851  out = fopen( "PWaves.dat", "w" );
2852  for ( i = 0; i < retLenLow; i++ )
2853  {
2854  fprintf( out,
2855  "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
2856  i*deltaT/mTScaled,
2857  creal(h22PTS->data->data[i]), cimag(h22PTS->data->data[i]),
2858  creal(h21PTS->data->data[i]), cimag(h21PTS->data->data[i]),
2859  creal(h20PTS->data->data[i]), cimag(h20PTS->data->data[i]),
2860  creal(h2m1PTS->data->data[i]), cimag(h2m1PTS->data->data[i]),
2861  creal(h2m2PTS->data->data[i]), cimag(h2m2PTS->data->data[i]) );
2862  }
2863  fclose( out );
2864  XLAL_PRINT_INFO("YP: P-frame waveforms written to file.\n");
2865  fflush(NULL);
2866  }
2867 
2868 
2869  /* Main loop for quasi-nonprecessing waveform generation -- HIGH SR */
2870  if ( !(alphaI2PTSHi = XLALCreateREAL8TimeSeries( "alphaI2P", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(betaI2PTSHi = XLALCreateREAL8TimeSeries( "betaI2P", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(gammaI2PTSHi = XLALCreateREAL8TimeSeries( "gammaI2P", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(alphaP2JTSHi = XLALCreateREAL8TimeSeries( "alphaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(betaP2JTSHi = XLALCreateREAL8TimeSeries( "betaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(gammaP2JTSHi = XLALCreateREAL8TimeSeries( "gammaP2J", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) )
2871  {
2873  XLALDestroyREAL8Vector( tlistHi );
2874  XLALDestroyREAL8Vector( timeJFull );
2875  XLALDestroyREAL8Vector( timeIFull );
2876  XLALDestroyREAL8Vector( tlistRDPatch );
2877  XLALDestroyREAL8Vector( tlistRDPatchHi );
2878  XLALPrintError("Failed to allocate alphaI2PTSHi or betaI2PTSHi or gammaI2PTSHi or alphaP2JTSHi or betaP2JTSHi or gammaP2JTSHi!\n");
2879  PRINT_PARAMS
2881  }
2882 
2883  if ( !(h22TSHi = XLALCreateCOMPLEX16TimeSeries( "H_22", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(h21TSHi = XLALCreateCOMPLEX16TimeSeries( "H_21", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(h20TSHi = XLALCreateCOMPLEX16TimeSeries( "H_20", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(h2m1TSHi = XLALCreateCOMPLEX16TimeSeries( "H_2m1", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi )) + !(h2m2TSHi = XLALCreateCOMPLEX16TimeSeries( "H_2m2", &tc, 0.0, deltaT, &lalStrainUnit, retLenHi ))) {
2885  XLALDestroyREAL8Vector( tlistHi );
2886  XLALDestroyREAL8Vector( timeJFull );
2887  XLALDestroyREAL8Vector( timeIFull );
2888  XLALDestroyREAL8Vector( tlistRDPatch );
2889  XLALDestroyREAL8Vector( tlistRDPatchHi );
2890  XLALPrintError("Failed to allocate h22TSHi or h21TSHi or h20TSHi or h2m1TSHi or h2m2TSHi!\n");
2891  PRINT_PARAMS
2893  }
2894 
2895  hIMRJTSHi = XLALCreateCOMPLEX16TimeSeries(
2896  "HIMRJHi", &tc, 0.0, deltaTHigh, &lalStrainUnit, retLenHi + retLenRDPatchHi);
2897 
2898  if ( !(tlistHi = XLALCreateREAL8Vector( retLenHi )) || !(tlistRDPatchHi = XLALCreateREAL8Vector( retLenHi + retLenRDPatchHi)) )
2899  {
2900  XLALPrintError("Failed to allocate REAL8Vector tlistHi!\n");
2901  PRINT_PARAMS
2903  }
2904  memset( tlistHi->data, 0, tlistHi->length * sizeof( REAL8 ));
2905  memset( tlistRDPatchHi->data, 0, tlistRDPatchHi->length * sizeof( REAL8 ));
2906  for ( i = 0; i < retLenHi; i++ )
2907  {
2908  tlistHi->data[i] = i * deltaTHigh/mTScaled + HiSRstart;
2909  tlistRDPatchHi->data[i] = i * deltaTHigh/mTScaled + HiSRstart;
2910  }
2911  for ( i = retLenHi; i < retLenHi + retLenRDPatchHi; i++ )
2912  {
2913  tlistRDPatchHi->data[i] = i * deltaTHigh/mTScaled + HiSRstart;
2914  }
2915 
2916 
2917  // Generating modes for finely sampled portion
2918  if(debugPK) {
2919  XLAL_PRINT_INFO("Generating precessing-frame modes for fine dynamics\n");
2920  fflush(NULL);
2921  }
2922  if (debugPK) out = fopen( "rotDynamicsHi.dat", "w" );
2923  for ( i = 0; i < retLenHi; i++ )
2924  {
2925  for ( j = 0; j < values->length; j++ )
2926  {
2927  values->data[j] = dynamicsHi->data[(j+1)*retLenHi + i];
2928  }
2929 
2930  /* Calculate dr/dt */
2931  memset( dvalues->data, 0, 14*sizeof(dvalues->data[0]));
2932  if( XLALSpinPrecHcapRvecDerivative( 0, values->data, dvalues->data,
2933  &seobParams) != XLAL_SUCCESS )
2934  {
2935  XLAL_PRINT_INFO( " Calculation of dr/dt at t = tPeakOmega \n");
2937  XLALDestroyREAL8Vector( tlistHi );
2938  XLALDestroyREAL8Vector( timeJFull );
2939  XLALDestroyREAL8Vector( timeIFull );
2940  XLALDestroyREAL8Vector( tlistRDPatch );
2941  XLALDestroyREAL8Vector( tlistRDPatchHi );
2942  XLALPrintError("XLALSpinPrecHcapRvecDerivative failed!\n");
2943  PRINT_PARAMS
2944  XLAL_ERROR( XLAL_EDOM );
2945  }
2946 
2947  /* Calculate omega */
2948  rvec[0] = posVecxHi.data[i];
2949  rvec[1] = posVecyHi.data[i];
2950  rvec[2] = posVeczHi.data[i];
2951  memcpy( rdotvec, dvalues->data, 3*sizeof(REAL8));
2952  cross_product( rvec, rdotvec, rcrossrdot );
2953 
2954  magR = sqrt(inner_product(rvec, rvec));
2955  omega = sqrt(inner_product(rcrossrdot, rcrossrdot)) / (magR*magR);
2956  v = cbrt( omega );
2957 
2958  /* Cartesian vectors needed to calculate Hamiltonian */
2959  cartPosVec.length = cartMomVec.length = 3;
2960  cartPosVec.data = cartPosData;
2961  cartMomVec.data = cartMomData;
2962  memset( cartPosData, 0, sizeof( cartPosData ) );
2963  memset( cartMomData, 0, sizeof( cartMomData ) );
2964 
2965  magLN = sqrt(inner_product(rcrossrdot, rcrossrdot));
2966  LNhx = rcrossrdot[0] / magLN;
2967  LNhy = rcrossrdot[1] / magLN;
2968  LNhz = rcrossrdot[2] / magLN;
2969 
2970  aI2P = AlphaHi->data[i];
2971  bI2P = BetaHi->data[i];
2972  gI2P = GammaHi->data[i];
2973 
2974  EulerAnglesP2J(&aP2J, &bP2J, &gP2J, aI2P, bI2P, gI2P, LNhx, LNhy, LNhz, JframeEx, JframeEy, JframeEz);
2975 
2976  /* I2P Euler angles are stored only for debugging purposes */
2977  alphaI2PTSHi->data->data[i] = -aI2P;
2978  betaI2PTSHi->data->data[i] = bI2P;
2979  gammaI2PTSHi->data->data[i] = -gI2P;
2980  alphaP2JTSHi->data->data[i] = -aP2J;
2981  betaP2JTSHi->data->data[i] = bP2J;
2982  gammaP2JTSHi->data->data[i] = -gP2J;
2983 
2984  /* Calculate the value of the Hamiltonian */
2985  memcpy( cartPosVec.data, values->data, 3*sizeof(REAL8) );
2986  memcpy( cartMomVec.data, values->data+3, 3*sizeof(REAL8) );
2987 
2988  /* Update Hamiltonian coefficients as per |Skerr| */
2989  s1Vec.data = s1Data;
2990  s2Vec.data = s2Data;
2991 
2992  s1VecOverMtMt.data = s1DataNorm;
2993  s2VecOverMtMt.data = s2DataNorm;
2994  for( k = 0; k < 3; k++ )
2995  {
2996  s1VecOverMtMt.data[k] = values->data[k+6];
2997  s2VecOverMtMt.data[k] = values->data[k+9];
2998  s1Vec.data[k] = s1VecOverMtMt.data[k] * mTotal * mTotal;
2999  s2Vec.data[k] = s2VecOverMtMt.data[k] * mTotal * mTotal;
3000  }
3001 
3002  seobParams.s1Vec = &s1VecOverMtMt;
3003  seobParams.s2Vec = &s2VecOverMtMt;
3004 
3005  XLALSimIMRSpinEOBCalculateSigmaStar( sigmaStar, m1, m2, &s1Vec, &s2Vec );
3006  XLALSimIMRSpinEOBCalculateSigmaKerr( sigmaKerr, m1, m2, &s1Vec, &s2Vec );
3007 
3008  seobParams.a = a = sqrt(inner_product(sigmaKerr->data, sigmaKerr->data));
3009 
3010  rcrossrdot[0] = LNhx;
3011  rcrossrdot[1] = LNhy;
3012  rcrossrdot[2] = LNhz;
3013  s1dotLN = inner_product(s1Vec.data, rcrossrdot) / (m1*m1);
3014  s2dotLN = inner_product(s2Vec.data, rcrossrdot) / (m2*m2);
3015 
3016  chiS = 0.5 * (s1dotLN + s2dotLN);
3017  chiA = 0.5 * (s1dotLN - s2dotLN);
3018 
3019  switch ( SpinAlignedEOBversion )
3020  {
3021  case 1:
3022  /* See below Eq. 17 of PRD 86, 041011 (2012) */
3023  tplspin = 0.0;
3024  break;
3025  case 2:
3026  /* See below Eq. 4 of PRD 89, 061502(R) (2014)*/
3027  tplspin = (1.-2.*eta) * chiS + (m1 - m2)/(m1 + m2) * chiA;
3028  break;
3029  default:
3030  XLALPrintError( "XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1 and v2 are available.\n", __func__);
3032  XLALDestroyREAL8Vector( tlistHi );
3033  XLALDestroyREAL8Vector( timeJFull );
3034  XLALDestroyREAL8Vector( timeIFull );
3035  XLALDestroyREAL8Vector( tlistRDPatch );
3036  XLALDestroyREAL8Vector( tlistRDPatchHi );
3037  PRINT_PARAMS
3039  break;
3040  }
3041 
3042  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs( &seobCoeffs, eta, a,
3043  SpinAlignedEOBversion ) == XLAL_FAILURE )
3044  XLAL_PRINT_INFO("\nSomething went wrong evaluating XLALSimIMRCalculateSpinPrecEOBHCoeffs in step %d of coarse dynamics\n",
3045  i );
3046 
3047  /* Update hlm coefficients */
3048  if ( XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients( eobParams.hCoeffs, m1, m2, eta,
3049  tplspin, chiS, chiA, 3 ) == XLAL_FAILURE ) {
3050  XLAL_PRINT_INFO("\nSomething went wrong evaluating XLALSimIMRCalculateSpinPrecEOBHCoeffs in step %d of coarse dynamics\n",
3051  i );
3053  XLALDestroyREAL8Vector( tlistHi );
3054  XLALDestroyREAL8Vector( timeJFull );
3055  XLALDestroyREAL8Vector( timeIFull );
3056  XLALDestroyREAL8Vector( tlistRDPatch );
3057  XLALDestroyREAL8Vector( tlistRDPatchHi );
3058  XLALPrintError("XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients failed!\n");
3059  PRINT_PARAMS
3060  XLAL_ERROR( XLAL_EDOM );
3061  }
3062 
3063  ham = XLALSimIMRSpinPrecEOBHamiltonian( eta, &cartPosVec, &cartMomVec,
3064  &s1VecOverMtMt, &s2VecOverMtMt,
3065  sigmaKerr, sigmaStar, seobParams.tortoise, &seobCoeffs );
3066 
3067  /* Calculate the polar data */
3068  polarDynamics.length = 4;
3069  polarDynamics.data = polData;
3070 
3071  /* Calculate the orbital angular momentum */
3072  cross_product(values->data, values->data+3, rcrossp);
3073 
3074  polarDynamics.data[0] = sqrt(inner_product(values->data, values->data));
3075  polarDynamics.data[1] = phiModHi.data[i] + phiDModHi.data[i];
3076  polarDynamics.data[2] = inner_product(values->data, values->data+3) / polarDynamics.data[0];
3077  polarDynamics.data[3] = sqrt(inner_product(rcrossp, rcrossp));
3078 
3079 
3080  if ( XLALSimIMRSpinEOBGetPrecSpinFactorizedWaveform( &hLM, &polarDynamics, values, v, ham, 2, 2, &seobParams )
3081  == XLAL_FAILURE )
3082  {
3084  XLALDestroyREAL8Vector( tlistHi );
3085  XLALDestroyREAL8Vector( timeJFull );
3086  XLALDestroyREAL8Vector( timeIFull );
3087  XLALDestroyREAL8Vector( tlistRDPatch );
3088  XLALDestroyREAL8Vector( tlistRDPatchHi );
3089  XLALPrintError("XLALSimIMRSpinEOBGetPrecSpinFactorizedWaveform failed!\n");
3090  PRINT_PARAMS
3091  XLAL_ERROR( XLAL_EDOM );
3092  }
3093  if ( XLALSimIMRSpinEOBNonQCCorrection( &hNQC, values, omega, &nqcCoeffs ) == XLAL_FAILURE )
3094  {
3096  XLALDestroyREAL8Vector( tlistHi );
3097  XLALDestroyREAL8Vector( timeJFull );
3098  XLALDestroyREAL8Vector( timeIFull );
3099  XLALDestroyREAL8Vector( tlistRDPatch );
3100  XLALDestroyREAL8Vector( tlistRDPatchHi );
3101  XLALPrintError("XLALSimIMRSpinEOBNonQCCorrection failed!\n");
3102  PRINT_PARAMS
3103  XLAL_ERROR( XLAL_EDOM );
3104  }
3105  hLM *= hNQC;
3106  h22TSHi->data->data[i] = hLM;
3107  h2m2TSHi->data->data[i] = conj(hLM);
3108 
3109  if (debugPK){
3110  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e ",
3111  i*deltaTHigh/mTScaled + HiSRstart, aI2P, bI2P, gI2P, aP2J, bP2J, gP2J );
3112  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e, %.16e\n",
3113  rdotvec[0], rdotvec[1], rdotvec[2], LNhx, LNhy, LNhz, creal(hLM), cimag(hLM), polData[0]);
3114  }
3115 
3116  if ( XLALSimIMRSpinEOBGetPrecSpinFactorizedWaveform( &hLM, &polarDynamics, values, v, ham, 2, 1, &seobParams )
3117  == XLAL_FAILURE )
3118  {
3120  XLALDestroyREAL8Vector( tlistHi );
3121  XLALDestroyREAL8Vector( timeJFull );
3122  XLALDestroyREAL8Vector( timeIFull );
3123  XLALDestroyREAL8Vector( tlistRDPatch );
3124  XLALDestroyREAL8Vector( tlistRDPatchHi );
3125  XLALPrintError("XLALSimIMRSpinEOBGetPrecSpinFactorizedWaveform failed!\n");
3126  PRINT_PARAMS
3127  XLAL_ERROR( XLAL_EDOM );
3128  }
3129  h21TSHi->data->data[i] = hLM;
3130  h2m1TSHi->data->data[i] = conj(hLM);
3131  h20TSHi->data->data[i] = 0.0;
3132  }
3133  if (debugPK){
3134  fclose( out );
3135  XLAL_PRINT_INFO("YP: quasi-nonprecessing modes generated.for High SR\n");
3136  }
3137 
3138  /* Add quasi-nonprecessing spherical harmonic modes to the SphHarmTimeSeries structure */
3139  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h22TSHi, 2, 2 );
3140  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h21TSHi, 2, 1 );
3141  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h20TSHi, 2, 0 );
3142  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h2m1TSHi, 2, -1 );
3143  hlmPTSHi = XLALSphHarmTimeSeriesAddMode( hlmPTSHi, h2m2TSHi, 2, -2 );
3144  XLALSphHarmTimeSeriesSetTData( hlmPTSHi, tlistHi );
3145 
3146  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h22TSHi, 2, 2 );
3147  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h21TSHi, 2, 1 );
3148  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h20TSHi, 2, 0 );
3149  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h2m1TSHi, 2, -1 );
3150  hlmPTSout = XLALSphHarmTimeSeriesAddMode( hlmPTSout, h2m2TSHi, 2, -2 );
3151  *hlmPTSoutput = hlmPTSout;
3152 
3153  h22PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 2 );
3154  h21PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 1 );
3155  h20PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 0 );
3156  h2m1PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, -1);
3157  h2m2PTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, -2);
3158 
3159  if (debugPK){
3160  XLAL_PRINT_INFO("YP: SphHarmTS structures populated for HIgh SR.\n");
3161 
3162  out = fopen( "PWavesHi.dat", "w" );
3163  for ( i = 0; i < retLenHi; i++ )
3164  {
3165  fprintf( out, "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
3166  i*deltaTHigh/mTScaled + HiSRstart, creal(h22PTSHi->data->data[i]),
3167  cimag(h22PTSHi->data->data[i]),
3168  creal(h21PTSHi->data->data[i]), cimag(h21PTSHi->data->data[i]),
3169  creal(h20PTSHi->data->data[i]), cimag(h20PTSHi->data->data[i]),
3170  creal(h2m1PTSHi->data->data[i]), cimag(h2m1PTSHi->data->data[i]),
3171  creal(h2m2PTSHi->data->data[i]), cimag(h2m2PTSHi->data->data[i]));
3172  }
3173  fclose( out );
3174  XLAL_PRINT_INFO("YP: P-frame waveforms written to file for High SR.\n");
3175  fflush(NULL);
3176  }
3177 
3178  int foundAmp = 0;
3179  //REAL8 tMaxAmp;
3180  /* double */ tAmpMax = XLALSimLocateAmplTime(&timeHi, h22PTSHi->data, radiusVec, &foundAmp, &tMaxAmp);
3181 
3182  if(foundAmp==0){
3183  if (debugPK){
3184  XLAL_PRINT_INFO("maximum of Amplitude or dot{Ampl} are not found \n");
3185  }
3186  }
3187  else{
3188  if (debugPK){
3189  XLAL_PRINT_INFO("The Amplitude-related time is found and it's %f \n", tAmpMax);
3190  }
3191  }
3192 
3193  if( foundAmp==0 && foundPeakOmega == 0){
3194  if (debugPK){
3195  XLALPrintError("Houston, we've got a problem SOS, SOS, SOS, cannot find the RD attachment point... m1 = %.16e, m2 = %.16e, fMin = %.16e, inclination = %.16e, Mtotal = %.16e, eta = %.16e, spin1 = {%.16e, %.16e, %.16e}, spin2 = {%.16e, %.16e, %.16e} \n",
3196  m1, m2, (double)fMin, (double)inc, mTotal, eta, spin1[0], spin1[1], spin1[2], spin2[0], spin2[1], spin2[2]);
3197  }
3198 
3199  tAttach = tAttach -2.0;
3200  //FREE_EVERYTHING
3201  //XLALDestroyREAL8Vector( timeJFull );
3202  //XLALDestroyREAL8Vector( timeIFull );
3203  //XLALDestroyREAL8Vector( tlistRDPatch );
3204  //XLALDestroyREAL8Vector( tlistRDPatchHi );
3205  //XLAL_ERROR( XLAL_EINVAL );
3206  }
3207 
3208 
3209  if (tAmpMax < tAttach){
3210  if (debugPK){
3211  XLAL_PRINT_INFO("Stas the attachment time will be modified from %f to %f \n", tAttach, tAmpMax);
3212  }
3213  tAttach = tAmpMax;
3214  }
3215 
3216  if (debugPK){
3217  XLAL_PRINT_INFO("Stas: the final decision on the attachment time is %f \n", tAttach);
3218  }
3219 
3220  /* Changing retLen back to the Low SR value */
3221  // retLen = retLenLow;
3222 
3223  // END UNOPTIMIZED CODE CHUNK (straight from LALSuite master, Nov 14, 2016). CONTINUES ALL THE WAY TO START OF STEP 6!
3224  }
3225 
3226 /* *********************************************************************************
3227  * *********************************************************************************
3228  * STEP 6) Rotate quasi-nonprecessing waveforms from precessing to final J-frame
3229  * *********************************************************************************
3230  * **********************************************************************************/
3231  if(!use_optimized) {
3232  if ( XLALSimInspiralPrecessionRotateModes( hlmPTS, alphaP2JTS, betaP2JTS, gammaP2JTS ) == XLAL_FAILURE )
3233  {
3235  XLALDestroyREAL8Vector( timeJFull );
3236  XLALDestroyREAL8Vector( timeIFull );
3237  XLALDestroyREAL8Vector( tlistRDPatch );
3238  XLALDestroyREAL8Vector( tlistRDPatchHi );
3239  XLALPrintError("XLALSimInspiralPrecessionRotateModes failed!\n");
3240  PRINT_PARAMS
3242  }
3243  h22JTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, 2 );
3244  h21JTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, 1 );
3245  h20JTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, 0 );
3246  h2m1JTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, -1);
3247  h2m2JTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, -2);
3248 
3249 
3250  if (debugPK){
3251  XLAL_PRINT_INFO("YP: PtoJ rotation done.\n");
3252  out = fopen( "JWaves.dat", "w" );
3253  for ( i = 0; i < retLenLow; i++ )
3254  {
3255  fprintf( out,
3256  "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
3257  i*deltaT/mTScaled,
3258  creal(h22JTS->data->data[i]), cimag(h22JTS->data->data[i]),
3259  creal(h21JTS->data->data[i]), cimag(h21JTS->data->data[i]),
3260  creal(h20JTS->data->data[i]), cimag(h20JTS->data->data[i]),
3261  creal(h2m1JTS->data->data[i]), cimag(h2m1JTS->data->data[i]),
3262  creal(h2m2JTS->data->data[i]), cimag(h2m2JTS->data->data[i]) );
3263  }
3264  fclose( out );
3265  XLAL_PRINT_INFO("YP: P-frame waveforms written to file.\n");
3266  fflush(NULL);
3267  }
3268  }
3269 
3270  /* Stas: Rotating the high sampling part */
3271  if ( XLALSimInspiralPrecessionRotateModes( hlmPTSHi,
3272  alphaP2JTSHi, betaP2JTSHi, gammaP2JTSHi ) == XLAL_FAILURE )
3273  {
3275  XLALDestroyREAL8Vector( timeJFull );
3276  XLALDestroyREAL8Vector( timeIFull );
3277  XLALDestroyREAL8Vector( tlistRDPatch );
3278  XLALDestroyREAL8Vector( tlistRDPatchHi );
3279  XLALPrintError("XLALSimInspiralPrecessionRotateModes failed!\n");
3280  PRINT_PARAMS
3282  }
3283  h22JTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 2 );
3284  h21JTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 1 );
3285  h20JTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, 0 );
3286  h2m1JTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, -1);
3287  h2m2JTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, -2);
3288 
3289  *hlmPTSHiOutput = hlmPTSHi;
3290 
3291  if (debugPK) {
3292  out = fopen( "JWavesHi.dat", "w" );
3293  for ( i = 0; i < retLenHi; i++ )
3294  {
3295  fprintf( out,
3296  "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
3297  timeHi.data[i]+HiSRstart,
3298  creal(h22JTSHi->data->data[i]), cimag(h22JTSHi->data->data[i]),
3299  creal(h21JTSHi->data->data[i]), cimag(h21JTSHi->data->data[i]),
3300  creal(h20JTSHi->data->data[i]), cimag(h20JTSHi->data->data[i]),
3301  creal(h2m1JTSHi->data->data[i]), cimag(h2m1JTSHi->data->data[i]),
3302  creal(h2m2JTSHi->data->data[i]), cimag(h2m2JTSHi->data->data[i]) );
3303  }
3304  fclose( out );
3305  }
3306 
3307  sigReHi = XLALCreateREAL8Vector( retLenHi + retLenRDPatchHi);
3308  sigImHi = XLALCreateREAL8Vector( retLenHi + retLenRDPatchHi);
3309  if ( !sigReHi || !sigImHi )
3310  {
3311  XLALPrintError("Failed to allocate REAL8Vector sigReHi or sigImHi!\n");
3312  PRINT_PARAMS
3314  }
3315  memset( sigReHi->data, 0, sigReHi->length * sizeof( sigReHi->data[0] ));
3316  memset( sigImHi->data, 0, sigImHi->length * sizeof( sigImHi->data[0] ));
3317 
3318 
3319 /* *********************************************************************************
3320  * *********************************************************************************
3321  * STEP 7) Attach ringdown to J-frame modes
3322  * *********************************************************************************
3323  * **********************************************************************************/
3324  if ( combSize > tAttach )
3325  {
3326  XLALPrintError( "Function: %s, The comb size looks to be too big!!!\n", __func__ );
3328  XLALDestroyREAL8Vector( timeJFull );
3329  XLALDestroyREAL8Vector( timeIFull );
3330  XLALDestroyREAL8Vector( tlistRDPatch );
3331  XLALDestroyREAL8Vector( tlistRDPatchHi );
3332  PRINT_PARAMS
3334  }
3335  rdMatchPoint->data[0] = combSize < tAttach ? tAttach - combSize : 0;
3336  rdMatchPoint->data[1] = tAttach;
3337  rdMatchPoint->data[2] = (retLenHi-1)*deltaTHigh/mTScaled;
3338  if (debugPK){
3339  XLAL_PRINT_INFO("YP::comb range: %f, %f\n",
3340  rdMatchPoint->data[0],rdMatchPoint->data[1]);
3341  XLAL_PRINT_INFO("Stas, tAttach = %f, comb range = %f to %f \n",
3342  tAttach, rdMatchPoint->data[0]+HiSRstart,
3343  rdMatchPoint->data[1]+HiSRstart);
3344  fflush(NULL);
3345  }
3346 
3347  rdMatchPoint->data[0] = trunc(rdMatchPoint->data[0] / (deltaTHigh/mTScaled) ) * (deltaTHigh/mTScaled);
3348  rdMatchPoint->data[1] = trunc(rdMatchPoint->data[1] / (deltaTHigh/mTScaled) ) * (deltaTHigh/mTScaled);
3349 
3350  if (debugPK){
3351  XLAL_PRINT_INFO("Stas: matching points (again) %f, %f or %f, %f \n",
3352  rdMatchPoint->data[0],rdMatchPoint->data[1],
3353  rdMatchPoint->data[0]+HiSRstart,rdMatchPoint->data[1]+HiSRstart);
3354  fflush(NULL);
3355  }
3356 
3357  sh = 0.;
3358  REAL8 chi = tplspin/(1. - 2.*eta);
3359  if (chi >= 0.7 && chi < 0.8) {
3360  sh = -9. * (eta - 0.25);
3361  }
3362  if ((eta > 30. / 31. / 31. && eta <= 10. / 121. && chi >= 0.8) || (eta <= 30. / 31. / 31. && chi >= 0.8 && chi < 0.9)) {
3363  //This is case 4 in T1400476 - v3
3364  sh = -9. * (eta - 0.25) * (1. + 2. * exp(-(chi - 0.85) * (chi - 0.85) / 0.05 / 0.05)) * (1. + 1. / (1. + exp((eta - 0.01) / 0.001)));
3365  }
3366  if (eta < 30. / 31. / 31. && chi >= 0.9) {
3367  //This is case 5 in T1400476 - v3
3368  sh = 0.55 - 9. * (eta - 0.25) * (1. + 2. * exp(-(chi - 0.85) * (chi - 0.85) / 0.05 / 0.05)) * (1. + 1. / (1. + exp((eta - 0.01) / 0.001)));
3369  }
3370  if (eta > 10. / 121. && chi >= 0.8) {
3371  //This is case 6 in T1400476 - v3
3372  sh = 1. - 9. * (eta - 0.25) * (1. + 2. * exp(-(chi - 0.85) * (chi - 0.85) / 0.05 / 0.05)) * (1. + 1. / (1. + exp((eta - 0.01) / 0.001)));
3373  }
3374 
3375 
3376  /* Self-adjusting ringdown attachment. See https://dcc.ligo.org/T1500548 */
3377  int CheckRDAttachment = 1;
3378  if (CheckRDAttachment ){
3379 
3380  if (debugPK) XLAL_PRINT_INFO("Stas: checking the RD attachment point....\n");fflush(NULL);
3381 
3382  int pass = 0;
3383  rdMatchPoint->data[0] = combSize < tAttach ? tAttach - combSize : 0;
3384  rdMatchPoint->data[1] = tAttach;
3385  rdMatchPoint->data[0] = rdMatchPoint->data[0] - sh;
3386  rdMatchPoint->data[1] = rdMatchPoint->data[1] - sh;
3387  rdMatchPoint->data[2] = (retLenHi-1)*deltaTHigh/mTScaled;
3388  rdMatchPoint->data[0] = trunc(rdMatchPoint->data[0] / (deltaTHigh/mTScaled) ) * (deltaTHigh/mTScaled);
3389  rdMatchPoint->data[1] = trunc(rdMatchPoint->data[1] / (deltaTHigh/mTScaled) ) * (deltaTHigh/mTScaled);
3390 
3391  REAL8 thr = 1.01;
3392  REAL8 ratio22 = 1.0;
3393  REAL8 ratio2m2 = 1.0;
3394  REAL8 timediff = 0.;
3395 
3396  for ( i = 0; i < retLenHi; i++ )
3397  {
3398  sigReHi->data[i] = creal(h22JTSHi->data->data[i]);
3399  sigImHi->data[i] = cimag(h22JTSHi->data->data[i]);
3400  }
3401 
3402  if( XLALSimCheckRDattachment(sigReHi, sigImHi, &ratio22, tAttach, 2, 2,
3403  deltaTHigh, m1, m2, 0.0, 0.0, chi1L, 0.0, 0.0, chi2L,
3404  &timeHi, rdMatchPoint, spinEOBApproximant, kappaJL, &timediff) == XLAL_FAILURE )
3405  {
3407  XLALDestroyREAL8Vector( timeJFull );
3408  XLALDestroyREAL8Vector( timeIFull );
3409  XLALDestroyREAL8Vector( tlistRDPatch );
3410  XLALDestroyREAL8Vector( tlistRDPatchHi );
3411  XLALPrintError("XLALSimCheckRDattachment failed!\n");
3412  PRINT_PARAMS
3413  XLAL_ERROR( XLAL_EDOM );
3414  }
3415 
3416  memset( sigReHi->data, 0, sigReHi->length * sizeof( sigReHi->data[0] ));
3417  memset( sigImHi->data, 0, sigImHi->length * sizeof( sigImHi->data[0] ));
3418 
3419  for ( i = 0; i < retLenHi; i++ )
3420  {
3421  sigReHi->data[i] = creal(h2m2JTSHi->data->data[i]);
3422  sigImHi->data[i] = cimag(h2m2JTSHi->data->data[i]);
3423  }
3424 
3425  if( XLALSimCheckRDattachment(sigReHi, sigImHi, &ratio2m2, tAttach, 2, -2,
3426  deltaTHigh, m1, m2, 0.0, 0.0, chi1L, 0.0, 0.0, chi2L,
3427  &timeHi, rdMatchPoint, spinEOBApproximant, kappaJL, &timediff ) == XLAL_FAILURE ) {
3429  XLALDestroyREAL8Vector( timeJFull );
3430  XLALDestroyREAL8Vector( timeIFull );
3431  XLALDestroyREAL8Vector( tlistRDPatch );
3432  XLALDestroyREAL8Vector( tlistRDPatchHi );
3433  XLALPrintError("XLALSimCheckRDattachment failed!\n");
3434  PRINT_PARAMS
3435  XLAL_ERROR( XLAL_EDOM );
3436  }
3437 
3438  if (debugPK){
3439  XLAL_PRINT_INFO("At first check: ratio22 ratio2m2 %e %e\n", ratio22, ratio2m2);fflush(NULL);
3440  }
3441  if(ratio22 <= thr && ratio2m2 <=thr){
3442  pass = 1;
3443  }
3444  if (pass == 0){
3445  thr = 1.;
3446  if (debugPK){
3447  XLAL_PRINT_INFO("Adjusting RD attachment point... \n");fflush(NULL);
3448  XLAL_PRINT_INFO("initial ratios: %f, %f \n", ratio22, ratio2m2);
3449  fflush(NULL);
3450  }
3451 
3452  memset( sigReHi->data, 0, sigReHi->length * sizeof( sigReHi->data[0] ));
3453  memset( sigImHi->data, 0, sigImHi->length * sizeof( sigImHi->data[0] ));
3454 
3455  int found_att = XLALSimAdjustRDattachmentTime( sigReHi, sigImHi, h22JTSHi, h2m2JTSHi,
3456  &ratio22, &ratio2m2, &tAttach, thr,
3457  deltaTHigh, m1, m2, 0.0, 0.0, chi1L, 0.0, 0.0, chi2L,
3458  &timeHi, rdMatchPoint, spinEOBApproximant, kappaJL, combSize, tMaxOmega, tMaxAmp);
3459 
3460  if (debugPK){
3461  if (found_att == 1){
3462  XLAL_PRINT_INFO("we have found new attachment point tAtt = %f, with ratios %f, %f \n",
3463  tAttach, ratio22, ratio2m2);fflush(NULL);
3464  }
3465  else if (found_att == 2) {
3466  XLAL_PRINT_INFO("we haven't found proper attachment point, we picked the best point at tAtt = %f with ratios %f, %f\n", tAttach, ratio22, ratio2m2);fflush(NULL);
3467 
3468  }
3469  else{
3470  XLAL_PRINT_INFO("we haven't found proper attachment point, best ratios are %f, %f at tAtt = %f \n",
3471  ratio22, ratio2m2, tAttach);fflush(NULL);
3472  }
3473  }
3474 
3475  }
3476  memset( sigReHi->data, 0, sigReHi->length * sizeof( sigReHi->data[0] ));
3477  memset( sigImHi->data, 0, sigImHi->length * sizeof( sigImHi->data[0] ));
3478 
3479 
3480  } //end of RD attachment if
3481 
3482  if (debugRD){
3483  out = fopen( "tAttach.dat", "w" );
3484  fprintf( out, "%.16e %.16e %.16e %.16e \n", tPeakOmega, deltaNQC, tAmpMax, tAttach);
3485  fclose(out);
3486 
3487  }
3488  AttachParams->data[0] = tPeakOmega;
3489  AttachParams->data[1] = deltaNQC;
3490  AttachParams->data[2] = tAmpMax;
3491  AttachParams->data[3] = tAttach;
3492  AttachParams->data[4] = HiSRstart;
3493 
3494  rdMatchPoint->data[0] = combSize < tAttach ? tAttach - combSize : 0;
3495  rdMatchPoint->data[1] = tAttach;
3496  rdMatchPoint->data[0] = rdMatchPoint->data[0] - sh;
3497  rdMatchPoint->data[1] = rdMatchPoint->data[1] - sh;
3498  rdMatchPoint->data[2] = (retLenHi-1)*deltaTHigh/mTScaled;
3499  rdMatchPoint->data[0] = trunc(rdMatchPoint->data[0] / (deltaTHigh/mTScaled) ) * (deltaTHigh/mTScaled);
3500  rdMatchPoint->data[1] = trunc(rdMatchPoint->data[1] / (deltaTHigh/mTScaled) ) * (deltaTHigh/mTScaled);
3501 
3502 
3503  /*** Stas Let's try to attach RD to 2,2 mode: ***/
3504  INT4 m = 0;
3505  for ( m = -2; m < 3; m++ )
3506  {
3507  hJTSHi = XLALSphHarmTimeSeriesGetMode( hlmPTSHi, 2, m );
3508  for ( i = 0; i < retLenHi; i++ )
3509  {
3510  sigReHi->data[i] = creal(hJTSHi->data->data[i]);
3511  sigImHi->data[i] = cimag(hJTSHi->data->data[i]);
3512  }
3513  if ( XLALSimIMREOBHybridAttachRingdownPrec( sigReHi, sigImHi, 2, m,
3514  deltaTHigh, m1, m2, 0.0, 0.0, chi1L, 0.0, 0.0, chi2L,
3515  &timeHi, rdMatchPoint, spinEOBApproximant, kappaJL )
3516  == XLAL_FAILURE ) {
3518  XLALDestroyREAL8Vector( timeJFull );
3519  XLALDestroyREAL8Vector( timeIFull );
3520  XLALDestroyREAL8Vector( tlistRDPatch );
3521  XLALDestroyREAL8Vector( tlistRDPatchHi );
3522  XLALPrintError("XLALSimIMREOBHybridAttachRingdownPrec failed!\n");
3523  PRINT_PARAMS
3524  XLAL_ERROR( XLAL_EDOM );
3525  }
3526 
3527  for ( i = 0; i < (int)sigReHi->length; i++ )
3528  {
3529  hIMRJTSHi->data->data[i] = (sigReHi->data[i]) + I * (sigImHi->data[i]);
3530  }
3531  hIMRlmJTSHi = XLALSphHarmTimeSeriesAddMode( hIMRlmJTSHi, hIMRJTSHi, 2, m );
3532  }
3533  XLALSphHarmTimeSeriesSetTData( hIMRlmJTSHi, tlistRDPatchHi );
3534  if (debugPK){ XLAL_PRINT_INFO("YP: J wave RD attachment done.\n"); fflush(NULL); }
3535 
3536  hIMR22JTSHi = XLALSphHarmTimeSeriesGetMode( hIMRlmJTSHi, 2, 2 );
3537  hIMR21JTSHi = XLALSphHarmTimeSeriesGetMode( hIMRlmJTSHi, 2, 1 );
3538  hIMR20JTSHi = XLALSphHarmTimeSeriesGetMode( hIMRlmJTSHi, 2, 0 );
3539  hIMR2m1JTSHi = XLALSphHarmTimeSeriesGetMode( hIMRlmJTSHi, 2, -1);
3540  hIMR2m2JTSHi = XLALSphHarmTimeSeriesGetMode( hIMRlmJTSHi, 2, -2);
3541 
3542  /** We search for maximum of the frame-invariant amplitude and set its time as time of
3543  * coalescence (or reference time) */
3544  // find tc which is accosiated with max of invariant amplitude:
3545  REAL8Vector *invAmp = XLALCreateREAL8Vector( hIMR22JTSHi->data->length );
3546  for (i=0; i < retLenHi + retLenRDPatchHi; i++ ){
3547  invAmp->data[i] = creal(hIMR22JTSHi->data->data[i])*creal(hIMR22JTSHi->data->data[i]) +
3548  cimag(hIMR22JTSHi->data->data[i]) * cimag(hIMR22JTSHi->data->data[i]) +
3549  creal(hIMR21JTSHi->data->data[i])*creal(hIMR21JTSHi->data->data[i]) +
3550  cimag(hIMR21JTSHi->data->data[i]) * cimag(hIMR21JTSHi->data->data[i]) +
3551  creal(hIMR20JTSHi->data->data[i])*creal(hIMR20JTSHi->data->data[i]) +
3552  cimag(hIMR20JTSHi->data->data[i]) * cimag(hIMR20JTSHi->data->data[i]) +
3553  creal(hIMR2m1JTSHi->data->data[i])*creal(hIMR2m1JTSHi->data->data[i]) +
3554  cimag(hIMR2m1JTSHi->data->data[i]) * cimag(hIMR2m1JTSHi->data->data[i]) +
3555  creal(hIMR2m2JTSHi->data->data[i])*creal(hIMR2m2JTSHi->data->data[i]) +
3556  cimag(hIMR2m2JTSHi->data->data[i]) * cimag(hIMR2m2JTSHi->data->data[i]);
3557  }
3558  REAL8 invAmpmax = invAmp->data[0];
3559  int i_maxiA = 0;
3560  for (i=1; i < retLenHi + retLenRDPatchHi - 1; i++){
3561  if ( invAmp->data[i] >= invAmp->data[i-1] && invAmp->data[i] > invAmp->data[i+1] && invAmp->data[i] > invAmpmax){
3562  i_maxiA = i;
3563  invAmpmax = invAmp->data[i];
3564  }
3565  }
3566  if(debugPK){
3567  XLAL_PRINT_INFO("We set tc = %.16e, %.16e \n", (tlistRDPatchHi->data[i_maxiA] ), -mTScaled * (tlistRDPatchHi->data[i_maxiA] ));
3568  }
3569 
3570 
3571  /* Having found the time of peak, we set the time of coalescence */
3572  //XLALGPSAdd(&tc, -mTScaled * (tPeakOmega + HiSRstart) );
3573  XLALGPSAdd( &tc, -mTScaled * (tlistRDPatchHi->data[i_maxiA] ));
3574  XLALDestroyREAL8Vector( invAmp ); // we don't need it anymore
3575 
3576  hPlusTS = XLALCreateREAL8TimeSeries( "H_PLUS",
3577  &tc, 0.0, deltaT, &lalStrainUnit, retLenLow + retLenRDPatchLow );
3578  hCrossTS = XLALCreateREAL8TimeSeries( "H_CROSS",
3579  &tc, 0.0, deltaT, &lalStrainUnit, retLenLow + retLenRDPatchLow );
3580 
3581 
3582 
3583  *hIMRlmJTSHiOutput = hIMRlmJTSHi;
3584  if (debugPK){
3585  out = fopen( "JIMRWavesHi.dat", "w" );
3586  for ( i = 0; i < retLenHi + retLenRDPatchHi; i++ )
3587  {
3588  fprintf( out,
3589  "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
3590  tlistRDPatchHi->data[i],
3591  creal(hIMR22JTSHi->data->data[i]), cimag(hIMR22JTSHi->data->data[i]),
3592  creal(hIMR21JTSHi->data->data[i]), cimag(hIMR21JTSHi->data->data[i]),
3593  creal(hIMR20JTSHi->data->data[i]), cimag(hIMR20JTSHi->data->data[i]),
3594  creal(hIMR2m1JTSHi->data->data[i]), cimag(hIMR2m1JTSHi->data->data[i]),
3595  creal(hIMR2m2JTSHi->data->data[i]), cimag(hIMR2m2JTSHi->data->data[i]) );
3596  }
3597  fclose( out );
3598 
3599  XLAL_PRINT_INFO("Stas: down sampling and make the complete waveform in J-frame\n");
3600  fflush(NULL);
3601  }
3602 
3603  int idxRD = 0; // V3OPT
3604 
3605  /*** attach hi sampling part and resample */
3606  if(use_optimized) { /* SEOBNRv3_opt makes big, similar sections conditional here to avoid placing conditionals in slower for-loops */
3607  hIMRJTS = XLALCreateCOMPLEX16TimeSeries( "HMRJLO2K", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow + retLenRDPatchLow );
3608  *hIMRlmJTSHiOutput = hIMRlmJTSHi;
3609  }
3610 
3611  for ( k = 2; k > -3; k-- ) {
3612  hIMRJTS2mHi = XLALSphHarmTimeSeriesGetMode( hIMRlmJTSHi, 2, k );
3613  for ( i = 0; i < retLenHi + retLenRDPatchHi; i++ )
3614  {
3615  sigReHi->data[i] = creal(hIMRJTS2mHi->data->data[i]);
3616  sigImHi->data[i] = cimag(hIMRJTS2mHi->data->data[i]);
3617  }
3618  /* recycling h20PTS */
3619  if(use_optimized) {
3620  for (i = 0; i< retLenLow; i++){
3621  if (i*deltaT/mTScaled > HiSRstart) break;//Andrea
3622  hIMRJTS->data->data[i] = 0.;
3623  }
3624  }else{
3625  hJTS = XLALSphHarmTimeSeriesGetMode( hlmPTS, 2, k );
3626  for (i = 0; i< retLenLow; i++){
3627  if (i*deltaT/mTScaled > HiSRstart) break;//Andrea
3628  hIMRJTS->data->data[i] = hJTS->data->data[i];
3629  }
3630  }
3631  idxRD = i;
3632 
3633  spline = gsl_spline_alloc( gsl_interp_cspline, retLenHi + retLenRDPatchHi);
3634  acc = gsl_interp_accel_alloc();
3635  gsl_spline_init( spline, tlistRDPatchHi->data, sigReHi->data, retLenHi + retLenRDPatchHi);
3636  for (i = idxRD; i< retLenLow+retLenRDPatchLow; i++){
3637  if( i*deltaT/mTScaled <= tlistRDPatchHi->data[ retLenHi + retLenRDPatchHi- 1]) {
3638  hIMRJTS->data->data[i] = gsl_spline_eval( spline, tlistRDPatch->data[i], acc );
3639  }
3640  else {
3641  hIMRJTS->data->data[i] = 0.;
3642  }
3643  }
3644 
3645  gsl_spline_free(spline);
3646  gsl_interp_accel_free(acc);
3647 
3648  spline = gsl_spline_alloc( gsl_interp_cspline, retLenHi + retLenRDPatchHi);
3649  acc = gsl_interp_accel_alloc();
3650  gsl_spline_init( spline, tlistRDPatchHi->data, sigImHi->data, retLenHi + retLenRDPatchHi);
3651  for (i = idxRD; i< retLenLow+retLenRDPatchLow; i++){
3652  if( i*deltaT/mTScaled <= tlistRDPatchHi->data[ retLenHi + retLenRDPatchHi- 1]) {
3653  hIMRJTS->data->data[i] += I * gsl_spline_eval( spline, tlistRDPatch->data[i], acc );
3654  }
3655  else {
3656  hIMRJTS->data->data[i] += I*0.;
3657  }
3658  }
3659  gsl_spline_free(spline);
3660  gsl_interp_accel_free(acc);
3661 
3662  hIMRlmJTS = XLALSphHarmTimeSeriesAddMode( hIMRlmJTS, hIMRJTS, 2, k );
3663  }
3664 
3665  for (i=0; i<(int)tlistRDPatch->length; i++){
3666  timeJFull->data[i] = tlistRDPatch->data[i];
3667  }
3668  XLALSphHarmTimeSeriesSetTData( hIMRlmJTS, timeJFull );
3669  if (debugPK){ XLAL_PRINT_INFO("Stas: J-wave with RD generated.\n"); fflush(NULL); }
3670 
3671  hIMR22JTS = XLALSphHarmTimeSeriesGetMode( hIMRlmJTS, 2, 2 );
3672  hIMR21JTS = XLALSphHarmTimeSeriesGetMode( hIMRlmJTS, 2, 1 );
3673  hIMR20JTS = XLALSphHarmTimeSeriesGetMode( hIMRlmJTS, 2, 0 );
3674  hIMR2m1JTS = XLALSphHarmTimeSeriesGetMode( hIMRlmJTS, 2, -1);
3675  hIMR2m2JTS = XLALSphHarmTimeSeriesGetMode( hIMRlmJTS, 2, -2);
3676 
3677  if (debugPK){
3678  out = fopen( "JIMRWaves.dat", "w" );
3679  for ( i = 0; i < retLenLow + retLenRDPatchLow; i++ )
3680  {
3681  fprintf( out,
3682  "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
3683  i*deltaT/mTScaled,
3684  creal(hIMR22JTS->data->data[i]), cimag(hIMR22JTS->data->data[i]),
3685  creal(hIMR21JTS->data->data[i]), cimag(hIMR21JTS->data->data[i]),
3686  creal(hIMR20JTS->data->data[i]), cimag(hIMR20JTS->data->data[i]),
3687  creal(hIMR2m1JTS->data->data[i]), cimag(hIMR2m1JTS->data->data[i]),
3688  creal(hIMR2m2JTS->data->data[i]), cimag(hIMR2m2JTS->data->data[i]) );
3689  }
3690  fclose( out );
3691  XLAL_PRINT_INFO("YP: IMR J wave written to file.\n");
3692  fflush(NULL);
3693  }
3694 
3695 
3696 /* *********************************************************************************
3697  * *********************************************************************************
3698  * STEP 8) Rotate modes from final final-J-frame to initial inertial frame
3699  * *********************************************************************************
3700  * **********************************************************************************/
3701  /* Euler Angles to go from final-J-frame to initial inertial frame */
3702  gamJtoI = atan2(JframeEz[1], -JframeEz[0]);
3703  betJtoI = acos(JframeEz[2]);
3704  alJtoI = atan2(JframeEy[2], JframeEx[2]);
3705  if (fabs(betJtoI - LAL_PI) < 1.e-10){
3706  gamJtoI = 0.0;
3707  alJtoI = atan2(JframeEx[1], JframeEx[0]);
3708  }
3709  if (fabs(betJtoI) < 1.e-10){
3710  gamJtoI = 0.0;
3711  alJtoI = atan2(JframeEx[1], JframeEx[0]);
3712  }
3713 
3714  if (debugPK){
3715  XLAL_PRINT_INFO("Stas: J->I EA = %.16e, %.16e, %.16e \n", alJtoI, betJtoI, gamJtoI);
3716  fflush(NULL);
3717  }
3718 
3719  alpI = XLALCreateREAL8TimeSeries( "alphaJ2I", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow + retLenRDPatchLow );
3720  betI = XLALCreateREAL8TimeSeries( "betaJ2I", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow + retLenRDPatchLow );
3721  gamI = XLALCreateREAL8TimeSeries( "gammaJ2I", &tc, 0.0, deltaT, &lalStrainUnit, retLenLow + retLenRDPatchLow );
3722 
3723  /** NOTE we are making again transformation between notations of Arun et. al adopted here and
3724  * Wiegner matrix (active rotation) coded up in LAL */
3725 
3726  for (i=0; i< retLenLow + retLenRDPatchLow; i++){
3727  alpI->data->data[i] = -alJtoI;
3728  betI->data->data[i] = betJtoI;
3729  gamI->data->data[i] = -gamJtoI;
3730  }
3731  for (i=0; i<(int)tlistRDPatch->length; i++){
3732  timeIFull->data[i] = tlistRDPatch->data[i];
3733  }
3734 
3735  hIMRlmITS = XLALSphHarmTimeSeriesAddMode( hIMRlmITS, hIMR22JTS, 2, 2 );
3736  hIMRlmITS = XLALSphHarmTimeSeriesAddMode( hIMRlmITS, hIMR21JTS, 2, 1 );
3737  hIMRlmITS = XLALSphHarmTimeSeriesAddMode( hIMRlmITS, hIMR20JTS, 2, 0 );
3738  hIMRlmITS = XLALSphHarmTimeSeriesAddMode( hIMRlmITS, hIMR2m1JTS, 2, -1 );
3739  hIMRlmITS = XLALSphHarmTimeSeriesAddMode( hIMRlmITS, hIMR2m2JTS, 2, -2 );
3740  XLALSphHarmTimeSeriesSetTData( hIMRlmITS, timeIFull );
3741 
3742  /* Rotate J-frame modes */
3743  if (debugPK){ XLAL_PRINT_INFO("Rotation to inertial I-frame\n"); fflush(NULL); }
3744  if ( XLALSimInspiralPrecessionRotateModes( hIMRlmITS,
3745  alpI, betI, gamI ) == XLAL_FAILURE ) {
3747  XLALPrintError("XLALSimInspiralPrecessionRotateModes failed!\n");
3748  PRINT_PARAMS
3750  }
3751  hIMR22ITS = XLALSphHarmTimeSeriesGetMode( hIMRlmITS, 2, 2 );
3752  hIMR21ITS = XLALSphHarmTimeSeriesGetMode( hIMRlmITS, 2, 1 );
3753  hIMR20ITS = XLALSphHarmTimeSeriesGetMode( hIMRlmITS, 2, 0 );
3754  hIMR2m1ITS = XLALSphHarmTimeSeriesGetMode( hIMRlmITS, 2, -1);
3755  hIMR2m2ITS = XLALSphHarmTimeSeriesGetMode( hIMRlmITS, 2, -2);
3756 
3757  *hIMRoutput = XLALSphHarmTimeSeriesAddMode( *hIMRoutput, hIMR22ITS, 2, 2 );
3758  *hIMRoutput = XLALSphHarmTimeSeriesAddMode( *hIMRoutput, hIMR21ITS, 2, 1 );
3759  *hIMRoutput = XLALSphHarmTimeSeriesAddMode( *hIMRoutput, hIMR20ITS, 2, 0 );
3760  *hIMRoutput = XLALSphHarmTimeSeriesAddMode( *hIMRoutput, hIMR2m1ITS, 2, -1 );
3761  *hIMRoutput = XLALSphHarmTimeSeriesAddMode( *hIMRoutput, hIMR2m2ITS, 2, -2 );
3762  XLALSphHarmTimeSeriesSetTData( *hIMRoutput, tlistRDPatch );
3763 
3764  if (debugPK){
3765  out = fopen( "IWaves.dat", "w" );
3766  for ( i = 0; i < retLenLow + retLenRDPatchLow; i++ )
3767  {
3768  fprintf( out,
3769  "%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
3770  tlistRDPatch->data[i],
3771  creal(hIMR22ITS->data->data[i]), cimag(hIMR22ITS->data->data[i]),
3772  creal(hIMR21ITS->data->data[i]), cimag(hIMR21ITS->data->data[i]),
3773  creal(hIMR20ITS->data->data[i]), cimag(hIMR20ITS->data->data[i]),
3774  creal(hIMR2m1ITS->data->data[i]), cimag(hIMR2m1ITS->data->data[i]),
3775  creal(hIMR2m2ITS->data->data[i]), cimag(hIMR2m2ITS->data->data[i]) );
3776  }
3777  fclose( out );
3778  }
3779 
3780 /* *********************************************************************************
3781  * *********************************************************************************
3782  * STEP 9) Compute h+, hx
3783  * ********************************************************************************
3784  * **********************************************************************************/
3785  if(!use_optimized) {
3786  //incl_temp = inc;
3787  //incl_temp = 0.0;
3788  /** NOTE that we have use now different convention: the phi_ref (or one might call it phi_c) is now
3789  * the azimuthal phase of the observer in the source (I-)frame. Together with inclination angle it defines
3790  * the position of the observer in the (I-)frame associated with the source at t=0 */
3791 
3792  Y22 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, 2 );
3793  Y2m2 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, -2 );
3794  Y21 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, 1 );
3795  Y2m1 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, -1 );
3796  Y20 = XLALSpinWeightedSphericalHarmonic( inc, LAL_PI/2.-phiC, -2, 2, 0 );
3797  /*if ( SpinsAlmostAligned ) {
3798  Y22 = XLALSpinWeightedSphericalHarmonic( inc, coa_phase_offset, -2, 2, 2 );
3799  Y2m2 = XLALSpinWeightedSphericalHarmonic( inc, coa_phase_offset, -2, 2, -2 );
3800  Y21 = XLALSpinWeightedSphericalHarmonic( inc, coa_phase_offset, -2, 2, 1 );
3801  Y2m1 = XLALSpinWeightedSphericalHarmonic( inc, coa_phase_offset, -2, 2, -1 );
3802  Y20 = XLALSpinWeightedSphericalHarmonic( inc, coa_phase_offset, -2, 2, 0 );
3803  }
3804  else {
3805  Y22 = XLALSpinWeightedSphericalHarmonic( incl_temp, coa_phase_offset, -2, 2, 2 );
3806  Y2m2 = XLALSpinWeightedSphericalHarmonic( incl_temp, coa_phase_offset, -2, 2, -2 );
3807  Y21 = XLALSpinWeightedSphericalHarmonic( incl_temp, coa_phase_offset, -2, 2, 1 );
3808  Y2m1 = XLALSpinWeightedSphericalHarmonic( incl_temp, coa_phase_offset, -2, 2, -1 );
3809  Y20 = XLALSpinWeightedSphericalHarmonic( incl_temp, coa_phase_offset, -2, 2, 0 );
3810  }*/
3811 
3812  if(debugPK){ XLAL_PRINT_INFO("Ylm %e %e %e %e %e %e %e %e %e %e \n", creal(Y22), cimag(Y22), creal(Y2m2), cimag(Y2m2), creal(Y21), cimag(Y21), creal(Y2m1), cimag(Y2m1), creal(Y20), cimag (Y20)); fflush(NULL); }
3813  }
3814  for ( i = 0; i < (INT4)hIMR22ITS->data->length; i++ )
3815  {
3816  x11 = Y22*hIMR22ITS->data->data[i] + Y21*hIMR21ITS->data->data[i]
3817  + Y20*hIMR20ITS->data->data[i] + Y2m1*hIMR2m1ITS->data->data[i]
3818  + Y2m2*hIMR2m2ITS->data->data[i];
3819  hPlusTS->data->data[i] = amp0*creal(x11);
3820  hCrossTS->data->data[i] = -amp0*cimag(x11);
3821  }
3822  if(use_optimized)
3823  {
3824  for ( i = 0; i < idxRD; i++ )
3825  {
3826  hPlusTS->data->data[i] = amp0*hVec->data[i+retLenLow];
3827  hCrossTS->data->data[i] = -amp0*hVec->data[i+2*retLenLow];
3828  }
3829  if( hVec != NULL ) XLALDestroyREAL8Array( hVec );
3830  }
3831 
3832  /* Point the output pointers to the relevant time series and return */
3833  (*hplus) = hPlusTS;
3834  (*hcross) = hCrossTS;
3835 
3836  if (debugPK){
3837  XLAL_PRINT_INFO("plus and cross are computed, freeing the memory\n");
3838  fflush(NULL);
3839  }
3840  XLALDestroyREAL8TimeSeries(alphaI2PTS);
3841  XLALDestroyREAL8TimeSeries(betaI2PTS);
3842  XLALDestroyREAL8TimeSeries(gammaI2PTS);
3843  XLALDestroyREAL8TimeSeries(alphaP2JTS);
3844  XLALDestroyREAL8TimeSeries(betaP2JTS);
3845  XLALDestroyREAL8TimeSeries(gammaP2JTS);
3846  XLALDestroyREAL8TimeSeries(alphaI2PTSHi);
3847  XLALDestroyREAL8TimeSeries(betaI2PTSHi);
3848  XLALDestroyREAL8TimeSeries(gammaI2PTSHi);
3849  XLALDestroyREAL8TimeSeries(alphaP2JTSHi);
3850  XLALDestroyREAL8TimeSeries(betaP2JTSHi);
3851  XLALDestroyREAL8TimeSeries(gammaP2JTSHi);
3858  XLALDestroySphHarmTimeSeries(hIMRlmJTS);
3859  XLALDestroySphHarmTimeSeries(hIMRlmITS);
3866  XLALDestroyCOMPLEX16TimeSeries(hIMRJTSHi);
3867  XLALDestroyREAL8Vector( values );
3868  XLALDestroyREAL8Vector( dvalues );
3869  XLALDestroyREAL8Vector( sigmaStar );
3870  XLALDestroyREAL8Vector( sigmaKerr );
3871  XLALDestroyREAL8Vector( sigReHi );
3872  XLALDestroyREAL8Vector( sigImHi );
3873  XLALAdaptiveRungeKuttaFree(integrator);
3874  XLALDestroyREAL8Array( dynamics );
3875  XLALDestroyREAL8Vector( Alpha );
3876  XLALDestroyREAL8Vector( Beta );
3877  XLALDestroyREAL8Vector( AlphaHi );
3878  XLALDestroyREAL8Vector( BetaHi );
3879  XLALDestroyREAL8Vector( Gamma );
3880  XLALDestroyREAL8Vector( GammaHi );
3884  XLALDestroyREAL8Vector( rdMatchPoint );
3885  XLALDestroyREAL8Vector( radiusVec );
3886  if ( dynamicsEOMLo != NULL ) {
3887  XLALDestroyREAL8Array( dynamicsEOMLo );
3888  }
3889  if ( dynamicsEOMHi != NULL ) {
3890  XLALDestroyREAL8Array( dynamicsEOMHi );
3891  }
3892 
3893  /* FIXME: Temporary code to convert REAL8Array to REAL8Vector because SWIG
3894  * doesn't seem to like REAL8Array */
3895  REAL8Vector *tmp_vec;
3896  tmp_vec = XLALCreateREAL8Vector(dynamicsHi->dimLength->data[0] * dynamicsHi->dimLength->data[1]);
3897  UINT4 tmp_idx_ii;
3898  for (tmp_idx_ii=0; tmp_idx_ii < tmp_vec->length; tmp_idx_ii++)
3899  {
3900  tmp_vec->data[tmp_idx_ii] = dynamicsHi->data[tmp_idx_ii];
3901  }
3902  *dynHi = tmp_vec;
3903  XLALDestroyREAL8Array( dynamicsHi );
3904  XLALDestroyREAL8Vector( valuesV2 );
3905  if (dynamicsV2 != NULL){
3906  XLALDestroyREAL8Array( dynamicsV2 );
3907  }
3908  if (dynamicsV2Hi != NULL){
3909  XLALDestroyREAL8Array( dynamicsV2Hi );
3910  }
3911  if(debugPK){ XLAL_PRINT_INFO("Memory cleanup ALL done.\n"); fflush(NULL); }
3912 
3913  return XLAL_SUCCESS;
3914  }
3915 
3916 #undef FREE_EVERYTHING
3917 #endif
INT4 XLALSimIMREOBGenerateQNMFreqV2Prec(COMPLEX16Vector *modefreqs, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1[3], const REAL8 spin2[3], UINT4 l, INT4 m, UINT4 nmodes, Approximant approximant)
This function generates the quasinormal mode frequencies for a black hole ringdown.
double XLALSimLocateAmplTime(REAL8Vector *timeHi, COMPLEX16Vector *hP22, REAL8Vector *radiusVec, int *found, REAL8 *tMaxAmp)
int XLALSimAdjustRDattachmentTime(REAL8Vector *signal1, REAL8Vector *signal2, COMPLEX16TimeSeries *h22, COMPLEX16TimeSeries *h2m2, REAL8 *ratio22, REAL8 *ratio2m2, REAL8 *tAttach, const REAL8 thr, const REAL8 dt, const REAL8 m1, const REAL8 m2, const REAL8 spin1x, const REAL8 spin1y, const REAL8 spin1z, const REAL8 spin2x, const REAL8 spin2y, const REAL8 spin2z, REAL8Vector *timeVec, REAL8Vector *matchrange, Approximant approximant, const REAL8 JLN, const REAL8 combSize, const REAL8 tMaxOmega, const REAL8 tMaxAmp)
double XLALSimLocateOmegaTime(REAL8Array *dynamicsHi, unsigned int numdynvars, unsigned int retLenHi, SpinEOBParams seobParams, SpinEOBHCoeffs seobCoeffs, REAL8 m1, REAL8 m2, REAL8Vector *radiusVec, int *found, REAL8 *tMaxOmega, INT4 use_optimized)
INT4 XLALSimCheckRDattachment(REAL8Vector *signal1, REAL8Vector *signal2, REAL8 *ratio, const REAL8 tAtt, const INT4 l, const INT4 m, const REAL8 dt, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1x, const REAL8 spin1y, const REAL8 spin1z, const REAL8 spin2x, const REAL8 spin2y, const REAL8 spin2z, REAL8Vector *timeVec, REAL8Vector *matchrange, Approximant approximant, const REAL8 JLN, REAL8 *timediff)
static int XLALSimIMRCalculateSpinPrecEOBHCoeffs(SpinEOBHCoeffs *coeffs, const REAL8 eta, const REAL8 a, const UINT4 SpinAlignedEOBversion)
This function is used to calculate some coefficients which will be used in the spinning EOB Hamiltoni...
static UNUSED INT4 XLALSimIMREOBHybridAttachRingdownPrec(REAL8Vector *signal1, REAL8Vector *signal2, const INT4 l, const INT4 m, const REAL8 dt, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1x, const REAL8 spin1y, const REAL8 spin1z, const REAL8 spin2x, const REAL8 spin2y, const REAL8 spin2z, REAL8Vector *timeVec, REAL8Vector *matchrange, Approximant approximant, const REAL8 JLN)
The main workhorse function for performing the ringdown attachment for EOB models EOBNRv2 and SEOBNRv...
static UNUSED int XLALSimIMRSpinEOBNonQCCorrection(COMPLEX16 *restrict nqc, REAL8Vector *restrict values, const REAL8 omega, EOBNonQCCoeffs *restrict coeffs)
This function calculates the non-quasicircular correction to apply to the waveform.
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakDeltaTv2(INT4 UNUSED l, INT4 UNUSED m, REAL8 UNUSED m1, REAL8 UNUSED m2, REAL8 chi1, REAL8 chi2)
The time difference between the orbital peak and the peak amplitude of the mode in question (currentl...
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakDeltaT(INT4 l, INT4 m, REAL8 UNUSED eta, REAL8 a)
The time difference between the orbital peak and the peak amplitude of the mode in question (currentl...
static UNUSED REAL8 XLALSimIMREOBGetNRSpinPeakOmegav2(INT4 UNUSED l, INT4 UNUSED m, REAL8 UNUSED eta, REAL8 a)
Peak frequency predicted by fitting NR results (currently only 2,2 available).
static UNUSED int XLALSimIMRGetEOBCalibratedSpinNQC(EOBNonQCCoeffs *restrict coeffs, INT4 UNUSED l, INT4 UNUSED m, REAL8 eta, REAL8 a)
More recent versions of the EOB models, such as EOBNRv2 and SEOBNRv1, utilise a non-quasicircular cor...
static UNUSED int XLALSimIMRGetEOBCalibratedSpinNQC3D(EOBNonQCCoeffs *restrict coeffs, INT4 UNUSED l, INT4 UNUSED m, REAL8 m1, REAL8 m2, REAL8 a, REAL8 chiAin)
Function to 3D-interpolate known amplitude NQC coeffcients of spin terms for SEOBNRv2,...
static UNUSED int XLALSimIMREOBComputeNewtonMultipolePrefixes(NewtonMultipolePrefixes *prefix, const REAL8 m1, const REAL8 m2)
Function which computes the various coefficients in the Newtonian multipole.
static double f_alphadotcosi(double x, void *inparams)
static int XLALSpinAlignedHcapDerivative(double t, const REAL8 values[], REAL8 dvalues[], void *funcParams)
static int XLALSimIMRSpinEOBCalculateSigmaKerr(REAL8Vector *sigmaKerr, REAL8 mass1, REAL8 mass2, REAL8Vector *s1, REAL8Vector *s2)
Function to calculate normalized spin of the deformed-Kerr background in SEOBNRv1.
static int XLALSimIMRSpinEOBCalculateSigmaStar(REAL8Vector *sigmaStar, REAL8 mass1, REAL8 mass2, REAL8Vector *s1, REAL8Vector *s2)
Function to calculate normalized spin of the test particle in SEOBNRv1.
static int XLALSimIMREOBCalcSpinFacWaveformCoefficients(FacWaveformCoeffs *const coeffs, SpinEOBParams *restrict params, const REAL8 m1, const REAL8 m2, const REAL8 eta, const REAL8 a, const REAL8 chiS, const REAL8 chiA, const UINT4 SpinAlignedEOBversion)
Spin Factors.
static int XLALSimIMREOBCalcSpinPrecFacWaveformCoefficients(FacWaveformCoeffs *const coeffs, const REAL8 m1, const REAL8 m2, const REAL8 eta, const REAL8 a, const REAL8 chiS, const REAL8 chiA, const UINT4 SpinAlignedEOBversion)
Waveform expressions are given by Taracchini et al.
static INT4 XLALSimIMRSpinEOBGetPrecSpinFactorizedWaveform(COMPLEX16 *restrict hlm, REAL8Vector *restrict values, REAL8Vector *restrict cartvalues, const REAL8 v, const REAL8 Hreal, const INT4 l, const INT4 m, SpinEOBParams *restrict params)
This function calculates hlm mode factorized-resummed waveform for given dynamical variables.
static REAL8 XLALSimIMRSpinPrecEOBHamiltonian(const REAL8 eta, REAL8Vector *restrict x, REAL8Vector *restrict p, REAL8Vector *restrict s1Vec, REAL8Vector *restrict s2Vec, REAL8Vector *restrict sigmaKerr, REAL8Vector *restrict sigmaStar, int tortoise, SpinEOBHCoeffs *coeffs)
static REAL8 * cross_product(const REAL8 values1[], const REAL8 values2[], REAL8 result[])
static int XLALSpinPrecHcapRvecDerivative(double UNUSED t, const REAL8 values[], REAL8 dvalues[], void *funcParams)
Function to calculate numerical derivatives of the spin EOB Hamiltonian, to get , as decribed in Eqs.
static REAL8 inner_product(const REAL8 values1[], const REAL8 values2[])
Functions to compute the inner product and cross products between vectors.
static int XLALSpinPrecHcapExactDerivative(double UNUSED t, const REAL8 values[], REAL8 dvalues[], void *funcParams)
Function to calculate numerical derivatives of the spin EOB Hamiltonian, which correspond to time der...
static int XLALSpinPrecHcapNumericalDerivative(double UNUSED t, const REAL8 values[], REAL8 dvalues[], void *funcParams)
Function to calculate numerical derivatives of the spin EOB Hamiltonian, which correspond to time der...
static int XLALSimIMRSpinEOBInitialConditions(REAL8Vector *initConds, const REAL8 mass1, const REAL8 mass2, const REAL8 fMin, const REAL8 inc, const REAL8 spin1[], const REAL8 spin2[], SpinEOBParams *params, INT4 use_optimized_v2)
Main function for calculating the spinning EOB initial conditions, following the quasi-spherical init...
static int XLALSimIMRSpinEOBInitialConditionsPrec(REAL8Vector *initConds, const REAL8 mass1, const REAL8 mass2, const REAL8 fMin, const REAL8 inc, const REAL8 spin1[], const REAL8 spin2[], SpinEOBParams *params, INT4 use_optimized)
Main function for calculating the spinning EOB initial conditions, following the quasi-spherical init...
#define PRINT_PARAMS
static UNUSED int XLALEOBSpinPrecStopConditionBasedOnPR(double UNUSED t, const double values[], double dvalues[], void UNUSED *funcParams)
Stopping conditions for dynamics integration for SEOBNRv3.
static int XLALSpinPrecAlignedHiSRStopCondition(double UNUSED t, const double UNUSED values[], double dvalues[], void UNUSED *funcParams)
Stopping condition for the high resolution SEOBNRv1/2 orbital evolution – stop when reaching a minimu...
static int XLALEOBSpinPrecAlignedStopCondition(double UNUSED t, const double values[], double dvalues[], void *funcParams)
Stopping condition for the regular resolution SEOBNRv1/2 orbital evolution – stop when reaching max o...
SEOBHCoeffConstants XLALEOBSpinPrecCalcSEOBHCoeffConstants(REAL8 eta)
Optimized routine for calculating coefficients for the v3 Hamiltonian.
#define FREE_SPHHARM
#define FREE_EVERYTHING
int XLALSimIMRSpinEOBWaveformAll(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8Vector **dynHi, SphHarmTimeSeries **hlmPTSoutput, SphHarmTimeSeries **hlmPTSHiOutput, SphHarmTimeSeries **hIMRlmJTSHiOutput, SphHarmTimeSeries **hIMRoutput, REAL8Vector **AttachPars, const REAL8 phiC, const REAL8 deltaT, const REAL8 m1SI, const REAL8 m2SI, const REAL8 fMin, const REAL8 r, const REAL8 inc, const REAL8 INspin1x, const REAL8 INspin1y, const REAL8 INspin1z, const REAL8 INspin2x, const REAL8 INspin2y, const REAL8 INspin2z, const UINT4 PrecEOBversion)
This function generates precessing spinning SEOBNRv3 waveforms h+ and hx.
int XLALSimIMRSpinEOBWaveform(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, const REAL8 phiC, const REAL8 deltaT, const REAL8 m1SI_in, const REAL8 m2SI_in, const REAL8 fMin, const REAL8 r, const REAL8 inc, const REAL8 INspin1[], const REAL8 INspin2[], const UINT4 PrecEOBversion)
Standard interface for SEOBNRv3 waveform generator: calls XLALSimIMRSpinEOBWaveformAll.
static UNUSED void EulerAnglesP2J(REAL8 *aP2J, REAL8 *bP2J, REAL8 *gP2J, const REAL8 aI2P, const REAL8 bI2P, const REAL8 gI2P, const REAL8 LNhx, const REAL8 LNhy, const REAL8 LNhz, const REAL8 JframeEx[], const REAL8 JframeEy[], const REAL8 JframeEz[])
Given Euler angles to go from initial inertial frame to precessing frama and the LNhat vector,...
static UNUSED int EulerAnglesI2P(REAL8Vector *Alpha, REAL8Vector *Beta, REAL8Vector *Gamma, INT4 *phaseCounterA, INT4 *phaseCounterB, const REAL8Vector tVec, const REAL8Vector posVecx, const REAL8Vector posVecy, const REAL8Vector posVecz, const UINT4 retLenLow, const REAL8 InitialAlpha, const REAL8 InitialGamma, UINT4 flag_highSR, const UINT4 use_optimized)
Given the trajectory in an inertial frame, this computes Euler angles of the roation from the inertia...
static int SEOBNRv3OptimizedInterpolatorGeneral(REAL8 *yin, REAL8 tinit, REAL8 deltat, UINT4 num_input_times, REAL8Array **yout, size_t dim)
static void XLALEOBSpinPrecGenerateHTSModesFromEOMSoln(COMPLEX16 *hTSm2, COMPLEX16 *hTSm1, COMPLEX16 *hTS0, COMPLEX16 *hTSp1, COMPLEX16 *hTSp2, int retLen, REAL8Array *dynamics, SpinEOBParams *seobParams)
static void XLALEOBSpinPrecGenerateHplusHcrossTSFromEOMSoln(REAL8Vector *h, int retLen, REAL8Vector *AlphaI2PVec, REAL8Vector *BetaI2PVec, REAL8Vector *GammaI2PVec, REAL8 Jx[3], REAL8 Jy[3], REAL8 Jz[3], COMPLEX16 Y[5], REAL8Array *dynamics, SpinEOBParams *seobParams)
Module containing the energy and flux functions for waveform generation.
static int XLALSpinPrecHcapRvecDerivative_exact(double UNUSED t, const REAL8 values[], REAL8 dvalues[], void *funcParams)
Function to calculate exact derivatives of the spin EOB Hamiltonian, to get , as decribed in Eqs.
#define fprintf
double i
Definition: bh_ringdown.c:118
double e
Definition: bh_ringdown.c:117
const double r2
sigmaKerr data[0]
REAL8Array * XLALCreateREAL8ArrayL(UINT4,...)
void XLALDestroyREAL8Array(REAL8Array *)
int XLALAdaptiveRungeKutta4(LALAdaptiveRungeKuttaIntegrator *integrator, void *params, REAL8 *yinit, REAL8 tinit, REAL8 tend, REAL8 deltat, REAL8Array **yout)
void XLALAdaptiveRungeKuttaFree(LALAdaptiveRungeKuttaIntegrator *integrator)
LALAdaptiveRungeKuttaIntegrator * XLALAdaptiveRungeKutta4InitEighthOrderInstead(int dim, int(*dydt)(double t, const double y[], double dydt[], void *params), int(*stop)(double t, const double y[], double dydt[], void *params), double eps_abs, double eps_rel)
int XLALAdaptiveRungeKuttaDenseandSparseOutput(LALAdaptiveRungeKuttaIntegrator *integrator, void *params, REAL8 *yinit, REAL8 tinit, REAL8 tend, REAL8 deltat, REAL8Array **sparse_output, REAL8Array **dense_output)
LALAdaptiveRungeKuttaIntegrator * XLALAdaptiveRungeKutta4Init(int dim, int(*dydt)(double t, const double y[], double dydt[], void *params), int(*stop)(double t, const double y[], double dydt[], void *params), double eps_abs, double eps_rel)
#define LAL_MSUN_SI
#define LAL_PI
#define LAL_MTSUN_SI
#define LAL_MRSUN_SI
#define LIGOTIMEGPSZERO
double complex COMPLEX16
double REAL8
int64_t INT8
uint32_t UINT4
int32_t INT4
Approximant
Enum that specifies the PN approximant to be used in computing the waveform.
@ SEOBNRv3
Spin precessing EOBNR model v3.
@ SEOBNRv3_opt
Optimized Spin precessing EOBNR model v3.
int XLALSimInspiralPrecessionRotateModes(SphHarmTimeSeries *h_lm, REAL8TimeSeries *alpha, REAL8TimeSeries *beta, REAL8TimeSeries *gam)
Takes in the h_lm spherical harmonic decomposed modes and rotates the modes by Euler angles alpha,...
SphHarmTimeSeries * XLALSphHarmTimeSeriesAddMode(SphHarmTimeSeries *appended, const COMPLEX16TimeSeries *inmode, UINT4 l, INT4 m)
Prepend a node to a linked list of SphHarmTimeSeries, or create a new head.
COMPLEX16TimeSeries * XLALSphHarmTimeSeriesGetMode(SphHarmTimeSeries *ts, UINT4 l, INT4 m)
Get the time series of a waveform's (l,m) spherical harmonic mode from a SphHarmTimeSeries linked lis...
void XLALSphHarmTimeSeriesSetTData(SphHarmTimeSeries *ts, REAL8Sequence *tdata)
Set the tdata member for all nodes in the list.
void XLALDestroySphHarmTimeSeries(SphHarmTimeSeries *ts)
Delete list from current pointer to the end of the list.
static const INT4 r
static const INT4 m
static const INT4 a
COMPLEX16 XLALSpinWeightedSphericalHarmonic(REAL8 theta, REAL8 phi, int s, int l, int m)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
void XLALDestroyCOMPLEX16TimeSeries(COMPLEX16TimeSeries *series)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
COMPLEX16TimeSeries * XLALCreateCOMPLEX16TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalStrainUnit
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
#define XLAL_PRINT_INFO(...)
#define XLAL_ERROR(...)
#define XLAL_PRINT_WARNING(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
int int XLALPrintWarning(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFUNC
XLAL_EDOM
XLAL_EINVAL
XLAL_EFAILED
XLAL_FAILURE
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
list p
COMPLEX16Sequence * data
COMPLEX16 * data
The coefficients which are used in calculating the non-quasicircular correction to the EOBNRv2 model.
Structure containing all the parameters needed for the EOB waveform.
FacWaveformCoeffs * hCoeffs
NewtonMultipolePrefixes * prefixes
Structure containing the coefficients for calculating the factorized waveform.
TidalEOBParams * tidal2
TidalEOBParams * tidal1
int(* stop)(double t, const double y[], double dydt[], void *params)
Structure containing all the terms of the Newtonian multipole which are constant over the course of t...
gsl_interp_accel * alpha_acc
gsl_interp_accel * beta_acc
UINT4Vector * dimLength
REAL8 * data
REAL8Sequence * data
REAL8 * data
Structure to carry a collection of spherical harmonic modes in COMPLEX16 time series.
Parameters for the spinning EOB model, used in calculating the Hamiltonian.
UINT4 SpinAlignedEOBversion
TidalEOBParams * tidal1
TidalEOBParams * tidal2
Parameters for the spinning EOB model.
SpinEOBHCoeffs * seobCoeffs
REAL8Vector * sigmaStar
EOBNonQCCoeffs * nqcCoeffs
REAL8Vector * s1Vec
EOBParams * eobParams
REAL8Vector * sigmaKerr
SEOBHCoeffConstants * seobCoeffConsts
Approximant seobApproximant
REAL8Vector * s2Vec
Tidal parameters for EOB model of NS: mByM - dimensionless ratio m_{NS}/M lambda2Tidal - dimensionles...
UINT4 * data
Definition: burst.c:245
double deltaT
Definition: unicorn.c:24