Logo coherent WaveBurst  
Library Reference Guide
Logo
geodesics.cc
Go to the documentation of this file.
1 /*
2 # Copyright (C) 2019 Sergey Klimenko, Valentin Necula
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 
19 #include "geodesics.hh"
20 
21 #include "math.h"
22 #include "stdlib.h"
23 
24 //return values of f_util:
25 
26 static double r, pr, phi, tau, r2, a2, r3, Delta, R02, Q, A, B, r_dot, w, pr_dot, Edot, Ldot;
27 
28 // Here we compute second and third time derivatives of r and phi
29 // for a geodesic for use in the quadrupole formula
30 // REMOVED first three arguments! (made global)
31 
32 
33 void geo_higher_deriv(double E, double L, double a,
34  double& r_dotdot, double& r_dotdotdot, double& wdot, double& wdotdot)
35 {
36  // r2=r*r; a2=a*a; r3=r2*r;
37  // Delta=r2+a2-2*r; R02=r2+a2*(1+2/r); Q=Delta/(E*R02-2*a*L/r) // Q=tau_dot
38  // w=(L*Q+2*a/r)/R02 # w=phi_dot ; A=(w**2*(r3-a2)+2*a*w-1); B=(a2-r)/r3
39  // r_dot=Delta*Q*pr/r2
40  // pr_dot=A/r2/Q + B*pr**2*Q
41 
42  double F = r3+a2*r-2*r2;
43  double Fdot = (3*r2+a2-4*r)*r_dot;
44  double G = E*(r3+a2*r+2*a2)-2*a*L;
45  double Gdot = E*(3*r2+a2)*r_dot;
46  double Qdot = (Fdot*G-F*Gdot)/G/G;
47  double H = L*Q*r+2*a;
48  double Hdot = L*(Q*r_dot+Qdot*r);
49  double I = (r3+a2*r+2*a2);
50  double Idot = (3*r2+a2)*r_dot;
51  wdot = (Hdot*I-H*Idot)/I/I;
52  double Adot = 2*w*wdot*(r3-a2)+w*w*(3*r2*r_dot)+2*a*wdot;
53  double Bdot = (-3*a2/r2/r2+2/r3)*r_dot;
54  double C = r2+a2-2*r;
55  C *= C;
56  double Cdot = 4*(r-1)*(r2+a2-2*r)*r_dot;
57  double D = E*R02*r2-2*a*L*r;
58  double Ddot = E*(4*r3+2*a2*r)*r_dot+r_dot*(2*a2*E-2*a*L);
59  double alpha = Delta*Q/r2;
60  double alphadot = (Cdot*D-C*Ddot)/D/D;
61  r_dotdot = alphadot*pr + alpha*pr_dot;
62  double Cdotdot = 4*(r-1)*(r2+a2-2*r)*r_dotdot + 4*(r_dot)*(r2+a2-2*r)*r_dot
63  + 8*(r-1)*(r-1)*r_dot*r_dot;
64  double Ddotdot = E*(4*r3+2*a2*r)*r_dotdot+ E*(12*r2+2*a2)*r_dot*r_dot +
65  r_dotdot*(2*a2*E-2*a*L);
66  double alphadotdot = (Cdotdot*D-C*Ddotdot)/D/D - 2*(Cdot*D-C*Ddot)*Ddot/D/D/D;
67  double pr_dotdot = Adot/r2/Q-A*(2*r*r_dot*Q+r2*Qdot)/(r2*Q)/(r2*Q)+Bdot*pr*pr*Q
68  + 2*B*pr*pr_dot*Q+B*pr*pr*Qdot;
69  r_dotdotdot = alphadotdot*pr + 2*alphadot*pr_dot + alpha*pr_dotdot;
70  double Fdotdot = (3*r2+a2-4*r)*r_dotdot+(6*r-4)*r_dot*r_dot;
71  double Gdotdot = E*(3*r2+a2)*r_dotdot + E*6*r*r_dot*r_dot;
72  double Qdotdot = (Fdotdot*G-F*Gdotdot)/G/G-2*(Fdot*G-F*Gdot)*Gdot/G/G/G;
73  double Hdotdot = L*(Q*r_dotdot+Qdotdot*r+2*Qdot*r_dot);
74  double Idotdot = (3*r2+a2)*r_dotdot + 6*r*r_dot*r_dot;
75  wdotdot = (Hdotdot*I-H*Idotdot)/I/I-2*(Hdot*I-H*Idot)*Idot/I/I/I;
76 }
77 
78 
79 void reduced_quad_dot(double r, double r_t, double r_tt, double r_ttt, double phi,
80 double phi_t, double phi_tt, double phi_ttt, double (&I_tt)[3][3], double (&I_ttt)[3][3])
81 { double X = r*r;
82  double X_t = 2*r*r_t;
83  double X_tt = 2*r_t*r_t+2*r*r_tt;
84  double X_ttt = 6*r_t*r_tt+2*r*r_ttt;
85 
86  double cos2phi = cos(2*phi);
87  double sin2phi = sin(2*phi);
88 
89  double A = cos2phi;
90  double A_t = -2*sin2phi*phi_t;
91  double A_tt = -4*cos2phi*phi_t*phi_t-2*sin2phi*phi_tt;
92  double A_ttt = 8*sin2phi*pow(phi_t,3)-8*cos2phi*phi_t*phi_tt
93  -4*cos2phi*phi_t*phi_tt-2*sin2phi*phi_ttt;
94 
95  double B = sin2phi;
96  double B_t = 2*cos2phi*phi_t;
97  double B_tt = -4*sin2phi*phi_t*phi_t+2*cos2phi*phi_tt;
98  double B_ttt = -8*cos2phi*pow(phi_t,3) - 8*sin2phi*phi_t*phi_tt
99  -4*sin2phi*phi_t*phi_tt + 2*cos2phi*phi_ttt;
100 
101  double M[3][3] = {1+3*A,3*B,0, 3*B,1-3*A,0, 0,0,-2};
102  double M_t[3][3] = {3*A_t, 3*B_t, 0, 3*B_t, -3*A_t, 0, 0,0,0};
103  double M_tt[3][3] = {3*A_tt, 3*B_tt, 0, 3*B_tt, -3*A_tt, 0, 0,0,0};
104  double M_ttt[3][3] ={3*A_ttt, 3*B_ttt, 0, 3*B_ttt, -3*A_ttt, 0, 0,0,0};
105 
106  for(int i=0; i<3; ++i)for(int j=0; j<3; ++j){
107  I_tt[i][j] = (X_tt*M[i][j]+X*M_tt[i][j]+2*X_t*M_t[i][j])/6;
108  I_ttt[i][j] = (X_ttt*M[i][j]+X*M_ttt[i][j]+3*X_tt*M_t[i][j]+3*X_t*M_tt[i][j])/6;
109  }
110 }
111 
112 void quad_loss(double r, double r_t, double r_tt, double r_ttt, double phi,
113  double phi_t, double phi_tt, double phi_ttt, double& E_dot, double& Lz_dot)
114 
115 /* Compute rate of energy and angular momentum loss according to quadrupole formula
116  Specifically, for a two body system (in units of total mass, M:=m1+m2=1)
117  where object one is located at d1 = d*m2 and d2 =d*m1 where
118  d = (r*cos(phi),r*sin(phi)) this returns (dE/dt)/mu**2
119  and (dL/dt)/mu**2 where mu is the reduced mass
120  The arguments are r and its first three time derivatives
121  and phi and its first three time derivatives. */
122 
123 { double I_tt[3][3], I_ttt[3][3];
124  reduced_quad_dot(r,r_t,r_tt,r_ttt,phi,phi_t,phi_tt,phi_ttt, I_tt, I_ttt);
125 
126  double sum = 0;
127  for(int i=0; i<3; ++i)for(int j=0; j<3; ++j) sum +=I_ttt[i][j]*I_ttt[i][j];
128 
129  E_dot = -0.2*sum;
130 
131  // Assuming angular momentum only changes in z direction
132  sum = 0;
133  for(int i=0; i<3; ++i)sum += I_tt[0][i]*I_ttt[i][1]- I_tt[1][i]*I_ttt[i][0];
134  Lz_dot = -0.4*sum;
135 }
136 
137 
138 void f_util(double* y, double Jspin, double mu)
139 { r = y[0];
140  pr = y[1];
141  phi = y[2];
142  tau = y[3];
143  double& E = y[4];
144  double& L = y[5];
145  double a = Jspin +mu*L;
146 
147  r2 = r*r;
148  a2 = a*a;
149  r3 = r2*r;
150 
151  Delta = r2 + a2 - 2*r;
152  R02 = r2 + a2*(1+2/r);
153  Q=Delta/(E*R02-2*a*L/r); // Q=tau_dot
154 
155  w=(L*Q+2*a/r)/R02; // w=phi_dot
156  A=(w*w*(r3-a2)+2*a*w-1);
157  B=(a2-r)/r3;
158 
159  r_dot=Delta*Q*pr/r2;
160  pr_dot=A/r2/Q + B*pr*pr*Q;
161 
162  double r_dotdot, r_dotdotdot, wdot, wdotdot;
163  geo_higher_deriv(E, L, a, r_dotdot, r_dotdotdot, wdot, wdotdot);
164 
165  quad_loss(r, r_dot, r_dotdot, r_dotdotdot, phi, w, wdot, wdotdot, Edot, Ldot);
166  Edot = mu*Edot;
167  Ldot = mu*Ldot;
168 }
169 
170 
171 // Returns h plus and h cross (times r) of GW from quadrupole formula.
172 // See note above quad_loss
173 void h_quad(double r, double r_t, double r_tt, double r_ttt,
174  double phi, double phi_t, double phi_tt, double phi_ttt,
175  double& hplus, double& hcross)
176 {
177  double I_tt[3][3];
178  double I_ttt[3][3];
179  reduced_quad_dot(r, r_t, r_tt, r_ttt, phi, phi_t, phi_tt, phi_ttt, I_tt, I_ttt);
180 
181  hplus = 2*I_tt[0][0];
182  hcross = 2*I_tt[0][1];
183 }
184 
185 
186 // ud has Jspin, mu
187 int f(realtype t, N_Vector y, N_Vector ydot, void* ud)
188 { realtype *ydata, *ydotdata;
189  realtype* udr = (realtype*)ud;
190  ydata = NV_DATA_S(y);
191  ydotdata = NV_DATA_S(ydot);
192 
193  f_util(ydata, udr[0], udr[1]);
194  ydotdata[0] = r_dot;
195  ydotdata[1] = pr_dot;
196  ydotdata[2] = w;
197  ydotdata[3] = Q;
198  ydotdata[4] = Edot;
199  ydotdata[5] = Ldot;
200  return 0;
201 }
202 
203 geodesic::geodesic(double r0, double phi0, double E0, double L0, int dir, double Jspin,
204 double mu, double dt)
205 { if(dir!=1 && dir!=-1){
206  printf("Error... dir must be +-1\n");
207  exit(1);
208  }
209  y = N_VNew_Serial(6);
210  ydata = NV_DATA_S(y);
211  ydata[0] = r0;
212  ydata[1] = 0.0;
213  ydata[2] = phi0;
214  ydata[3] = 0.0;
215  ydata[4] = E0;
216  ydata[5] = L0;
217  udata[0] = Jspin;
218  udata[1] = mu;
219  tret = 0;
220  f_util(ydata, Jspin, mu);
221  double Q2 = Q*Q;
222  ydata[1] = dir*sqrt(fabs(r2/Delta/Q2*(1-2/::r-Q2-w*(R02*w-4*sqrt(a2)/::r))));
223 
224 #ifdef SUNDIALS_PACKAGE_VERSION
225  cvode_mem =CVodeCreate(CV_ADAMS, CV_FUNCTIONAL); // SUNDIALS_VERSION = 2.7.0
226 #else
227 #if SUNDIALS_VERSION_MAJOR > 4 || (SUNDIALS_VERSION_MAJOR == 4 && \
228  (SUNDIALS_VERSION_MINOR > 0 || (SUNDIALS_VERSION_MINOR == 0 && \
229  SUNDIALS_VERSION_PATCH >= 1 ))) // SUNDIALS_VERSION >= 4.0.1
230  cvode_mem =CVodeCreate(CV_ADAMS);
231 #else
232  cvode_mem =CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
233 #endif
234 #endif
235  if(!cvode_mem){
236  printf("cvode_mem initialization failed\n");
237  exit(1);
238  }
239  CVodeSetUserData(cvode_mem, udata);
240 
241  if(CVodeInit(cvode_mem, f, tret, y) != CV_SUCCESS){
242  printf("cvodeInit failed\n");
243  exit(1);
244  }
245 
246  if(CVodeSStolerances(cvode_mem, 1e-4, 1e-7)!= CV_SUCCESS){
247  printf("failed setting tolerances\n");
248  exit(1);
249  }
250 
251  r = pr = phi = tau = t = Et = Lt = hplus = hcross =0;
252 }
253 
255 { delete [] r;
256  delete [] pr;
257  delete [] phi;
258  delete [] tau;
259  delete [] t;
260  delete [] Et;
261  delete [] Lt;
262  delete [] hplus;
263  delete [] hcross;
264 }
265 
266 
267 double min(double x, double y)
268 { return x<y ? x : y;}
269 
270 bool geodesic::integrate(double D_t, int& N, double rmin, bool stop_alr)
271 { double dt = D_t/N;
272  this->r = new double[N+1];
273  this->pr = new double[N+1];
274  this->phi = new double[N+1];
275  this->tau = new double[N+1];
276  this->Et = new double[N+1];
277  this->Lt = new double[N+1];
278  this->t = new double[N+1];
279 
280  this->r[0] = ydata[0];
281  this->pr[0] = ydata[1];
282  this->phi[0] = ydata[2];
283  this->tau[0] = ydata[3];
284  this->Et[0] = ydata[4];
285  this->Lt[0] = ydata[5];
286  this->t[0] = tret;
287 
288  double r_stop = 0;
289  if(stop_alr) r_stop = 2*( 1+cos( 2*(acos(-min(udata[0] + udata[1]*this->Lt[0], 1))/3 )));
290  if(rmin>r_stop)r_stop = rmin;
291  int i=0;
292  while(i<N && r[i]>r_stop){
293  if(CVode(cvode_mem, tret+dt, y, &tret, CV_NORMAL)!=CV_SUCCESS)return false;
294  ++i;
295  this->r[i] = ydata[0];
296  this->pr[i] = ydata[1];
297  this->phi[i] = ydata[2];
298  this->tau[i] = ydata[3];
299  this->Et[i] = ydata[4];
300  this->Lt[i] = ydata[5];
301  this->t[i] = tret;
302  if(stop_alr){
303  r_stop = 2*( 1+cos( 2*(acos(-min(udata[0] + udata[1]*this->Lt[i], 1))/3 )));
304  if(rmin>r_stop)r_stop = rmin;
305  }
306  }
307  bool ret = (i==N);
308 
309  N=i+1;
310  hplus = new double[N];
311  hcross = new double[N];
312  double r_tt, r_ttt, phi_tt, phi_ttt;
313  double hp, hc;
314 
315  for(i = 0; i<N; ++i){
316  ydata[0] = this->r[i];
317  ydata[1] = this->pr[i];
318  ydata[2] = this->phi[i];
319  ydata[3] = this->tau[i];
320  ydata[4] = this->Et[i];
321  ydata[5] = this->Lt[i];
322  if(i==2000){
323  // ydata[0] = 7.256704e+00;
324  // ydata[1] = -4.276535e-02;
325  // ydata[2] = 5.112497e+01;
326  // ydata[3] = 1.728791e+03;
327  // ydata[4] = 9.438350e-01;
328  // ydata[5] = 3.180806e+00;
329  }
330  f_util(ydata, udata[0], udata[1]);
331  geo_higher_deriv(ydata[4], ydata[5], sqrt(a2), r_tt, r_ttt, phi_tt, phi_ttt);
332 
333  h_quad(::r,r_dot, r_tt, r_ttt, ::phi, w, phi_tt, phi_ttt, hp, hc);
334  hplus[i] = udata[1]*hp;
335  hcross[i] = udata[1]*hc;
336  }
337  return ret;
338 }
339 
340 
341 void printfutil(double* y)
342 { printf("%.6le %.6le %.6le %.6le %.6le %.6le\n", r, pr, phi, tau, r2, a2);
343  printf("%.6le %.6le %.6le %.6le %.6le %.6le\n", r3, Delta, R02, Q, A, B);
344  printf("%.6le %.6le %.6le %.6le %.6le\n",r_dot, w, pr_dot, Edot, Ldot);
345  double r_tt, r_ttt, phi_tt, phi_ttt;
346  double hp, hc;
347 
348  geo_higher_deriv(y[0], y[1], sqrt(a2), r_tt, r_ttt, phi_tt, phi_ttt);
349  printf("%.6le %.6le %.6le %.6le %.6le\n", sqrt(a2), r_tt, r_ttt, phi_tt, phi_ttt);
350  h_quad(::r,r_dot, r_tt, r_ttt, ::phi, w, phi_tt, phi_ttt, hp, hc);
351  printf("%.6le %.6le\n", hp, hc);
352 }
wavearray< double > t(hp.size())
double * Et
Definition: geodesics.hh:36
static const double C
Definition: GNGen.cc:28
static double r3
Definition: geodesics.cc:26
double M
Definition: DrawEBHH.C:13
static double B
Definition: geodesics.cc:26
static double r
Definition: geodesics.cc:26
void geo_higher_deriv(double E, double L, double a, double &r_dotdot, double &r_dotdotdot, double &wdot, double &wdotdot)
Definition: geodesics.cc:33
double min(double x, double y)
Definition: geodesics.cc:267
static double R02
Definition: geodesics.cc:26
static double Q
Definition: geodesics.cc:26
wavearray< double > a(hp.size())
cout<< endl;cout<< "ts size = "<< ts.size()<< " ts rate = "<< ts.rate()<< endl;tf.Forward(ts, wdm);int levels=tf.getLevel();cout<< "tf size = "<< tf.size()<< endl;double dF=tf.resolution();double dT=1./(2 *dF);cout<< "rate(hz) : "<< RATE<< "\ layers : "<< nLAYERS<< "\ dF(hz) : "<< dF<< "\ dT(ms) : "<< dT *1000.<< endl;int itime=TIME_PIXEL_INDEX;int ifreq=FREQ_PIXEL_INDEX;int index=(levels+1) *itime+ifreq;double time=itime *dT;double freq=(ifreq >0) ? ifreq *dF :dF/4;cout<< endl;cout<< "PIXEL TIME = "<< time<< " sec "<< endl;cout<< "PIXEL FREQ = "<< freq<< " Hz "<< endl;cout<< endl;wavearray< double > x
static double w
Definition: geodesics.cc:26
static double Ldot
Definition: geodesics.cc:26
geodesic(double r0, double phi0, double E0, double L0, int dir, double Jspin, double mu=0, double dt=1)
Definition: geodesics.cc:203
void * cvode_mem
Definition: geodesics.hh:42
wavearray< double > hp
Definition: DrawInspiral.C:43
double * hcross
Definition: geodesics.hh:36
int j
Definition: cwb_net.C:28
i drho i
bool integrate(double D_t, int &N, double rmin=0, bool stop_alr=false)
Definition: geodesics.cc:270
#define N
void reduced_quad_dot(double r, double r_t, double r_tt, double r_ttt, double phi, double phi_t, double phi_tt, double phi_ttt, double(&I_tt)[3][3], double(&I_ttt)[3][3])
Definition: geodesics.cc:79
double * t
Definition: geodesics.hh:36
double G
Definition: DrawEBHH.C:12
static double r2
Definition: geodesics.cc:26
static double Edot
Definition: geodesics.cc:26
double * hplus
Definition: geodesics.hh:36
static double pr_dot
Definition: geodesics.cc:26
double D[50000]
printf("total live time: non-zero lags = %10.1f \, liveTot)
void printfutil(double *y)
Definition: geodesics.cc:341
static double tau
Definition: geodesics.cc:26
realtype tret
Definition: geodesics.hh:40
static double A
Definition: geodesics.cc:26
double F
double * r
Definition: geodesics.hh:36
double e
double dt
double * phi
Definition: geodesics.hh:36
static double r_dot
Definition: geodesics.cc:26
double * Lt
Definition: geodesics.hh:36
static double phi
Definition: geodesics.cc:26
double fabs(const Complex &x)
Definition: numpy.cc:55
static double a2
Definition: geodesics.cc:26
N_Vector y
Definition: geodesics.hh:39
realtype udata[2]
Definition: geodesics.hh:40
void h_quad(double r, double r_t, double r_tt, double r_ttt, double phi, double phi_t, double phi_tt, double phi_ttt, double &hplus, double &hcross)
Definition: geodesics.cc:173
void f_util(double *y, double Jspin, double mu)
Definition: geodesics.cc:138
double * tau
Definition: geodesics.hh:36
int f(realtype t, N_Vector y, N_Vector ydot, void *ud)
Definition: geodesics.cc:187
static double pr
Definition: geodesics.cc:26
wavearray< double > y
Definition: Test10.C:31
static double Delta
Definition: geodesics.cc:26
exit(0)
realtype * ydata
Definition: geodesics.hh:41
double * pr
Definition: geodesics.hh:36
void quad_loss(double r, double r_t, double r_tt, double r_ttt, double phi, double phi_t, double phi_tt, double phi_ttt, double &E_dot, double &Lz_dot)
Definition: geodesics.cc:112