LALInspiral 5.0.3.1-eeff03c
LALNewtonianMultipole.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2010 Craig Robinson
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 2 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 with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20
21/**
22 * \author Craig Robinson
23 *
24 * Functions to construct the Newtonian multipolar waveform as given
25 * by Damour et al, Phys.Rev.D79:064004,2009.
26 *
27 * In addition to the function used to do this,
28 * XLALCalculateNewtonianMultipole(), this file also contains a function
29 * for calculating the standard scalar spherical harmonics Ylm.
30 */
31
32#include <math.h>
33#include <lal/LALInspiral.h>
34#include <lal/LALEOBNRv2Waveform.h>
35
36#include <gsl/gsl_sf_gamma.h>
37
38
39static REAL8
41 const int m
42 );
43
44static int
46 INT4 l,
47 INT4 m,
48 REAL8 phi);
49
50static int
52 COMPLEX16 *prefix,
53 const REAL8 m1,
54 const REAL8 m2,
55 const INT4 l,
56 const INT4 m );
57
58
61 const REAL8 m1,
62 const REAL8 m2 )
63{
64
65 INT4 l, m;
66
67 memset( prefix, 0, sizeof( NewtonMultipolePrefixes ) );
68
69 for ( l = 2; l <= LALEOB_MAX_MULTIPOLE; l++ )
70 {
71 for ( m = 1; m <= l; m++ )
72 {
73 CalculateThisMultipolePrefix( &(prefix->values[l][m]), m1, m2, l, m );
74 }
75 }
76 return XLAL_SUCCESS;
77}
78
79
80int
82 COMPLEX16 *multipole,
83 REAL8 x,
84 REAL8 r,
85 REAL8 phi,
86 UINT4 l,
87 INT4 m,
89 )
90{
91
92 INT4 xlalStatus;
93
95
96 INT4 epsilon = (l + m) % 2;
97
98 y = 0.0;
99
100 /* Calculate the necessary Ylm */
101 xlalStatus = XLALScalarSphHarmThetaPiBy2( &y, l - epsilon, - m, phi );
102 if (xlalStatus != XLAL_SUCCESS )
103 {
105 }
106
107
108 if ( (l == 4 && m == 4) || ( l == 2 && m == 1 ) )
109 {
110 *multipole = params->prefixes->values[l][m] * (pow( x, (REAL8)(l+epsilon)/2.0 - 1.0)/r);
111 }
112 else
113 {
114 *multipole = params->prefixes->values[l][m] * (pow( x, (REAL8)(l+epsilon)/2.0));
115 }
116 *multipole = *multipole * y;
117
118 return XLAL_SUCCESS;
119}
120
121
122/* In the calculation of the Newtonian multipole, we only use
123 * the spherical harmonic with theta set to pi/2. Since this
124 * is always the case, we can use this information to use a
125 * faster version of the spherical harmonic code
126 */
127
128static int
130 INT4 l,
131 INT4 m,
132 REAL8 phi)
133{
134
135 REAL8 legendre;
136 INT4 absM = abs( m );
137
138 if ( l < 0 || absM > (INT4) l )
139 {
141 }
142
143 /* For some reason GSL will not take negative m */
144 /* We will have to use the relation between sph harmonics of +ve and -ve m */
145 legendre = XLALAssociatedLegendreXIsZero( l, absM );
146 if ( XLAL_IS_REAL8_FAIL_NAN( legendre ))
147 {
149 }
150
151 /* Compute the values for the spherical harmonic */
152 *y = crect( legendre * cos(m * phi), legendre * sin(m * phi) );
153
154 /* If m is negative, perform some jiggery-pokery */
155 if ( m < 0 && absM % 2 == 1 )
156 {
157 *y = - (*y);
158 }
159
160 return XLAL_SUCCESS;
161}
162
163
164
165static REAL8
167 const int m )
168{
169
170 REAL8 legendre;
171
172 if ( l < 0 )
173 {
174 XLALPrintError( "l cannot be < 0\n" );
176 }
177
178 if ( m < 0 || m > l )
179 {
180 XLALPrintError( "Invalid value of m!\n" );
182 }
183
184 /* we will switch on the values of m and n */
185 switch ( l )
186 {
187 case 1:
188 switch ( m )
189 {
190 case 1:
191 legendre = - 1.;
192 break;
193 default:
195 }
196 break;
197 case 2:
198 switch ( m )
199 {
200 case 2:
201 legendre = 3.;
202 break;
203 case 1:
204 legendre = 0.;
205 break;
206 default:
208 }
209 break;
210 case 3:
211 switch ( m )
212 {
213 case 3:
214 legendre = -15.;
215 break;
216 case 2:
217 legendre = 0.;
218 break;
219 case 1:
220 legendre = 1.5;
221 break;
222 default:
224 }
225 break;
226 case 4:
227 switch ( m )
228 {
229 case 4:
230 legendre = 105.;
231 break;
232 case 3:
233 legendre = 0.;
234 break;
235 case 2:
236 legendre = - 7.5;
237 break;
238 case 1:
239 legendre = 0;
240 break;
241 default:
243 }
244 break;
245 case 5:
246 switch ( m )
247 {
248 case 5:
249 legendre = - 945.;
250 break;
251 case 4:
252 legendre = 0.;
253 break;
254 case 3:
255 legendre = 52.5;
256 break;
257 case 2:
258 legendre = 0;
259 break;
260 case 1:
261 legendre = - 1.875;
262 break;
263 default:
265 }
266 break;
267 case 6:
268 switch ( m )
269 {
270 case 6:
271 legendre = 10395.;
272 break;
273 case 5:
274 legendre = 0.;
275 break;
276 case 4:
277 legendre = - 472.5;
278 break;
279 case 3:
280 legendre = 0;
281 break;
282 case 2:
283 legendre = 13.125;
284 break;
285 case 1:
286 legendre = 0;
287 break;
288 default:
290 }
291 break;
292 case 7:
293 switch ( m )
294 {
295 case 7:
296 legendre = - 135135.;
297 break;
298 case 6:
299 legendre = 0.;
300 break;
301 case 5:
302 legendre = 5197.5;
303 break;
304 case 4:
305 legendre = 0.;
306 break;
307 case 3:
308 legendre = - 118.125;
309 break;
310 case 2:
311 legendre = 0.;
312 break;
313 case 1:
314 legendre = 2.1875;
315 break;
316 default:
318 }
319 break;
320 case 8:
321 switch ( m )
322 {
323 case 8:
324 legendre = 2027025.;
325 break;
326 case 7:
327 legendre = 0.;
328 break;
329 case 6:
330 legendre = - 67567.5;
331 break;
332 case 5:
333 legendre = 0.;
334 break;
335 case 4:
336 legendre = 1299.375;
337 break;
338 case 3:
339 legendre = 0.;
340 break;
341 case 2:
342 legendre = - 19.6875;
343 break;
344 case 1:
345 legendre = 0.;
346 break;
347 default:
349 }
350 break;
351 default:
352 XLALPrintError( "Unsupported (l, m): %d, %d\n", l, m );
354 }
355
356 legendre *= sqrt( (REAL8)(2*l+1)*gsl_sf_fact( l-m ) / (4.*LAL_PI*gsl_sf_fact(l+m)));
357
358 return legendre;
359}
360
361static int
363 COMPLEX16 *prefix,
364 const REAL8 m1,
365 const REAL8 m2,
366 const INT4 l,
367 const INT4 m )
368
369{
370
371
372 COMPLEX16 n;
373 REAL8 c;
374
375 REAL8 x1, x2; /* Scaled versions of component masses */
376
377 REAL8 mult1, mult2;
378
379 REAL8 totalMass;
380 REAL8 eta;
381
382 INT4 epsilon;
383 INT4 sign; /* To give the sign of some additive terms */
384
385
386 n = 0.0;
387
388 totalMass = m1 + m2;
389
390 epsilon = ( l + m ) % 2;
391
392 x1 = m1 / totalMass;
393 x2 = m2 / totalMass;
394
395 eta = m1*m2/(totalMass*totalMass);
396
397 if ( abs( m % 2 ) == 0 )
398 {
399 sign = 1;
400 }
401 else
402 {
403 sign = -1;
404 }
405
406 c = pow( x2, l + epsilon - 1 ) + sign * pow(x1, l + epsilon - 1 );
407
408 /* Dependent on the value of epsilon, we get different n */
409 if ( epsilon == 0 )
410 {
411
412 n = crect( 0, m );
413 n = cpow( n, (REAL8)l );
414
415 mult1 = 8.0 * LAL_PI / gsl_sf_doublefact(2u*l + 1u);
416 mult2 = (REAL8)((l+1) * (l+2)) / (REAL8)(l * ((INT4)l - 1));
417 mult2 = sqrt(mult2);
418
419 n = n * mult1;
420 n = n * mult2;
421 }
422 else if ( epsilon == 1 )
423 {
424
425 n = crect( 0, m );
426 n = cpow( n, (REAL8)l );
427 n = -n;
428
429 mult1 = 16.*LAL_PI / gsl_sf_doublefact( 2u*l + 1u );
430
431 mult2 = (REAL8)( (2*l + 1) * (l+2) * (l*l - m*m) );
432 mult2 /= (REAL8)( (2*l - 1) * (l+1) * l * (l-1) );
433 mult2 = sqrt(mult2);
434
435 n = n * crect( 0, mult1 );
436 n = n * mult2;
437 }
438 else
439 {
440 XLALPrintError( "Epsilon must be 0 or 1.\n");
442 }
443
444 *prefix = n * ( eta * c );
445
446 return XLAL_SUCCESS;
447}
#define LALEOB_MAX_MULTIPOLE
static int CalculateThisMultipolePrefix(COMPLEX16 *prefix, const REAL8 m1, const REAL8 m2, const INT4 l, const INT4 m)
static REAL8 XLALAssociatedLegendreXIsZero(const int l, const int m)
static int XLALScalarSphHarmThetaPiBy2(COMPLEX16 *y, INT4 l, INT4 m, REAL8 phi)
int l
#define LAL_PI
#define crect(re, im)
double complex COMPLEX16
double REAL8
uint32_t UINT4
int32_t INT4
int XLALCalculateNewtonianMultipole(COMPLEX16 *multipole, REAL8 x, REAL8 r, REAL8 phi, UINT4 l, INT4 m, EOBParams *params)
int XLALComputeNewtonMultipolePrefixes(NewtonMultipolePrefixes *prefix, const REAL8 m1, const REAL8 m2)
static const INT4 r
static const INT4 m
#define XLAL_ERROR_REAL8(...)
#define XLAL_ERROR(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_IS_REAL8_FAIL_NAN(val)
XLAL_SUCCESS
XLAL_EFUNC
XLAL_EINVAL
list y
c
int n
x
COMPLEX16 values[LALEOB_MAX_MULTIPOLE+1][LALEOB_MAX_MULTIPOLE+1]