LALSimulation  5.4.0.1-fe68b98
LALSimIMRSpinPrecEOBEulerAngles.c
Go to the documentation of this file.
1 #ifndef _LALSIMIMRSPINPRECEOBEULERANGLES_C
2 #define _LALSIMIMRSPINPRECEOBEULERANGLES_C
3 
4 
5 /**
6  * Computes the Euler angles in the (z,y,z) convention corresponding to a given 3*3 active rotation matrix
7  * R has to be 3*3
8  */
10 {
11  /* Matrix element (i,j) at location 3*i + j */
12  REAL8 a = atan2(R->data[3*1 + 2], R->data[3*0 + 2]);
13  REAL8 b = acos(R->data[3*2 + 2]);
14  REAL8 c = atan2(R->data[3*2 + 1], -R->data[3*2 + 0]);
15  *alpha = a;
16  *beta = b;
17  *gamma = c;
18  return XLAL_SUCCESS;
19 }
20 /**
21  * Active rotation matrix from orthonormal basis (e1, e2, e3) to (e1', e2', e3')
22  * Input are e1', e2', e3' decomposed on (e1, e2, e3)
23  * All vectors are 3-vectors, R matrix 3*3 has to be already allocated
24  */
25 static UNUSED int RotationMatrixActiveFromBasisVectors(REAL8Array* R, const REAL8 e1p[], const REAL8 e2p[], const REAL8 e3p[])
26 {
27  R->data[3*0 + 0] = e1p[0];
28  R->data[3*1 + 0] = e1p[1];
29  R->data[3*2 + 0] = e1p[2];
30  R->data[3*0 + 1] = e2p[0];
31  R->data[3*1 + 1] = e2p[1];
32  R->data[3*2 + 1] = e2p[2];
33  R->data[3*0 + 2] = e3p[0];
34  R->data[3*1 + 2] = e3p[1];
35  R->data[3*2 + 2] = e3p[2];
36  return XLAL_SUCCESS;
37 }
38 
39 /**
40  * Computes RHS of ODE for gamma. Eq. 10 of PRD 89, 084006 (2014)
41  */
42 static double f_alphadotcosi( double x, void * inparams )
43 {
45 
46  REAL8 alphadot = gsl_spline_eval_deriv( params->alpha_spline, x, params->alpha_acc );
47  REAL8 beta = gsl_spline_eval( params->beta_spline, x, params->beta_acc );
48 
49  return -1. * alphadot * cos(beta);
50 
51 }
52 /**
53  * Given the trajectory in an inertial frame, this computes Euler angles
54  * of the roation from the inertial frame to the minimal-rotation frame
55  * that co-precesses with LN(t) = rvec(t) x rdotvec(t)
56  */
57 static UNUSED int EulerAnglesI2P(REAL8Vector *Alpha, /**<< output: alpha Euler angle */
58  REAL8Vector *Beta, /**<< output: beta Euler angle */
59  REAL8Vector *Gamma, /**<< output: gamma Euler angle */
60  INT4 *phaseCounterA, /**<< output: counter for unwrapping of alpha */
61  INT4 *phaseCounterB, /**<< output: counter for unwrapping of beta */
62  const REAL8Vector tVec, /**<< time series */
63  const REAL8Vector posVecx, /**<< x time series */
64  const REAL8Vector posVecy, /**<< y time series */
65  const REAL8Vector posVecz, /**<< z time series */
66  const UINT4 retLenLow, /**<< Array length of the trajectory */
67  const REAL8 InitialAlpha, /**<< Initial alpha (used only if flag_highSR=1) */
68  const REAL8 InitialGamma, /**<< Initial gamma */
69  UINT4 flag_highSR, /**<< Flag to indicate whether one is analyzing the high SR trajectory */
70  const UINT4 use_optimized /**<< Flag to indicate whether one is using SEOBNRv3_opt */) {
71  UINT4 i = 0;
72  REAL8Vector *LN_x = NULL, *LN_y = NULL, *LN_z = NULL;
73  REAL8 tmpR[3], tmpRdot[3], magLN;
74  PrecEulerAnglesIntegration precEulerparams;
75  REAL8 inGamma = InitialGamma;
76 
77  LN_x = XLALCreateREAL8Vector( retLenLow );
78  LN_y = XLALCreateREAL8Vector( retLenLow );
79  LN_z = XLALCreateREAL8Vector( retLenLow );
80 
81  gsl_spline *x_spline = gsl_spline_alloc( gsl_interp_cspline, retLenLow );
82  gsl_spline *y_spline = gsl_spline_alloc( gsl_interp_cspline, retLenLow );
83  gsl_spline *z_spline = gsl_spline_alloc( gsl_interp_cspline, retLenLow );
84 
85  gsl_interp_accel *x_acc = gsl_interp_accel_alloc();
86  gsl_interp_accel *y_acc = gsl_interp_accel_alloc();
87  gsl_interp_accel *z_acc = gsl_interp_accel_alloc();
88 
89  gsl_spline_init( x_spline, tVec.data, posVecx.data, retLenLow );
90  gsl_spline_init( y_spline, tVec.data, posVecy.data, retLenLow );
91  gsl_spline_init( z_spline, tVec.data, posVecz.data, retLenLow );
92 
93  for( i=0; i < retLenLow; i++ )
94  {
95  tmpR[0] = posVecx.data[i]; tmpR[1] = posVecy.data[i]; tmpR[2] = posVecz.data[i];
96  tmpRdot[0] = gsl_spline_eval_deriv( x_spline, tVec.data[i], x_acc );
97  tmpRdot[1] = gsl_spline_eval_deriv( y_spline, tVec.data[i], y_acc );
98  tmpRdot[2] = gsl_spline_eval_deriv( z_spline, tVec.data[i], z_acc );
99 
100  LN_x->data[i] = tmpR[1] * tmpRdot[2] - tmpR[2] * tmpRdot[1];
101  LN_y->data[i] = tmpR[2] * tmpRdot[0] - tmpR[0] * tmpRdot[2];
102  LN_z->data[i] = tmpR[0] * tmpRdot[1] - tmpR[1] * tmpRdot[0];
103 
104  magLN = sqrt(LN_x->data[i] * LN_x->data[i] + LN_y->data[i] * LN_y->data[i]
105  + LN_z->data[i] * LN_z->data[i]);
106  LN_x->data[i] /= magLN; LN_y->data[i] /= magLN; LN_z->data[i] /= magLN;
107 
108  /* Eq. 19 of PRD 89, 084006 (2014) */
109  /* Also unwrap the two angles */
110  if (fabs(LN_x->data[i]) <= 1.e-10 && fabs(LN_y->data[i]) <=1.e-10){
111  Alpha->data[i] = 0.0;
112  inGamma = 0.0;
113  } else {
114  Alpha->data[i] = atan2( LN_y->data[i], LN_x->data[i] )
115  + *phaseCounterA * LAL_TWOPI;
116  if (i==0 && flag_highSR != 1){
117  inGamma = -Alpha->data[i];
118  }
119  }
120 
121  while( i>0 && Alpha->data[i] - Alpha->data[i-1] > 5. ) {
122  *phaseCounterA = *phaseCounterA - 1;
123  Alpha->data[i] -= LAL_TWOPI;
124  }
125  while( i && Alpha->data[i] - Alpha->data[i-1] < -5. ) {
126  *phaseCounterA = *phaseCounterA + 1;
127  Alpha->data[i] += LAL_TWOPI;
128  }
129  if (LN_z->data[i] >1.) {
130  LN_z->data[i] = 1.;
131  }
132  if (LN_z->data[i] <-1.) {
133  LN_z->data[i] = -1.;
134  }
135  if ( flag_highSR == 1) {
136  Alpha->data[i] -= (Alpha->data[0] - InitialAlpha);
137  }
138 
139  if (fabs(1.0 - LN_z->data[i]) < 1.e-12){
140  REAL8 LN_xy;
141  LN_xy = sqrt(LN_x->data[i]*LN_x->data[i] +
142  LN_y->data[i]*LN_y->data[i]);
143  //LN_z->data[i] = sqrt(1.0 - LN_xy*LN_xy);
144  Beta->data[i] = atan2(LN_xy, LN_z->data[i]);
145  //printf("here ");
146  }else{
147  Beta->data[i] = acos( LN_z->data[i] );
148  }
149  if( i>0 && Beta->data[i] > Beta->data[i-1] ) {
150  *phaseCounterB = *phaseCounterB - 1;
151  }
152  }
153  // Integrate \dot{\alpha} \cos{\beta} to get the final Euler angle
154  // Eq. 20 of PRD 89, 084006 (2014)
155  gsl_spline_init( x_spline, tVec.data, Alpha->data, retLenLow );
156  gsl_spline_init( y_spline, tVec.data, Beta->data, retLenLow );
157 
158  precEulerparams.alpha_spline = x_spline;
159  precEulerparams.alpha_acc = x_acc;
160  precEulerparams.beta_spline = y_spline;
161  precEulerparams.beta_acc = y_acc;
162 
163  Gamma->data[0] = inGamma;
164  if(use_optimized){
165  for( i = 1; i < retLenLow; i++ ){
166  double t1 = tVec.data[i-1];
167  double t2 = tVec.data[i];
168  Gamma->data[i] = Gamma->data[i-1] + (1.0/90.0)*(t2 - t1)*(7.0*f_alphadotcosi(t1,&precEulerparams)
169  + 32.0*f_alphadotcosi((t1+3.0*t2)/4.0,&precEulerparams)
170  + 12.0*f_alphadotcosi((t1+t2)/2.0,&precEulerparams)
171  + 32.0*f_alphadotcosi((3.0*t1+t2)/4.0,&precEulerparams)
172  + 7.0*f_alphadotcosi(t2,&precEulerparams));/* Boole's Rule */
173  }
174  }else{
175  gsl_integration_workspace * precEulerw = gsl_integration_workspace_alloc (1000);
176  gsl_function precEulerF;
177  REAL8 precEulerresult = 0, precEulererror = 0;
178  precEulerF.function = &f_alphadotcosi;
179  precEulerF.params = &precEulerparams;
180  for( i = 1; i < retLenLow; i++ ) {
181  gsl_integration_qags (&precEulerF, tVec.data[i-1], tVec.data[i], 1e-9, 1e-9, 1000, precEulerw, &precEulerresult, &precEulererror);
182  Gamma->data[i] = Gamma->data[i-1] + precEulerresult;
183  }
184  gsl_integration_workspace_free( precEulerw );
185  }
186 
187  gsl_spline_free( x_spline );
188  gsl_spline_free( y_spline );
189  gsl_spline_free( z_spline );
190  gsl_interp_accel_free( x_acc );
191  gsl_interp_accel_free( y_acc );
192  gsl_interp_accel_free( z_acc );
193  XLALDestroyREAL8Vector( LN_x );
194  XLALDestroyREAL8Vector( LN_y );
195  XLALDestroyREAL8Vector( LN_z );
196  return XLAL_SUCCESS;
197 }
198 
199 /**
200  * Given Euler angles to go from initial inertial frame to precessing frama
201  * and the LNhat vector, this functions computes the Euler angles to
202  * go from the precessing frame to the frame of the total angular
203  * momentum
204  */
205 static UNUSED void EulerAnglesP2J(
206  REAL8 *aP2J, /**<< alpha Euler angle from precessing to final-J frame */
207  REAL8 *bP2J, /**<< beta Euler angle from precessing to final-J frame */
208  REAL8 *gP2J, /**<< gamma Euler angle from precessing to final-J frame */
209  const REAL8 aI2P, /**<< alpha Euler angle from inertial to precessing frame */
210  const REAL8 bI2P, /**<< beta Euler angle from inertial to precessing frame */
211  const REAL8 gI2P, /**<< gamma Euler angle from inertial to precessing frame */
212  const REAL8 LNhx, /**<< x component of LNhat */
213  const REAL8 LNhy, /**<< y component of LNhat */
214  const REAL8 LNhz, /**<< z component of LNhat */
215  const REAL8 JframeEx[], /**<< x-axis of the total-angular-momentum frame */
216  const REAL8 JframeEy[], /**<< y-axis of the total-angular-momentum frame */
217  const REAL8 JframeEz[] /**<< z-axis of the total-angular-momentum frame */
218 ) {
219  REAL8 LframeEx[3] = {0,0,0}, LframeEy[3] = {0,0,0}, LframeEz[3] = {0,0,0};
220  LframeEx[0] = cos(aI2P)*cos(bI2P)*cos(gI2P) - sin(aI2P)*sin(gI2P);
221  LframeEx[1] = sin(aI2P)*cos(bI2P)*cos(gI2P) + cos(aI2P)*sin(gI2P);
222  LframeEx[2] = -sin(bI2P)*cos(gI2P);
223  LframeEy[0] = -cos(aI2P)*cos(bI2P)*sin(gI2P) - sin(aI2P)*cos(gI2P);
224  LframeEy[1] = -sin(aI2P)*cos(bI2P)*sin(gI2P) + cos(aI2P)*cos(gI2P);
225  LframeEy[2] = sin(bI2P)*sin(gI2P);
226  LframeEz[0] = LNhx;
227  LframeEz[1] = LNhy;
228  LframeEz[2] = LNhz;
229  REAL8 normJ, normLz;
230  normJ = JframeEz[0]*JframeEz[0]+JframeEz[1]*JframeEz[1]+JframeEz[2]*JframeEz[2];
231  normLz = LframeEz[0]*LframeEz[0]+LframeEz[1]*LframeEz[1]+LframeEz[2]*LframeEz[2];
232  *aP2J = atan2(JframeEz[0]*LframeEy[0]+JframeEz[1]*LframeEy[1]+JframeEz[2]*LframeEy[2],
233  JframeEz[0]*LframeEx[0]+JframeEz[1]*LframeEx[1]+JframeEz[2]*LframeEx[2]);
234  REAL8 cosarg = JframeEz[0]*LframeEz[0]+JframeEz[1]*LframeEz[1]+JframeEz[2]*LframeEz[2];
235  if ( cosarg >= 1. && cosarg < 1. + 1.e-10 ) {
236  cosarg = 1.;
237  }
238  if ( cosarg <= -1. && cosarg > -1. - 1.e-10 ) {
239  cosarg = -1.;
240  }
241  *bP2J = acos( cosarg );
242  if (*bP2J < 1.e-4){
243  cosarg = (JframeEz[0]*LframeEz[0]+JframeEz[1]*LframeEz[1]+JframeEz[2]*LframeEz[2])/sqrt(normJ*normLz);
244  if ( cosarg >= 1. && cosarg < 1. + 1.e-10 ) {
245  cosarg = 1.;
246  }
247  if ( cosarg <= -1. && cosarg > -1. - 1.e-10 ) {
248  cosarg = -1.;
249  }
250  *bP2J = acos( cosarg );
251  }
252  *gP2J = atan2( JframeEy[0]*LframeEz[0]+JframeEy[1]*LframeEz[1]+JframeEy[2]*LframeEz[2],
253  -(JframeEx[0]*LframeEz[0]+JframeEx[1]*LframeEz[1]+JframeEx[2]*LframeEz[2]));
254 
255  /* I2P Euler angles are stored only for debugging purposes */
256  if ( fabs(*bP2J-LAL_PI) < 1.e-10){
257  *gP2J = 0.0;
258  *aP2J = atan2( JframeEx[1], JframeEx[0]);
259  }
260 
261  if ( fabs(*bP2J) < 1.e-10){
262  *gP2J = 0.0;
263  *aP2J = atan2( JframeEx[1], JframeEx[0]);
264  }
265 }
266 
267 #endif // _LALSIMIMRSPINPRECEOBEULERANGLES_C
static double f_alphadotcosi(double x, void *inparams)
Computes RHS of ODE for gamma.
static UNUSED void EulerAnglesP2J(REAL8 *aP2J, REAL8 *bP2J, REAL8 *gP2J, const REAL8 aI2P, const REAL8 bI2P, const REAL8 gI2P, const REAL8 LNhx, const REAL8 LNhy, const REAL8 LNhz, const REAL8 JframeEx[], const REAL8 JframeEy[], const REAL8 JframeEz[])
Given Euler angles to go from initial inertial frame to precessing frama and the LNhat vector,...
static UNUSED int RotationMatrixActiveFromBasisVectors(REAL8Array *R, const REAL8 e1p[], const REAL8 e2p[], const REAL8 e3p[])
Active rotation matrix from orthonormal basis (e1, e2, e3) to (e1', e2', e3') Input are e1',...
static UNUSED int EulerAnglesI2P(REAL8Vector *Alpha, REAL8Vector *Beta, REAL8Vector *Gamma, INT4 *phaseCounterA, INT4 *phaseCounterB, const REAL8Vector tVec, const REAL8Vector posVecx, const REAL8Vector posVecy, const REAL8Vector posVecz, const UINT4 retLenLow, const REAL8 InitialAlpha, const REAL8 InitialGamma, UINT4 flag_highSR, const UINT4 use_optimized)
Given the trajectory in an inertial frame, this computes Euler angles of the roation from the inertia...
static UNUSED int EulerAnglesZYZFromRotationMatrixActive(REAL8 *alpha, REAL8 *beta, REAL8 *gamma, REAL8Array *R)
Computes the Euler angles in the (z,y,z) convention corresponding to a given 3*3 active rotation matr...
static double beta(const double a, const double b, const sysq *system)
Internal function that computes the spin-orbit couplings.
#define c
double i
Definition: bh_ringdown.c:118
double e
Definition: bh_ringdown.c:117
#define LAL_PI
#define LAL_TWOPI
double REAL8
uint32_t UINT4
int32_t INT4
static const INT4 a
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
XLAL_SUCCESS
list x
double alpha
Definition: sgwb.c:106
gsl_interp_accel * alpha_acc
gsl_interp_accel * beta_acc
REAL8 * data
REAL8 * data
Definition: burst.c:245