LALSimulation  5.4.0.1-fe68b98
LALSimIMRSpinEOBHamiltonianPrec.c
Go to the documentation of this file.
1 /**
2  * \author Craig Robinson, Yi Pan, Stas Babak, Prayush Kumar, Andrea Taracchini
3  *
4  * Functions for calculating the effective one-body Hamiltonian for
5  * spinning binaries, as described in
6  * Taracchini et al. ( PRD 86, 024011 (2012), arXiv 1202.0790 ).
7  * All equation numbers in this file refer to equations of this paper,
8  * unless otherwise specified.
9  * This code borrows hugely from a C implementation originally written
10  * by Enrico Barausse, following Barausse and Buonanno
11  * PRD 81, 084024 (2010) and PRD 84, 104027 (2011), henceforth BB1 and BB2
12  */
13 
14 #ifndef _LALSIMIMRSPINEOBHAMILTONIANPREC_C
15 #define _LALSIMIMRSPINEOBHAMILTONIANPREC_C
16 
17 #include <stdio.h>
18 #include <math.h>
19 #include <gsl/gsl_deriv.h>
20 
21 #include <lal/LALSimInspiral.h>
22 #include <lal/LALSimIMR.h>
23 
24 #include "LALSimIMRSpinEOB.h"
25 
29 
31 
32 
33 /*------------------------------------------------------------------------------------------
34  *
35  * Prototypes of functions defined in this code.
36  *
37  *------------------------------------------------------------------------------------------
38  */
39 
40 /**
41  * This function calculates the DeltaR potential function in the spin EOB Hamiltonian
42  */
44  SpinEOBHCoeffs *coeffs, /**<< Pre-computed coefficients which appear in the function */
45  const REAL8 r, /**<< Current orbital radius (in units of total mass) */
46  const REAL8 eta, /**<< Symmetric mass ratio */
47  const REAL8 a /**<< Normalized deformed Kerr spin */
48  );
49 
51  const REAL8 eta,
52  REAL8Vector * restrict x,
53  REAL8Vector * restrict p,
54  REAL8Vector * restrict s1Vec,
55  REAL8Vector * restrict s2Vec,
56  REAL8Vector * restrict sigmaKerr,
57  REAL8Vector * restrict sigmaStar,
58  int tortoise,
59  SpinEOBHCoeffs *coeffs);
60 
62  SpinEOBHCoeffs *coeffs,
63  const REAL8 r,
64  const REAL8 eta,
65  const REAL8 a
66  );
67 
68 /* Precessing EOB's function declarations below */
69 static REAL8 inner_product( const REAL8 values1[],
70  const REAL8 values2[]
71  );
72 
73 static REAL8* cross_product( const REAL8 values1[],
74  const REAL8 values2[],
75  REAL8 result[] );
76 
77 static REAL8* rotate_vector(const REAL8 v[], const REAL8 k[], const REAL8 theta,REAL8 result[] );
78 
80  const REAL8 values[], /**<< Dynamical variables */
81  SpinEOBParams *funcParams /**<< EOB parameters */
82  );
83 
85  const REAL8 values[], /**<< Dynamical variables */
86  SpinEOBParams *funcParams /**<< EOB parameters */
87  );
88 
90  double UNUSED t, /**<< UNUSED */
91  const REAL8 values[], /**<< Dynamical variables */
92  REAL8 dvalues[], /**<< Time derivatives of variables (returned) */
93  void *funcParams /**<< EOB parameters */
94  );
95 
96 static double GSLSpinPrecHamiltonianWrapperForRvecDerivs( double x, void *params );
97 
98 static double GSLSpinPrecHamiltonianWrapperFordHdpphi( double x, void *params );
99 
100 
101 /*------------------------------------------------------------------------------------------
102  *
103  * Defintions of functions.
104  *
105  *------------------------------------------------------------------------------------------
106  */
107 
108 /**
109  *
110  * Function to calculate the value of the spinning Hamiltonian for given values
111  * of the dynamical variables (in a Cartesian co-ordinate system). The inputs are
112  * as follows:
113  *
114  * x - the separation vector r expressed in Cartesian co-ordinates
115  * p - the momentum vector (with the radial component tortoise pr*)
116  * sigmaKerr - spin of the effective Kerr background (a combination of the individual spin vectors)
117  * sigmaStar - spin of the effective particle (a different combination of the individual spins).
118  * coeffs - coefficients which crop up in the Hamiltonian. These can be calculated using the
119  * XLALCalculateSpinEOBParams() function.
120  *
121  * The function returns a REAL8, which will be the value of the Hamiltonian if all goes well;
122  * otherwise, it will return the XLAL REAL8 failure NaN.
123  * The Hamiltonian function is described in PRD 81, 084024 (2010) and
124  * PRD 84, 104027 (2011)
125  */
127  const REAL8 eta, /**<< Symmetric mass ratio */
128  REAL8Vector * restrict x, /**<< Position vector */
129  REAL8Vector * restrict p, /**<< Momentum vector (tortoise radial component pr*) */
130  REAL8Vector * restrict s1Vec, /**<< Spin vector 1 */
131  REAL8Vector * restrict s2Vec, /**<< Spin vector 2 */
132  REAL8Vector * restrict sigmaKerr, /**<< Spin vector sigma_kerr */
133  REAL8Vector * restrict sigmaStar, /**<< Spin vector sigma_star */
134  INT4 tortoise, /**<< flag to state whether the momentum is the tortoise co-ord */
135  SpinEOBHCoeffs *coeffs /**<< Structure containing various coefficients */
136  )
137 {
138  /* Flag for debug output */
139  int debugPK = 0;
140 
141  /* Dump out inputs when debug flag is set */
142  if(debugPK){
143  XLAL_PRINT_INFO( "In Hamiltonian: tortoise flag = %d\n", (int) tortoise );
144  XLAL_PRINT_INFO( "x = %.16e\t%.16e\t%.16e\n", x->data[0], x->data[1], x->data[2] );
145  XLAL_PRINT_INFO( "p = %.16e\t%.16e\t%.16e\n", p->data[0], p->data[1], p->data[2] );
146  XLAL_PRINT_INFO( "sStar = %.16e\t%.16e\t%.16e\n", sigmaStar->data[0],
147  sigmaStar->data[1], sigmaStar->data[2] );
148  XLAL_PRINT_INFO( "sKerr = %.16e\t%.16e\t%.16e\n", sigmaKerr->data[0],
149  sigmaKerr->data[1], sigmaKerr->data[2] );}
150 
151  /* Update the Hamiltonian coefficients, if spins are evolving. Right
152  now, this code path is always executed. In the future, v3 and v2
153  code may be merged, and we want to skip this step in the
154  non-precessing limit. */
155  int UsePrecH = 1;
156 
157  SpinEOBHCoeffs tmpCoeffs;
158  REAL8 L[3] = {0, 0, 0};
159  REAL8 Lhat[3] = {0, 0, 0.0};
160  cross_product(x->data, p->data, L); // Note that L = r x p is invariant under tortoise transform
161  REAL8 L_mag = sqrt(inner_product(L, L));
162  for (UINT4 jj = 0; jj < 3; jj++)
163  {
164  Lhat[jj] = L[jj] / L_mag;
165  }
166 
167  REAL8 tempS1_p = inner_product(s1Vec->data, Lhat);
168  REAL8 tempS2_p = inner_product(s2Vec->data, Lhat);
169  REAL8 S1_perp[3] = {0, 0, 0};
170  REAL8 S2_perp[3] = {0, 0, 0};
171  REAL8 S_perp[3] = {0,0,0};
172  for (UINT4 jj = 0; jj < 3; jj++)
173  {
174  S1_perp[jj] = s1Vec->data[jj] - tempS1_p * Lhat[jj];
175  S2_perp[jj] = s2Vec->data[jj] - tempS2_p * Lhat[jj];
176  S_perp[jj] = S1_perp[jj]+S2_perp[jj];
177  }
178  REAL8 sKerr_norm = sqrt(inner_product(sigmaKerr->data, sigmaKerr->data));
179  REAL8 S_con = 0.0;
180  if (sKerr_norm>1e-6){
181  S_con = sigmaKerr->data[0] * Lhat[0] + sigmaKerr->data[1] * Lhat[1] + sigmaKerr->data[2] * Lhat[2];
182  S_con /= (1 - 2 * eta);
183  // Last division by 2 is to ensure the spin oebys the Kerr bound.
184  S_con += inner_product(S_perp, sigmaKerr->data) / sKerr_norm / (1 - 2 * eta) / 2.;
185  }
186 
187  REAL8 chi = S_con;
188  if ( UsePrecH && coeffs->updateHCoeffs )
189  {
190 
191  REAL8 tmpa; // = magnitude of S_1 + S_2
192  tmpa = sqrt(sigmaKerr->data[0]*sigmaKerr->data[0]
193  + sigmaKerr->data[1]*sigmaKerr->data[1]
194  + sigmaKerr->data[2]*sigmaKerr->data[2]);
195 
196  // Update coefficients, checking for errors
197  if (coeffs->SpinAlignedEOBversion ==4){
198  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs_v2( &tmpCoeffs, eta,
199  tmpa, chi, coeffs->SpinAlignedEOBversion ) == XLAL_FAILURE )
200  {
202  }
203  }
204  else{
205  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs( &tmpCoeffs, eta,
206  tmpa, coeffs->SpinAlignedEOBversion ) == XLAL_FAILURE )
207  {
209  }
210  }
211 
212 
213  // Copy over underlying model version number
214  tmpCoeffs.SpinAlignedEOBversion = coeffs->SpinAlignedEOBversion;
215  tmpCoeffs.updateHCoeffs = coeffs->updateHCoeffs;
216 
217  coeffs = &tmpCoeffs;
218  }
219 
220  REAL8 r, r2, nx, ny, nz;
221  REAL8 sKerr_x, sKerr_y, sKerr_z, a, a2;
222  REAL8 sStar_x, sStar_y, sStar_z;
223  REAL8 e3_x, e3_y, e3_z;
224  REAL8 costheta; /* Cosine of angle between Skerr and r */
225  REAL8 xi2, xi_x, xi_y, xi_z; /* Cross product of unit vectors in direction of Skerr and r */
226  REAL8 vx, vy, vz, pxir, pvr, pn, prT, pr, pf, ptheta2; /*prT is the tortoise pr */
227  REAL8 w2, rho2;
228  REAL8 u, u2, u3, u4, u5;
230  REAL8 D, qq, ww, B, w, BR, wr, nur, mur;
231  REAL8 wcos, nucos, mucos, ww_r, Lambda_r;
232  REAL8 logTerms, deltaU, deltaU_u, Q, deltaT_r, pn2, pp;
233  REAL8 deltaSigmaStar_x, deltaSigmaStar_y, deltaSigmaStar_z;
234  REAL8 sx, sy, sz, sxi, sv, sn, s3;
235  REAL8 H, Hns, Hs, Hss, Hreal, Hwcos, Hwr, HSOL, HSONL;
236 
237  /* Terms which come into the 3.5PN mapping of the spins */
239 
240  /*Temporary p vector which we will make non-tortoise */
241  REAL8 tmpP[3] = {0.};
242 
243  REAL8 csi;
244  REAL8 logu;
245 
246  r2 = x->data[0]*x->data[0] + x->data[1]*x->data[1] + x->data[2]*x->data[2];
247  r = sqrt(r2);
248  u = 1./r;
249  u2 = u*u;
250  u3 = u2*u;
251  u4 = u2*u2;
252  u5 = u4*u;
253 
254  nx = x->data[0] *u;
255  ny = x->data[1] *u;
256  nz = x->data[2] *u;
257 
258  sKerr_x = sigmaKerr->data[0];
259  sKerr_y = sigmaKerr->data[1];
260  sKerr_z = sigmaKerr->data[2];
261 
262  sStar_x = sigmaStar->data[0];
263  sStar_y = sigmaStar->data[1];
264  sStar_z = sigmaStar->data[2];
265 
266  a2 = sKerr_x*sKerr_x + sKerr_y*sKerr_y + sKerr_z*sKerr_z;
267  a = sqrt( a2 );
268 
269  if(a !=0.)
270  {
271  const REAL8 inva = 1./a;
272  e3_x = sKerr_x * inva;
273  e3_y = sKerr_y * inva;
274  e3_z = sKerr_z * inva;
275  }
276  else
277  {
278  e3_x = 1./sqrt(3.);
279  e3_y = 1./sqrt(3.);
280  e3_z = 1./sqrt(3.);
281  }
282  UNUSED REAL8 result[3] = {0.0, 0.0, 0.0};
283  UNUSED REAL8 e3[3] = {e3_x, e3_y, e3_z};
284  UNUSED REAL8 nhat[3] = {nx,ny,nz};
285  UNUSED REAL8 lambda_hat[3]={0.0,0.0,0.0};
286  cross_product(Lhat,nhat,lambda_hat);
287  UNUSED REAL8 nrm = sqrt(inner_product(lambda_hat,lambda_hat));
288  for (int k=0;k<3;k++){
289  lambda_hat[k]/=nrm;
290  }
291  // Check if e_3 is aligned with n
292 
293  if (1. - fabs(e3_x * nx + e3_y * ny + e3_z * nz) <= 1.e-8)
294  {
295  if (coeffs->SpinAlignedEOBversion == 4){
296  UNUSED REAL8 angle = 1.8e-3; // This is ~0.1 degrees
297  rotate_vector(e3, lambda_hat, angle, result);
298  e3_x = result[0];
299  e3_y = result[1];
300  e3_z = result[2];
301  }
302  else{
303  e3_x = e3_x+0.1;
304  e3_y = e3_y+0.1;
305  const REAL8 invnorm = 1./sqrt(e3_x*e3_x + e3_y*e3_y + e3_z*e3_z);
306  e3_x = e3_x*invnorm;
307  e3_y = e3_y*invnorm;
308  e3_z = e3_z*invnorm;
309  }
310  }
311  costheta = e3_x*nx + e3_y*ny + e3_z*nz;
312 
313  xi2=1. - costheta*costheta;
314 
315  xi_x = -e3_z*ny + e3_y*nz;
316  xi_y = e3_z*nx - e3_x*nz;
317  xi_z = -e3_y*nx + e3_x*ny;
318 
319  vx = -nz*xi_y + ny*xi_z;
320  vy = nz*xi_x - nx*xi_z;
321  vz = -ny*xi_x + nx*xi_y;
322 
323  w2 = r2 + a2;
324  rho2 = r2 + a2*costheta*costheta;
325 
326  if(debugPK)XLAL_PRINT_INFO( "KK = %.16e\n", coeffs->KK );
327  const REAL8 invm1PlusetaKK = 1./(-1. + eta * coeffs->KK);
328  /* Eq. 5.75 of BB1 */
329  bulk = invm1PlusetaKK*(invm1PlusetaKK + (2.*u)) + a2*u2;
330  /* Eq. 5.73 of BB1 */
331  // use ln(u) = log_2(u)/log_2(e) and the fact that log2 is faster than ln
332  // this relies on the compiler evaluating the expression at compile time.
333  // which apparently not all do so in stead of 1./log2(exp(1.)) I use the
334  // result returned by Maple.
335  const REAL8 invlog_2e = 0.69314718055994530941723212145817656807550013436026;
336  logu = log2(u)*invlog_2e;
337  const REAL8 logarg = coeffs->k1*u + coeffs->k2*u2 + coeffs->k3*u3 + coeffs->k4*u4
338  + coeffs->k5*u5 + coeffs->k5l*u5*logu;
339  logTerms = 1. + eta*coeffs->k0 + eta*log1p(fabs(1. + logarg) - 1.);
340  if(debugPK)XLAL_PRINT_INFO( "bulk = %.16e, logTerms = %.16e\n", bulk, logTerms );
341  /* Eq. 5.73 of BB1 */
342  deltaU = fabs(bulk*logTerms);
343  /* Eq. 5.71 of BB1 */
344  deltaT = r2*deltaU;
345  /* ddeltaU/du */
346  deltaU_u = 2.*(invm1PlusetaKK + a2*u)*logTerms +
347  bulk * (eta*(coeffs->k1 + u*(2.*coeffs->k2 + u*(3.*coeffs->k3 + u*(4.*coeffs->k4 + 5.*(coeffs->k5+coeffs->k5l*logu)*u)))))
348  / (1. + logarg);
349  /* ddeltaT/dr */
350  deltaT_r = 2.*r*deltaU - deltaU_u;
351  /* Eq. 5.39 of BB1 */
352  Lambda = fabs(w2*w2 - a2*deltaT*xi2);
353  // RH: this is horrible, but faster than 3 divisions
354  const REAL8 invrho2xi2Lambda = 1./(rho2*xi2*Lambda);
358  /* Eq. 5.83 of BB1, inverse */
359  D = 1. + log1p(6.*eta*u2 + 2.*(26. - 3.*eta)*eta*u3);
360  /* Eq. 5.38 of BB1 */
361  deltaR = deltaT*D;
362  /* See Hns below, Eq. 4.34 of Damour et al. PRD 62, 084011 (2000) */
363  qq = 2.*eta*(4. - 3.*eta);
364  /* See Hns below. In Sec. II D of BB2 b3 and bb3 coeffs are chosen to be zero. */
365  ww=2.*a*r + coeffs->b3*eta*a2*a*u + coeffs->bb3*eta*a*u;
366 
367  /* We need to transform the momentum to get the tortoise co-ord */
368  /* Eq. 28 of Pan et al. PRD 81, 084041 (2010) */
369  // RH: this assumes that tortoise can be 0 or 1 or 2.
370  csi = sqrt( fabs(deltaT * deltaR) )/ w2;
371  // non-unity only for tortoise==1
372  const REAL8 csi1 = 1.0 + (1.-fabs(1.-tortoise)) * (csi - 1.0);
373  // non-unity only for tortoise==2
374  const REAL8 csi2 = 1.0 + (0.5-copysign(0.5, 1.5-tortoise)) * (csi - 1.0);
375 
376  if(debugPK){
377  XLAL_PRINT_INFO( "csi1(miami) = %.16e\n", csi1 );
378  XLAL_PRINT_INFO( "csi2(miami) = %.16e\n", csi2 );}
379 
380  prT = (p->data[0]*nx + p->data[1]*ny + p->data[2]*nz)*csi2;
381  /* p->data is BL momentum vector; tmpP is tortoise momentum vector */
382  tmpP[0] = p->data[0] - nx * prT * (1. - 1./csi1);
383  tmpP[1] = p->data[1] - ny * prT * (1. - 1./csi1);
384  tmpP[2] = p->data[2] - nz * prT * (1. - 1./csi1);
385 
386  pxir = (tmpP[0]*xi_x + tmpP[1]*xi_y + tmpP[2]*xi_z) * r;
387  pvr = (tmpP[0]*vx + tmpP[1]*vy + tmpP[2]*vz) * r;
388  pn = tmpP[0]*nx + tmpP[1]*ny + tmpP[2]*nz;
389 
390  pr = pn;
391  pf = pxir;
392  ptheta2 = pvr * pvr *invxi2;
393 
394  if(debugPK)
395  {XLAL_PRINT_INFO( "pr = %.16e, prT = %.16e\n", pr, prT );
396 
397  XLAL_PRINT_INFO( " a = %.16e, r = %.16e\n", a, r );
398  XLAL_PRINT_INFO( "D = %.16e, ww = %.16e, rho = %.16e, Lambda = %.16e, xi = %.16e\npr = %.16e, pf = %.16e, deltaR = %.16e, deltaT = %.16e\n",
399  D, ww, sqrt(rho2), Lambda, sqrt(xi2), pr, pf, deltaR, deltaT );}
400 
401  /* Eqs. 5.36 - 5.46 of BB1 */
402  /* Note that the tortoise prT appears only in the quartic term, explained in Eqs. 14 and 15 of Tarrachini et al. */
403  Hns = sqrt((1. + ((prT*prT)*(prT*prT))*qq*u2 + ptheta2*invrho2 + pf*pf*rho2*invLambda*invxi2 + pr*pr*deltaR*invrho2)
404  * (rho2*deltaT) * invLambda) + pf*ww*invLambda;
405 
406  if(debugPK){
407  XLAL_PRINT_INFO( "term 1 in Hns: %.16e\n", prT*prT*prT*prT*qq*u2 );
408  XLAL_PRINT_INFO( "term 2 in Hns: %.16e\n", ptheta2/rho2 );
409  XLAL_PRINT_INFO( "term 3 in Hns = %.16e\n", pf*pf*rho2/(Lambda*xi2) );
410  XLAL_PRINT_INFO( "term 4 in Hns = %.16e\n", pr*pr*deltaR/rho2 );
411  XLAL_PRINT_INFO( "term 5 in Hns = %.16e\n", Lambda/(rho2*deltaT) );
412  XLAL_PRINT_INFO( "term 6 in Hns = %.16e\n", pf*ww/Lambda );}
413 
414  /* Eqs. 5.30 - 5.33 of BB1 */
415  B = sqrt(deltaT);
416  // RH: this is horrible but faster than 3 divisions
417  const REAL8 sqrtdeltaT = B;
418  const REAL8 sqrtdeltaR = sqrt(deltaR);
423  w = ww*invLambda;
424  //nu = 0.5 * log(deltaT*rho2/Lambda);
425  //MU = 0.5 * log(rho2);
426  const REAL8 expnu = sqrt(deltaT*rho2*invLambda);
427  const REAL8 expMU = sqrt(rho2);
428  // RH: this is horrible but faster than 2 divisions
429  const REAL8 invexpnuexpMU = 1./(expnu*expMU);
430  const REAL8 invexpnu = expMU*invexpnuexpMU;
432  /* dLambda/dr */
433  Lambda_r = 4.*r*w2 - a2*deltaT_r*xi2;
434 
435  ww_r=2.*a - (a2*a*coeffs->b3*eta)*u2 - coeffs->bb3*eta*a*u2;
436  /* Eqs. 5.47a - 5.47d of BB1 */
437  BR = (-deltaT*invsqrtdeltaR + deltaT_r*0.5)*invsqrtdeltaT;
438  wr = (-Lambda_r*ww + Lambda*ww_r)*(invLambda*invLambda);
439  nur = (r*invrho2 + (w2 * (-4.*r*deltaT + w2*deltaT_r) ) * 0.5*invdeltaT*invLambda );
440  mur = (r*invrho2 - invsqrtdeltaR);
441  /* Eqs. 5.47f - 5.47h of BB1 */
444  mucos = (a2*costheta)*invrho2;
445  /* Eq. 5.52 of BB1, (YP) simplified */
447  if(debugPK){
448  XLAL_PRINT_INFO( "Q = %.16e, pvr = %.16e, xi2 = %.16e , deltaT = %.16e, rho2 = %.16e, Lambda = %.16e, pxir = %.16e, B = %.16e\n", Q, pvr, xi2, deltaT, rho2, Lambda, pxir, B );
449  }
450  pn2 = pr * pr * deltaR * invrho2;
451  pp = Q - 1.;
452 
453  if(debugPK){
454  XLAL_PRINT_INFO( "pn2 = %.16e, pp = %.16e\n", pn2, pp );
455  XLAL_PRINT_INFO( "sigmaKerr = %.16e, sigmaStar = %.16e\n", sKerr_z, sStar_z );}
456 
457  /* Eq. 5.68 of BB1, (YP) simplified for aa=bb=0. */
458  deltaSigmaStar_x=eta*((-8. - 3.*r*(12.*pn2 - pp))*sKerr_x + (14. + (- 30.*pn2 + 4.*pp)*r)*sStar_x)*(1./12.)*u;
459 
460  deltaSigmaStar_y=eta*((-8. - 3.*r*(12.*pn2 - pp))*sKerr_y + (14. + (- 30.*pn2 + 4.*pp)*r)*sStar_y)*(1./12.)*u;
461 
462  deltaSigmaStar_z=eta*((-8. - 3.*r*(12.*pn2 - pp))*sKerr_z + (14. + (- 30.*pn2 + 4.*pp)*r)*sStar_z)*(1./12.)*u;
463 
464 
465  /* Now compute the additional 3.5PN terms. */
466  /* Eq. 52 of BB2, (YP) simplified for zero gauge parameters */
467  // RH: below is horner(%, [eta,r])
468  // sMultiplier1 = -(2.*eta*(-353. + 27.*eta) + 2.*(103.*eta - 60.*eta*eta)*pp*r
469  // + (120.*(-3.))*(eta*eta)*(pn2*pn2)*(r*r) + (eta*(23. + 3.*eta))*(pp*pp)*(r*r )
470  // + 6.*pn2*r*(- 47.*eta + 54.*(eta*eta) + (- 16.*eta + 21.*(eta*eta))*pp*r))
471  // * (1./72.) * u2;
472  sMultiplier1 = (-706.0+(206.0*pp-282.0*pn2+(-96.0*pn2*pp+23.0*pp*pp)*r)*r
473  +(54.0+( -120.0*pp+324.0*pn2+(-360.0*pn2*pn2+126.0*pn2*pp
474  +3.0*pp*pp)*r)*r)*eta)*eta*u2
475  *(-1./72.0);
476  /* Eq. 52 of BB2, (YP) simplified for zero gauge parameters */
477  //RH: below is horner(expand(%), [eta,r])
478  // sMultiplier2 = (-16.*(7.*eta*(8. + 3.*eta)) + 4.*(- 109.*eta + 51.*eta*eta)*pp*r
479  // + 810.*(eta*eta)*(pn2*pn2)*(r*r) - 45.*eta*(pp*pp)*(r*r)
480  // - 6.*pn2*r*(16.*eta + 147.*eta*eta + (- 6.*eta + 39.*(eta*eta))*pp*r))
481  // * (1./144.) * u2;
482  sMultiplier2 = (-56.0/9.0*u2+(-2.0/3.0*pn2*u2-109.0/36.0*pp*u2
483  +(pn2*pp*u2/4.0-5.0/16.0*pp*pp*u2)*r)*r
484  +(-7.0/3.0*u2+(-49.0/8.0*pn2*u2+17.0/12.0*pp*u2
485  +(45.0/8.0* pn2*pn2*u2
486  -13.0/8.0*pn2*pp*u2)*r)*r)*eta)
487  *eta;
488  /* Eq. 52 of BB2 */
489  deltaSigmaStar_x += sMultiplier1*sigmaStar->data[0] + sMultiplier2*sigmaKerr->data[0];
490  deltaSigmaStar_y += sMultiplier1*sigmaStar->data[1] + sMultiplier2*sigmaKerr->data[1];
491  deltaSigmaStar_z += sMultiplier1*sigmaStar->data[2] + sMultiplier2*sigmaKerr->data[2];
492 
493  /* And now the (calibrated) 4.5PN term */
494  deltaSigmaStar_x += coeffs->d1 * eta * sigmaStar->data[0] * u3;
495  deltaSigmaStar_y += coeffs->d1 * eta * sigmaStar->data[1] * u3;
496  deltaSigmaStar_z += coeffs->d1 * eta * sigmaStar->data[2] * u3;
497  deltaSigmaStar_x += coeffs->d1v2 * eta * sigmaKerr->data[0] * u3;
498  deltaSigmaStar_y += coeffs->d1v2 * eta * sigmaKerr->data[1] * u3;
499  deltaSigmaStar_z += coeffs->d1v2 * eta * sigmaKerr->data[2] * u3;
500 
501 
502  if(debugPK){
503  XLAL_PRINT_INFO( "deltaSigmaStar_x = %.16e, deltaSigmaStar_y = %.16e, deltaSigmaStar_z = %.16e\n", deltaSigmaStar_x, deltaSigmaStar_y, deltaSigmaStar_z );}
504 
505  sx = sStar_x + deltaSigmaStar_x;
506  sy = sStar_y + deltaSigmaStar_y;
507  sz = sStar_z + deltaSigmaStar_z;
508 
509 
510  sxi = sx*xi_x + sy*xi_y + sz*xi_z;
511  sv = sx*vx + sy*vy + sz*vz;
512  sn = sx*nx + sy*ny + sz*nz;
513 
514  s3 = sx*e3_x + sy*e3_y + sz*e3_z;
515  /* Eq. 3.45 of BB1, second term */
516  const REAL8 sqrtQ = sqrt(Q);
517  const REAL8 inv2B1psqrtQsqrtQ = 1./(2.*B*(1. + sqrtQ)*sqrtQ);
519  B*B*xi2*((expMU*expMU)*(sqrtQ + Q)*sv + pn*pvr*sn*sqrtdeltaR - pn*pn*sv*deltaR)))*inv2B1psqrtQsqrtQ*invxi2;
520  /* Eq. 3.45 of BB1, third term */
521  Hwcos = ((invexpMU*invexpMU*invexpMU*invexpnu)*(sn*(-((expMU*expMU)*(expnu*expnu)*(pxir*pxir)) + B*B*(pvr*pvr - (expMU*expMU)*(sqrtQ + Q)*xi2)) -
522  B*pn*(B*pvr*sv - (expMU*expnu)*pxir*sxi)*sqrtdeltaR))*inv2B1psqrtQsqrtQ;
523  /* Eq. 3.44 of BB1, leading term */
525  /* Eq. 3.44 of BB1, next-to-leading term */
526  HSONL = ((expnu*(invexpMU*invexpMU))*(-(B*expMU*expnu*nucos*pxir*(1. + 2.*sqrtQ)*sn*xi2) +
527  (-(BR*(expMU*expnu)*pxir*(1. + sqrtQ)*sv) + B*((expMU*expnu)*nur*pxir*(1. + 2.*sqrtQ)*sv + B*mur*pvr*sxi +
528  B*sxi*(-(mucos*pn*xi2) + sqrtQ*(mur*pvr - nur*pvr + (-mucos + nucos)*pn*xi2))))*sqrtdeltaR))*invxi2/(deltaT*(sqrtQ + Q));
529  /* Eq. 3.43 and 3.45 of BB1 */
530  Hs = w*s3 + Hwr*wr + Hwcos*wcos + HSOL + HSONL;
531  /* Eq. 5.70 of BB1, last term */
532  Hss = -0.5*u3 * (sx*sx + sy*sy + sz*sz - 3.*sn*sn);
533  /* Eq. 5.70 of BB1 */
534  H = Hns + Hs + Hss;
535 
536  /* Add the additional calibrated term */
537  H += coeffs->dheffSS * eta * (sKerr_x*sStar_x + sKerr_y*sStar_y + sKerr_z*sStar_z) *u4;
538  /* One more calibrated term proportional to S1^2+S2^2. Note that we use symmetric expressions of m1,m2 and S1,S2 */
539  H += coeffs->dheffSSv2 * eta * u4
540  * (s1Vec->data[0]*s1Vec->data[0] + s1Vec->data[1]*s1Vec->data[1] + s1Vec->data[2]*s1Vec->data[2]
541  +s2Vec->data[0]*s2Vec->data[0] + s2Vec->data[1]*s2Vec->data[1] + s2Vec->data[2]*s2Vec->data[2]);
542  if(debugPK){
543  XLAL_PRINT_INFO( "Hns = %.16e, Hs = %.16e, Hss = %.16e\n", Hns, Hs, Hss );
544  XLAL_PRINT_INFO( "H = %.16e\n", H );}
545  /* Real Hamiltonian given by Eq. 2, ignoring the constant -1. */
546  Hreal = sqrt(1. + 2.*eta *(fabs(H) - 1.));
547 
548  if(debugPK)
549  XLAL_PRINT_INFO( "Hreal = %.16e\n", Hreal );
550 
551  if(isnan(Hreal)) {
553  "\n\nInside Hamiltonian: Hreal is a NAN. Printing its components below:\n");
554  XLALPrintError( "(deltaU, bulk, logTerms, log arg) = (%.16e, %.16e, %.16e, %.16e)\n", deltaU, bulk, logTerms, 1. + coeffs->k1*u + coeffs->k2*u2 + coeffs->k3*u3 + coeffs->k4*u4
555  + coeffs->k5*u5 + coeffs->k5l*u5*logu);
556 
557  XLALPrintError( "In Hamiltonian: tortoise flag = %d\n", (int) tortoise );
558  XLALPrintError( "x = %.16e\t%.16e\t%.16e\n", x->data[0], x->data[1], x->data[2] );
559  XLALPrintError( "p = %.16e\t%.16e\t%.16e\n", p->data[0], p->data[1], p->data[2] );
560  XLALPrintError( "sStar = %.16e\t%.16e\t%.16e\n", sigmaStar->data[0],
561  sigmaStar->data[1], sigmaStar->data[2] );
562  XLALPrintError( "sKerr = %.16e\t%.16e\t%.16e\n", sigmaKerr->data[0],
563  sigmaKerr->data[1], sigmaKerr->data[2] );
564  XLALPrintError("csi = %.16e, Q = %.16e, pvr = %.16e, xi2 = %.16e , deltaT = %.16e, rho2 = %.16e, Lambda = %.16e, pxir = %.16e, B = %.16e\n", csi,Q, pvr, xi2, deltaT, rho2, Lambda, pxir, B );
565 
566  XLALPrintError( "KK = %.16e\n", coeffs->KK );
567  XLALPrintError( "bulk = %.16e, logTerms = %.16e\n", bulk, logTerms );
568  XLALPrintError("csi(miami) = %.16e\n", csi);
569  XLALPrintError( " a = %.16e, r = %.16e\n", a, r );
570  XLALPrintError( "D = %.16e, ww = %.16e, rho = %.16e, Lambda = %.16e, xi = %.16e\npr = %.16e, pf = %.16e, deltaR = %.16e, deltaT = %.16e\n",
571  D, ww, sqrt(rho2), Lambda, sqrt(xi2), pr, pf, deltaR, deltaT );
572  XLALPrintError( "pr = %.16e, prT = %.16e\n", pr, prT );
573 
574  XLALPrintError( " a = %.16e, r = %.16e\n", a, r );
575  XLALPrintError( "D = %.16e, ww = %.16e, rho = %.16e, Lambda = %.16e, xi = %.16e\npr = %.16e, pf = %.16e, deltaR = %.16e, deltaT = %.16e\n",
576  D, ww, sqrt(rho2), Lambda, sqrt(xi2), pr, pf, deltaR, deltaT );
577  XLALPrintError( "pr = %.16e, prT = %.16e\n", pr, prT );
578  XLALPrintError( "pn2 = %.16e, pp = %.16e\n", pn2, pp );
579  XLALPrintError( "deltaSigmaStar_x = %.16e, deltaSigmaStar_y = %.16e, deltaSigmaStar_z = %.16e\n",
580  deltaSigmaStar_x, deltaSigmaStar_y, deltaSigmaStar_z );
581 
582  XLALPrintError( "term 1 in Hns: %.16e\n", prT*prT*prT*prT*qq*u2 );
583  XLALPrintError( "term 2 in Hns: %.16e\n", ptheta2/rho2 );
584  XLALPrintError( "term 3 in Hns = %.16e\n", pf*pf*rho2/(Lambda*xi2) );
585  XLALPrintError( "term 4 in Hns = %.16e\n", pr*pr*deltaR/rho2 );
586  XLALPrintError( "term 5 in Hns = %.16e\n", Lambda/(rho2*deltaT) );
587  XLALPrintError( "term 6 in Hns = %.16e\n", pf*ww/Lambda );
588 
589  XLALPrintError( "Hns = %.16e, Hs = %.16e, Hss = %.16e\n", Hns, Hs, Hss );
590  XLALPrintError( "H = %.16e\n", H );
591 
592  XLALPrintError("Done printing components.\n\n");
593  XLALPrintError( "XLAL Error - %s: Hreal = nan in Hamiltonian \n", __func__);
595  }
596 
597  return Hreal;
598 }
599 
600 /**
601  * This function calculates the function \f$\Delta_t(r)\f$ which appears in the spinning EOB
602  * potential function. Eqs. 5.73 of PRD 81, 084024 (2010) augmented by 4PN, linear-in-eta corrections:
603  * see also section "New 4PN term in the radial potential" of https://dcc.ligo.org/T1400476
604  */
606  SpinEOBHCoeffs *coeffs, /**<< Pre-computed coefficients which appear in the function */
607  const REAL8 r, /**<< Current orbital radius (in units of total mass) */
608  const REAL8 eta, /**<< Symmetric mass ratio */
609  const REAL8 a /**<< Normalized deformed Kerr spin */
610  )
611 
612 {
613 
614  REAL8 a2;
615  REAL8 u, u2, u3, u4, u5;
617 
618  REAL8 bulk;
619  REAL8 logTerms;
620  REAL8 deltaU;
621  REAL8 deltaT;
622 
623  u = 1./r;
624  u2 = u*u;
625  u3 = u2*u;
626  u4 = u2*u2;
627  u5 = u4*u;
628 
629  a2 = a*a;
630 
631  m1PlusetaKK = -1. + eta * coeffs->KK;
632 
633  bulk = 1./(m1PlusetaKK*m1PlusetaKK) + (2.*u)/m1PlusetaKK + a2*u2;
634 
635  logTerms = 1. + eta*coeffs->k0 + eta*log(fabs(1. + coeffs->k1*u + coeffs->k2*u2 + coeffs->k3*u3 + coeffs->k4*u4
636  + coeffs->k5*u5 + coeffs->k5l*u5*log(u)));
637  deltaU = bulk*logTerms;
638  deltaU = fabs(deltaU);
639  deltaT = r*r*deltaU;
640 
641  return deltaT;
642 }
643 
644 
645 /**
646  * This function calculates the function \f$\Delta_r(r)\f$ which appears in the spinning EOB
647  * potential function. Eqs. 5.83 of PRD 81, 084024 (2010)
648  */
650  SpinEOBHCoeffs *coeffs, /**<< Pre-computed coefficients which appear in the function */
651  const REAL8 r, /**<< Current orbital radius (in units of total mass) */
652  const REAL8 eta, /**<< Symmetric mass ratio */
653  const REAL8 a /**<< Normalized deformed Kerr spin */
654  )
655 {
656 
657  REAL8 u2, u3;
658  REAL8 D;
659  REAL8 deltaT; /* The potential function, not a time interval... */
660  REAL8 deltaR;
661 
662  u2 = 1./(r*r);
663  u3 = u2 / r;
664 
665  D = 1. + log(1. + 6.*eta*u2 + 2.*(26. - 3.*eta)*eta*u3);
666 
668 
669  deltaR = deltaT*D;
670  return deltaR;
671 }
672 
673 
674 /* ************************************************************************* */
675 /* ************************************************************************* */
676 /* *************** PRECESSING EOB FUNCTIONS ************************** */
677 /* ************************************************************************* */
678 /* ************************************************************************* */
679 
680 /**
681  * Functions to compute the inner product and cross products
682  * between vectors
683  * */
684 static REAL8 inner_product( const REAL8 values1[],
685  const REAL8 values2[] )
686 {
687  REAL8 result = 0;
688  for( int i = 0; i < 3 ; i++ )
689  result += values1[i] * values2[i];
690 
691  return result;
692 }
693 
694 static REAL8* cross_product( const REAL8 values1[],
695  const REAL8 values2[],
696  REAL8 result[] )
697 {
698  result[0] = values1[1]*values2[2] - values1[2]*values2[1];
699  result[1] = values1[2]*values2[0] - values1[0]*values2[2];
700  result[2] = values1[0]*values2[1] - values1[1]*values2[0];
701 
702  return result;
703 }
704 
705 /**
706  * Rotate the vector v around the axis k by an angle theta, counterclockwise
707  * Note that this assumes that the rotation axis k is normalized.
708  * */
709 UNUSED static REAL8* rotate_vector(const REAL8 v[], const REAL8 k[], const REAL8 theta,REAL8 result[] ){
710  // Rodrigues rotation formula, see https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
711  REAL8 kcrossv[3]={0,0,0};
712  cross_product(k,v,kcrossv);
713  REAL8 kdotv = inner_product(k,v);
714  for (UINT4 ii=0;ii<3;ii++){
715  result[ii] = v[ii]*cos(theta)+kcrossv[ii]*sin(theta)+k[ii]*kdotv*(1-cos(theta));
716  }
717  return result;
718 }
719 /**
720  * Function to calculate the value of omega for the PRECESSING EOB waveform.
721  * Needs the dynamics in Cartesian coordinates.
722  *
723  * First, the frame is rotated so that L is along the y-axis.
724  * this rotation includes the spins.
725  *
726  * Second, \f$\vec{r}\f$ and \f$\vec{p}\f$ are converted to polar coordinates
727  * (and not the spins). As L is along the y-axis, \f$\theta\f$ defined as the
728  * angle between L and the y-axis is 0, which is a cyclic coordinate now and
729  * that fixes
730  * \f$p_\theta = 0\f$.
731  *
732  * Third, \f$p_r\f$ is set to 0.
733  *
734  * Fourth, the polar \f$(r,\phi,p_r=0,p_\phi)\f$ and the Cartesian spin vectors
735  * are used to compute the derivative
736  * \f$\partial Hreal/\partial p_\phi |p_r=0\f$.
737  */
739  const REAL8 values[], /**<< Dynamical variables */
740  SpinEOBParams *funcParams /**<< EOB parameters */
741  )
742 {
743  int debugPK = 1;
744  if (debugPK){
745  for(int i =0; i < 12; i++)
746  if( isnan(values[i]) ) {
747  XLAL_PRINT_INFO("XLALSimIMRSpinPrecEOBCalcOmega::values %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]);
748  XLALPrintError( "XLAL Error - %s: nan in input values \n", __func__);
750  }
751  }
752 
753  /* ********************************************************************* */
754  /* ************ Memory Allocation ************************************** */
755  /* ********************************************************************* */
756  static const REAL8 STEP_SIZE = 1.0e-4;
757  REAL8 tmpvar = 0;
758 
760 
761  /* Cartesian values for calculating the Hamiltonian */
762  REAL8 cartValues[14] = {0.}, dvalues[14] = {0.};
763  REAL8 cartvalues[14] = {0.}, polarvalues[6] = {0.}; /* The rotated cartesian/polar values */
764  REAL8 polarRPcartSvalues[14] = {0.};
765  memcpy( cartValues, values, 14 * sizeof(REAL8) );
766 
767  INT4 i, j;
768 
769  REAL8 rvec[3] = {0.,0,0}, pvec[3] = {0.,0,0};
770  REAL8 s1vec[3] = {0.,0,0}, s2vec[3] = {0.,0,0};
771 
772  REAL8 rdotvec[3] = {0.,0,0};
773  REAL8 rvecprime[3] = {0.,0,0}, pvecprime[3] = {0.,0,0},
774  s1vecprime[3]= {0.,0,0}, s2vecprime[3]= {0.,0,0};
775  REAL8 rvectmp[3] = {0.,0,0}, pvectmp[3] = {0.,0,0},
776  s1vectmp[3] = {0.,0,0}, s2vectmp[3]= {0.,0,0};
777  REAL8 LNhatprime[3]= {0.,0,0}, LNhatTmp[3]= {0.,0,0};
778  REAL8 rcrossrdot[3] = {0.,0,0};
779 
780  REAL8 Rot1[3][3] ={{0.}}; // Rotation matrix for prevention of blowing up
781  REAL8 Rot2[3][3] ={{0.}} ;
782  REAL8 LNhat[3] = {0.,0,0};
783 
784  REAL8 Xhat[3] = {1, 0, 0};
785  UNUSED REAL8 Yhat[3] = {0, 1, 0};
786  UNUSED REAL8 Zhat[3] = {0, 0, 1};
787 
788  REAL8 Xprime[3] = {0.,0,0}, Yprime[3] = {0.,0,0}, Zprime[3] = {0.,0,0};
789 
790  gsl_function F;
791  INT4 gslStatus;
792 
793  REAL8 omega;
794 
795  /* The error in a derivative as measured by GSL */
796  REAL8 absErr;
797 
798  /* ********************************************************************* */
799  /* ************ Main Logic begins ************************************ */
800  /* ********************************************************************* */
801 
802  /* Copy over the coordinates and spins */
803  memcpy( rvec, values, 3*sizeof(REAL8) );
804  memcpy( pvec, values+3, 3*sizeof(REAL8) );
805  memcpy( s1vec, values+6, 3*sizeof(REAL8) );
806  memcpy( s2vec, values+9, 3*sizeof(REAL8) );
807 
808  /* Calculate rDot = \f$\partial Hreal / \partial p_r\f$ */
809  memset( dvalues, 0, 14 * sizeof(REAL8) );
810  if( XLALSpinPrecHcapRvecDerivative( 0, values, dvalues,
811  (void*) funcParams) == XLAL_FAILURE )
812  {
814  }
815  memcpy( rdotvec, dvalues, 3*sizeof(REAL8) );
816  if (debugPK){
817  for(int ii =0; ii < 12; ii++)
818  if( isnan(dvalues[ii]) ) {
819  XLAL_PRINT_INFO("XLALSimIMRSpinPrecEOBCalcOmega::dvalues %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", dvalues[0], dvalues[1], dvalues[2], dvalues[3], dvalues[4], dvalues[5], dvalues[6], dvalues[7], dvalues[8], dvalues[9], dvalues[10], dvalues[11]);
820  XLALPrintError( "XLAL Error - %s: nan in dvalues \n", __func__);
822  }
823  }
824 
825  /* Calculate LN = r cross rDot */
826  cross_product( rvec, rdotvec, rcrossrdot );
827  REAL8 rcrossrdotNorm = sqrt(inner_product( rcrossrdot, rcrossrdot ));
828  for( i = 0; i < 3; i++ )
829  rcrossrdot[i] /= rcrossrdotNorm;
830  memcpy( LNhat, rcrossrdot, 3 * sizeof(REAL8) );
831 
832 
833  /* ********************************************************************* */
834  /* First, the frame is rotated so that L is along the y-axis. */
835  /* this rotation includes the spins. */
836  /* ********************************************************************* */
837 
838  // For Now , set first rotation matrix to identity
839  // Check if LNhat and Xhat are too aligned, in which case rotate LNhat
840  if( inner_product(LNhat, Xhat) < 0.9 )
841  {
842  Rot1[0][0] = 1.; Rot1[0][1] = 0; Rot1[0][2] = 0;
843  Rot1[1][0] = 0.; Rot1[1][1] = 1; Rot1[1][2] = 0;
844  Rot1[2][0] = 0.; Rot1[2][1] = 0; Rot1[2][2] = 1;
845 
846  memcpy(Xprime, LNhat, 3 * sizeof(REAL8));
847  cross_product( Xprime, Xhat, Yprime );
848  tmpvar = sqrt(inner_product(Yprime, Yprime));
849 
850  for( i=0; i<3; i++)
851  Yprime[i] /= tmpvar;
852 
853  cross_product(Xprime, Yprime, Zprime);
854  tmpvar = sqrt(inner_product(Zprime, Zprime));
855  for( i=0; i<3; i++)
856  Zprime[i] /= tmpvar;
857  }
858  else
859  {
860  Rot1[0][0] = 1./sqrt(2); Rot1[0][1] = -1/sqrt(2); Rot1[0][2] = 0;
861  Rot1[1][0] = 1./sqrt(2); Rot1[1][1] = 1./sqrt(2); Rot1[1][2] = 0;
862  Rot1[2][0] = 0.; Rot1[2][1] = 0; Rot1[2][2] = 1;
863  LNhatTmp[0] = LNhatTmp[1] = LNhatTmp[2] = 0.;
864 
865  for(i=0; i<3; i++)
866  for(j=0; j<3; j++)
867  LNhatTmp[i] += Rot1[i][j]*LNhat[j];
868 
869  memcpy(Xprime, LNhatTmp, 3*sizeof(REAL8));
870  cross_product(Xprime, Xhat, Yprime);
871  tmpvar = sqrt(inner_product(Yprime, Yprime));
872 
873  for( i=0; i<3; i++)
874  Yprime[i] /= tmpvar;
875 
876  cross_product(Xprime, Yprime, Zprime);
877  tmpvar = sqrt(inner_product(Zprime, Zprime));
878  for( i=0; i<3; i++)
879  Zprime[i] /= tmpvar;
880  }
881 
882  Rot2[0][0] = Xprime[0]; Rot2[0][1] = Xprime[1]; Rot2[0][2] = Xprime[2];
883  Rot2[1][0] = Yprime[0]; Rot2[1][1] = Yprime[1]; Rot2[1][2] = Yprime[2];
884  Rot2[2][0] = Zprime[0]; Rot2[2][1] = Zprime[1]; Rot2[2][2] = Zprime[2];
885 
886  memset( rvectmp, 0, 3 * sizeof(REAL8) );
887  memset( pvectmp, 0, 3 * sizeof(REAL8) );
888  memset( s1vectmp, 0, 3 * sizeof(REAL8) );
889  memset( s2vectmp, 0, 3 * sizeof(REAL8) );
890  memset( rvecprime, 0, 3 * sizeof(REAL8) );
891  memset( pvecprime, 0, 3 * sizeof(REAL8) );
892  memset( s1vecprime, 0, 3 * sizeof(REAL8) );
893  memset( s2vecprime, 0, 3 * sizeof(REAL8) );
894  memset( LNhatprime, 0, 3 * sizeof(REAL8) );
895  memset( LNhatTmp, 0, 3 * sizeof(REAL8) );
896 
897  /* Perform the actual rotation */
898  for (i=0; i<3; i++)
899  for(j=0; j<3; j++)
900  {
901  rvectmp[i] += Rot1[i][j]*rvec[j];
902  pvectmp[i] += Rot1[i][j]*pvec[j];
903  s1vectmp[i] += Rot1[i][j]*s1vec[j];
904  s2vectmp[i] += Rot1[i][j]*s2vec[j];
905  LNhatTmp[i] += Rot1[i][j]*LNhat[j];
906  }
907  for (i=0; i<3; i++)
908  for(j=0; j<3; j++)
909  {
910  rvecprime[i] += Rot2[i][j]*rvectmp[j];
911  pvecprime[i] += Rot2[i][j]*pvectmp[j];
912  s1vecprime[i] += Rot2[i][j]*s1vectmp[j];
913  s2vecprime[i] += Rot2[i][j]*s2vectmp[j];
914  LNhatprime[i] += Rot2[i][j]*LNhatTmp[j];
915  }
916 
917  memcpy(cartvalues, rvecprime, 3*sizeof(REAL8));
918  memcpy(cartvalues+3, pvecprime, 3*sizeof(REAL8));
919  memcpy(cartvalues+6, s1vecprime, 3*sizeof(REAL8));
920  memcpy(cartvalues+9, s2vecprime, 3*sizeof(REAL8));
921 
922  /* ********************************************************************* */
923  /* Second, \f$\vec{r}\f$ and \f$\vec{p}\f$ are converted to polar
924  * coordinates (and not the spins).
925  * As L is along the y-axis, \f$\theta\f$ defined as the angle between
926  * L and the y-axis is 0, which is a cyclic coordinate now and that fixes
927  * \f$p_\theta = 0\f$. */
928  /* ********************************************************************* */
929 
930  /** the polarvalues, respectively, are
931  * \f${r, \theta, \phi, p_r, p_\theta, p_\phi}\f$ */
932  polarvalues[0] = sqrt(inner_product(rvecprime,rvecprime));
933  polarvalues[1] = acos(rvecprime[0] / polarvalues[0]);
934  polarvalues[2] = atan2(-rvecprime[1], rvecprime[2]);
935  //polarvalues[3] = inner_product(rvecprime, pvecprime) / polarvalues[0];
936  /* FIX p_r = 0 */
937  polarvalues[3] = 0;
938 
939  REAL8 rvecprime_x_xhat[3] = {0.}, rvecprime_x_xhat_x_rvecprime[3] = {0.};
940  cross_product(rvecprime, Xhat, rvecprime_x_xhat);
941  cross_product(rvecprime_x_xhat, rvecprime, rvecprime_x_xhat_x_rvecprime);
942 
943  polarvalues[4] = -inner_product(rvecprime_x_xhat_x_rvecprime, pvecprime)
944  / polarvalues[0] / sin(polarvalues[1]);
945  polarvalues[5] = -inner_product(rvecprime_x_xhat, pvecprime);
946 
947 
948  /* ********************************************************************* */ /* Finally, Differentiate Hamiltonian w.r.t. p_\phi, keeping p_r = 0 */
949  /* ********************************************************************* */
950 
951  /* Populate the vector specifying the dynamical variables in mixed frames */
952  memcpy( polarRPcartSvalues, cartvalues, 12*sizeof(REAL8));
953  memcpy( polarRPcartSvalues, polarvalues, 6*sizeof(REAL8));
954 
955  /* Set up pointers for GSL */
956  params.values = polarRPcartSvalues;
957  params.params = funcParams;
958 
960  F.params = &params;
961 
962  /* Now calculate omega. In the chosen co-ordinate system, */
963  /* we need dH/dpphi to calculate this, i.e. varyParam = 5 */
964  params.varyParam = 5;
965  XLAL_CALLGSL( gslStatus = gsl_deriv_central( &F, polarvalues[5],
966  STEP_SIZE, &omega, &absErr ) );
967 
968  if ( gslStatus != GSL_SUCCESS )
969  {
970  XLALPrintError( "XLAL Error - %s: Failure in GSL function\n", __func__ );
972  }
973 
974  return omega;
975 }
976 
977 
978 /**
979  * Function to calculate the non-Keplerian coefficient for the PRECESSING EOB
980  * model.
981  *
982  * radius \f$r\f$ times the cuberoot of the returned number is \f$r_\Omega\f$
983  * defined in Eq. A2, i.e. the function returns
984  * \f$(r_{\Omega} / r)^3\f$
985  * = \f$1/(r^3 (\partial Hreal/\partial p_\phi |p_r=0)^2)\f$.
986  */
987 static REAL8
989  const REAL8 values[], /**<< Dynamical variables */
990  SpinEOBParams *funcParams /**<< EOB parameters */
991  )
992 {
993  int debugPK = 1;
994  if (debugPK){
995  for(int i =0; i < 12; i++)
996  if( isnan(values[i]) ) {
997  XLAL_PRINT_INFO("XLALSimIMRSpinPrecEOBNonKeplerCoeff::values %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n",
998  values[0], values[1], values[2], values[3], values[4], values[5],
999  values[6], values[7], values[8], values[9], values[10], values[11]);
1000  XLALPrintError( "XLAL Error - %s: nan in values \n", __func__);
1002  }
1003  }
1004 
1005  REAL8 omegaCirc = 0;
1006  REAL8 tmpValues[14]= {0.};
1007  REAL8 r3;
1008 
1009  /* We need to find the values of omega assuming pr = 0 */
1010  memcpy( tmpValues, values, sizeof(tmpValues) );
1011  omegaCirc = XLALSimIMRSpinPrecEOBCalcOmega( tmpValues, funcParams );
1012  if ( XLAL_IS_REAL8_FAIL_NAN( omegaCirc ) )
1013  {
1015  }
1016 
1017  r3 = pow(inner_product(values, values), 3./2.);
1018  return 1.0/(omegaCirc*omegaCirc*r3);
1019 }
1020 
1021 /**
1022  * Function to calculate numerical derivatives of the spin EOB Hamiltonian,
1023  * to get \f$dr/dt\f$, as decribed in Eqs. A4 of PRD 81, 084041 (2010)
1024  * This function is not used by the spin-aligned SEOBNRv1 model.
1025  */
1027  double UNUSED t, /**<< UNUSED */
1028  const REAL8 values[], /**<< Dynamical variables */
1029  REAL8 dvalues[], /**<< Time derivatives of variables (returned) */
1030  void *funcParams /**<< EOB parameters */
1031  )
1032 {
1033  UNUSED int debugPK = 1;
1034  //if (debugPK){
1035  for(int i =0; i < 12; i++){
1036  if( isnan(values[i]) ) {
1037  XLAL_PRINT_INFO("XLALSpinPrecHcapRvecDerivative::values %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]);
1038  XLALPrintError( "XLAL Error - %s: nan in input values \n", __func__);
1040  }
1041 
1042  if( isnan(dvalues[i]) ) {
1043  XLAL_PRINT_INFO("XLALSpinPrecHcapRvecDerivative::dvalues %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", dvalues[0], dvalues[1], dvalues[2], dvalues[3], dvalues[4], dvalues[5], dvalues[6], dvalues[7], dvalues[8], dvalues[9], dvalues[10], dvalues[11]);
1044  XLALPrintError( "XLAL Error - %s: nan in the input dvalues \n", __func__);
1046  }
1047  }
1048  //}
1049 
1050  static const REAL8 STEP_SIZE = 1.0e-4;
1051 
1052  UNUSED static const INT4 lMax = 8;
1053 
1055 
1056  /* Since we take numerical derivatives wrt dynamical variables */
1057  /* but we want them wrt time, we use this temporary vector in */
1058  /* the conversion */
1059  REAL8 tmpDValues[14] = {0.};
1060 
1061  REAL8 H; //Hamiltonian
1062  //REAL8 flux;
1063 
1064  gsl_function F;
1065  INT4 gslStatus;
1066  UINT4 SpinAlignedEOBversion;
1067  UINT4 SpinAlignedEOBversionForWaveformCoefficients;
1068 
1069  UINT4 i, j, k;//, l;
1070 
1071  REAL8Vector rVec, pVec;
1072  REAL8 rData[3] = {0.}, pData[3] = {0.};
1073 
1074  /* We need r, phi, pr, pPhi to calculate the flux */
1075  REAL8 UNUSED r;
1076  REAL8Vector UNUSED polarDynamics;
1077  REAL8 polData[4] = {0.};
1078 
1079  REAL8 mass1, mass2, eta;
1080  REAL8 UNUSED rrTerm2, pDotS1, pDotS2;
1081  REAL8Vector s1, s2, s1norm, s2norm, sKerr, sStar;
1082  REAL8 s1Data[3]= {0.}, s2Data[3]= {0.}, s1DataNorm[3]= {0.}, s2DataNorm[3]= {0.};
1083  REAL8 sKerrData[3]= {0.}, sStarData[3]= {0.};
1084  REAL8 /*magS1, magS2,*/ chiS, chiA, a, tplspin;
1085  REAL8 UNUSED s1dotL, s2dotL;
1086  REAL8 UNUSED rcrossrDot[3]= {0.}, rcrossrDotMag, s1dotLN, s2dotLN;
1087 
1088 
1089  /* Orbital angular momentum */
1090  REAL8 Lx, Ly, Lz, magL;
1091  REAL8 Lhatx, Lhaty, Lhatz;
1092  //REAL8 dLx, dLy, dLz;
1093  //REAL8 dLhatx, dLhaty, dMagL;
1094 
1095  //REAL8 alphadotcosi;
1096 
1097  //REAL8 rCrossV_x, rCrossV_y, rCrossV_z, omega;
1098 
1099  /* The error in a derivative as measured by GSL */
1100  REAL8 absErr;
1101 
1102  REAL8 tmpP[3]= {0.}, rMag, rMag2, prT;
1103  REAL8 u, u2, u3, u4, u5, w2, a2;
1105  REAL8 UNUSED eobD_r, deltaU_u, deltaU_r, deltaT_r;
1106  REAL8 dcsi, csi;
1107 
1108  REAL8 tmpValues[12]= {0.};
1109  REAL8 UNUSED Tmatrix[3][3]= {{0.}}, invTmatrix[3][3]= {{0.}}, dTijdXk[3][3][3]= {{{0.}}};
1110  //REAL8 tmpPdotT1[3], tmpPdotT2[3], tmpPdotT3[3]; // 3 terms of Eq. A5
1111 
1112  /* Set up pointers for GSL */
1113  params.values = values;
1114  params.params = (SpinEOBParams *)funcParams;
1115 
1117  F.params = &params;
1118 
1119  mass1 = params.params->eobParams->m1;
1120  mass2 = params.params->eobParams->m2;
1121  eta = params.params->eobParams->eta;
1122  SpinAlignedEOBversion = params.params->seobCoeffs->SpinAlignedEOBversion;
1123  SpinEOBHCoeffs *coeffs = (SpinEOBHCoeffs*) params.params->seobCoeffs;
1124 
1125  /* For precessing binaries, the effective spin of the Kerr
1126  * background evolves with time. The coefficients used to compute
1127  * the Hamiltonian depend on the Kerr spin, and hence need to
1128  * be updated for the current spin values */
1129  if ( 0 )
1130  {/*{{{*/
1131  /* Set up structures and calculate necessary (spin-only) PN parameters */
1132  /* Due to precession, these need to get calculated in every step */
1133  //memset( params.params->seobCoeffs, 0, sizeof(SpinEOBHCoeffs) );
1134 
1135  REAL8 tmps1Data[3]= {0.}, tmps2Data[3]= {0.}; REAL8Vector tmps1Vec, tmps2Vec;
1136  memcpy( tmps1Data, values+6, 3*sizeof(REAL8) );
1137  memcpy( tmps2Data, values+9, 3*sizeof(REAL8) );
1138  tmps1Vec.data = tmps1Data; tmps2Vec.data = tmps2Data;
1139  tmps1Vec.length = tmps2Vec.length = 3;
1140 
1141  REAL8Vector *tmpsigmaKerr = NULL;
1142  REAL8Vector *tmpsigmaStar = NULL;
1143  if ( !(tmpsigmaKerr = XLALCreateREAL8Vector( 3 )) )
1144  {
1146  }
1147 
1148  if ( !(tmpsigmaStar = XLALCreateREAL8Vector( 3 )) )
1149  {
1151  }
1152 
1153  if ( XLALSimIMRSpinEOBCalculateSigmaKerr( tmpsigmaKerr, mass1, mass2,
1154  &tmps1Vec, &tmps2Vec ) == XLAL_FAILURE )
1155  {
1156  XLALDestroyREAL8Vector( tmpsigmaKerr );
1158  }
1159 
1160  if ( XLALSimIMRSpinEOBCalculateSigmaStar( tmpsigmaStar, mass1, mass2,
1161  &tmps1Vec, &tmps2Vec ) == XLAL_FAILURE )
1162  {
1163  XLALDestroyREAL8Vector( tmpsigmaKerr );
1164  XLALDestroyREAL8Vector( tmpsigmaStar );
1166  }
1167 
1168  /* Update a with the Kerr background spin
1169  * Pre-compute the Hamiltonian coefficients */
1170  //REAL8Vector *delsigmaKerr = params.params->sigmaKerr;
1171  params.params->sigmaKerr = tmpsigmaKerr;
1172  params.params->sigmaStar = tmpsigmaStar;
1173  params.params->a = sqrt( tmpsigmaKerr->data[0]*tmpsigmaKerr->data[0]
1174  + tmpsigmaKerr->data[1]*tmpsigmaKerr->data[1]
1175  + tmpsigmaKerr->data[2]*tmpsigmaKerr->data[2] );
1176  //tmpsigmaKerr->data[2];
1177  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs( params.params->seobCoeffs, eta,
1178  params.params->a, SpinAlignedEOBversion ) == XLAL_FAILURE )
1179  {
1180  XLALDestroyREAL8Vector( params.params->sigmaKerr );
1182  }
1183 
1184  params.params->seobCoeffs->SpinAlignedEOBversion = SpinAlignedEOBversion;
1185  /* Release the old memory */
1186  //if(0)XLALDestroyREAL8Vector( delsigmaKerr );
1187  /*}}}*/}
1188 
1189  /* Set the position/momenta vectors to point to the appropriate things */
1190  rVec.length = pVec.length = 3;
1191  rVec.data = rData;
1192  pVec.data = pData;
1193  memcpy( rData, values, sizeof(rData) );
1194  memcpy( pData, values+3, sizeof(pData) );
1195 
1196  /* We need to re-calculate the parameters at each step as precessing
1197  * spins will not be constant */
1198 
1199  /* We cannot point to the values vector directly as it leads to a warning */
1200  s1.length = s2.length = s1norm.length = s2norm.length = 3;
1201  s1.data = s1Data;
1202  s2.data = s2Data;
1203  s1norm.data = s1DataNorm;
1204  s2norm.data = s2DataNorm;
1205 
1206  memcpy( s1Data, values+6, 3*sizeof(REAL8) );
1207  memcpy( s2Data, values+9, 3*sizeof(REAL8) );
1208  memcpy( s1DataNorm, values+6, 3*sizeof(REAL8) );
1209  memcpy( s2DataNorm, values+9, 3*sizeof(REAL8) );
1210 
1211  for ( i = 0; i < 3; i++ )
1212  {
1213  s1Data[i] *= (mass1+mass2)*(mass1+mass2);
1214  s2Data[i] *= (mass1+mass2)*(mass1+mass2);
1215  }
1216 
1217  sKerr.length = 3;
1218  sKerr.data = sKerrData;
1219  XLALSimIMRSpinEOBCalculateSigmaKerr( &sKerr, mass1, mass2, &s1, &s2 );
1220 
1221  sStar.length = 3;
1222  sStar.data = sStarData;
1223  XLALSimIMRSpinEOBCalculateSigmaStar( &sStar, mass1, mass2, &s1, &s2 );
1224 
1225  a = sqrt(sKerr.data[0]*sKerr.data[0] + sKerr.data[1]*sKerr.data[1]
1226  + sKerr.data[2]*sKerr.data[2]);
1227 
1228  if (isnan(a)){
1229  XLALPrintError( "XLAL Error - %s: a = nan \n", __func__);
1231  }
1232  if(debugPK && isnan(a))
1233  XLAL_PRINT_INFO("a is nan in XLALSpinPrecHcapRvecDerivative \n");
1234 
1235  ///* set the tortoise flag to 2 */
1236  //INT4 oldTortoise = params.params->tortoise;
1237  //params.params->tortoise = 2;
1238 
1239  /* Convert momenta to p */
1240  rMag = sqrt(rData[0]*rData[0] + rData[1]*rData[1] + rData[2]*rData[2]);
1241  prT = pData[0]*(rData[0]/rMag) + pData[1]*(rData[1]/rMag)
1242  + pData[2]*(rData[2]/rMag);
1243 
1244  rMag2 = rMag * rMag;
1245  u = 1./rMag;
1246  u2 = u*u;
1247  u3 = u2*u;
1248  u4 = u2*u2;
1249  u5 = u4*u;
1250  a2 = a*a;
1251  w2 = rMag2 + a2;
1252  /* Eq. 5.83 of BB1, inverse */
1253  D = 1. + log(1. + 6.*eta*u2 + 2.*(26. - 3.*eta)*eta*u3);
1254  eobD_r = (u2/(D*D))*(12.*eta*u + 6.*(26. - 3.*eta)*eta*u2)/(1.
1255  + 6.*eta*u2 + 2.*(26. - 3.*eta)*eta*u3);
1256  m1PlusetaKK = -1. + eta * coeffs->KK;
1257  /* Eq. 5.75 of BB1 */
1258  bulk = 1./(m1PlusetaKK*m1PlusetaKK) + (2.*u)/m1PlusetaKK + a2*u2;
1259  /* Eq. 5.73 of BB1 */
1260  logTerms = 1. + eta*coeffs->k0 + eta*log(fabs(1. + coeffs->k1*u
1261  + coeffs->k2*u2 + coeffs->k3*u3 + coeffs->k4*u4
1262  + coeffs->k5*u5 + coeffs->k5l*u5*log(u)));
1263  /* Eq. 5.73 of BB1 */
1264  deltaU = bulk*logTerms;
1265  deltaU = fabs(deltaU);
1266 
1267  /* Eq. 5.71 of BB1 */
1268  deltaT = rMag2*deltaU;
1269  /* ddeltaU/du */
1270  deltaU_u = 2.*(1./m1PlusetaKK + a2*u)*logTerms +
1271  bulk * (eta*(coeffs->k1 + u*(2.*coeffs->k2 + u*(3.*coeffs->k3
1272  + u*(4.*coeffs->k4 + 5.*(coeffs->k5+coeffs->k5l*log(u))*u)))))
1273  / (1. + coeffs->k1*u + coeffs->k2*u2 + coeffs->k3*u3
1274  + coeffs->k4*u4 + (coeffs->k5+coeffs->k5l*log(u))*u5);
1275  deltaU_r = -u2 * deltaU_u;
1276  /* Eq. 5.38 of BB1 */
1277  deltaR = deltaT*D;
1278  if ( params.params->tortoise )
1279  csi = sqrt( fabs(deltaT * deltaR) )/ w2; /* Eq. 28 of Pan et al. PRD 81, 084041 (2010) */
1280  else
1281  csi = 1.0;
1282 
1283  for( i = 0; i < 3; i++ )
1284  {
1285  tmpP[i] = pData[i] - (rData[i]/rMag) * prT * (csi-1.)/csi;
1286  }
1287 
1288 
1289  /* Calculate the T-matrix, required to convert P from tortoise to
1290  * non-tortoise coordinates, and/or vice-versa. This is given explicitly
1291  * in Eq. A3 of 0912.3466 */
1292  for( i = 0; i < 3; i++ )
1293  for( j = 0; j <= i; j++ )
1294  {
1295  Tmatrix[i][j] = Tmatrix[j][i] = (rData[i]*rData[j]/rMag2)
1296  * (csi - 1.);
1297 
1298  invTmatrix[i][j] = invTmatrix[j][i] =
1299  - (csi - 1)/csi * (rData[i]*rData[j]/rMag2);
1300 
1301  if( i==j ){
1302  Tmatrix[i][j]++;
1303  invTmatrix[i][j]++; }
1304 
1305  }
1306 
1307  dcsi = csi * (2./rMag + deltaU_r/deltaU) + csi*csi*csi
1308  / (2.*rMag2*rMag2 * deltaU*deltaU) * ( rMag*(-4.*w2)/D - eobD_r*(w2*w2));
1309 
1310  for( i = 0; i < 3; i++ )
1311  for( j = 0; j < 3; j++ )
1312  for( k = 0; k < 3; k++ )
1313  {
1314  dTijdXk[i][j][k] =
1315  (rData[i]*KRONECKER_DELTA(j,k) + KRONECKER_DELTA(i,k)*rData[j])
1316  *(csi - 1.)/rMag2
1317  + rData[i]*rData[j]*rData[k]/rMag2/rMag*(-2./rMag*(csi - 1.) + dcsi);
1318  }
1319 
1320  //if (debugPK){
1321  for(i =0; i < 12; i++){
1322  if( isnan(values[i]) ) {
1323  XLAL_PRINT_INFO("XLALSpinPrecHcapRvecDerivative (just before diff)::values %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]);
1324  XLALPrintError( "XLAL Error - %s: values = nan \n", __func__);
1326  }
1327 
1328  if( isnan(dvalues[i]) ) {
1329  XLAL_PRINT_INFO("XLALSpinPrecHcapRvecDerivative (just before diff)::dvalues %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", dvalues[0], dvalues[1], dvalues[2], dvalues[3], dvalues[4], dvalues[5], dvalues[6], dvalues[7], dvalues[8], dvalues[9], dvalues[10], dvalues[11]);
1330  XLALPrintError( "XLAL Error - %s: dvalues = nan \n", __func__);
1332  }
1333  }
1334 //}
1335 
1336  /* Now calculate derivatives w.r.t. each parameter */
1337  // RH: Check if components i=0..5 (position and momenta) do not change the a parameter used for spin
1338  // RH: this breaks the loop below for i>=6
1339  SpinEOBHCoeffs tmpCoeffs;
1340  {
1341  // RH: taken from GSLSpinHamiltonianWrapperForRvecDerivs
1342  /* These are the vectors which will be used in the call to the Hamiltonian */
1343  REAL8Vector spin1, spin2;
1344  REAL8Vector sigmaKerr;
1345  REAL8 tmpVec[12]= {0.};
1346  REAL8 tmpsKerrData[3]= {0.};
1347  REAL8 mT2 = (mass1+mass2)*(mass1+mass2);
1348 
1349  /* Use a temporary vector to avoid corrupting the main function */
1350  memcpy( tmpVec, values, sizeof(tmpVec) );
1351 
1352  /* Set the LAL-style vectors to point to the appropriate things */
1353  sigmaKerr.length = 3;
1354  spin1.length = 3;
1355  spin2.length = 3;
1356 
1357  spin1.data = tmpVec+6;
1358  spin2.data = tmpVec+9;
1359  sigmaKerr.data = tmpsKerrData;
1360 
1361  /* To compute the SigmaKerr and SigmaStar, we need the non-normalized
1362  * spin values, i.e. S_i. The spins being evolved are S_i/M^2. */
1363  for ( i = 0; i < 3; i++ )
1364  {
1365  spin1.data[i] *= mT2;
1366  spin2.data[i] *= mT2;
1367  }
1368 
1369  /* Calculate various spin parameters */
1370  XLALSimIMRSpinEOBCalculateSigmaKerr( &sigmaKerr, mass1, mass2,
1371  &spin1, &spin2 );
1372 
1373  REAL8 tmpa;
1374  /* Calculate the orbital angular momentum */
1375  Lx = values[1] * values[5] - values[2] * values[4];
1376  Ly = values[2] * values[3] - values[0] * values[5];
1377  Lz = values[0] * values[4] - values[1] * values[3];
1378 
1379  magL = sqrt(Lx * Lx + Ly * Ly + Lz * Lz);
1380  Lhatx = Lx / magL;
1381  Lhaty = Ly / magL;
1382  Lhatz = Lz / magL;
1383  REAL8 Lhat[3] = {Lhatx, Lhaty, Lhatz};
1384  REAL8 tempS1_p = inner_product(s1Data, Lhat);
1385  REAL8 tempS2_p = inner_product(s2Data, Lhat);
1386  REAL8 S1_perp[3] = {0, 0, 0};
1387  REAL8 S2_perp[3] = {0, 0, 0};
1388  for(UINT4 jj=0; jj<3; jj++){
1389  S1_perp[jj] = 1/mT2*(s1Data[jj]-tempS1_p*Lhat[jj]);
1390  S2_perp[jj] = 1/mT2*(s2Data[jj]-tempS2_p*Lhat[jj]);
1391  }
1392  REAL8 sKerr_norm = sqrt(inner_product(sigmaKerr.data, sigmaKerr.data));
1393  REAL8 S_con = 0.0;
1394  if (sKerr_norm>1e-6){
1395  S_con = sigmaKerr.data[0] * Lhat[0] + sigmaKerr.data[1] * Lhat[1] + sigmaKerr.data[2] * Lhat[2];
1396  S_con /= (1 - 2 * eta);
1397  S_con += (inner_product(S1_perp, sigmaKerr.data) + inner_product(S2_perp, sigmaKerr.data)) / sKerr_norm / (1 - 2 * eta) / 2.;
1398  }
1399 
1400  REAL8 chi = S_con;
1401  tmpa = sqrt(sigmaKerr.data[0]*sigmaKerr.data[0]
1402  + sigmaKerr.data[1]*sigmaKerr.data[1]
1403  + sigmaKerr.data[2]*sigmaKerr.data[2]);
1404  if (SpinAlignedEOBversion == 4){
1405  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs_v2( &tmpCoeffs, eta,
1406  tmpa, chi, coeffs->SpinAlignedEOBversion ) == XLAL_FAILURE )
1407  {
1409  }
1410  }
1411  else
1412  {
1413  if ( XLALSimIMRCalculateSpinPrecEOBHCoeffs( &tmpCoeffs, eta,
1414  tmpa, coeffs->SpinAlignedEOBversion ) == XLAL_FAILURE )
1415  {
1417  }
1418  }
1419 
1420 
1421  tmpCoeffs.SpinAlignedEOBversion = params.params->seobCoeffs->SpinAlignedEOBversion;
1422  tmpCoeffs.updateHCoeffs = 0;
1423  }
1424  SpinEOBHCoeffs *oldCoeffs = params.params->seobCoeffs;
1425  params.params->seobCoeffs = &tmpCoeffs;
1426  for ( i = 3; i < 6; i++ )
1427  {
1428  params.varyParam = i;
1429  if ( i >=6 && i < 9 )
1430  {
1431  XLAL_ERROR( XLAL_EFUNC ); // this should never happen
1432  params.params->seobCoeffs->updateHCoeffs = 1;
1433  XLAL_CALLGSL( gslStatus = gsl_deriv_central( &F, values[i],
1434  STEP_SIZE*mass1*mass1, &tmpDValues[i], &absErr ) );
1435  }
1436  else if ( i >= 9 )
1437  {
1438  XLAL_ERROR( XLAL_EFUNC ); // this should never happen
1439  params.params->seobCoeffs->updateHCoeffs = 1;
1440  XLAL_CALLGSL( gslStatus = gsl_deriv_central( &F, values[i],
1441  STEP_SIZE*mass2*mass2, &tmpDValues[i], &absErr ) );
1442  }
1443  else if ( i < 3 )
1444  {
1445  XLAL_ERROR( XLAL_EFUNC ); // this should never happen
1446  params.params->tortoise = 2;
1447  memcpy( tmpValues, params.values, sizeof(tmpValues) );
1448  tmpValues[3] = tmpP[0]; tmpValues[4] = tmpP[1]; tmpValues[5] = tmpP[2];
1449  params.values = tmpValues;
1450 
1451  XLAL_CALLGSL( gslStatus = gsl_deriv_central( &F, values[i],
1452  STEP_SIZE, &tmpDValues[i], &absErr ) );
1453 
1454  params.values = values;
1455  params.params->tortoise = 1;
1456  }
1457  else
1458  {
1459  params.params->seobCoeffs->updateHCoeffs = 1;
1460 
1461  XLAL_CALLGSL( gslStatus = gsl_deriv_central( &F, values[i],
1462  STEP_SIZE, &tmpDValues[i], &absErr ) );
1463  }
1464  if ( gslStatus != GSL_SUCCESS )
1465  {
1466  XLALPrintError( "XLAL Error %s - Failure in GSL function\n", __func__ );
1468  }
1469  }
1470  params.params->seobCoeffs = oldCoeffs;
1471  if (debugPK){
1472  for( i =0; i < 12; i++)
1473  if( isnan(tmpDValues[i]) ) {
1474  XLAL_PRINT_INFO("XLALSpinPrecHcapRvecDerivative (just after diff)::tmpDValues %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", tmpDValues[0], tmpDValues[1], tmpDValues[2], tmpDValues[3], tmpDValues[4], tmpDValues[5], tmpDValues[6], tmpDValues[7], tmpDValues[8], tmpDValues[9], tmpDValues[10], tmpDValues[11]);
1475  }
1476  }
1477 
1478  /* Calculate the orbital angular momentum */
1479  Lx = values[1]*values[5] - values[2]*values[4];
1480  Ly = values[2]*values[3] - values[0]*values[5];
1481  Lz = values[0]*values[4] - values[1]*values[3];
1482 
1483  magL = sqrt( Lx*Lx + Ly*Ly + Lz*Lz );
1484 
1485  Lhatx = Lx/magL;
1486  Lhaty = Ly/magL;
1487  Lhatz = Lz/magL;
1488 
1489  /* Calculate the polar data */
1490  polarDynamics.length = 4;
1491  polarDynamics.data = polData;
1492 
1493  r = polData[0] = sqrt( values[0]*values[0] + values[1]*values[1]
1494  + values[2]*values[2] );
1495  polData[1] = 0;
1496  polData[2] = (values[0]*values[3] + values[1]*values[4]
1497  + values[2]*values[5]) / polData[0];
1498  polData[3] = magL;
1499 
1500 
1501  // Compute \vec{S_i} \dot \vec{L}
1502  s1dotL = (s1Data[0]*Lhatx + s1Data[1]*Lhaty + s1Data[2]*Lhatz)
1503  / (mass1*mass1);
1504  s2dotL = (s2Data[0]*Lhatx + s2Data[1]*Lhaty + s2Data[2]*Lhatz)
1505  / (mass2*mass2);
1506 
1507  // Compute \vec{L_N} = \vec{r} \times \.{\vec{r}},
1508  // \vec{S_i} \dot \vec{L_N} and chiS and chiA
1509  rcrossrDot[0] = values[1]*tmpDValues[5] - values[2]*tmpDValues[4];
1510  rcrossrDot[1] = values[2]*tmpDValues[3] - values[0]*tmpDValues[5];
1511  rcrossrDot[2] = values[0]*tmpDValues[4] - values[1]*tmpDValues[3];
1512  rcrossrDotMag = sqrt( rcrossrDot[0]*rcrossrDot[0]
1513  + rcrossrDot[1]*rcrossrDot[1] + rcrossrDot[2]*rcrossrDot[2] );
1514 
1515  rcrossrDot[0] /= rcrossrDotMag;
1516  rcrossrDot[1] /= rcrossrDotMag;
1517  rcrossrDot[2] /= rcrossrDotMag;
1518 
1519  s1dotLN = (s1Data[0]*rcrossrDot[0] + s1Data[1]*rcrossrDot[1]
1520  + s1Data[2]*rcrossrDot[2]) / (mass1*mass1);
1521  s2dotLN = (s2Data[0]*rcrossrDot[0] + s2Data[1]*rcrossrDot[1]
1522  + s2Data[2]*rcrossrDot[2]) / (mass2*mass2);
1523 
1524  REAL8 mT2 = (mass1+mass2)*(mass1+mass2);
1525  if (SpinAlignedEOBversion==4){
1526  chiS = 0.5 * (s1dotL + s2dotL);
1527  chiA = 0.5 * (s1dotL - s2dotL);
1528  }
1529  else{
1530  chiS = 0.5 * (s1dotLN + s2dotLN);
1531  chiA = 0.5 * (s1dotLN - s2dotLN);
1532  }
1533  REAL8 Lhat[3] = {Lhatx, Lhaty, Lhatz};
1534  REAL8 tempS1_p = inner_product(s1Data, Lhat);
1535  REAL8 tempS2_p = inner_product(s2Data, Lhat);
1536  REAL8 S1_perp[3] = {0, 0, 0};
1537  REAL8 S2_perp[3] = {0, 0, 0};
1538 
1539  for (UINT4 jj = 0; jj < 3; jj++)
1540  {
1541  S1_perp[jj] = 1 / mT2 * (s1Data[jj] - tempS1_p * Lhat[jj]);
1542  S2_perp[jj] = 1 / mT2 * (s2Data[jj] - tempS2_p * Lhat[jj]);
1543  }
1544 
1545  REAL8 sKerr_norm = sqrt(inner_product(sKerr.data, sKerr.data));
1546 
1547  REAL8 S_con = 0.0;
1548  if (sKerr_norm > 1e-6){
1549  S_con = sKerr.data[0] * Lhat[0] + sKerr.data[1] * Lhat[1] + sKerr.data[2] * Lhat[2];
1550  S_con /= (1 - 2 * eta);
1551  S_con += (inner_product(S1_perp, sKerr.data) + inner_product(S2_perp, sKerr.data)) / sKerr_norm / (1 - 2 * eta) / 2.;
1552  }
1553 
1554  REAL8 chi = S_con;
1555  /* Compute the test-particle limit spin of the deformed-Kerr background */
1556  switch ( SpinAlignedEOBversion )
1557  {
1558  case 1:
1559  tplspin = 0.0;
1560  break;
1561  case 2:
1562  case 4:
1563  tplspin = (1.-2.*eta) * chiS + (mass1 - mass2)/(mass1 + mass2) * chiA;
1564  break;
1565  default:
1566  XLALPrintError( "XLAL Error - %s: Unknown SEOBNR version!\nAt present only v1 and v2 are available.\n", __func__);
1568  break;
1569  }
1570 
1571  for( i = 0; i< 3; i++ )
1572  {
1573  params.params->s1Vec->data[i] = s1norm.data[i];
1574  params.params->s2Vec->data[i] = s2norm.data[i];
1575  params.params->sigmaStar->data[i] = sStar.data[i];
1576  params.params->sigmaKerr->data[i] = sKerr.data[i];
1577  }
1578 
1579  //params.params->s1Vec = &s1norm;
1580  //params.params->s2Vec = &s2norm;
1581  //params.params->sigmaStar = &sStar;
1582  //params.params->sigmaKerr = &sKerr;
1583  params.params->a = a;
1584 
1585  if (SpinAlignedEOBversion == 2) {
1586  SpinAlignedEOBversionForWaveformCoefficients = 3;
1587  }
1588  else{
1589  SpinAlignedEOBversionForWaveformCoefficients = SpinAlignedEOBversion;
1590  }
1591 
1592  if (params.params->alignedSpins==1) {
1594  params.params->eobParams->hCoeffs, mass1, mass2, eta, tplspin,
1595  chiS, chiA, SpinAlignedEOBversion);
1596  }
1597  else {
1599  params.params->eobParams->hCoeffs, mass1, mass2, eta, tplspin,
1600  chiS, chiA, SpinAlignedEOBversionForWaveformCoefficients);
1601  }
1602  if (SpinAlignedEOBversion == 4){
1603 
1604  XLALSimIMRCalculateSpinPrecEOBHCoeffs_v2( params.params->seobCoeffs, eta, a, chi,
1605  SpinAlignedEOBversion );
1606 
1607  //H = XLALSimIMRSpinPrecEOBHamiltonian( eta, &rVec, &pVec, s1proj, s2proj,
1608  //&sKerr, &sStar, params.params->tortoise, params.params->seobCoeffs );
1609  }
1610  else{
1612  SpinAlignedEOBversion );
1613 
1614 
1615  }
1616  H = XLALSimIMRSpinPrecEOBHamiltonian( eta, &rVec, &pVec, &s1norm, &s2norm,
1617  &sKerr, &sStar, params.params->tortoise, params.params->seobCoeffs );
1618  H = H * (mass1 + mass2);
1619 
1620  /* Now make the conversion */
1621  /* rVectorDot */
1622  for( i = 0; i < 3; i++ )
1623  for( j = 0, dvalues[i] = 0.; j < 3; j++ )
1624  dvalues[i] += tmpDValues[j+3]*Tmatrix[i][j];
1625 
1626  return XLAL_SUCCESS;
1627 }
1628 
1629 /**
1630  * Wrapper for GSL to call the Hamiltonian function. This is simply the function
1631  * GSLSpinPrecHamiltonianWrapper copied over. The alternative was to make it non-static
1632  * which increases runtime as static functions can be better optimized.
1633  */
1634 static double GSLSpinPrecHamiltonianWrapperForRvecDerivs( double x, void *params )
1635 {
1636  int debugPK = 1;
1637  HcapDerivParams *dParams = (HcapDerivParams *)params;
1638 
1639  EOBParams *eobParams = (EOBParams*) dParams->params->eobParams;
1640  SpinEOBHCoeffs UNUSED *coeffs = (SpinEOBHCoeffs*) dParams->params->seobCoeffs;
1641 
1642  REAL8 tmpVec[12]= {0.};
1643  REAL8 s1normData[3]= {0.}, s2normData[3]= {0.}, sKerrData[3]= {0.}, sStarData[3]= {0.};
1644 
1645  /* These are the vectors which will be used in the call to the Hamiltonian */
1646  REAL8Vector r, p, spin1, spin2, spin1norm, spin2norm;
1647  REAL8Vector sigmaKerr, sigmaStar;
1648 
1649  INT4 i;
1650  REAL8 a;
1651  REAL8 m1 = eobParams->m1;
1652  REAL8 m2 = eobParams->m2;
1653  REAL8 UNUSED mT2 = (m1+m2)*(m1+m2);
1654  REAL8 UNUSED eta = m1*m2/mT2;
1655 
1656  INT4 oldTortoise = dParams->params->tortoise;
1657  /* Use a temporary vector to avoid corrupting the main function */
1658  memcpy( tmpVec, dParams->values, sizeof(tmpVec) );
1659 
1660  if (debugPK){
1661  for( i =0; i < 12; i++)
1662  if( isnan(tmpVec[i]) ) {
1663  XLAL_PRINT_INFO("GSLSpinPrecHamiltonianWrapperForRvecDerivs (from input)::tmpVec %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", tmpVec[0], tmpVec[1], tmpVec[2], tmpVec[3], tmpVec[4], tmpVec[5], tmpVec[6], tmpVec[7], tmpVec[8], tmpVec[9], tmpVec[10], tmpVec[11]);
1664  }
1665  }
1666 
1667  /* Set the relevant entry in the vector to the correct value */
1668  tmpVec[dParams->varyParam] = x;
1669 
1670  /* Set the LAL-style vectors to point to the appropriate things */
1671  r.length = p.length = spin1.length = spin2.length = spin1norm.length = spin2norm.length = 3;
1672  sigmaKerr.length = sigmaStar.length = 3;
1673  r.data = tmpVec;
1674  p.data = tmpVec+3;
1675 
1676  spin1.data = tmpVec+6;
1677  spin2.data = tmpVec+9;
1678  spin1norm.data = s1normData;
1679  spin2norm.data = s2normData;
1680  sigmaKerr.data = sKerrData;
1681  sigmaStar.data = sStarData;
1682 
1683  memcpy( s1normData, tmpVec+6, 3*sizeof(REAL8) );
1684  memcpy( s2normData, tmpVec+9, 3*sizeof(REAL8) );
1685 
1686  /* To compute the SigmaKerr and SigmaStar, we need the non-normalized
1687  * spin values, i.e. S_i. The spins being evolved are S_i/M^2. */
1688  for ( i = 0; i < 3; i++ )
1689  {
1690  spin1.data[i] *= mT2;
1691  spin2.data[i] *= mT2;
1692  }
1693 
1694  /* Calculate various spin parameters */
1695  XLALSimIMRSpinEOBCalculateSigmaKerr( &sigmaKerr, eobParams->m1,
1696  eobParams->m2, &spin1, &spin2 );
1697  XLALSimIMRSpinEOBCalculateSigmaStar( &sigmaStar, eobParams->m1,
1698  eobParams->m2, &spin1, &spin2 );
1699  a = sqrt( sigmaKerr.data[0]*sigmaKerr.data[0]
1700  + sigmaKerr.data[1]*sigmaKerr.data[1]
1701  + sigmaKerr.data[2]*sigmaKerr.data[2] );
1702  if ( isnan( a ) )
1703  {
1704  XLAL_PRINT_INFO( "a is nan in GSLSpinPrecHamiltonianWrapperForRvecDerivs!!\n");
1705  XLALPrintError( "XLAL Error - %s: a = nan \n", __func__);
1707  }
1708 
1709  double magR = r.data[0]*r.data[0] + r.data[1]*r.data[1] + r.data[2]*r.data[2];
1710 
1711  if(debugPK) {
1712  if(0 && magR < 1.96 * 1.96) {
1713  XLAL_PRINT_INFO("GSLSpinPrecHamiltonianWrapperForRvecDerivs (JUST inputs)::tmpVec %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", tmpVec[0], tmpVec[1], tmpVec[2], tmpVec[3], tmpVec[4], tmpVec[5], tmpVec[6], tmpVec[7], tmpVec[8], tmpVec[9], tmpVec[10], tmpVec[11]);
1714 
1715  XLAL_PRINT_INFO(" R = %3.10f\n\n", sqrt(magR));
1716  }
1717  }
1718 
1719  REAL8 SpinEOBH = XLALSimIMRSpinPrecEOBHamiltonian( eobParams->eta, &r, &p, &spin1norm, &spin2norm, &sigmaKerr, &sigmaStar, dParams->params->tortoise, dParams->params->seobCoeffs ) / eobParams->eta;
1720 
1721  if( isnan(SpinEOBH) )
1722  {
1723  XLAL_PRINT_INFO("H is nan in GSLSpinPrecHamiltonianWrapperForRvecDerivs. \n");
1724 
1725  XLAL_PRINT_INFO("GSLSpinPrecHamiltonianWrapperForRvecDerivs (JUST inputs)::tmpVec %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", tmpVec[0], tmpVec[1], tmpVec[2], tmpVec[3], tmpVec[4], tmpVec[5], tmpVec[6], tmpVec[7], tmpVec[8], tmpVec[9], tmpVec[10], tmpVec[11]);
1726 
1727  XLAL_PRINT_INFO(" R = %3.10f\n\n", sqrt(magR));
1728  XLALPrintError( "XLAL Error - %s: H = nan \n", __func__);
1730  }
1731 
1732  if ( dParams->varyParam < 3 )dParams->params->tortoise = oldTortoise;
1733  return SpinEOBH;
1734 }
1735 
1736 
1737 /**
1738  * Wrapper for GSL to call the Hamiltonian function. This is simply the function
1739  * GSLSpinPrecHamiltonianWrapper copied over. The alternative was to make it non-static
1740  * which increases runtime as static functions can be better optimized.
1741  */
1742 static double GSLSpinPrecHamiltonianWrapperFordHdpphi( double x, void *params )
1743 {
1744  HcapDerivParams *dParams = (HcapDerivParams *)params;
1745 
1746  EOBParams *eobParams = (EOBParams*) dParams->params->eobParams;
1747  SpinEOBHCoeffs UNUSED *coeffs = (SpinEOBHCoeffs*) dParams->params->seobCoeffs;
1748 
1749  REAL8 tmpVec[12] = {0.};
1750  REAL8 rpolar[3] = {0.}, rcart[3] = {0.}, ppolar[3] = {0.}, pcart[3] = {0.};
1751  REAL8 s1normData[3] = {0.}, s2normData[3] = {0.}, sKerrData[3] = {0.}, sStarData[3] = {0.};
1752 
1753  /* These are the vectors which will be used in the call to the Hamiltonian */
1754  REAL8Vector r, p, spin1, spin2, spin1norm, spin2norm;
1755  REAL8Vector sigmaKerr, sigmaStar;
1756 
1757  INT4 i;
1758  REAL8 a;
1759  REAL8 m1 = eobParams->m1;
1760  REAL8 m2 = eobParams->m2;
1761  REAL8 UNUSED mT2 = (m1+m2)*(m1+m2);
1762  REAL8 UNUSED eta = m1*m2/mT2;
1763 
1764  /* Use a temporary vector to avoid corrupting the main function */
1765  memcpy( tmpVec, dParams->values, sizeof(tmpVec) );
1766 
1767  /* Set the relevant entry in the vector to the correct value */
1768  tmpVec[dParams->varyParam] = x;
1769 
1770  /* Set the LAL-style vectors to point to the appropriate things */
1771  r.length = p.length = spin1.length = spin2.length = spin1norm.length = spin2norm.length = 3;
1772  sigmaKerr.length = sigmaStar.length = 3;
1773 
1774  /* Now rotate the R and P vectors from polar coordinates to Cartesian */
1775  memcpy( rpolar, tmpVec, 3*sizeof(REAL8));
1776  memcpy( ppolar, tmpVec+3, 3*sizeof(REAL8));
1777 
1778  rcart[0] = rpolar[0] * cos(rpolar[1]);
1779  rcart[1] =-rpolar[0] * sin(rpolar[1])*sin(rpolar[2]);
1780  rcart[2] = rpolar[0] * sin(rpolar[1])*cos(rpolar[2]);
1781 
1782  if( rpolar[1]==0. || rpolar[1]==LAL_PI )
1783  {
1784  rpolar[1] = LAL_PI/2.;
1785 
1786  if( rpolar[1]==0.)
1787  rpolar[2] = 0.;
1788  else
1789  rpolar[2] = LAL_PI;
1790 
1791  pcart[0] = ppolar[0]*sin(rpolar[1])*cos(rpolar[2])
1792  + ppolar[1]/rpolar[0]*cos(rpolar[1])*cos(rpolar[2])
1793  - ppolar[2]/rpolar[0]/sin(rpolar[1])*sin(rpolar[2]);
1794  pcart[1] = ppolar[0]*sin(rpolar[1])*sin(rpolar[2])
1795  + ppolar[1]/rpolar[0]*cos(rpolar[1])*sin(rpolar[2])
1796  + ppolar[2]/rpolar[0]/sin(rpolar[1])*cos(rpolar[2]);
1797  pcart[2] = ppolar[0]*cos(rpolar[1])- ppolar[1]/rpolar[0]*sin(rpolar[1]);
1798  }
1799  else
1800  {
1801  pcart[0] = ppolar[0]*cos(rpolar[1]) -ppolar[1]/rpolar[0]*sin(rpolar[1]);
1802  pcart[1] =-ppolar[0]*sin(rpolar[1])*sin(rpolar[2])
1803  -ppolar[1]/rpolar[0]*cos(rpolar[1])*sin(rpolar[2])
1804  -ppolar[2]/rpolar[0]/sin(rpolar[1])*cos(rpolar[2]);
1805  pcart[2] = ppolar[0]*sin(rpolar[1])*cos(rpolar[2])
1806  +ppolar[1]/rpolar[0]*cos(rpolar[1])*cos(rpolar[2])
1807  -ppolar[2]/rpolar[0]/sin(rpolar[1])*sin(rpolar[2]);
1808  }
1809 
1810  r.data = rcart;
1811  p.data = pcart;
1812 
1813  spin1.data = tmpVec+6;
1814  spin2.data = tmpVec+9;
1815  spin1norm.data = s1normData;
1816  spin2norm.data = s2normData;
1817  sigmaKerr.data = sKerrData;
1818  sigmaStar.data = sStarData;
1819 
1820  memcpy( s1normData, tmpVec+6, 3*sizeof(REAL8) );
1821  memcpy( s2normData, tmpVec+9, 3*sizeof(REAL8) );
1822 
1823  /* To compute the SigmaKerr and SigmaStar, we need the non-normalized
1824  * spin values, i.e. S_i. The spins being evolved are S_i/M^2. */
1825  for ( i = 0; i < 3; i++ )
1826  {
1827  spin1.data[i] *= mT2;
1828  spin2.data[i] *= mT2;
1829  }
1830 
1831  /* Calculate various spin parameters */
1832  XLALSimIMRSpinEOBCalculateSigmaKerr( &sigmaKerr, eobParams->m1,
1833  eobParams->m2, &spin1, &spin2 );
1834  XLALSimIMRSpinEOBCalculateSigmaStar( &sigmaStar, eobParams->m1,
1835  eobParams->m2, &spin1, &spin2 );
1836  a = sqrt( sigmaKerr.data[0]*sigmaKerr.data[0]
1837  + sigmaKerr.data[1]*sigmaKerr.data[1]
1838  + sigmaKerr.data[2]*sigmaKerr.data[2] );
1839  if ( isnan( a ) )
1840  {
1841  XLAL_PRINT_INFO( "a is nan in GSLSpinPrecHamiltonianWrapperFordHdpphi !!\n");
1842  XLAL_PRINT_INFO("rpolar, ppolar = %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", rpolar[0], rpolar[1], rpolar[2], ppolar[0], ppolar[1], ppolar[2]);
1843  XLAL_PRINT_INFO("rcart, pcart = %3.10f %3.10f %3.10f %3.10f %3.10f %3.10f\n", rcart[0], rcart[1], rcart[2], pcart[0], pcart[1], pcart[2]);
1844  XLALPrintError( "XLAL Error - %s: a = nan \n", __func__);
1846  }
1847  REAL8 SpinEOBH = XLALSimIMRSpinPrecEOBHamiltonian( eobParams->eta, &r, &p, &spin1norm, &spin2norm, &sigmaKerr, &sigmaStar, dParams->params->tortoise, dParams->params->seobCoeffs ) / eobParams->eta;
1848 
1849  return SpinEOBH;
1850 }
1851 
1852 #endif /*_LALSIMIMRSPINPRECEOBHAMILTONIAN_C*/
static int XLALSimIMRCalculateSpinPrecEOBHCoeffs_v2(SpinEOBHCoeffs *coeffs, const REAL8 eta, REAL8 a, REAL8 chi, const UINT4 SpinAlignedEOBversion)
This function is used to calculate some coefficients which will be used in the spinning EOB Hamiltoni...
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 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.
#define KRONECKER_DELTA(i, j)
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 double GSLSpinPrecHamiltonianWrapperForRvecDerivs(double x, void *params)
Wrapper for GSL to call the Hamiltonian function.
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 UNUSED REAL8 XLALSimIMRSpinPrecEOBNonKeplerCoeff(const REAL8 values[], SpinEOBParams *funcParams)
Function to calculate the non-Keplerian coefficient for the PRECESSING EOB model.
static REAL8 * cross_product(const REAL8 values1[], const REAL8 values2[], REAL8 result[])
static REAL8 * rotate_vector(const REAL8 v[], const REAL8 k[], const REAL8 theta, REAL8 result[])
Rotate the vector v around the axis k by an angle theta, counterclockwise Note that this assumes that...
static double GSLSpinPrecHamiltonianWrapperFordHdpphi(double x, void *params)
Wrapper for GSL to call the Hamiltonian function.
static REAL8 XLALSimIMRSpinPrecEOBHamiltonianDeltaT(SpinEOBHCoeffs *coeffs, const REAL8 r, const REAL8 eta, const REAL8 a)
This function calculates the function which appears in the spinning EOB potential function.
static UNUSED REAL8 XLALSimIMRSpinPrecEOBHamiltonianDeltaR(SpinEOBHCoeffs *coeffs, const REAL8 r, const REAL8 eta, const REAL8 a)
This function calculates the DeltaR potential function in the spin EOB Hamiltonian.
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 REAL8 XLALSimIMRSpinPrecEOBCalcOmega(const REAL8 values[], SpinEOBParams *funcParams)
Function to calculate the value of omega for the PRECESSING EOB waveform.
REAL8 Hreal
#define XLAL_CALLGSL(statement)
double i
Definition: bh_ringdown.c:118
double e
Definition: bh_ringdown.c:117
double theta
Definition: bh_sphwf.c:118
const double pn2
const double sx
const double pp
const double Hns
const double pvr
const double sMultiplier1
const double sxi
const double csi1
const double prT
const double Hss
const double sz
const double Hs
const double Q
const double HSONL
const double pn
const double sy
const double csi2
const double Hwr
const double sv
const double sqrtQ
const double pxir
const double HSOL
const double H
const double pr
const double pf
const double s3
const double sMultiplier2
const double sn
const double Hwcos
const double ptheta2
const double ww
const double deltaU
const double nur
const double mucos
const double expnu
const double invLambda
const double invdeltaT
const double deltaR
const double invxi2
const double invexpMU
const double u
const double w2
const double sqrtdeltaT
const double logu
const double u3
const double bulk
const double wr
const double r2
const double invsqrtdeltaT
const double ny
const double invrho2xi2Lambda
const double nucos
const double vy
const double wcos
const double invm1PlusetaKK
const double BR
const double u5
const double logarg
const double qq
const double invexpnuexpMU
const double a2
const double expMU
const double xi2
const double w
const double invrho2
const double m1PlusetaKK
const double rho2
const double u2
const double vz
const double u4
const double mur
const double csi
const double Lambda
const double costheta
const double nz
const double invdeltaTsqrtdeltaTsqrtdeltaR
const double B
const double vx
const double invsqrtdeltaR
const double nx
const double logTerms
const double sqrtdeltaR
#define LAL_PI
double REAL8
uint32_t UINT4
int32_t INT4
static const INT4 r
static const INT4 a
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
#define XLAL_ERROR_REAL8(...)
#define XLAL_PRINT_INFO(...)
#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_EFUNC
XLAL_EINVAL
XLAL_FAILURE
list x
list p
Structure containing all the parameters needed for the EOB waveform.
const REAL8 * values
SpinEOBParams * params
REAL8 * data
Parameters for the spinning EOB model, used in calculating the Hamiltonian.
UINT4 SpinAlignedEOBversion
Parameters for the spinning EOB model.
SpinEOBHCoeffs * seobCoeffs
EOBParams * eobParams
Definition: burst.c:245
LALDict * params
Definition: inspiral.c:248
double deltaT
Definition: unicorn.c:24