LALSimulation  5.4.0.1-fe68b98
LALSimIMRSpinEOBInitialConditions.c
Go to the documentation of this file.
1 #include <lal/LALSimInspiral.h>
2 #include <lal/LALSimIMR.h>
3 
4 #include <gsl/gsl_vector.h>
5 #include <gsl/gsl_matrix.h>
6 #include <gsl/gsl_blas.h>
7 
8 #include <gsl/gsl_multiroots.h>
9 #include <gsl/gsl_deriv.h>
10 
11 #include "LALSimIMRSpinEOB.h"
14 /* OPTIMIZED */
17 /* END OPTIMIZED */
19 
20 #ifndef _LALSIMIMRSPINEOBINITIALCONDITIONS_C
21 #define _LALSIMIMRSPINEOBINITIALCONDITIONS_C
22 
23 /**
24  * Structure consisting SEOBNR parameters that can be used by gsl root finders
25  */
26 typedef
27 struct tagSEOBRootParams
28 {
29  REAL8 values[12]; /**<< Dynamical variables, x, y, z, px, py, pz, S1x, S1y, S1z, S2x, S2y and S2z */
30  SpinEOBParams *params; /**<< Spin EOB parameters -- physical, pre-computed, etc. */
31  REAL8 omega; /**<< Orbital frequency */
33 }
35 
36 /**
37  * Calculates the dot product of two vectors
38  */
39 static inline
40 REAL8
41 CalculateDotProduct( const REAL8 a[], const REAL8 b[] )
42 {
43  return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
44 }
45 
46 
47 /**
48  * calculates the ith component of the cross product of two vectors,
49  * where i is in the range 0-2.
50  */
51 static inline
52 REAL8
53 CalculateCrossProduct( const INT4 i, const REAL8 a[], const REAL8 b[] )
54 {
55  return a[(i+1)%3]*b[(i+2)%3] - a[(i+2)%3]*b[(i+1)%3];
56 }
57 
58 
59 /**
60  * Normalizes the given vector
61  */
62 static inline
63 int
65 {
66  REAL8 norm = sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] );
67 
68  a[0] /= norm;
69  a[1] /= norm;
70  a[2] /= norm;
71 
72  return XLAL_SUCCESS;
73 }
74 
75 /**
76  * Calculate the rotation matrix and its inverse.
77  * Rotate the ex-ey-ez frame to the r-v-L frame.
78  * This static function is called only by XLALSimIMRSpinEOBInitialConditions
79  */
80 static int
82  gsl_matrix *rotMatrix, /**< OUTPUT, rotation matrix */
83  gsl_matrix *rotInverse, /**< OUTPUT, rotation matrix inversed */
84  REAL8 r[], /**< position vector */
85  REAL8 v[], /**< velocity vector */
86  REAL8 L[] /**< orbital angular momentum */
87  )
88 {
89 
90  /** a, b, g are the angles alpha, beta and gamma */
91  /* Use a, b and g to avoid shadowing gamma and getting a warning */
92  REAL8 a, b, g;
93  REAL8 cosa, sina, cosb, sinb, cosg, sing;
94 
95  /* Calculate the Euclidean Euler angles */
96 
97  /* We need to avoid a singularity if L is along z axis */
98  if ( L[2] > 0.9999 )
99  {
100  a = b = g = 0.0;
101  }
102  else
103  {
104  a = atan2( L[0], -L[1] );
105  b = atan2( sqrt( L[0]*L[0] + L[1]*L[1] ), L[2] );
106  g = atan2( r[2], v[2] );
107  }
108 
109  if ( ( cosa = cos( a ) ) < 1.0e-16 ) cosa = 0.0;
110  if ( ( sina = sin( a ) ) < 1.0e-16 ) sina = 0.0;
111  if ( ( cosb = cos( b ) ) < 1.0e-16 ) cosb = 0.0;
112  if ( ( sinb = sin( b ) ) < 1.0e-16 ) sinb = 0.0;
113  if ( ( cosg = cos( g ) ) < 1.0e-16 ) cosg = 0.0;
114  if ( ( sing = sin( g ) ) < 1.0e-16 ) sing = 0.0;
115 
116 /**
117  * Implement the Rotation Matrix following the "x-convention"
118  * 1. rotate about the z-axis by an angle a, rotation matrix Rz(a);
119  * 2. rotate about the former x-axis (now x') by an angle b, rotation matrix Rx(b);
120  * 3. rotate about the former z-axis (now z') by an algle g, rotation matrix Rz(g);
121  */
122  /* populate the matrix */
123  gsl_matrix_set( rotMatrix, 0, 0, cosg*cosa - cosb*sina*sing );
124  gsl_matrix_set( rotMatrix, 0, 1, cosg*sina + cosb*cosa*sing );
125  gsl_matrix_set( rotMatrix, 0, 2, sing*sinb );
126  gsl_matrix_set( rotMatrix, 1, 0, -sing*cosa - cosb*sina*cosg );
127  gsl_matrix_set( rotMatrix, 1, 1, -sing*sina + cosb*cosa*cosg );
128  gsl_matrix_set( rotMatrix, 1, 2, cosg*sinb );
129  gsl_matrix_set( rotMatrix, 2, 0, sinb*sina );
130  gsl_matrix_set( rotMatrix, 2, 1, -sinb*cosa );
131  gsl_matrix_set( rotMatrix, 2, 2, cosb );
132 
133  /* Now populate the transpose (which should be the inverse) */
134  gsl_matrix_transpose_memcpy( rotInverse, rotMatrix );
135 
136  /* Test that the code does what it should do */
137  /* gsl_matrix *ab = gsl_matrix_alloc( 3, 3 );
138  gsl_blas_dgemm( CblasNoTrans, CblasNoTrans, 1., rotMatrix, rotInverse, 0., ab );
139  */
140 
141  /*printf( "The generated rotation matrix:?\n" );
142  for ( int i = 0; i < 3; i++ )
143  {
144  for ( int j = 0; j < 3; j++ )
145  {
146  printf( "%.16e\t", gsl_matrix_get( rotMatrix, i, j ) );
147  }
148  printf( "\n" );
149  }*/
150 
151  /*printf( "Is the transpose of the rotation matrix the inverse?\n" );
152  for ( int i = 0; i < 3; i++ )
153  {
154  for ( int j = 0; j < 3; j++ )
155  {
156  printf( "%.16e\t", gsl_matrix_get( ab, i, j ) );
157  }
158  printf( "\n" );
159  }*/
160  /*gsl_matrix_free( ab );*/
161 
162  return XLAL_SUCCESS;
163 }
164 
165 
166 /**
167  * Applies a rotation matrix to a given vector
168  */
169 static int
171  gsl_matrix *rotMatrix, /**< rotation matrix */
172  REAL8 a[] /**< OUTPUT, vector rotated */
173  )
174 {
175 
176  gsl_vector *tmpVec1 = gsl_vector_alloc( 3 );
177  gsl_vector *tmpVec2 = gsl_vector_calloc( 3 );
178 
179  gsl_vector_set( tmpVec1, 0, a[0] );
180  gsl_vector_set( tmpVec1, 1, a[1] );
181  gsl_vector_set( tmpVec1, 2, a[2] );
182 
183  gsl_blas_dgemv( CblasNoTrans, 1.0, rotMatrix, tmpVec1, 0.0, tmpVec2 );
184 
185  a[0] = gsl_vector_get( tmpVec2, 0 );
186  a[1] = gsl_vector_get( tmpVec2, 1 );
187  a[2] = gsl_vector_get( tmpVec2, 2 );
188 
189  gsl_vector_free( tmpVec1 );
190  gsl_vector_free( tmpVec2 );
191 
192  return XLAL_SUCCESS;
193 }
194 
195 /**
196  * Performs a co-ordinate transformation from spherical to Cartesian co-ordinates.
197  * In the code from Tyson Littenberg, this was only applicable to the special theta=pi/2, phi=0 case.
198  * This special transformation is a static function called only by
199  * GSLSpinHamiltonianDerivWrapper and XLALSimIMRSpinEOBInitialConditions
200  */
202  REAL8 qCart[], /**<< OUTPUT, position vector in Cartesean coordinates */
203  REAL8 pCart[], /**<< OUTPUT, momentum vector in Cartesean coordinates */
204  const REAL8 qSph[], /**<< position vector in spherical coordinates */
205  const REAL8 pSph[] /**<< momentum vector in spherical coordinates */
206  )
207 {
208 
209  REAL8 r;
210  REAL8 pr, pTheta, pPhi;
211 
212  REAL8 x, y, z;
213  REAL8 pX, pY, pZ;
214 
215  r = qSph[0];
216  pr = pSph[0];
217  pTheta = pSph[1];
218  pPhi = pSph[2];
219 
220  x = r;
221  y = 0.0;
222  z = 0.0;
223 
224  pX = pr;
225  pY = pPhi / r;
226  pZ = - pTheta / r;
227 
228  /* Copy these values to the output vectors */
229  qCart[0] = x;
230  qCart[1] = y;
231  qCart[2] = z;
232  pCart[0] = pX;
233  pCart[1] = pY;
234  pCart[2] = pZ;
235 
236  return XLAL_SUCCESS;
237 }
238 
239 
240 /**
241  * Perform a co-ordinate transformation from Cartesian to spherical co-ordinates.
242  * In the code from Tyson Littenberg, this was only applicable to the special theta=pi/2, phi=0 case.
243  * This special transformation is a static function called only by XLALSimIMRSpinEOBInitialConditions
244  */
246  REAL8 qSph[], /**<< OUTPUT, position vector in spherical coordinates */
247  REAL8 pSph[], /**<< OUTPUT, momentum vector in Cartesean coordinates */
248  const REAL8 qCart[], /**<< position vector in spherical coordinates */
249  const REAL8 pCart[] /**<< momentum vector in Cartesean coordinates */
250  )
251 {
252 
253  REAL8 r;
254  REAL8 pr, pTheta, pPhi;
255 
256  REAL8 x; //, y, z;
257  REAL8 pX, pY, pZ;
258 
259  x = qCart[0];
260  //y = qCart[1];
261  //z = qCart[2];
262  pX = pCart[0];
263  pY = pCart[1];
264  pZ = pCart[2];
265 
266  r = x;
267  pr = pX;
268  pTheta = - r * pZ;
269  pPhi = r * pY;
270 
271  /* Fill the output vectors */
272  qSph[0] = r;
273  qSph[1] = LAL_PI_2;
274  qSph[2] = 0.0;
275  pSph[0] = pr;
276  pSph[1] = pTheta;
277  pSph[2] = pPhi;
278 
279  return XLAL_SUCCESS;
280 }
281 
282 /**
283  * Root function for gsl root finders.
284  * The gsl root finder with look for gsl_vector *x position in parameter space
285  * where the returned values in gsl_vector *f are zero.
286  * The functions on which we search for roots are:
287  * dH/dr, dH/dptheta and dH/dpphi-omega,
288  * namely, Eqs. 4.8 and 4.9 of Buonanno et al. PRD 74, 104005 (2006).
289  */
290 static int
291 XLALFindSphericalOrbit( const gsl_vector *x, /**<< Parameters requested by gsl root finder */
292  void *params, /**<< Spin EOB parameters */
293  gsl_vector *f /**<< Function values for the given parameters */
294  )
295 {
296  SEOBRootParams *rootParams = (SEOBRootParams *) params;
297 
298  REAL8 py, pz, r, ptheta, pphi;
299 
300  /* Numerical derivative of Hamiltonian wrt given value */
301  REAL8 dHdx, dHdpy, dHdpz;
302  REAL8 dHdr, dHdptheta, dHdpphi;
303 
304  /* Populate the appropriate values */
305  /* In the special theta=pi/2 phi=0 case, r is x */
306  rootParams->values[0] = r = gsl_vector_get( x, 0 );
307  rootParams->values[4] = py = gsl_vector_get( x, 1 );
308  rootParams->values[5] = pz = gsl_vector_get( x, 2 );
309 
310  // printf( "Values r = %.16e, py = %.16e, pz = %.16e\n", r, py, pz );
311 
312  ptheta = - r * pz;
313  pphi = r * py;
314 
315  /* dHdR */
316  dHdx = XLALSpinHcapNumDerivWRTParam( 0, rootParams->values, rootParams->params );
317  if ( XLAL_IS_REAL8_FAIL_NAN( dHdx ) )
318  {
320  }
321  //printf( "dHdx = %.16e\n", dHdx );
322 
323  /* dHdPphi (I think we can use dHdPy in this coord system) */
324  /* TODO: Check this is okay */
325  dHdpy = XLALSpinHcapNumDerivWRTParam( 4, rootParams->values, rootParams->params );
326  if ( XLAL_IS_REAL8_FAIL_NAN( dHdpy ) )
327  {
329  }
330 
331  /* dHdPtheta (I think we can use dHdPz in this coord system) */
332  /* TODO: Check this is okay */
333  dHdpz = XLALSpinHcapNumDerivWRTParam( 5, rootParams->values, rootParams->params );
334  if ( XLAL_IS_REAL8_FAIL_NAN( dHdpz ) )
335  {
337  }
338 
339  /* Now convert to spherical polars */
340  dHdr = dHdx - dHdpy * pphi / (r*r) + dHdpz * ptheta / (r*r);
341  dHdptheta = - dHdpz / r;
342  dHdpphi = dHdpy / r;
343 
344  /* populate the function vector */
345  gsl_vector_set( f, 0, dHdr );
346  gsl_vector_set( f, 1, dHdptheta );
347  gsl_vector_set( f, 2, dHdpphi - rootParams->omega );
348 
349  //printf( "Current funcvals = %.16e %.16e %.16e\n", gsl_vector_get( f, 0 ), gsl_vector_get( f, 1 ),
350  // gsl_vector_get( f, 2 )/*dHdpphi*/ );
351 
352  return XLAL_SUCCESS;
353 }
354 
355 /**
356  * Wrapper for calculating specific derivative of the Hamiltonian in spherical co-ordinates,
357  * dH/dr, dH/dptheta and dH/dpphi.
358  * It only works for the specific co-ord system we use here
359  */
360 static double GSLSpinHamiltonianDerivWrapperHybrid( double x, /**<< Derivative at x */
361  void *params /**<< Function parameters */)
362 {
363 
365  REAL8 sphValues[12];
366  REAL8 cartValues[12];
367 
368  REAL8 dHdr, dHdx, dHdpy, dHdpz;
369  REAL8 r, ptheta, pphi;
370 
371  memcpy( sphValues, dParams->sphValues, sizeof( sphValues ) );
372  sphValues[dParams->varyParam1] = x;
373 
374  SphericalToCartesian( cartValues, cartValues+3, sphValues, sphValues+3 );
375  memcpy( cartValues+6, sphValues+6, 6*sizeof(REAL8) );
376 
377  r = sphValues[0];
378  ptheta = sphValues[4];
379  pphi = sphValues[5];
380 
381  /* Return the appropriate derivative according to varyParam2 */
382 
383  switch ( dParams->varyParam2 )
384  {
385  case 0:
386  /* dHdr */
387  dHdx = XLALSpinHcapHybDerivWRTParam( 0, cartValues, dParams->params );
388  dHdpy = XLALSpinHcapHybDerivWRTParam( 4, cartValues, dParams->params );
389  dHdpz = XLALSpinHcapHybDerivWRTParam( 5, cartValues, dParams->params );
390 
391  dHdr = dHdx - dHdpy * pphi / (r*r) + dHdpz * ptheta / (r*r);
392  //printf( "dHdr = %.16e\n", dHdr );
393  return dHdr;
394 
395  break;
396  case 4:
397  /* dHdptheta */
398  dHdpz = XLALSpinHcapHybDerivWRTParam( 5, cartValues, dParams->params );
399  return - dHdpz / r;
400  break;
401  case 5:
402  /* dHdpphi */
403  dHdpy = XLALSpinHcapHybDerivWRTParam( 4, cartValues, dParams->params );
404  return dHdpy / r;
405  break;
406  default:
407  XLALPrintError( "This option is not supported in the second derivative function!\n" );
409  break;
410  }
411 }
412 
413 
414 /**
415  * Wrapper for calculating specific derivative of the Hamiltonian in spherical co-ordinates,
416  * dH/dr, dH/dptheta and dH/dpphi.
417  * It only works for the specific co-ord system we use here
418  */
419 static double GSLSpinHamiltonianDerivWrapper( double x, /**<< Derivative at x */
420  void *params /**<< Function parameters */)
421 {
422 
424 
425  REAL8 sphValues[12];
426  REAL8 cartValues[12];
427 
428  REAL8 dHdr, dHdx, dHdpy, dHdpz;
429  REAL8 r, ptheta, pphi;
430 
431  memcpy( sphValues, dParams->sphValues, sizeof( sphValues ) );
432  sphValues[dParams->varyParam1] = x;
433 
434  SphericalToCartesian( cartValues, cartValues+3, sphValues, sphValues+3 );
435  memcpy( cartValues+6, sphValues+6, 6*sizeof(REAL8) );
436 
437  r = sphValues[0];
438  ptheta = sphValues[4];
439  pphi = sphValues[5];
440 
441  /* Return the appropriate derivative according to varyParam2 */
442  switch ( dParams->varyParam2 )
443  {
444  case 0:
445  /* dHdr */
446  dHdx = XLALSpinHcapNumDerivWRTParam( 0, cartValues, dParams->params );
447  dHdpy = XLALSpinHcapNumDerivWRTParam( 4, cartValues, dParams->params );
448  dHdpz = XLALSpinHcapNumDerivWRTParam( 5, cartValues, dParams->params );
449 
450  dHdr = dHdx - dHdpy * pphi / (r*r) + dHdpz * ptheta / (r*r);
451  //printf( "dHdr = %.16e\n", dHdr );
452  return dHdr;
453 
454  break;
455  case 4:
456  /* dHdptheta */
457  dHdpz = XLALSpinHcapNumDerivWRTParam( 5, cartValues, dParams->params );
458  return - dHdpz / r;
459  break;
460  case 5:
461  /* dHdpphi */
462  dHdpy = XLALSpinHcapNumDerivWRTParam( 4, cartValues, dParams->params );
463  return dHdpy / r;
464  break;
465  default:
466  XLALPrintError( "This option is not supported in the second derivative function!\n" );
468  break;
469  }
470 }
471 
472 static REAL8 XLALCalculateSphHamiltonianDeriv2Hybrid( const int idx1, /**<< Derivative w.r.t. index 1 */
473  const int idx2, /**<< Derivative w.r.t. index 2 */
474  const REAL8 values[], /**<< Dynamical variables in spherical coordinates */
475  SpinEOBParams *params /**<< Spin EOB Parameters */
476  )
477 {
478  static const REAL8 STEP_SIZE = 1.0e-4;
479 
480  REAL8 result;
481  REAL8 UNUSED absErr;
482 
483  HcapSphDeriv2Params dParams;
484 
485  gsl_function F;
486  INT4 UNUSED gslStatus;
487 
488  dParams.sphValues = values;
489  dParams.varyParam1 = idx1;
490  dParams.varyParam2 = idx2;
491  dParams.params = params;
492 
494  F.params = &dParams;
495  XLAL_CALLGSL( gslStatus = gsl_deriv_central( &F, values[idx1],
496  STEP_SIZE, &result, &absErr ) );
497 
498  if ( gslStatus != GSL_SUCCESS )
499  {
500  XLALPrintError( "XLAL Error %s - Failure in GSL function\n", __func__ );
502  }
503  return result;
504 }
505 
506 
507 /* Function to calculate the second derivative of the Hamiltonian. */
508 /* The derivatives are taken with respect to indices idx1, idx2 */
510  const int idx1, /**<< Derivative w.r.t. index 1 */
511  const int idx2, /**<< Derivative w.r.t. index 2 */
512  const REAL8 values[], /**<< Dynamical variables in spherical coordinates */
513  SpinEOBParams *params /**<< Spin EOB Parameters */
514  )
515 {
516 
517  static const REAL8 STEP_SIZE = 1.0e-4;
518 
519  REAL8 result;
520  REAL8 UNUSED absErr;
521 
522  HcapSphDeriv2Params dParams;
523 
524  gsl_function F;
525  INT4 UNUSED gslStatus;
526 
527  dParams.sphValues = values;
528  dParams.varyParam1 = idx1;
529  dParams.varyParam2 = idx2;
530  dParams.params = params;
531 
532  /*printf( " In second deriv function: values\n" );
533  for ( int i = 0; i < 12; i++ )
534  {
535  printf( "%.16e ", values[i] );
536  }
537  printf( "\n" );
538 */
539  F.function = GSLSpinHamiltonianDerivWrapper;
540  F.params = &dParams;
541 
542  /* GSL seemed to give weird answers - try my own code */
543  /*result = GSLSpinHamiltonianDerivWrapper( values[idx1] + STEP_SIZE, &dParams )
544  - GSLSpinHamiltonianDerivWrapper( values[idx1] - STEP_SIZE, &dParams );
545  printf( "%.16e - %.16e / 2h\n", GSLSpinHamiltonianDerivWrapper( values[idx1] + STEP_SIZE, &dParams ), GSLSpinHamiltonianDerivWrapper( values[idx1] - STEP_SIZE, &dParams ) );
546 
547  result = result / ( 2.*STEP_SIZE );
548 */
549 
550  XLAL_CALLGSL( gslStatus = gsl_deriv_central( &F, values[idx1],
551  STEP_SIZE, &result, &absErr ) );
552 
553  if ( gslStatus != GSL_SUCCESS )
554  {
555  XLALPrintError( "XLAL Error %s - Failure in GSL function\n", __func__ );
557  }
558 
559  //printf( "Second deriv abs err = %.16e\n", absErr );
560 
561  //printf( "RESULT = %.16e\n", result );
562  return result;
563 }
564 
565 /**
566  * Main function for calculating the spinning EOB initial conditions, following the
567  * quasi-spherical initial conditions described in Sec. IV A of
568  * Buonanno, Chen & Damour PRD 74, 104005 (2006).
569  * All equation numbers in the comments of this function refer to this paper.
570  * Inputs are binary parameters (masses, spin vectors and inclination),
571  * EOB model parameters and initial frequency.
572  * Outputs are initial dynamical variables in a vector
573  * (x, y, z, px, py, pz, S1x, S1y, S1z, S2x, S2y, S2z).
574  * In the paper, the initial conditions are solved for a given initial radius,
575  * while in this function, they are solved for a given inital orbital frequency.
576  * This difference is reflected in solving Eq. (4.8).
577  * The calculation is done in 5 steps:
578  * STEP 1) Rotate to LNhat0 along z-axis and N0 along x-axis frame, where
579  * LNhat0 and N0 are initial normal to orbital plane and initial orbital separation;
580  * STEP 2) After rotation in STEP 1, in spherical coordinates,
581  * phi0 and theta0 are given directly in Eq. (4.7),
582  * r0, pr0, ptheta0 and pphi0 are obtained by solving Eqs. (4.8) and (4.9)
583  * (using gsl_multiroot_fsolver).
584  * At this step, we find initial conditions for a spherical orbit without
585  * radiation reaction.
586  * STEP 3) Rotate to L0 along z-axis and N0 along x-axis frame, where
587  * L0 is the initial orbital angular momentum and
588  * L0 is calculated using initial position and linear momentum obtained in STEP 2.
589  * STEP 4) In the L0-N0 frame, we calculate (dE/dr)|sph using Eq. (4.14),
590  * then initial dr/dt using Eq. (4.10), and finally pr0 using Eq. (4.15).
591  * STEP 5) Rotate back to the original inertial frame by inverting the rotation of STEP 3 and
592  * then inverting the rotation of STEP 1.
593  */
594 
596  REAL8Vector *initConds, /**<< OUTPUT, Initial dynamical variables */
597  const REAL8 mass1, /**<< mass 1 */
598  const REAL8 mass2, /**<< mass 2 */
599  const REAL8 fMin, /**<< Initial frequency (given) */
600  const REAL8 inc, /**<< Inclination */
601  const REAL8 spin1[], /**<< Initial spin vector 1 */
602  const REAL8 spin2[], /**<< Initial spin vector 2 */
603  SpinEOBParams *params, /**<< Spin EOB parameters */
604  INT4 use_optimized_v2 /**<< Use optimized v2? */
605  )
606 {
607 
608  if ( !initConds )
609  {
611  }
612 
613 
614  static const int UNUSED lMax = 8;
615 
616  int i;
617 
618  /* Variable to keep track of whether the user requested the tortoise */
619  int tmpTortoise;
620 
621  UINT4 SpinAlignedEOBversion;
622 
623  REAL8 mTotal;
624  REAL8 eta;
625  REAL8 omega, v0; /* Initial velocity and angular frequency */
626 
627  REAL8 ham; /* Hamiltonian */
628 
629  REAL8 LnHat[3]; /* Initial orientation of angular momentum */
630  REAL8 rHat[3]; /* Initial orientation of radial vector */
631  REAL8 vHat[3]; /* Initial orientation of velocity vector */
632  REAL8 Lhat[3]; /* Direction of relativistic ang mom */
633  REAL8 qHat[3];
634  REAL8 pHat[3];
635 
636  /* q and p vectors in Cartesian and spherical coords */
637  REAL8 qCart[3], pCart[3];
638  REAL8 qSph[3], pSph[3];
639 
640  /* We will need to manipulate the spin vectors */
641  /* We will use temporary vectors to do this */
642  REAL8 tmpS1[3];
643  REAL8 tmpS2[3];
644  REAL8 tmpS1Norm[3];
645  REAL8 tmpS2Norm[3];
646 
647  REAL8Vector qCartVec, pCartVec;
648  REAL8Vector s1Vec, s2Vec, s1VecNorm, s2VecNorm;
649  REAL8Vector sKerr, sStar;
650  REAL8 sKerrData[3], sStarData[3];
651  REAL8 a = 0.; //, chiS, chiA;
652  //REAL8 chi1, chi2;
653 
654  /* We will need a full values vector for calculating derivs of Hamiltonian */
655  REAL8 sphValues[12];
656  REAL8 cartValues[12];
657 
658  /* Matrices for rotating to the new basis set. */
659  /* It is more convenient to calculate the ICs in a simpler basis */
660  gsl_matrix *rotMatrix = NULL;
661  gsl_matrix *invMatrix = NULL;
662  gsl_matrix *rotMatrix2 = NULL;
663  gsl_matrix *invMatrix2 = NULL;
664 
665  /* Root finding stuff for finding the spherical orbit */
666  SEOBRootParams rootParams;
667  const gsl_multiroot_fsolver_type *T = gsl_multiroot_fsolver_hybrids;
668  gsl_multiroot_fsolver *rootSolver = NULL;
669 
670  gsl_multiroot_function rootFunction;
671  gsl_vector *initValues = NULL;
672  gsl_vector *finalValues = NULL;
673  int gslStatus;
674  const int maxIter = 100;
675 
676  memset( &rootParams, 0, sizeof( rootParams ) );
677 
678  mTotal = mass1 + mass2;
679  eta = mass1 * mass2 / (mTotal * mTotal);
680  memcpy( tmpS1, spin1, sizeof(tmpS1) );
681  memcpy( tmpS2, spin2, sizeof(tmpS2) );
682  memcpy( tmpS1Norm, spin1, sizeof(tmpS1Norm) );
683  memcpy( tmpS2Norm, spin2, sizeof(tmpS2Norm) );
684  for ( i = 0; i < 3; i++ )
685  {
686  tmpS1Norm[i] /= mTotal * mTotal;
687  tmpS2Norm[i] /= mTotal * mTotal;
688  }
689  SpinAlignedEOBversion = params->seobCoeffs->SpinAlignedEOBversion;
690  /* We compute the ICs for the non-tortoise p, and convert at the end */
691  tmpTortoise = params->tortoise;
692  params->tortoise = 0;
693 
694  EOBNonQCCoeffs *nqcCoeffs = NULL;
695  nqcCoeffs = params->nqcCoeffs;
696 
697  /* STEP 1) Rotate to LNhat0 along z-axis and N0 along x-axis frame, where LNhat0 and N0 are initial normal to
698  * orbital plane and initial orbital separation;
699  */
700 
701  /* Set the initial orbital ang mom direction. Taken from STPN code */
702  LnHat[0] = sin(inc);
703  LnHat[1] = 0.;
704  LnHat[2] = cos(inc);
705 
706  /* Set the radial direction - need to take care to avoid singularity if L is along z axis */
707  if ( LnHat[2] > 0.9999 )
708  {
709  rHat[0] = 1.;
710  rHat[1] = rHat[2] = 0.;
711  }
712  else
713  {
714  REAL8 theta0 = atan( - LnHat[2] / LnHat[0] ); /* theta0 is between 0 and Pi */
715  rHat[0] = sin( theta0 );
716  rHat[1] = 0;
717  rHat[2] = cos( theta0 );
718  }
719 
720  /* Now we can complete the triad */
721  vHat[0] = CalculateCrossProduct( 0, LnHat, rHat );
722  vHat[1] = CalculateCrossProduct( 1, LnHat, rHat );
723  vHat[2] = CalculateCrossProduct( 2, LnHat, rHat );
724 
725  NormalizeVector( vHat );
726 
727  /* XXX Test code XXX */
728  /*for ( i = 0; i < 3; i++ )
729  {
730  printf ( " LnHat[%d] = %.16e, rHat[%d] = %.16e, vHat[%d] = %.16e\n", i, LnHat[i], i, rHat[i], i, vHat[i] );
731  }
732 
733  printf("\n\n" );
734  for ( i = 0; i < 3; i++ )
735  {
736  printf ( " s1[%d] = %.16e, s2[%d] = %.16e\n", i, tmpS1[i], i, tmpS2[i] );
737  }*/
738 
739  /* Allocate and compute the rotation matrices */
740  XLAL_CALLGSL( rotMatrix = gsl_matrix_alloc( 3, 3 ) );
741  XLAL_CALLGSL( invMatrix = gsl_matrix_alloc( 3, 3 ) );
742  if ( !rotMatrix || !invMatrix )
743  {
744  if ( rotMatrix ) gsl_matrix_free( rotMatrix );
745  if ( invMatrix ) gsl_matrix_free( invMatrix );
747  }
748 
749  if ( CalculateRotationMatrix( rotMatrix, invMatrix, rHat, vHat, LnHat ) == XLAL_FAILURE )
750  {
751  gsl_matrix_free( rotMatrix );
752  gsl_matrix_free( invMatrix );
754  }
755 
756  /* Rotate the orbital vectors and spins */
757  ApplyRotationMatrix( rotMatrix, rHat );
758  ApplyRotationMatrix( rotMatrix, vHat );
759  ApplyRotationMatrix( rotMatrix, LnHat );
760  ApplyRotationMatrix( rotMatrix, tmpS1 );
761  ApplyRotationMatrix( rotMatrix, tmpS2 );
762  ApplyRotationMatrix( rotMatrix, tmpS1Norm );
763  ApplyRotationMatrix( rotMatrix, tmpS2Norm );
764 
765  /* XXX Test code XXX */
766  /*printf( "\nAfter applying rotation matrix:\n\n" );
767  for ( i = 0; i < 3; i++ )
768  {
769  printf ( " LnHat[%d] = %.16e, rHat[%d] = %.16e, vHat[%d] = %.16e\n", i, LnHat[i], i, rHat[i], i, vHat[i] );
770  }
771 
772  printf("\n\n" );
773  for ( i = 0; i < 3; i++ )
774  {
775  printf ( " s1[%d] = %.16e, s2[%d] = %.16e\n", i, tmpS1[i], i, tmpS2[i] );
776  }*/
777 
778  /* STEP 2) After rotation in STEP 1, in spherical coordinates, phi0 and theta0 are given directly in Eq. (4.7),
779  * r0, pr0, ptheta0 and pphi0 are obtained by solving Eqs. (4.8) and (4.9) (using gsl_multiroot_fsolver).
780  * At this step, we find initial conditions for a spherical orbit without radiation reaction.
781  */
782 
783  /* Calculate the initial velocity from the given initial frequency */
784  omega = LAL_PI * mTotal * LAL_MTSUN_SI * fMin;
785  v0 = cbrt( omega );
786 
787  /* Given this, we can start to calculate the initial conditions */
788  /* for spherical coords in the new basis */
789  rootParams.omega = omega;
790  rootParams.params = params;
791 
792  /* To start with, we will just assign Newtonian-ish ICs to the system */
793  rootParams.values[0] = 1./(v0*v0); /* Initial r */
794  rootParams.values[4] = v0; /* Initial p */
795  memcpy( rootParams.values+6, tmpS1, sizeof( tmpS1 ) );
796  memcpy( rootParams.values+9, tmpS2, sizeof( tmpS2 ) );
797 
798  //printf( "ICs guess: r = %.16e, p = %.16e\n", rootParams.values[0], rootParams.values[4] );
799 
800  /* Initialise the gsl stuff */
801  XLAL_CALLGSL( rootSolver = gsl_multiroot_fsolver_alloc( T, 3 ) );
802  if ( !rootSolver )
803  {
804  gsl_matrix_free( rotMatrix );
805  gsl_matrix_free( invMatrix );
807  }
808 
809  XLAL_CALLGSL( initValues = gsl_vector_calloc( 3 ) );
810  if ( !initValues )
811  {
812  gsl_multiroot_fsolver_free( rootSolver );
813  gsl_matrix_free( rotMatrix );
814  gsl_matrix_free( invMatrix );
816  }
817 
818  gsl_vector_set( initValues, 0, rootParams.values[0] );
819  gsl_vector_set( initValues, 1, rootParams.values[4] );
820 
821  rootFunction.f = XLALFindSphericalOrbit;
822  rootFunction.n = 3;
823  rootFunction.params = &rootParams;
824 
825  gsl_multiroot_fsolver_set( rootSolver, &rootFunction, initValues );
826 
827  /* We are now ready to iterate to find the solution */
828  i = 0;
829 
830  do
831  {
832  XLAL_CALLGSL( gslStatus = gsl_multiroot_fsolver_iterate( rootSolver ) );
833  if ( gslStatus != GSL_SUCCESS )
834  {
835  XLALPrintError( "Error in GSL iteration function!\n" );
836  gsl_multiroot_fsolver_free( rootSolver );
837  gsl_vector_free( initValues );
838  gsl_matrix_free( rotMatrix );
839  gsl_matrix_free( invMatrix );
841  }
842 
843  XLAL_CALLGSL( gslStatus = gsl_multiroot_test_residual( rootSolver->f, 1.0e-10 ) );
844  i++;
845  }
846  while ( gslStatus == GSL_CONTINUE && i <= maxIter );
847 
848  if ( i > maxIter && gslStatus != GSL_SUCCESS )
849  {
850  gsl_multiroot_fsolver_free( rootSolver );
851  gsl_vector_free( initValues );
852  gsl_matrix_free( rotMatrix );
853  gsl_matrix_free( invMatrix );
855  }
856 
857  finalValues = gsl_multiroot_fsolver_root( rootSolver );
858 
859  /*printf( "Spherical orbit conditions here given by the following:\n" );
860  printf( " x = %.16e, py = %.16e, pz = %.16e\n", gsl_vector_get( finalValues, 0 ),
861  gsl_vector_get( finalValues, 1 ), gsl_vector_get( finalValues, 2 ) );*/
862 
863  memset( qCart, 0, sizeof(qCart) );
864  memset( pCart, 0, sizeof(pCart) );
865 
866  qCart[0] = gsl_vector_get( finalValues, 0 );
867  pCart[1] = gsl_vector_get( finalValues, 1 );
868  pCart[2] = gsl_vector_get( finalValues, 2 );
869 
870  /* Free the GSL root finder, since we're done with it */
871  gsl_multiroot_fsolver_free( rootSolver );
872  gsl_vector_free( initValues );
873 
874  /* STEP 3) Rotate to L0 along z-axis and N0 along x-axis frame, where L0 is the initial orbital angular momentum
875  * and L0 is calculated using initial position and linear momentum obtained in STEP 2.
876  */
877 
878  /* Now we can calculate the relativistic L and rotate to a new basis */
879  memcpy( qHat, qCart, sizeof(qCart) );
880  memcpy( pHat, pCart, sizeof(pCart) );
881 
882  NormalizeVector( qHat );
883  NormalizeVector( pHat );
884 
885  Lhat[0] = CalculateCrossProduct( 0, qHat, pHat );
886  Lhat[1] = CalculateCrossProduct( 1, qHat, pHat );
887  Lhat[2] = CalculateCrossProduct( 2, qHat, pHat );
888 
889  NormalizeVector( Lhat );
890 
891  XLAL_CALLGSL( rotMatrix2 = gsl_matrix_alloc( 3, 3 ) );
892  XLAL_CALLGSL( invMatrix2 = gsl_matrix_alloc( 3, 3 ) );
893 
894  if ( CalculateRotationMatrix( rotMatrix2, invMatrix2, qHat, pHat, Lhat ) == XLAL_FAILURE )
895  {
896  gsl_matrix_free( rotMatrix );
897  gsl_matrix_free( invMatrix );
899  }
900 
901  ApplyRotationMatrix( rotMatrix2, rHat );
902  ApplyRotationMatrix( rotMatrix2, vHat );
903  ApplyRotationMatrix( rotMatrix2, LnHat );
904  ApplyRotationMatrix( rotMatrix2, tmpS1 );
905  ApplyRotationMatrix( rotMatrix2, tmpS2 );
906  ApplyRotationMatrix( rotMatrix2, tmpS1Norm );
907  ApplyRotationMatrix( rotMatrix2, tmpS2Norm );
908  ApplyRotationMatrix( rotMatrix2, qCart );
909  ApplyRotationMatrix( rotMatrix2, pCart );
910 
911  /* STEP 4) In the L0-N0 frame, we calculate (dE/dr)|sph using Eq. (4.14), then initial dr/dt using Eq. (4.10),
912  * and finally pr0 using Eq. (4.15).
913  */
914 
915  /* Now we can calculate the flux. Change to spherical co-ords */
916  CartesianToSpherical( qSph, pSph, qCart, pCart );
917  memcpy( sphValues, qSph, sizeof( qSph ) );
918  memcpy( sphValues+3, pSph, sizeof( pSph ) );
919  memcpy( sphValues+6, tmpS1, sizeof(tmpS1) );
920  memcpy( sphValues+9, tmpS2, sizeof(tmpS2) );
921 
922  memcpy( cartValues, qCart, sizeof(qCart) );
923  memcpy( cartValues+3, pCart, sizeof(pCart) );
924  memcpy( cartValues+6, tmpS1, sizeof(tmpS1) );
925  memcpy( cartValues+9, tmpS2, sizeof(tmpS2) );
926 
927  REAL8 dHdpphi, d2Hdr2, d2Hdrdpphi;
928  REAL8 rDot, dHdpr, flux, dEdr;
929 
930  if(use_optimized_v2) {
931  /* TODO: Full, analytic derivatives have not been computed yet for d2Hdr2 or d2Hdrdpphi,
932  * so we use hybrid version. */
933  d2Hdr2 = XLALCalculateSphHamiltonianDeriv2Hybrid( 0, 0, sphValues, params );
934  d2Hdrdpphi = XLALCalculateSphHamiltonianDeriv2Hybrid( 0, 5, sphValues, params );
935  /* Full analytical version of dHdpphi. */
936  dHdpphi = XLALSpinHcapExactDerivWRTParam( 4, cartValues, params ) / sphValues[0];
937  } else {
938  d2Hdr2 = XLALCalculateSphHamiltonianDeriv2( 0, 0, sphValues, params );
939  d2Hdrdpphi = XLALCalculateSphHamiltonianDeriv2( 0, 5, sphValues, params );
940  dHdpphi = XLALSpinHcapNumDerivWRTParam( 4, cartValues, params ) / sphValues[0];
941  }
942  dEdr = - dHdpphi * d2Hdr2 / d2Hdrdpphi;
943 
944  //printf( "d2Hdr2 = %.16e d2Hdrdpphi = %.16e dHdpphi = %.16e\n", d2Hdr2, d2Hdrdpphi, dHdpphi );
945 
946  if ( d2Hdr2 != 0.0 )
947  {
948  /* We will need to calculate the Hamiltonian to get the flux */
949  s1Vec.length = s2Vec.length = s1VecNorm.length = s2VecNorm.length = sKerr.length = sStar.length = 3;
950  s1Vec.data = tmpS1;
951  s2Vec.data = tmpS2;
952  s1VecNorm.data = tmpS1Norm;
953  s2VecNorm.data = tmpS2Norm;
954  sKerr.data = sKerrData;
955  sStar.data = sStarData;
956 
957  qCartVec.length = pCartVec.length = 3;
958  qCartVec.data = qCart;
959  pCartVec.data = pCart;
960 
961  //chi1 = tmpS1[0]*LnHat[0] + tmpS1[1]*LnHat[1] + tmpS1[2]*LnHat[2];
962  //chi2 = tmpS2[0]*LnHat[0] + tmpS2[1]*LnHat[1] + tmpS2[2]*LnHat[2];
963 
964  //printf( "magS1 = %.16e, magS2 = %.16e\n", chi1, chi2 );
965 
966  //chiS = 0.5 * ( chi1 / (mass1*mass1) + chi2 / (mass2*mass2) );
967  //chiA = 0.5 * ( chi1 / (mass1*mass1) - chi2 / (mass2*mass2) );
968 
969  XLALSimIMRSpinEOBCalculateSigmaKerr( &sKerr, mass1, mass2, &s1Vec, &s2Vec );
970  XLALSimIMRSpinEOBCalculateSigmaStar( &sStar, mass1, mass2, &s1Vec, &s2Vec );
971 
972  /* The a in the flux has been set to zero, but not in the Hamiltonian */
973  a = sqrt(sKerr.data[0]*sKerr.data[0] + sKerr.data[1]*sKerr.data[1] + sKerr.data[2]*sKerr.data[2]);
974  //XLALSimIMREOBCalcSpinFacWaveformCoefficients( params->eobParams->hCoeffs, mass1, mass2, eta, /*a*/0.0, chiS, chiA );
975  //XLALSimIMRCalculateSpinEOBHCoeffs( params->seobCoeffs, eta, a );
976  if(use_optimized_v2) {
977  ham = XLALSimIMRSpinEOBHamiltonianOptimized( eta, &qCartVec, &pCartVec, &s1VecNorm, &s2VecNorm, &sKerr, &sStar, params->tortoise, params->seobCoeffs );
978  } else {
979  ham = XLALSimIMRSpinEOBHamiltonian( eta, &qCartVec, &pCartVec, &s1VecNorm, &s2VecNorm, &sKerr, &sStar, params->tortoise, params->seobCoeffs );
980  }
981  //printf( "hamiltonian at this point is %.16e\n", ham );
982 
983  /* And now, finally, the flux */
984  REAL8Vector polarDynamics;
985  REAL8 polarData[4];
986 
987  polarDynamics.length = 4;
988  polarDynamics.data = polarData;
989 
990  polarData[0] = qSph[0];
991  polarData[1] = 0.;
992  polarData[2] = pSph[0];
993  polarData[3] = pSph[2];
994 
995  flux = XLALInspiralSpinFactorizedFlux( &polarDynamics, nqcCoeffs, omega, params, ham, lMax, SpinAlignedEOBversion );
996  flux = flux / eta;
997 
998  rDot = - flux / dEdr;
999 
1000  /* We now need dHdpr - we take it that it is safely linear up to a pr of 1.0e-3 */
1001  cartValues[3] = 1.0e-3;
1002  if(use_optimized_v2) {
1003  dHdpr = XLALSpinHcapExactDerivWRTParam( 3, cartValues, params );
1004  } else {
1005  dHdpr = XLALSpinHcapNumDerivWRTParam( 3, cartValues, params );
1006  }
1007  /*printf( "Ingredients going into prDot:\n" );
1008  printf( "flux = %.16e, dEdr = %.16e, dHdpr = %.16e\n", flux, dEdr, dHdpr );*/
1009 
1010  /* We can now calculate what pr should be taking into account the flux */
1011  pSph[0] = rDot / (dHdpr / cartValues[3] );
1012  }
1013  else
1014  {
1015  /* Since d2Hdr2 has evaluated to zero, we cannot do the above. Just set pr to zero */
1016  //printf( "d2Hdr2 is zero!\n" );
1017  pSph[0] = 0;
1018  }
1019 
1020  /* Now we are done - convert back to cartesian coordinates ) */
1021  SphericalToCartesian( qCart, pCart, qSph, pSph );
1022 
1023  /* STEP 5) Rotate back to the original inertial frame by inverting the rotation of STEP 3 and then
1024  * inverting the rotation of STEP 1.
1025  */
1026 
1027  /* Undo rotations to get back to the original basis */
1028  /* Second rotation */
1029  ApplyRotationMatrix( invMatrix2, rHat );
1030  ApplyRotationMatrix( invMatrix2, vHat );
1031  ApplyRotationMatrix( invMatrix2, LnHat );
1032  ApplyRotationMatrix( invMatrix2, tmpS1 );
1033  ApplyRotationMatrix( invMatrix2, tmpS2 );
1034  ApplyRotationMatrix( invMatrix2, tmpS1Norm );
1035  ApplyRotationMatrix( invMatrix2, tmpS2Norm );
1036  ApplyRotationMatrix( invMatrix2, qCart );
1037  ApplyRotationMatrix( invMatrix2, pCart );
1038 
1039  /* First rotation */
1040  ApplyRotationMatrix( invMatrix, rHat );
1041  ApplyRotationMatrix( invMatrix, vHat );
1042  ApplyRotationMatrix( invMatrix, LnHat );
1043  ApplyRotationMatrix( invMatrix, tmpS1 );
1044  ApplyRotationMatrix( invMatrix, tmpS2 );
1045  ApplyRotationMatrix( invMatrix, tmpS1Norm );
1046  ApplyRotationMatrix( invMatrix, tmpS2Norm );
1047  ApplyRotationMatrix( invMatrix, qCart );
1048  ApplyRotationMatrix( invMatrix, pCart );
1049 
1050  /* If required, apply the tortoise transform */
1051  if ( tmpTortoise )
1052  {
1053  REAL8 r = sqrt(qCart[0]*qCart[0] + qCart[1]*qCart[1] + qCart[2]*qCart[2] );
1054  REAL8 deltaR = XLALSimIMRSpinEOBHamiltonianDeltaR( params->seobCoeffs, r, eta, a );
1055  REAL8 deltaT = XLALSimIMRSpinEOBHamiltonianDeltaT( params->seobCoeffs, r, eta, a );
1056  REAL8 csi = sqrt( deltaT * deltaR )/(r*r + a*a);
1057 
1058  REAL8 pr = (qCart[0]*pCart[0] + qCart[1]*pCart[1] + qCart[2]*pCart[2])/r;
1059 
1060  params->tortoise = tmpTortoise;
1061 
1062  //printf( "Applying the tortoise to p (csi = %.26e)\n", csi );
1063 
1064  for ( i = 0; i < 3; i++ )
1065  {
1066  pCart[i] = pCart[i] + qCart[i] * pr * (csi - 1.) / r;
1067  }
1068  }
1069 
1070  /* Now copy the initial conditions back to the return vector */
1071  memcpy( initConds->data, qCart, sizeof(qCart) );
1072  memcpy( initConds->data+3, pCart, sizeof(pCart) );
1073  memcpy( initConds->data+6, tmpS1Norm, sizeof(tmpS1Norm) );
1074  memcpy( initConds->data+9, tmpS2Norm, sizeof(tmpS2Norm) );
1075 
1076  gsl_matrix_free(rotMatrix2);
1077  gsl_matrix_free(invMatrix2);
1078 
1079  gsl_matrix_free(rotMatrix);
1080  gsl_matrix_free(invMatrix);
1081 
1082  //printf( "THE FINAL INITIAL CONDITIONS:\n");
1083  /*printf( " %.16e %.16e %.16e\n%.16e %.16e %.16e\n%.16e %.16e %.16e\n%.16e %.16e %.16e\n", initConds->data[0], initConds->data[1], initConds->data[2],
1084  initConds->data[3], initConds->data[4], initConds->data[5], initConds->data[6], initConds->data[7], initConds->data[8],
1085  initConds->data[9], initConds->data[10], initConds->data[11] );*/
1086 
1087  return XLAL_SUCCESS;
1088 }
1089 
1090 #endif /*_LALSIMIMRSPINEOBINITIALCONDITIONS_C*/
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 REAL8 XLALInspiralSpinFactorizedFlux(REAL8Vector *values, EOBNonQCCoeffs *nqcCoeffs, const REAL8 omega, SpinEOBParams *ak, const REAL8 H, const UINT4 lMax, const UINT4 SpinAlignedEOBversion)
static REAL8 XLALSimIMRSpinEOBHamiltonianDeltaR(SpinEOBHCoeffs *coeffs, const REAL8 r, const REAL8 eta, const REAL8 a)
This function calculates the DeltaR potential function in the spin EOB Hamiltonian.
static REAL8 XLALSimIMRSpinEOBHamiltonian(const REAL8 eta, REAL8Vector *restrict x, REAL8Vector *restrict p, REAL8Vector *restrict s1Vec, REAL8Vector *restrict s2Vec, REAL8Vector *restrict sigmaKerr, REAL8Vector *restrict sigmaStar, int tortoise, SpinEOBHCoeffs *coeffs)
static REAL8 XLALSimIMRSpinEOBHamiltonianDeltaT(SpinEOBHCoeffs *coeffs, const REAL8 r, const REAL8 eta, const REAL8 a)
This function calculates the function which appears in the spinning EOB potential function.
UNUSED REAL8 XLALSimIMRSpinEOBHamiltonianOptimized(const REAL8 eta, REAL8Vector *restrict x, REAL8Vector *restrict p, REAL8Vector *restrict s1Vec, REAL8Vector *restrict s2Vec, REAL8Vector *restrict sigmaKerr, REAL8Vector *restrict sigmaStar, INT4 tortoise, SpinEOBHCoeffs *coeffs)
Function to calculate the value of the spinning Hamiltonian for given values of the dynamical variabl...
static REAL8 XLALSpinHcapExactDerivWRTParam(const INT4 paramIdx, const REAL8 values[], SpinEOBParams *params)
Calculate the derivative of the Hamiltonian w.r.t.
static REAL8 XLALSpinHcapHybDerivWRTParam(const INT4 paramIdx, const REAL8 values[], SpinEOBParams *funcParams)
static REAL8 XLALSpinHcapNumDerivWRTParam(const INT4 paramIdx, const REAL8 values[], SpinEOBParams *params)
Calculate the derivative of the Hamiltonian w.r.t.
static int ApplyRotationMatrix(gsl_matrix *rotMatrix, REAL8 a[])
Applies a rotation matrix to a given vector.
static REAL8 XLALCalculateSphHamiltonianDeriv2(const int idx1, const int idx2, const REAL8 values[], SpinEOBParams *params)
static double GSLSpinHamiltonianDerivWrapperHybrid(double x, void *params)
Wrapper for calculating specific derivative of the Hamiltonian in spherical co-ordinates,...
static int CartesianToSpherical(REAL8 qSph[], REAL8 pSph[], const REAL8 qCart[], const REAL8 pCart[])
Perform a co-ordinate transformation from Cartesian to spherical co-ordinates.
static REAL8 CalculateCrossProduct(const INT4 i, const REAL8 a[], const REAL8 b[])
calculates the ith component of the cross product of two vectors, where i is in the range 0-2.
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 NormalizeVector(REAL8 a[])
Normalizes the given vector.
static REAL8 XLALCalculateSphHamiltonianDeriv2Hybrid(const int idx1, const int idx2, const REAL8 values[], SpinEOBParams *params)
static REAL8 CalculateDotProduct(const REAL8 a[], const REAL8 b[])
Calculates the dot product of two vectors.
static int CalculateRotationMatrix(gsl_matrix *rotMatrix, gsl_matrix *rotInverse, REAL8 r[], REAL8 v[], REAL8 L[])
Calculate the rotation matrix and its inverse.
static int XLALFindSphericalOrbit(const gsl_vector *x, void *params, gsl_vector *f)
Root function for gsl root finders.
static double GSLSpinHamiltonianDerivWrapper(double x, void *params)
Wrapper for calculating specific derivative of the Hamiltonian in spherical co-ordinates,...
static int SphericalToCartesian(REAL8 qCart[], REAL8 pCart[], const REAL8 qSph[], const REAL8 pSph[])
Performs a co-ordinate transformation from spherical to Cartesian co-ordinates.
#define XLAL_CALLGSL(statement)
double i
Definition: bh_ringdown.c:118
const double pr
const double deltaR
const double csi
#define LAL_PI_2
#define LAL_PI
#define LAL_MTSUN_SI
double REAL8
uint32_t UINT4
int32_t INT4
static const INT4 r
static const INT4 a
#define XLAL_ERROR_REAL8(...)
#define XLAL_ERROR(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_IS_REAL8_FAIL_NAN(val)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EMAXITER
XLAL_EDOM
XLAL_EINVAL
XLAL_FAILURE
list x
list y
The coefficients which are used in calculating the non-quasicircular correction to the EOBNRv2 model.
const REAL8 * sphValues
SpinEOBParams * params
REAL8 * data
Structure consisting SEOBNR parameters that can be used by gsl root finders.
REAL8 omega
< Orbital frequency
REAL8 values[12]
< Dynamical variables, x, y, z, px, py, pz, S1x, S1y, S1z, S2x, S2y and S2z
SpinEOBParams * params
< Spin EOB parameters – physical, pre-computed, etc.
Parameters for the spinning EOB model.
Definition: burst.c:245
double deltaT
Definition: unicorn.c:24