LALSimulation  5.4.0.1-fe68b98
LALSimInspiralEOBPostAdiabatic.c
Go to the documentation of this file.
1 #include <lal/LALSimIMR.h>
2 #include <lal/LALSimInspiral.h>
3 #include <lal/Date.h>
4 #include <lal/TimeSeries.h>
5 #include <lal/Units.h>
6 #include <lal/LALAdaptiveRungeKuttaIntegrator.h>
7 #include <lal/SphericalHarmonics.h>
8 #include <lal/LALSimSphHarmMode.h>
10 #include <lal/LALDict.h>
11 
12 #include <gsl/gsl_sf_gamma.h>
13 #include <gsl/gsl_matrix.h>
14 #include <gsl/gsl_poly.h>
15 #include <gsl/gsl_spline.h>
16 #include <gsl/gsl_roots.h>
17 #include <gsl/gsl_deriv.h>
18 
20 #include "LALSimIMREOBNRv2.h"
21 #include "LALSimInspiralPrecess.h"
23 #include "LALSimIMRSpinEOB.h"
24 
26 
29 
32 
33 
34 #define ROOT_SOLVER_ABS_TOL 1.0e-10
35 #define ROOT_SOLVER_REL_TOL 1.0e-8
36 
37 /**
38  * Function which comstructs the radial grid on which the post-adiabatic
39  * approximation will be computed
40  */
41 int
43  REAL8Vector *rVec,
44  /**<< OUTPUT, the computed radial grid */
45  LALDict *LALParams
46  /**<< Pointer to a dictionary containing parameters for the
47  post-adiabatic routine */
48 )
49 {
50  const REAL8 rInitial = XLALDictLookupREAL8Value(
51  LALParams, "rInitial"
52  );
53  const UINT4 rSize = XLALDictLookupUINT4Value(
54  LALParams, "rSize"
55  );
57  LALParams, "dr"
58  );
59 
60  UINT4 i;
61 
62  for (i = 0; i < rSize; i++)
63  {
64  rVec->data[i] = rInitial - i*dr;
65  }
66 
67  return XLAL_SUCCESS;
68 }
69 
70 /**
71  * Function which implements eq. (2.5) of arXiv:2105.06983 for the
72  * purposes of root solving
73  */
74 double
76  REAL8 j0_sol,
77  /**<< The value of j0 = pphi */
78  void *params
79  /**<< Struct of parameters necessary for evaluating the function */
80 )
81 {
82  struct PostAdiabaticRootSolveParams *j0Params = (
84  );
85 
87  j0Params->LALParams, "dr"
88  );
89 
90  REAL8 r = j0Params->r;
91  REAL8 prstar = j0Params->prstar;
92  LALDict *LALParams = j0Params->LALParams;
93 
94  REAL8 partialHBypartialr = XLALSimInspiralEOBPAPartialHByPartialr(
95  dr,
96  r,
97  prstar,
98  j0_sol,
99  j0Params->seobParams,
100  LALParams
101  );
102 
103  return partialHBypartialr;
104 }
105 
106 /**
107  * Function which implements eq. (2.6) of arXiv:2105.06983 for the
108  * purposes of root solving
109  */
110 double
112  REAL8 prstar_sol,
113  /**<< The value of prstar (pr*) */
114  void *params
115  /**<< Struct of parameters necessary for evaluating the function */
116 )
117 {
118  struct PostAdiabaticRootSolveParams *prstarParams = (
120  );
121 
122  REAL8 r = prstarParams->r;
123  REAL8 prstar = prstar_sol;
124  REAL8 dprstar = prstarParams->dprstar;
125  REAL8 pphi = prstarParams->pphi;
126  REAL8 dprstarBydpr = prstarParams->csi;
127  SpinEOBParams *seobParams = prstarParams->seobParams;
128  EOBNonQCCoeffs *nqcCoeffs = prstarParams->nqcCoeffs;
129 
130  REAL8 dpphiBydr = prstarParams->dpphiBydr;
131 
132  LALDict *LALParams = prstarParams->LALParams;
133 
134  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
135  LALParams,
136  "analyticFlag"
137  );
138 
139  REAL8 pol[4] = {r, 0., prstar, pphi};
140  REAL8 omega;
141  REAL8 flux;
142 
143  REAL8 result;
144 
145  if (analyticFlag == 0)
146  {
148  dprstar,
149  r,
150  prstar,
151  pphi,
152  seobParams,
153  LALParams
154  );
155 
157  pol,
158  dprstar,
159  seobParams,
160  LALParams
161  );
162 
164  r,
165  prstar,
166  pphi,
167  omega,
168  seobParams,
169  nqcCoeffs,
170  LALParams
171  );
172 
173  result = dpphiBydr * dHBydprstar * dprstarBydpr - flux / omega;
174  }
175  else
176  {
177  REAL8 cartCoordinates[6] = {r, 0., 0., prstar, pphi/r, 0.};
178 
180  3,
181  cartCoordinates,
182  seobParams
183  );
184 
186  pol,
187  dprstar,
188  seobParams,
189  LALParams
190  );
191 
193  r,
194  prstar,
195  pphi,
196  omega,
197  seobParams,
198  nqcCoeffs,
199  LALParams
200  );
201 
202  result = dpphiBydr * dHBydpx * dprstarBydpr - flux / omega;
203  }
204 
205  return result;
206 }
207 
208 /**
209  * Function which implements eq. (2.7) of arXiv:2105.06983 for the
210  * purposes of root solving
211  */
212 double
214  REAL8 pphi_sol,
215  /**<< The value of pphi */
216  void *params
217  /**<< Struct of parameters necessary for evaluating the function */
218 )
219 {
220  struct PostAdiabaticRootSolveParams *pphiParams = (
222  );
223 
224  REAL8 r = pphiParams->r;
225  REAL8 prstar = pphiParams->prstar;
226  REAL8 dprstar = pphiParams->dprstar;
227  REAL8 pphi = pphi_sol;
228  REAL8 dprstarBydr = pphiParams->dprstarBydr;
229  REAL8 dprstarBydpr = pphiParams->csi;
230  LALDict *LALParams = pphiParams->LALParams;
231 
233  LALParams, "dr"
234  );
235  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
236  LALParams, "analyticFlag"
237  );
238 
239  REAL8 pol[4] = {r, 0., prstar, pphi};
240  REAL8 omega;
241  REAL8 flux;
242 
243  REAL8 result;
244 
245  if (analyticFlag == 0)
246  {
248  dprstar,
249  r,
250  prstar,
251  pphi,
252  pphiParams->seobParams,
253  LALParams
254  );
255 
257  dr,
258  r,
259  prstar,
260  pphi,
261  pphiParams->seobParams,
262  LALParams
263  );
264 
266  pol,
267  dprstar,
268  pphiParams->seobParams,
269  LALParams
270  );
271 
273  r,
274  prstar,
275  pphi,
276  omega,
277  pphiParams->seobParams,
278  pphiParams->nqcCoeffs,
279  LALParams
280  );
281 
282  result = (
283  dprstarBydr * dHBydprstar + dHBydr
284  - (prstar / pphi) * flux / (omega * dprstarBydpr)
285  );
286  }
287  else
288  {
289  REAL8 cartCoordinates[6] = {r, 0., 0., prstar, pphi/r, 0.};
290 
292  0,
293  cartCoordinates,
294  pphiParams->seobParams
295  );
296 
298  3,
299  cartCoordinates,
300  pphiParams->seobParams
301  );
302 
304  4,
305  cartCoordinates,
306  pphiParams->seobParams
307  );
308 
310  pol,
311  dprstar,
312  pphiParams->seobParams,
313  LALParams
314  );
315 
317  r,
318  prstar,
319  pphi,
320  omega,
321  pphiParams->seobParams,
322  pphiParams->nqcCoeffs,
323  LALParams
324  );
325 
326  result = (
327  dprstarBydr * dHBydpx
328  + (dHBydx - dHBydpy * pphi / (r * r))
329  - (prstar / pphi) * (flux / omega) / dprstarBydpr
330  );
331  }
332 
333  return result;
334 }
335 
336 /**
337  * Root finder function which is used for computing the adiabatic and
338  * post-adiabatic approximations.
339  */
340 int
342  struct PostAdiabaticRoot *result,
343  /**<< OUTPUT, a structure containing the result of the root finding */
344  double (*Func)(REAL8, void *),
345  /**<< The function which needs to be solved */
347  /**<< Struct of parameters necessary for evaluating the function */
348  REAL8 x_lower,
349  /**<< Lower end of the interval in which the finding will be done */
350  REAL8 x_upper,
351  /**<< Upper end of the interval in which the finding will be done */
352  REAL8 absTol,
353  /**<< Absolute tolerance for the root finding */
354  REAL8 relTol,
355  /**<< Relative tolerance for the root finding */
356  INT2 parity
357  /**<< Parity indicating which variable is being solved for */
358 )
359 {
360  INT4 maxIters = 1000;
361  INT4 iters;
362  INT4 status;
363  REAL8 x;
364 
365  iters = 0;
366  x = 0.0;
367 
368  gsl_function F;
369 
370  F.function = Func;
371  F.params = params;
372 
373  const gsl_root_fsolver_type *solver_type;
374  solver_type = gsl_root_fsolver_falsepos;
375 
376  gsl_root_fsolver *solver;
377  solver = gsl_root_fsolver_alloc(solver_type);
378 
379  REAL8 F_lower = Func(x_lower, params);
380  REAL8 F_upper = Func(x_upper, params);
381 
382  if (parity)
383  {
384  if (F_lower*F_upper >= 0.0)
385  {
386  x_lower = -0.5;
387  x_upper = -1.e-16;
388  }
389 
390  F_lower = Func(x_lower, params);
391  F_upper = Func(x_upper, params);
392 
393  if (F_lower*F_upper >= 0.0)
394  {
395  XLAL_ERROR(XLAL_EFUNC, "Derivatives have the wrong sign.");
396  }
397  }
398  else
399  {
400  while (F_lower*F_upper >= 0.0)
401  {
402  x_lower *= 0.9;
403  x_upper *= 1.1;
404 
405  F_lower = Func(x_lower, params);
406  F_upper = Func(x_upper, params);
407  }
408  }
409 
410  gsl_root_fsolver_set(solver, &F, x_lower, x_upper);
411 
412  status = GSL_CONTINUE;
413 
414  do
415  {
416  iters++;
417 
418  status = gsl_root_fsolver_iterate(solver);
419 
420  if (status != GSL_SUCCESS)
421  break;
422 
423  x = gsl_root_fsolver_root(solver);
424  x_lower = gsl_root_fsolver_x_lower(solver);
425  x_upper = gsl_root_fsolver_x_upper(solver);
426 
427  status = gsl_root_test_interval(
428  x_lower, x_upper,
429  absTol, relTol
430  );
431  }
432  while (iters <= maxIters && status == GSL_CONTINUE);
433 
434  result->root = x;
435  result->status = status;
436  result->nIter = iters;
437 
438  if (status != GSL_SUCCESS)
439  {
440  XLALPrintError("Root finding status: %d\n", status);
442  }
443 
444  gsl_root_fsolver_free (solver);
445 
446  return XLAL_SUCCESS;
447 }
448 
449 /**
450  * Function which reverses a 1D array
451  */
452 int
454  REAL8Vector *Vec,
455  /**<< The vector which will be reversed */
456  REAL8Vector *reverseVec
457  /**<< OUTPUT, the reversed vector */
458 )
459 {
460  UINT4 vecLength;
461  vecLength = Vec->length;
462 
463  UINT4 i;
464 
465  for (i = 0; i < vecLength; i++)
466  {
467  reverseVec->data[i] = Vec->data[vecLength-i-1];
468  }
469 
470  return XLAL_SUCCESS;
471 }
472 
473 /**
474  * Function which add a constant to each element of an array
475  */
476 int
478  REAL8Vector *Vec,
479  /**<< The vector which will be shifted */
480  REAL8 offset,
481  /**<< The constant offset */
482  REAL8Vector *offsetVec
483  /**<< OUTPUT, the offset vector */
484 )
485 {
486  UINT4 vecLength;
487  vecLength = Vec->length;
488 
489  UINT4 i;
490 
491  for (i = 0; i < vecLength; i++)
492  {
493  offsetVec->data[i] = Vec->data[i] + offset;
494  }
495 
496  return XLAL_SUCCESS;
497 }
498 
499 /**
500  * This function rescales each element of an array by a given factor
501  */
502 int
504  REAL8Vector *Vec,
505  /**<< The vector which will be rescaled */
506  REAL8 factor,
507  /**<< The rescaling factor */
508  REAL8Vector *rescaledVec
509  /**<< OUTPUT, the rescaled vector */
510 )
511 {
512  UINT4 vecLength;
513  vecLength = Vec->length;
514 
515  UINT4 i;
516 
517  for (i = 0; i < vecLength; i++)
518  {
519  rescaledVec->data[i] = factor * Vec->data[i];
520  }
521 
522  return XLAL_SUCCESS;
523 }
524 
525 /**
526  * This function calculates the adiabatic (0th order PA) approximation
527  * of the inspiral dynamics. The procedure is:
528  * Step 1) At each point along the inspiral, calculate the circular
529  * value for the orbital angular momentum j0
530  * Step 2) At each point along the inspiral, improve j0 by solving
531  * eq. (2.5) of arXiv:2105.06983 for pphi.
532  */
533 int
535  REAL8Vector *rVec,
536  /**<< Pointer to the vector containing the radial grid */
537  REAL8Vector *phiVec,
538  /**<< Pointer to the vector containing the phi values */
539  REAL8Vector *prstarVec,
540  /**<< Pointer to the vector containing the prstar values */
541  REAL8Vector *pphiVec,
542  /**<< Pointer to the vector containing the pphi values */
543  REAL8Vector *pphi0Vec,
544  /**<< Pointer to the vector containing the initial pphi values */
545  REAL8Vector *dpphiBydrVec,
546  /**<< Pointer to the vector containing the dpphi/dr values */
547  REAL8Vector *csiVec,
548  /**<< Pointer to the vector containing the csi values */
549  REAL8Vector *omegaVec,
550  /**<< Pointer to the vector containing the omega values */
552  /**<< SEOB parameters */
553  LALDict *LALParams
554  /**<< Pointer to a dictionary containing parameters for the
555  post-adiabatic routine */
556 )
557 {
558  const UINT4 rSize = XLALDictLookupUINT4Value(LALParams, "rSize");
559  const REAL8 nu = XLALDictLookupREAL8Value(LALParams, "nu");
560  const REAL8 sigmaKerr = XLALDictLookupREAL8Value(LALParams, "aK");
562 
563  UINT4 i;
564 
565  REAL8 DeltaT;
566  REAL8 DeltaR;
567  struct PostAdiabaticRootSolveParams j0Params;
568 
569  for (i = 0; i < rSize; i++)
570  {
572  seobParams->seobCoeffs, rVec->data[i], nu, sigmaKerr
573  );
575  seobParams->seobCoeffs, rVec->data[i], nu, sigmaKerr
576  );
577 
578  csiVec->data[i] = (
579  sqrt(DeltaT*DeltaR)
580  / (rVec->data[i] * rVec->data[i] + sigmaKerr * sigmaKerr)
581  );
582 
583  REAL8 Newtonianj0;
585  rVec->data[i]
586  );
587 
588  j0Params.r = rVec->data[i];
589  j0Params.prstar = prstarVec->data[i];
590  j0Params.seobParams = seobParams;
591  j0Params.LALParams = LALParams;
592 
593  REAL8 pphi0_lower;
594  REAL8 pphi0_upper;
595 
596  pphi0_lower = 0.1 * Newtonianj0;
597  pphi0_upper = 1.9 * Newtonianj0;
598 
599  struct PostAdiabaticRoot pphiRoot;
600 
602  &pphiRoot,
604  &j0Params,
605  pphi0_lower,
606  pphi0_upper,
609  0
610  ) != XLAL_SUCCESS)
611  {
612  XLAL_ERROR(XLAL_EFUNC, "Root solver failed!");
613  }
614 
615  pphiVec->data[i] = pphiRoot.root;
616  pphi0Vec->data[i] = pphiRoot.root;
617 
618  REAL8 polarDynamics[4];
619 
620  polarDynamics[0] = rVec->data[i];
621  polarDynamics[1] = phiVec->data[i];
622  polarDynamics[2] = prstarVec->data[i];
623  polarDynamics[3] = pphiVec->data[i];
624 
626  polarDynamics,
627  dr,
628  seobParams,
629  LALParams
630  );
631  }
632 
633  REAL8Vector *rReverseVec = XLALCreateREAL8Vector(rSize);
634  memset(
635  rReverseVec->data, 0,
636  rReverseVec->length * sizeof(REAL8)
637  );
638 
639  REAL8Vector *pphiReverseVec = XLALCreateREAL8Vector(rSize);
640  memset(
641  pphiReverseVec->data, 0,
642  pphiReverseVec->length * sizeof(REAL8)
643  );
644 
645  REAL8Vector *dpphiBydrReverseVec = XLALCreateREAL8Vector(rSize);
646  memset(
647  dpphiBydrReverseVec->data, 0,
648  dpphiBydrReverseVec->length * sizeof(REAL8)
649  );
650 
651  XLALReverseREAL8Vector(rVec, rReverseVec);
652  XLALReverseREAL8Vector(pphiVec, pphiReverseVec);
654  rReverseVec, pphiReverseVec, dpphiBydrReverseVec
655  );
656  XLALReverseREAL8Vector(dpphiBydrReverseVec, dpphiBydrVec);
657 
658  XLALDestroyREAL8Vector(rReverseVec);
659  XLALDestroyREAL8Vector(pphiReverseVec);
660  XLALDestroyREAL8Vector(dpphiBydrReverseVec);
661 
662  return XLAL_SUCCESS;
663 }
664 
665 /**
666  * This function calculates the (n-th order) post-adiabatic approximation
667  * of the inspiral dynamics. The procedure is:
668  * Step 0) Initialise all necessary variables and allocate memory space.
669  * Step 1) Iterate the PA order n from 1 to 8.
670  * Step 2) At odd n (orders 1, 3, 5, 7) improve the approximation for
671  * prstar (pr*) by solving eq. (2.6) of arXiv:2105.06983.
672  * Step 3) At even n (orders 2, 4, 6, 8) improve the approximation for
673  * pphi by solving eq. (2.7) of arXiv:2105.06983.
674  * Step 4) Compute the derivative dt/dr and dphi/dr which will be needed
675  * for computing the quantities t(r) and phi(r).
676  */
677 int
679  REAL8Vector *rVec,
680  /**<< Pointer to the vector containing the radial grid */
681  REAL8Vector *phiVec,
682  /**<< Pointer to the vector containing the phi values */
683  REAL8Vector *dphiBydrVec,
684  /**<< Pointer to the vector containing the dphi/dr values */
685  REAL8Vector *prstarVec,
686  /**<< Pointer to the vector containing the prstar (pr*) values */
687  REAL8Vector *dprstarBydrVec,
688  /**<< Pointer to the vector containing the dprstar/dr values */
689  REAL8Vector *pphiVec,
690  /**<< Pointer to the vector containing the pphi values */
691  REAL8Vector *dpphiBydrVec,
692  /**<< Pointer to the vector containing the dpphi/dr values */
693  REAL8Vector *dtBydrVec,
694  /**<< Pointer to the vector containing the dt/dr values */
695  REAL8Vector *csiVec,
696  /**<< Pointer to the vector containing the csi values */
697  REAL8Vector *omegaVec,
698  /**<< Pointer to the vector containing the omega values */
699  SpinEOBParams *seobParams,
700  /**<< SEOB parameters */
701  EOBNonQCCoeffs *nqcCoeffs,
702  /**<< Input NQC coeffs */
703  LALDict *LALParams
704  /**<< Pointer to a dictionary containing parameters for the
705  post-adiabatic routine */
706 )
707 {
708  const UINT4 PAOrder = XLALDictLookupUINT4Value(
709  LALParams, "PAOrder"
710  );
711 
712  const UINT4 rSize = XLALDictLookupUINT4Value(
713  LALParams, "rSize"
714  );
715 
716  const REAL8 dr = XLALDictLookupREAL8Value(
717  LALParams, "dr"
718  );
719 
720  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
721  LALParams, "analyticFlag"
722  );
723 
724  REAL8Vector *fluxVec = XLALCreateREAL8Vector(rSize);
725  memset(
726  fluxVec->data, 0,
727  fluxVec->length * sizeof(REAL8)
728  );
729 
730  REAL8Vector *rReverseVec = XLALCreateREAL8Vector(rSize);
731  memset(
732  rReverseVec->data, 0,
733  rReverseVec->length * sizeof(REAL8)
734  );
735 
736  XLALReverseREAL8Vector(rVec,rReverseVec);
737 
738  REAL8Vector *pphiReverseVec = XLALCreateREAL8Vector(rSize);
739  memset(
740  pphiReverseVec->data, 0,
741  pphiReverseVec->length * sizeof(REAL8)
742  );
743 
744  REAL8Vector *dpphiBydrReverseVec = XLALCreateREAL8Vector(rSize);
745  memset(
746  dpphiBydrReverseVec->data, 0,
747  dpphiBydrReverseVec->length * sizeof(REAL8)
748  );
749 
750  REAL8Vector *prstarReverseVec = XLALCreateREAL8Vector(rSize);
751  memset(
752  prstarReverseVec->data, 0,
753  prstarReverseVec->length * sizeof(REAL8)
754  );
755 
756  REAL8Vector *dprstarBydrReverseVec = XLALCreateREAL8Vector(rSize);
757  memset(
758  dprstarBydrReverseVec->data, 0,
759  dprstarBydrReverseVec->length * sizeof(REAL8)
760  );
761 
762  REAL8Vector *dprstarVec = XLALCreateREAL8Vector(rSize);
763  memset(
764  dprstarVec->data, 0,
765  dprstarVec->length * sizeof(REAL8)
766  );
767 
768  UINT4 i;
769 
770  if (analyticFlag == 0)
771  {
772  for (i = 0; i < rSize; i++)
773  {
774  dprstarVec->data[i] = 1.e-4;
775  }
776  }
777 
778  REAL8 polarDynamics[4];
779 
780  UINT4 n;
781  UINT4 parity = 0;
782 
783  for (n = 1; n <= PAOrder; n++)
784  {
785  parity = n%2;
786 
787  if ((n > 1) && (analyticFlag == 0))
788  {
789  XLALSimInspiralEOBPAMeanValueOrder8(prstarVec, dprstarVec);
790  }
791 
792  if (parity)
793  {
794  for (i = 0; i < rSize; i++)
795  {
796  struct PostAdiabaticRootSolveParams prstarParams;
797  prstarParams.r = rVec->data[i];
798  prstarParams.dprstar = dprstarVec->data[i];
799  prstarParams.phi = 0.;
800  prstarParams.pphi = pphiVec->data[i];
801  prstarParams.dpphiBydr = dpphiBydrVec->data[i];
802  prstarParams.csi = csiVec->data[i];
803  prstarParams.LALParams = LALParams;
804  prstarParams.seobParams = seobParams;
805  prstarParams.nqcCoeffs = nqcCoeffs;
806  REAL8 x_lower;
807  REAL8 x_upper;
808 
809  x_upper = 0.8 * prstarVec->data[i];
810  x_lower = 1.2 * prstarVec->data[i];
811 
812  struct PostAdiabaticRoot prstarRoot;
813 
815  &prstarRoot,
817  &prstarParams,
818  x_lower,
819  x_upper,
822  parity
823  ) != XLAL_SUCCESS)
824  {
825  XLAL_ERROR(XLAL_EFUNC, "Root finder failed!");
826  }
827 
828  prstarVec->data[i] = prstarRoot.root;
829 
830  polarDynamics[0] = rVec->data[i];
831  polarDynamics[1] = phiVec->data[i];
832  polarDynamics[2] = prstarVec->data[i];
833  polarDynamics[3] = pphiVec->data[i];
834 
836  polarDynamics,
837  dr,
838  seobParams,
839  LALParams
840  );
841  }
842 
843  XLALReverseREAL8Vector(prstarVec, prstarReverseVec);
844  memset(
845  dprstarBydrReverseVec->data, 0,
846  dprstarBydrReverseVec->length * sizeof(REAL8)
847  );
848 
850  rReverseVec, prstarReverseVec, dprstarBydrReverseVec
851  );
852 
854  dprstarBydrReverseVec, dprstarBydrVec
855  );
856  }
857  else
858  {
859  for (i = 0; i < rSize; i++)
860  {
861  struct PostAdiabaticRoot pphiRoot;
862 
863  struct PostAdiabaticRootSolveParams pphiParams;
864  pphiParams.r = rVec->data[i];
865  pphiParams.csi = csiVec->data[i];
866  pphiParams.prstar = prstarVec->data[i];
867  pphiParams.dprstar = dprstarVec->data[i];
868  pphiParams.dprstarBydr = dprstarBydrVec->data[i];
869  pphiParams.LALParams = LALParams;
870  pphiParams.seobParams = seobParams;
871  pphiParams.nqcCoeffs = nqcCoeffs;
872 
873  REAL8 x_lower = 0.9 * pphiVec->data[i];
874  REAL8 x_upper = 1.1 * pphiVec->data[i];
875 
877  &pphiRoot,
879  &pphiParams,
880  x_lower,
881  x_upper,
884  parity
885  ) != XLAL_SUCCESS)
886  {
887  XLAL_ERROR(XLAL_EFUNC, "Root finder failed!");
888  }
889 
890  pphiVec->data[i] = pphiRoot.root;
891 
892  polarDynamics[0] = rVec->data[i];
893  polarDynamics[1] = phiVec->data[i];
894  polarDynamics[2] = prstarVec->data[i];
895  polarDynamics[3] = pphiVec->data[i];
896 
898  polarDynamics,
899  dr,
900  seobParams,
901  LALParams
902  );
903  }
904 
905  XLALReverseREAL8Vector(pphiVec, pphiReverseVec);
906  memset(
907  dpphiBydrReverseVec->data, 0,
908  dpphiBydrReverseVec->length * sizeof(REAL8)
909  );
910 
912  rReverseVec, pphiReverseVec, dpphiBydrReverseVec
913  );
914  XLALReverseREAL8Vector(dpphiBydrReverseVec, dpphiBydrVec);
915  }
916  }
917 
918  if ((parity) && (analyticFlag == 0))
919  {
920  XLALSimInspiralEOBPAMeanValueOrder8(prstarVec, dprstarVec);
921  }
922 
923  REAL8 dHBydprstar;
924 
925  for(i = 0; i < rSize; i++)
926  {
928  dprstarVec->data[i],
929  rVec->data[i],
930  prstarVec->data[i],
931  pphiVec->data[i],
932  seobParams,
933  LALParams
934  );
935  dtBydrVec->data[i] = (
936  1. / (dHBydprstar * csiVec->data[i])
937  );
938  dphiBydrVec->data[i] = omegaVec->data[i] * dtBydrVec->data[i];
939  }
940 
941  XLALDestroyREAL8Vector(fluxVec);
942  XLALDestroyREAL8Vector(rReverseVec);
943  XLALDestroyREAL8Vector(pphiReverseVec);
944  XLALDestroyREAL8Vector(dpphiBydrReverseVec);
945  XLALDestroyREAL8Vector(prstarReverseVec);
946  XLALDestroyREAL8Vector(dprstarBydrReverseVec);
947  XLALDestroyREAL8Vector(dprstarVec);
948 
949  return XLAL_SUCCESS;
950 }
951 
952 /**
953  * Function which calculates the partial derivative dH/dr
954  */
955 REAL8
957  REAL8 h,
958  /**<< Value of the differentiation step h */
959  REAL8 r,
960  /**<< Value of the radial coordinate r */
961  REAL8 prstar,
962  /**<< Value of the radial momentum in tortoise coordinates prstar */
963  REAL8 pphi,
964  /**<< Value of the angular momentum pphhi */
966  /**<< SEOB parameters */
967  LALDict *LALParams
968  /**<< Pointer to a dictionary containing parameters for the
969  post-adiabatic routine */
970 )
971 {
972  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
973  LALParams,
974  "analyticFlag"
975  );
976 
977  REAL8 partialHByPartialr = 0.;
978 
979  if (analyticFlag == 0)
980  {
981  REAL8 coeffs[9] = {
982  1./280., -4./105., 1./5., -4./5., 0, 4./5., -1./5., 4./105., -1./280.
983  };
984 
985  INT4 i;
986 
987  for (i = -4; i <= 4; i++)
988  {
989  if (i != 0)
990  {
991  partialHByPartialr += (
993  r + i*h,
994  prstar,
995  pphi,
997  LALParams
998  )
999  );
1000  }
1001  }
1002 
1003  partialHByPartialr /= h;
1004  }
1005  else
1006  {
1007  REAL8 cartCoordinates[6] = {r, 0., 0., prstar, pphi/r, 0.};
1008 
1010  0,
1011  cartCoordinates,
1012  seobParams
1013  );
1014 
1016  4,
1017  cartCoordinates,
1018  seobParams
1019  );
1020 
1021  partialHByPartialr = dHBydx - dHBydpy*pphi/(r*r);
1022  }
1023 
1024  return partialHByPartialr;
1025 }
1026 
1027 /**
1028  * Function which calculates the partial derivative dH/dprstar
1029  */
1030 REAL8
1032  REAL8 h,
1033  /**<< Value of the differentiation step h */
1034  REAL8 r,
1035  /**<< Value of the radial coordinate r */
1036  REAL8 prstar,
1037  /**<< Value of the radial momentum in tortoise coordinates prstar */
1038  REAL8 pphi,
1039  /**<< Value of the angular momentum pphhi */
1041  /**<< SEOB parameters */
1042  LALDict *LALParams
1043  /**<< Pointer to a dictionary containing parameters for the
1044  post-adiabatic routine */
1045 )
1046 {
1047  REAL8 coeffs[9] = {
1048  1./280., -4./105., 1./5., -4./5., 0, 4./5., -1./5., 4./105., -1./280.
1049  };
1050 
1051  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
1052  LALParams, "analyticFlag"
1053  );
1054 
1055  REAL8 partialHByPartialprstar = 0.;
1056 
1057  if (analyticFlag == 0)
1058  {
1059  INT4 i;
1060 
1061  for (i = -4; i <= 4; i++)
1062  {
1063  if (i != 0)
1064  {
1065  partialHByPartialprstar += (
1067  r,
1068  prstar + i*h,
1069  pphi,
1071  LALParams
1072  )
1073  );
1074  }
1075  }
1076 
1077  partialHByPartialprstar /= h;
1078  }
1079  else
1080  {
1081  REAL8 cartCoordinates[6] = {r, 0., 0., prstar, pphi/r, 0.};
1082 
1084  3,
1085  cartCoordinates,
1086  seobParams
1087  );
1088 
1089  partialHByPartialprstar = dHBydpx;
1090  }
1091 
1092  return partialHByPartialprstar;
1093 }
1094 
1095 /**
1096  * Function which performs an 8-order mean smoothing of a vector
1097  */
1098 int
1100  REAL8Vector *inputVec,
1101  /**<< The vector which should be smoothed */
1102  REAL8Vector *meanVec
1103  /**<< OUTPUT, the vector after mean smoothing */
1104 )
1105 {
1106  UINT4 vecLength = inputVec->length;
1107 
1108  UINT4 i;
1109  UINT4 j;
1110 
1111  for (i = 0; i < vecLength; i++)
1112  {
1113  if (i == 0)
1114  {
1115  for (j = 0; j < 8; j++)
1116  {
1117  meanVec->data[i] += fabs(
1118  inputVec->data[j+1] - inputVec->data[j]
1119  );
1120  }
1121  }
1122  else if (i == 1)
1123  {
1124  for (j = 0; j < 8; j++)
1125  {
1126  meanVec->data[i] += fabs(
1127  inputVec->data[j+1] - inputVec->data[j]
1128  );
1129  }
1130  }
1131  else if (i == 2)
1132  {
1133  for (j = 0; j < 8; j++)
1134  {
1135  meanVec->data[i] += fabs(
1136  inputVec->data[j+1] - inputVec->data[j]
1137  );
1138  }
1139  }
1140  else if (i == 3)
1141  {
1142  for (j = 0; j < 8; j++)
1143  {
1144  meanVec->data[i] += fabs(
1145  inputVec->data[j+1] - inputVec->data[j]
1146  );
1147  }
1148  }
1149  else if (i == vecLength-4)
1150  {
1151  for (j = 0; j < 8; j++)
1152  {
1153  meanVec->data[i] += fabs(
1154  inputVec->data[i+j-5] - inputVec->data[i+j-4]
1155  );
1156  }
1157  }
1158  else if (i == vecLength-3)
1159  {
1160  for (j = 0; j < 8; j++)
1161  {
1162  meanVec->data[i] += fabs(
1163  inputVec->data[i+j-6] - inputVec->data[i+j-5]
1164  );
1165  }
1166  }
1167  else if (i == vecLength-2)
1168  {
1169  for (j = 0; j < 8; j++)
1170  {
1171  meanVec->data[i] += fabs(
1172  inputVec->data[i+j-7] - inputVec->data[i+j-6]
1173  );
1174  }
1175  }
1176  else if (i == vecLength-1)
1177  {
1178  for (j = 0; j < 8; j++)
1179  {
1180  meanVec->data[i] += fabs(
1181  inputVec->data[i+j-8] - inputVec->data[i+j-7]
1182  );
1183  }
1184  }
1185  else
1186  {
1187  for (j = 0; j < 8; j++)
1188  {
1189  meanVec->data[i] += fabs(
1190  inputVec->data[i+j-4] - inputVec->data[i+j-3]
1191  );
1192  }
1193  }
1194 
1195  meanVec->data[i] /= 8.0;
1196  }
1197 
1198  return XLAL_SUCCESS;
1199 }
1200 
1201 /**
1202  * A wrapper for the SEOB Hamiltonian, depending on the user choices
1203  */
1204 REAL8
1206  REAL8 r,
1207  /**<< Value of the radial coordinate r */
1208  REAL8 prstar,
1209  /**<< Value of the radial momentum in tortoise coordinates prstar */
1210  REAL8 pphi,
1211  /**<< Value of the angular momentum pphhi */
1212  SpinEOBHCoeffs *seobCoeffs,
1213  /**<< SEOB parameters */
1214  LALDict *LALParams
1215  /**<< Pointer to a dictionary containing parameters for the
1216  post-adiabatic routine */
1217 )
1218 {
1219  const REAL8 nu = XLALDictLookupREAL8Value(LALParams, "nu");
1220  const REAL8 a1 = XLALDictLookupREAL8Value(LALParams, "a1");
1221  const REAL8 a2 = XLALDictLookupREAL8Value(LALParams, "a2");
1222  const REAL8 aK = XLALDictLookupREAL8Value(LALParams, "aK");
1223  const REAL8 Sstar = XLALDictLookupREAL8Value(LALParams, "Sstar");
1224  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
1225  LALParams, "analyticFlag"
1226  );
1227 
1228  REAL8 H;
1229 
1230  REAL8Vector xCartVec,pCartVec;
1231  xCartVec.length = pCartVec.length = 3;
1232  REAL8 xCart[3] = {r, 0., 0.};
1233  REAL8 pCart[3] = {prstar, pphi/r, 0.};
1234  xCartVec.data = xCart;
1235  pCartVec.data = pCart;
1236 
1237  REAL8Vector a1CartVec, a2CartVec, aKCartVec, SstarCartVec;
1238  a1CartVec.length = a2CartVec.length = 3;
1239  aKCartVec.length = SstarCartVec.length = 3;
1240  REAL8 spin1[3] = {0., 0., a1};
1241  REAL8 spin2[3] = {0., 0., a2};
1242  REAL8 aKV[3] = {0., 0., aK};
1243  REAL8 SstarV[3] = {0., 0., Sstar};
1244  a1CartVec.data = spin1;
1245  a2CartVec.data = spin2;
1246  aKCartVec.data = aKV;
1247  SstarCartVec.data = SstarV;
1248 
1249  // tortoise flag:
1250  // 0 - unstarred coordinates pr, pphi
1251  // 1 - starred coordinates prstar, pphistar = pphi
1252  UINT4 tortoiseFlag;
1253  tortoiseFlag = 1;
1254 
1255  if (analyticFlag == 0)
1256  {
1258  nu,
1259  &xCartVec,
1260  &pCartVec,
1261  &a1CartVec,
1262  &a2CartVec,
1263  &aKCartVec,
1264  &SstarCartVec,
1265  tortoiseFlag,
1266  seobCoeffs
1267  );
1268  }
1269  else
1270  {
1272  nu,
1273  &xCartVec,
1274  &pCartVec,
1275  &a1CartVec,
1276  &a2CartVec,
1277  &aKCartVec,
1278  &SstarCartVec,
1279  tortoiseFlag,
1280  seobCoeffs
1281  );
1282  }
1283 
1284  H /= nu;
1285 
1286  return H;
1287 }
1288 
1289 /**
1290  * A wrapper for the factorized flux, depending on the user choices
1291  */
1292 REAL8
1294  REAL8 r,
1295  /**<< Value of the radial coordinate r */
1296  REAL8 prstar,
1297  /**<< Value of the radial momentum in tortoise coordinates prstar */
1298  REAL8 pphi,
1299  /**<< Value of the angular momentum pphhi */
1300  REAL8 omega,
1301  /**<< Value of the orbital frequency omega */
1303  /**<< SEOB parameters */
1305  /**<< Input NQC coeffs */
1306  LALDict *LALParams
1307  /**<< Pointer to a dictionary containing parameters for the
1308  post-adiabatic routine */
1309 )
1310 {
1311  const REAL8 nu = XLALDictLookupREAL8Value(LALParams, "nu");
1312  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
1313  LALParams,
1314  "analyticFlag"
1315  );
1316 
1317  REAL8 H;
1319  r,
1320  prstar,
1321  pphi,
1323  LALParams
1324  );
1325  H *= nu;
1326 
1327  /* polarDynamics contains r, phi, pr, pphi */
1328  REAL8Vector polarDynamics;
1329  polarDynamics.length = 4;
1330  REAL8 pol[4] = {r, 0., prstar, pphi};
1331  polarDynamics.data = pol;
1332 
1333  const UINT4 lMax = 8;
1334 
1335  const UINT4 SpinAlignedEOBversion = 4;
1336 
1337  REAL8 Flux;
1338 
1339  if (analyticFlag == 0)
1340  {
1342  &polarDynamics,
1343  nqcCoeffs,
1344  omega,
1345  seobParams,
1346  H,
1347  lMax,
1348  SpinAlignedEOBversion
1349  );
1350  }
1351  else
1352  {
1354  &polarDynamics,
1355  nqcCoeffs,
1356  omega,
1357  seobParams,
1358  H,
1359  lMax,
1360  SpinAlignedEOBversion
1361  );
1362  }
1363 
1364  Flux /= nu;
1365  Flux *= -1.;
1366 
1367  return Flux;
1368 }
1369 
1370 /**
1371  * This function generates post-adiabatic inspiral for spin-aligned
1372  * binary in the SEOB formalism. The procedure is described in
1373  * https://arxiv.org/abs/2105.06983 (or
1374  * https://journals.aps.org/prd/abstract/10.1103/PhysRevD.104.124087)
1375  * STEP 0) Initialise variables and set up a radial grid on which the
1376  * post-adiabatic routine will be done.
1377  * STEP 1) Compute the (quasi-circular) adiabatic approximation
1378  * according to eq. (2.5) of arXiv:2105.06983.
1379  * STEP 2) Perform the post-adiabatic routine, by computing improvements
1380  * to prstar and pphi in alternating order, according to eqs. (2.6) and
1381  * (2.7) of arXiv:2105.06983.
1382  * STEP 3) The time t and orbital phase phi are computed via cubic
1383  * quadrature using eqs. (2.10) from arXiv:2105.06983.
1384  */
1385 int
1387  REAL8Array **dynamics,
1388  /**<< OUTPUT, real part of the modes */
1389  REAL8 m1,
1390  /**<< mass-1 */
1391  REAL8 m2,
1392  /**<< mass-2 */
1393  REAL8 spin1z,
1394  /**<< z-component of spin-1, dimensionless */
1395  REAL8 spin2z,
1396  /**<< z-component of spin-2, dimensionless */
1397  const REAL8Vector initVals,
1398  /**<< initial values (r, phi, pr, pphi) for the post-adiabatic
1399  routine */
1400  UINT4 SpinAlignedEOBversion,
1401  /**<< 1 for SEOBNRv1, 2 for SEOBNRv2, 4 for SEOBNRv4,
1402  201 for SEOBNRv2T, 401 for SEOBNRv4T, 41 for SEOBNRv4HM */
1404  /**<< SEOB parameters */
1406  /**<< NQC coefficients */
1407  LALDict *PAParams
1408  /**<< Pointer to a dictionary containing parameters for the
1409  post-adiabatic routine */
1410 )
1411 {
1412  if (SpinAlignedEOBversion != 4)
1413  {
1414  XLAL_ERROR(
1415  XLAL_EFUNC,
1416  "XLALSimInspiralEOBPostAdiabatic can only be used with SpinAlignedEOBversion = 4.\n"
1417  );
1418  }
1419  REAL8 mass_swap = 0.0;
1420  REAL8 spin_swap = 0.0;
1421  if (m2>m1){
1422  mass_swap = m1;
1423  spin_swap = spin1z;
1424  m1 = m2;
1425  m2 = mass_swap;
1426  spin1z = spin2z;
1427  spin2z = spin_swap;
1428  }
1431 
1432  REAL8 chi1 = spin1z;
1433  REAL8 chi2 = spin2z;
1434 
1435  const UINT4 PAOrder = XLALDictLookupUINT4Value(PAParams, "PAOrder");
1436 
1437  const UINT2 analyticFlag = XLALDictLookupUINT2Value(
1438  PAParams,
1439  "analyticFlag"
1440  );
1441 
1444 
1445  REAL8 a1 = XLALSimInspiralEOBPACalculatea(X1, chi1);
1447 
1448  REAL8 aK = a1 + a2;
1449 
1450  REAL8 Sstar = XLALSimInspiralEOBPACalculateSstar(X1, X2, chi1, chi2);
1451 
1452  REAL8 rInitial = initVals.data[0];
1453 
1454  REAL8 rFinalPrefactor = 1.6;
1456  seobParams->a
1457  );
1458  REAL8 rFinal = rFinalPrefactor * rf;
1459 
1460  if (rInitial <= rFinal)
1461  {
1463  }
1464 
1465  REAL8 rSwitchPrefactor = 1.6;
1466  REAL8 rSwitch = rSwitchPrefactor * rf;
1467 
1468  if (rInitial <= rSwitch)
1469  {
1471  }
1472 
1473  REAL8 dr = 0.3;
1474 
1475  UINT4 rSize = (int) ceil((rInitial-rFinal)/dr);
1476 
1477  if (rSize <= 4)
1478  {
1480  }
1481  else if (rSize < 10)
1482  {
1483  rSize = 10;
1484  }
1485 
1486  dr = XLALSimInspiralEOBPACalculatedr(rInitial, rFinal, rSize);
1487 
1488  LALDict *LALparams = XLALCreateDict();
1489 
1490  XLALDictInsertREAL8Value(LALparams, "q", q);
1491  XLALDictInsertREAL8Value(LALparams, "nu", nu);
1492 
1493  XLALDictInsertREAL8Value(LALparams, "chi1", chi1);
1494  XLALDictInsertREAL8Value(LALparams, "chi2", chi2);
1495 
1496  XLALDictInsertUINT4Value(LALparams, "PAOrder", PAOrder);
1497  XLALDictInsertUINT2Value(LALparams, "analyticFlag", analyticFlag);
1498 
1499  XLALDictInsertREAL8Value(LALparams, "X1", X1);
1500  XLALDictInsertREAL8Value(LALparams, "X2", X2);
1501 
1502  XLALDictInsertREAL8Value(LALparams, "a1", a1);
1503  XLALDictInsertREAL8Value(LALparams, "a2", a2);
1504  XLALDictInsertREAL8Value(LALparams, "aK", aK);
1505 
1506  XLALDictInsertREAL8Value(LALparams, "Sstar", Sstar);
1507 
1508  XLALDictInsertREAL8Value(LALparams, "rInitial", rInitial);
1509  XLALDictInsertREAL8Value(LALparams, "rFinal", rFinal);
1510  XLALDictInsertUINT4Value(LALparams, "rSize", rSize);
1511  XLALDictInsertREAL8Value(LALparams, "dr", dr);
1512 
1513  REAL8Vector *rVec = XLALCreateREAL8Vector(rSize);
1514  memset(
1515  rVec->data, 0,
1516  rVec->length * sizeof(REAL8)
1517  );
1518 
1519  REAL8Vector *rReverseVec = XLALCreateREAL8Vector(rSize);
1520  memset(
1521  rReverseVec->data, 0,
1522  rReverseVec->length * sizeof(REAL8)
1523  );
1524 
1525  REAL8Vector *tVec = XLALCreateREAL8Vector(rSize);
1526  memset(
1527  tVec->data, 0,
1528  tVec->length * sizeof(REAL8)
1529  );
1530 
1531  REAL8Vector *tReverseVec = XLALCreateREAL8Vector(rSize);
1532  memset(
1533  tReverseVec->data, 0,
1534  tReverseVec->length * sizeof(REAL8)
1535  );
1536 
1537  REAL8Vector *dtBydrVec = XLALCreateREAL8Vector(rSize);
1538  memset(
1539  dtBydrVec->data, 0,
1540  dtBydrVec->length * sizeof(REAL8)
1541  );
1542 
1543  REAL8Vector *dtBydrReverseVec = XLALCreateREAL8Vector(rSize);
1544  memset(
1545  dtBydrReverseVec->data, 0,
1546  dtBydrReverseVec->length * sizeof(REAL8)
1547  );
1548 
1549  REAL8Vector *phiVec = XLALCreateREAL8Vector(rSize);
1550  memset(
1551  phiVec->data, 0,
1552  phiVec->length * sizeof(REAL8)
1553  );
1554 
1555  REAL8Vector *phiReverseVec = XLALCreateREAL8Vector(rSize);
1556  memset(
1557  phiReverseVec->data, 0,
1558  phiReverseVec->length * sizeof(REAL8)
1559  );
1560 
1561  REAL8Vector *dphiBydrVec = XLALCreateREAL8Vector(rSize);
1562  memset(
1563  dphiBydrVec->data, 0,
1564  dphiBydrVec->length * sizeof(REAL8)
1565  );
1566 
1567  REAL8Vector *dphiBydrReverseVec = XLALCreateREAL8Vector(rSize);
1568  memset(
1569  dphiBydrReverseVec->data, 0,
1570  dphiBydrReverseVec->length * sizeof(REAL8)
1571  );
1572 
1573  REAL8Vector *csiVec = XLALCreateREAL8Vector(rSize);
1574  memset(
1575  csiVec->data, 0,
1576  csiVec->length * sizeof(REAL8)
1577  );
1578 
1579  REAL8Vector *omegaVec = XLALCreateREAL8Vector(rSize);
1580  memset(
1581  omegaVec->data, 0,
1582  omegaVec->length * sizeof(REAL8)
1583  );
1584 
1585  REAL8Vector *omegaReverseVec = XLALCreateREAL8Vector(rSize);
1586  memset(
1587  omegaReverseVec->data, 0,
1588  omegaReverseVec->length * sizeof(REAL8)
1589  );
1590 
1591  REAL8Vector *fluxVec = XLALCreateREAL8Vector(rSize);
1592  memset(
1593  fluxVec->data, 0,
1594  fluxVec->length * sizeof(REAL8)
1595  );
1596 
1597  REAL8Vector *pphiVec = XLALCreateREAL8Vector(rSize);
1598  memset(
1599  pphiVec->data, 0,
1600  pphiVec->length * sizeof(REAL8)
1601  );
1602 
1603  REAL8Vector *pphi0Vec = XLALCreateREAL8Vector(rSize);
1604  memset(
1605  pphi0Vec->data, 0,
1606  pphi0Vec->length * sizeof(REAL8)
1607  );
1608 
1609  REAL8Vector *pphiReverseVec = XLALCreateREAL8Vector(rSize);
1610  memset(
1611  pphiReverseVec->data, 0,
1612  pphiReverseVec->length * sizeof(REAL8)
1613  );
1614 
1615  REAL8Vector *prstarVec = XLALCreateREAL8Vector(rSize);
1616  memset(
1617  prstarVec->data, 0,
1618  prstarVec->length * sizeof(REAL8)
1619  );
1620 
1621  REAL8Vector *dprstarBydrVec = XLALCreateREAL8Vector(rSize);
1622  memset(
1623  dprstarBydrVec->data, 0,
1624  dprstarBydrVec->length * sizeof(REAL8)
1625  );
1626 
1627  REAL8Vector *dpphiBydrVec = XLALCreateREAL8Vector(rSize);
1628  memset(
1629  dpphiBydrVec->data, 0,
1630  dpphiBydrVec->length * sizeof(REAL8)
1631  );
1632 
1633  REAL8Vector *dpphiBydrReverseVec = XLALCreateREAL8Vector(rSize);
1634  memset(
1635  dpphiBydrReverseVec->data, 0,
1636  dpphiBydrReverseVec->length * sizeof(REAL8)
1637  );
1638 
1639  REAL8Vector *prstarReverseVec = XLALCreateREAL8Vector(rSize);
1640  memset(
1641  prstarReverseVec->data, 0,
1642  prstarReverseVec->length * sizeof(REAL8)
1643  );
1644 
1645  REAL8Vector *dprstarBydrReverseVec = XLALCreateREAL8Vector(rSize);
1646  memset(
1647  dprstarBydrReverseVec->data, 0,
1648  dprstarBydrReverseVec->length * sizeof(REAL8)
1649  );
1650 
1651  REAL8Vector *domegadrVec = XLALCreateREAL8Vector(rSize);
1652  memset(
1653  domegadrVec->data, 0,
1654  domegadrVec->length * sizeof(REAL8)
1655  );
1656 
1657  REAL8Vector *domegadrReverseVec = XLALCreateREAL8Vector(rSize);
1658  memset(
1659  domegadrReverseVec->data, 0,
1660  domegadrReverseVec->length * sizeof(REAL8)
1661  );
1662 
1663  REAL8Vector *adiabatic_param_Vec = XLALCreateREAL8Vector(rSize);
1664  memset(
1665  adiabatic_param_Vec->data, 0,
1666  adiabatic_param_Vec->length * sizeof(REAL8)
1667  );
1668 
1670  rVec,
1671  LALparams
1672  );
1673 
1675  rVec,
1676  phiVec,
1677  prstarVec,
1678  pphiVec,
1679  pphi0Vec,
1680  dpphiBydrVec,
1681  csiVec,
1682  omegaVec,
1683  seobParams,
1684  LALparams
1685  ) != XLAL_SUCCESS)
1686  {
1687  XLAL_ERROR(
1688  XLAL_EFUNC,
1689  "XLALSimInspiralEOBPACalculateAdiabaticDynamics failed."
1690  );
1691  }
1692 
1693  XLALReverseREAL8Vector(rVec, rReverseVec);
1694 
1695  if (PAOrder > 0)
1696  {
1698  rVec,
1699  phiVec,
1700  dphiBydrVec,
1701  prstarVec,
1702  dprstarBydrVec,
1703  pphiVec,
1704  dpphiBydrVec,
1705  dtBydrVec,
1706  csiVec,
1707  omegaVec,
1708  seobParams,
1709  nqcCoeffs,
1710  LALparams
1711  ) != XLAL_SUCCESS)
1712  {
1713  XLAL_ERROR(
1714  XLAL_EFUNC,
1715  "XLALSimInspiralEOBPACalculatePostAdiabaticDynamics failed."
1716  );
1717  }
1718  }
1719 
1720  XLALCumulativeIntegral3(rVec, dtBydrVec, tVec);
1721 
1722  XLALCumulativeIntegral3(rVec, dphiBydrVec, phiVec);
1723 
1724  UINT4 i, j;
1725  XLALReverseREAL8Vector(omegaVec, omegaReverseVec);
1727  rReverseVec, omegaReverseVec, domegadrReverseVec
1728  );
1729  XLALReverseREAL8Vector(domegadrReverseVec, domegadrVec);
1730 
1731  // Figure out where we are going to stop
1732  UNUSED REAL8 adiabatic_param = 0.0;
1733  UNUSED REAL8 r,prstar,pphi,csi,omega,domegadr;
1734 
1735  UINT4 idx_stop = 0;
1736 
1737  for (j=0; j<rSize; j++)
1738  {
1739  r = rVec->data[j];
1740 
1741  if (idx_stop == 0 && rSwitch >= r)
1742  {
1743  idx_stop = j;
1744  break;
1745  }
1746  }
1747 
1748  if (idx_stop == 0)
1749  {
1750  idx_stop = rSize - 1;
1751  }
1752 
1753  UINT4 outSize = idx_stop;
1754 
1755  *dynamics = XLALCreateREAL8ArrayL(2, 5, outSize);
1756 
1757  for (i = 0; i < outSize; i++)
1758  {
1759  (*dynamics)->data[i] = tVec->data[i];
1760  (*dynamics)->data[outSize + i] = rVec->data[i];
1761  (*dynamics)->data[2*outSize + i] = phiVec->data[i];
1762  (*dynamics)->data[3*outSize + i] = prstarVec->data[i];
1763  (*dynamics)->data[4*outSize + i] = pphiVec->data[i];
1764  }
1765 
1766  XLALDestroyREAL8Vector(tVec);
1767  XLALDestroyREAL8Vector(tReverseVec);
1768  XLALDestroyREAL8Vector(rVec);
1769  XLALDestroyREAL8Vector(rReverseVec);
1770  XLALDestroyREAL8Vector(phiVec);
1771  XLALDestroyREAL8Vector(phiReverseVec);
1772  XLALDestroyREAL8Vector(prstarVec);
1773  XLALDestroyREAL8Vector(pphiVec);
1774  XLALDestroyREAL8Vector(pphiReverseVec);
1775  XLALDestroyREAL8Vector(pphi0Vec);
1776  XLALDestroyREAL8Vector(omegaVec);
1777  XLALDestroyREAL8Vector(fluxVec);
1778  XLALDestroyREAL8Vector(csiVec);
1779  XLALDestroyREAL8Vector(prstarReverseVec);
1780  XLALDestroyREAL8Vector(dprstarBydrVec );
1781  XLALDestroyREAL8Vector(dpphiBydrVec);
1782  XLALDestroyREAL8Vector(dpphiBydrReverseVec);
1783  XLALDestroyREAL8Vector(dprstarBydrReverseVec);
1784  XLALDestroyREAL8Vector(dphiBydrVec);
1785  XLALDestroyREAL8Vector(dphiBydrReverseVec);
1786  XLALDestroyREAL8Vector(dtBydrVec);
1787  XLALDestroyREAL8Vector(dtBydrReverseVec);
1788  XLALDestroyREAL8Vector(omegaReverseVec);
1789  XLALDestroyREAL8Vector(domegadrVec);
1790  XLALDestroyREAL8Vector(domegadrReverseVec);
1791  XLALDestroyREAL8Vector(adiabatic_param_Vec);
1792 
1793  XLALDestroyDict(LALparams);
1794 
1795  if (outSize < 4)
1796  {
1797  XLAL_ERROR(
1798  XLAL_EFUNC,
1799  "PA inspiral doesn't have enough points for interpolation."
1800  );
1801  }
1802 
1803  return XLAL_SUCCESS;
1804 }
void XLALDestroyDict(LALDict *dict)
LALDict * XLALCreateDict(void)
int XLALDictInsertUINT4Value(LALDict *dict, const char *key, UINT4 value)
int XLALDictInsertUINT2Value(LALDict *dict, const char *key, UINT2 value)
REAL8 XLALDictLookupREAL8Value(LALDict *dict, const char *key)
UINT2 XLALDictLookupUINT2Value(LALDict *dict, const char *key)
int XLALDictInsertREAL8Value(LALDict *dict, const char *key, REAL8 value)
UINT4 XLALDictLookupUINT4Value(LALDict *dict, const char *key)
static REAL8 XLALInspiralSpinFactorizedFlux_PA(REAL8Vector *values, EOBNonQCCoeffs *nqcCoeffs, const REAL8 omega, SpinEOBParams *ak, const REAL8 H, const UINT4 lMax, const UINT4 SpinAlignedEOBversion)
static REAL8 XLALInspiralSpinFactorizedFluxOptimized(REAL8Vector *values, EOBNonQCCoeffs *nqcCoeffs, const REAL8 omega, SpinEOBParams *ak, const REAL8 H, const INT4 lMax, const UINT4 SpinAlignedEOBversion)
This function calculates the spin factorized-resummed GW energy flux for given dynamical variables.
static REAL8 XLALSimIMRSpinEOBHamiltonianDeltaR(SpinEOBHCoeffs *coeffs, const REAL8 r, const REAL8 eta, const REAL8 a)
This function calculates the DeltaR potential function in the spin EOB Hamiltonian.
static REAL8 XLALSimIMRSpinEOBHamiltonian(const REAL8 eta, REAL8Vector *restrict x, REAL8Vector *restrict p, REAL8Vector *restrict s1Vec, REAL8Vector *restrict s2Vec, REAL8Vector *restrict sigmaKerr, REAL8Vector *restrict sigmaStar, int tortoise, SpinEOBHCoeffs *coeffs)
static REAL8 XLALSimIMRSpinEOBHamiltonianDeltaT(SpinEOBHCoeffs *coeffs, const REAL8 r, const REAL8 eta, const REAL8 a)
This function calculates the function which appears in the spinning EOB potential function.
UNUSED REAL8 XLALSimIMRSpinEOBHamiltonianOptimized(const REAL8 eta, REAL8Vector *restrict x, REAL8Vector *restrict p, REAL8Vector *restrict s1Vec, REAL8Vector *restrict s2Vec, REAL8Vector *restrict sigmaKerr, REAL8Vector *restrict sigmaStar, INT4 tortoise, SpinEOBHCoeffs *coeffs)
Function to calculate the value of the spinning Hamiltonian for given values of the dynamical variabl...
static REAL8 XLALSpinHcapExactDerivWRTParam(const INT4 paramIdx, const REAL8 values[], SpinEOBParams *params)
Calculate the derivative of the Hamiltonian w.r.t.
REAL8 XLALSimInspiralEOBPACalculateMassRatio(const REAL8 m1, const REAL8 m2)
Function which calculates the mass ratio q from the masses m1 and m2.
REAL8 XLALSimInspiralEOBPACalculatea(REAL8 X, REAL8 chi)
Function which calculates the spin parameter a.
REAL8 XLALSimIMRSpinAlignedEOBPACalculateOmega(REAL8 polarDynamics[], REAL8 dr, SpinEOBParams *seobParams, LALDict *LALParams)
Function which calculates the frequency Omega.
REAL8 XLALSimInspiralEOBPACalculatedr(REAL8 rStart, REAL8 rFinal, UINT4 rSize)
Function which calculates the spacing of the radial grid.
REAL8 XLALSimInspiralEOBPACalculateSymmetricMassRatio(const REAL8 q)
Function which calculates the symmetric mass ratio nu from the mass ratio q.
REAL8 XLALSimInspiralEOBPACalculateSstar(REAL8 X1, REAL8 X2, REAL8 chi1, REAL8 chi2)
Function which calculates the spin parameter Sstar (S*)
REAL8 XLALSimInspiralEOBPostAdiabaticFinalRadiusAlternative(REAL8 a)
Function which calculates the final radius at which the post-adiabatic routine stops.
REAL8 XLALSimInspiralEOBPACalculateNewtonianj0(REAL8 r)
Function which calculates the circular angular momentum j0.
REAL8 XLALSimInspiralEOBPACalculateX2(const REAL8 nu)
Function which calculates the parameter X2 from the symmetric mass ratio nu.
REAL8 XLALSimInspiralEOBPACalculateX1(REAL8 nu)
Function which calculates the parameter X1 from the symmetric mass ratio nu.
int XLALCumulativeIntegral3(REAL8Vector *XVec, REAL8Vector *YVec, REAL8Vector *integralVec)
Function which calculates the 3-order cumulative derivative of a numerical function.
int XLALFDDerivative1Order8(REAL8Vector *XVec, REAL8Vector *YVec, REAL8Vector *derivativeVec)
Function which calculates the 8-order first finite difference derivative of a numerical function.
int XLALSimInspiralEOBPAMeanValueOrder8(REAL8Vector *inputVec, REAL8Vector *meanVec)
Function which performs an 8-order mean smoothing of a vector.
int XLALRescaleREAL8Vector(REAL8Vector *Vec, REAL8 factor, REAL8Vector *rescaledVec)
This function rescales each element of an array by a given factor.
REAL8 XLALSimInspiralEOBPAPartialHByPartialr(REAL8 h, REAL8 r, REAL8 prstar, REAL8 pphi, SpinEOBParams *seobParams, LALDict *LALParams)
Function which calculates the partial derivative dH/dr.
REAL8 XLALSimInspiralEOBPAFluxWrapper(REAL8 r, REAL8 prstar, REAL8 pphi, REAL8 omega, SpinEOBParams *seobParams, EOBNonQCCoeffs *nqcCoeffs, LALDict *LALParams)
A wrapper for the factorized flux, depending on the user choices.
double XLALSimInspiralEOBPostAdiabaticdpphiFunc(REAL8 pphi_sol, void *params)
Function which implements eq.
double XLALSimInspiralEOBPostAdiabaticdprstarFunc(REAL8 prstar_sol, void *params)
Function which implements eq.
int XLALSimInspiralEOBPACalculateRadialGrid(REAL8Vector *rVec, LALDict *LALParams)
Function which comstructs the radial grid on which the post-adiabatic approximation will be computed.
REAL8 XLALSimInspiralEOBPAHamiltonianWrapper(REAL8 r, REAL8 prstar, REAL8 pphi, SpinEOBHCoeffs *seobCoeffs, LALDict *LALParams)
A wrapper for the SEOB Hamiltonian, depending on the user choices.
REAL8 XLALSimInspiralEOBPAPartialHByPartialprstar(REAL8 h, REAL8 r, REAL8 prstar, REAL8 pphi, SpinEOBParams *seobParams, LALDict *LALParams)
Function which calculates the partial derivative dH/dprstar.
int XLALSimInspiralEOBPACalculatePostAdiabaticDynamics(REAL8Vector *rVec, REAL8Vector *phiVec, REAL8Vector *dphiBydrVec, REAL8Vector *prstarVec, REAL8Vector *dprstarBydrVec, REAL8Vector *pphiVec, REAL8Vector *dpphiBydrVec, REAL8Vector *dtBydrVec, REAL8Vector *csiVec, REAL8Vector *omegaVec, SpinEOBParams *seobParams, EOBNonQCCoeffs *nqcCoeffs, LALDict *LALParams)
This function calculates the (n-th order) post-adiabatic approximation of the inspiral dynamics.
int XLALSimInspiralEOBPostAdiabatic(REAL8Array **dynamics, REAL8 m1, REAL8 m2, REAL8 spin1z, REAL8 spin2z, const REAL8Vector initVals, UINT4 SpinAlignedEOBversion, SpinEOBParams *seobParams, EOBNonQCCoeffs *nqcCoeffs, LALDict *PAParams)
This function generates post-adiabatic inspiral for spin-aligned binary in the SEOB formalism.
#define ROOT_SOLVER_REL_TOL
int XLALOffsetREAL8Vector(REAL8Vector *Vec, REAL8 offset, REAL8Vector *offsetVec)
Function which add a constant to each element of an array.
int XLALSimInspiralEOBPACalculateAdiabaticDynamics(REAL8Vector *rVec, REAL8Vector *phiVec, REAL8Vector *prstarVec, REAL8Vector *pphiVec, REAL8Vector *pphi0Vec, REAL8Vector *dpphiBydrVec, REAL8Vector *csiVec, REAL8Vector *omegaVec, SpinEOBParams *seobParams, LALDict *LALParams)
This function calculates the adiabatic (0th order PA) approximation of the inspiral dynamics.
int XLALReverseREAL8Vector(REAL8Vector *Vec, REAL8Vector *reverseVec)
Function which reverses a 1D array.
int XLALSimInspiralEOBPostAdiabaticRootFinder(struct PostAdiabaticRoot *result, double(*Func)(REAL8, void *), struct PostAdiabaticRootSolveParams *params, REAL8 x_lower, REAL8 x_upper, REAL8 absTol, REAL8 relTol, INT2 parity)
Root finder function which is used for computing the adiabatic and post-adiabatic approximations.
double XLALSimInspiralEOBPostAdiabaticj0Func(REAL8 j0_sol, void *params)
Function which implements eq.
#define ROOT_SOLVER_ABS_TOL
double i
Definition: bh_ringdown.c:118
const double H
const double a2
const double csi
REAL8Array * XLALCreateREAL8ArrayL(UINT4,...)
double REAL8
int16_t INT2
uint16_t UINT2
uint32_t UINT4
int32_t INT4
static const INT4 r
static const INT4 q
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
#define XLAL_ERROR(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
XLAL_ERANGE
XLAL_EFUNC
list x
string status
The coefficients which are used in calculating the non-quasicircular correction to the EOBNRv2 model.
REAL8 root
INT4 nIter
INT4 status
REAL8 dprstarBydr
REAL8 pphi
LALDict * LALParams
REAL8 prstar
REAL8 dprstar
REAL8 r
REAL8 phi
SpinEOBParams * seobParams
REAL8 dpphiBydr
REAL8 csi
REAL8 dr
REAL8 omega
EOBNonQCCoeffs * nqcCoeffs
REAL8 * data
Parameters for the spinning EOB model, used in calculating the Hamiltonian.
Parameters for the spinning EOB model.
SpinEOBHCoeffs * seobCoeffs
Definition: burst.c:245