Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALSimulation 6.2.0.1-b246709
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 */
69static REAL8 inner_product( const REAL8 values1[],
70 const REAL8 values2[]
71 );
72
73static REAL8* cross_product( const REAL8 values1[],
74 const REAL8 values2[],
75 REAL8 result[] );
76
77static 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
96static double GSLSpinPrecHamiltonianWrapperForRvecDerivs( double x, void *params );
97
98static 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
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;
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;
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 */
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. */
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 );
441 /* Eqs. 5.47f - 5.47h of BB1 */
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;
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)));
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... */
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 * */
684static 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
694static 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 * */
709UNUSED 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 */
987static 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];
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 */
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
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 */
1635{
1636 int debugPK = 1;
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 */
1742static double GSLSpinPrecHamiltonianWrapperFordHdpphi( double x, void *params )
1743{
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
p
x
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