FLAG  1.0b1
Exact Fourier-Laguerre transform in spherical coordinates
flag_fbtest.c
Go to the documentation of this file.
1 // FLAG package
2 // Copyright (C) 2012
3 // Boris Leistedt & Jason McEwen
4 
5 #include "flag.h"
6 #include <math.h>
7 #include <stdlib.h>
8 #include <complex.h>
9 #include <fftw3.h>
10 #include <ssht.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <assert.h>
14 #include <time.h>
15 
16 #define MAX(a,b) ((a) > (b) ? (a) : (b))
17 
18 double maxerr_cplx(complex double *a, complex double *b, int size)
19 {
20  double value = 0;
21  int i;
22  for(i = 0; i<size; i++){
23  //printf("%6.5e %6.5e %6.5e\n", creal(a[i]-b[i]), cimag(a[i]-b[i]), cabs(a[i]-b[i]));
24  value = MAX( cabs( a[i]-b[i] ), value );
25  }
26  return value;
27 }
28 
29 double maxerr(double *a, double *b, int size)
30 {
31  double value = 0;
32  int i;
33  for(i = 0; i<size; i++){
34  value = MAX( abs( a[i]-b[i] ), value );
35  }
36  return value;
37 }
38 
39 double ran2_dp(int idum)
40 {
41  int IM1=2147483563,IM2=2147483399,IMM1=IM1-1,
42  IA1=40014,IA2=40692,IQ1=53668,IQ2=52774,IR1=12211,IR2=3791,
43  NTAB=32,NDIV=1+IMM1/NTAB;
44 
45  double AM=1./IM1,EPS=1.2e-7,RNMX=1.-EPS;
46  int j,k;
47  static int iv[32],iy,idum2 = 123456789;
48  // N.B. in C static variables are initialised to 0 by default.
49 
50  if (idum <= 0) {
51  idum= (-idum>1 ? -idum : 1); // max(-idum,1);
52  idum2=idum;
53  for(j=NTAB+8;j>=1;j--) {
54  k=idum/IQ1;
55  idum=IA1*(idum-k*IQ1)-k*IR1;
56  if (idum < 0) idum=idum+IM1;
57  if (j < NTAB) iv[j-1]=idum;
58  }
59  iy=iv[0];
60  }
61  k=idum/IQ1;
62  idum=IA1*(idum-k*IQ1)-k*IR1;
63  if (idum < 0) idum=idum+IM1;
64  k=idum2/IQ2;
65  idum2=IA2*(idum2-k*IQ2)-k*IR2;
66  if (idum2 < 0) idum2=idum2+IM2;
67  j=1+iy/NDIV;
68  iy=iv[j-1]-idum2;
69  iv[j-1]=idum;
70  if(iy < 1)iy=iy+IMM1;
71  return (AM*iy < RNMX ? AM*iy : RNMX); // min(AM*iy,RNMX);
72 
73 }
74 
75 void flag_random_f(complex double *f, int L, int N, int seed)
76 {
77  int i;
78  srand( time(NULL) );
79  for (i=0; i<flag_core_f_size_mw(L, N); i++){
80  f[i] = (2.0*ran2_dp(seed) - 1.0) + I * (2.0*ran2_dp(seed) - 1.0);
81  }
82 }
83 
84 void flag_random_flmn(complex double *flmn, int L, int N, int seed)
85 {
86  int i;
87  srand( time(NULL) );
88  for (i=0; i<flag_core_flmn_size(L, N); i++){
89  flmn[i] = (2.0*ran2_dp(seed) - 1.0) + I * (2.0*ran2_dp(seed) - 1.0);//rand()/795079784.0;
90  }
91 }
92 
93 void flag_random_flmn_real(complex double *flmn, int L, int N, int seed)
94 {
95  int en, el, m, msign, i, i_op, offset;
96  int flmsize = ssht_flm_size(L);
97 
98  for (en=0; en<N; en++) {
99  offset = en * flmsize;
100  for (el=0; el<L; el++) {
101  m = 0;
102  ssht_sampling_elm2ind(&i, el, m);
103  flmn[offset+i] = (2.0*ran2_dp(seed) - 1.0);
104  for (m=1; m<=el; m++) {
105  ssht_sampling_elm2ind(&i, el, m);
106  flmn[offset+i] = (2.0*ran2_dp(seed) - 1.0) + I * (2.0*ran2_dp(seed) - 1.0);
107  ssht_sampling_elm2ind(&i_op, el, -m);
108  msign = m & 1;
109  msign = 1 - msign - msign; // (-1)^m
110  flmn[offset+i_op] = msign * conj(flmn[offset+i]);
111  }
112  }
113  }
114 }
115 
116 void print_f(const complex double *f,int L, int N)
117 {
118  int mapsize = ssht_fr_size_mw(L);
119  int n, j;
120  for(n=0;n<N+1;n++){
121  printf("\n -- Layer %i -- \n", n);
122  for(j=0;j<mapsize;j++){
123  printf(" (%f,%f) ",creal(f[n*mapsize+j]),cimag(f[n*mapsize+j]));
124  }
125  }
126  printf("\n");
127 }
128 
129 void print_f_real(const double *f,int L, int N)
130 {
131  int mapsize = ssht_fr_size_mw(L);
132  int n, j;
133  for(n=0;n<N+1;n++){
134  printf("\n -- Layer %i -- \n", n);
135  for(j=0;j<mapsize;j++){
136  printf(" %f ",(f[n*mapsize+j]));
137  }
138  }
139  printf("\n");
140 }
141 
142 void print_flmn(const complex double *flmn,int L, int N)
143 {
144  int mapsize = ssht_flm_size(L);
145  int n, j;
146  for(n=0;n<N;n++){
147  printf("\n -- Layer %i -- \n", n);
148  for(j=0;j<mapsize;j++){
149  printf(" (%f,%f) ",creal(flmn[n*mapsize+j]),cimag(flmn[n*mapsize+j]));
150  }
151  }
152  printf("\n");
153 }
154 
155 void flag_sbesselslag_test_simple(int Nk, int N, double R, int seed)
156 {
157  clock_t time_start, time_end;
158  int n, i;
159 
160  //------- Parameters
161 
162  int ell = 0;
163  int Nnodes = N;
164  int Ninte = 20000;
165  double kmin = 0.01;
166  double kmax = 25.0;
167  double rmin = 0;
168  double rmax = 2000;
169 
170 
171  //------- Input function : f(r) = 1 / r^2
172 
173  double *f = (double*)calloc(Nnodes, sizeof(double));
174  double *nodes = (double*)calloc(Nnodes, sizeof(double));
175  double *weights = (double*)calloc(N, sizeof(double));
176  flag_spherlaguerre_sampling(nodes, weights, R, N);
177 
178  for (n=0; n<Nnodes; n++)
179  f[n] = pow(nodes[n], -2.0);
180 
181  double *fn = (double*)calloc(N, sizeof(double));
182  flag_spherlaguerre_analysis(fn, f, nodes, weights, N);
183  double tau = flag_spherlaguerre_tau(R, N);
184 
185  double *kvalues = (double*)calloc(Nk, sizeof(double));
186  for (n=0; n<Nk; n++)
187  kvalues[n] = kmin + (kmax - kmin)*(double)n/(double)Nk;
188 
189 
190  //------- FLK from analytical expression : f_0(k) = sqrt(pi/2) / k
191 
192  double *flk_anal = (double*)calloc(Nk, sizeof(double));
193  for (n=0; n<Nnodes; n++)
194  flk_anal[n] = 1.253314137 / kvalues[n];
195 
196 
197  //------- FLK from discrete integral (naive)
198 
199  double *flk_int = (double*)calloc(Nk, sizeof(double));
200  double r1, r2, f1, f2, h = (rmax - rmin) / Ninte;
201  for (n=0; n<Nnodes; n++){
202  flk_int[n] = 0.0;
203  for (i = 0; i < Ninte; i++){
204  r1 = rmin + i * h;
205  f1 = sin(r1) / r1;
206  r2 = rmin + (i + 1) * h;
207  f2 = sin(r2) / r2;
208  if(!isnan(f1) && !isinf(f1) && !isnan(f2) && !isinf(f2))
209  flk_int[n] += ((f1 + f2) * h) / (2.0 * kvalues[n]);
210  }
211  }
212 
213  //------- FLK from spherical Laguerre transform
214  printf("Running flag_spherlaguerre2spherbessel\n");
215  double *flk_slag = (double*)calloc(Nk, sizeof(double));
216  flag_spherlaguerre2spherbessel(flk_slag, fn, kvalues, Nk, N, ell, tau);
217  printf("Finished flag_spherlaguerre2spherbessel\n");
218 
219 
220  //-------
221 
222  for (n = 0; n < Nk; n++){
223  printf("> k = %f : integ = %f / analyt = %f / spherlag = %f\n", kvalues[n], flk_int[n], flk_anal[n], flk_slag[n]);
224  }
225  for (n = 0; n < Nk; n++){
226  printf("> k = %f : spherlag / analyt = %f \n", kvalues[n], flk_slag[n] / flk_anal[n]);
227  }
228 
229  free(f);
230  free(fn);
231  free(weights);
232  free(flk_slag);
233  free(flk_anal);
234  free(flk_int);
235 }
236 
237 
238 void flag_sbesselslag_test_jlK(double Kval, int ell, int Nk, int N, double R, int seed)
239 {
240 
241  // Input function : f(r) = j_ell(Kr)
242  double *f = (double*)calloc(N, sizeof(double));
243  double *nodes = (double*)calloc(N, sizeof(double));
244  double *weights = (double*)calloc(N, sizeof(double));
245  flag_spherlaguerre_sampling(nodes, weights, R, N);
246  int n;
247  for (n=0; n<N; n++)
248  f[n] = j_ell(Kval * nodes[n], ell);
249 
250  // SLAG analysis
251  double *fn = (double*)calloc(N, sizeof(double));
252  flag_spherlaguerre_analysis(fn, f, nodes, weights, N);
253  double tau = flag_spherlaguerre_tau(R, N);
254 
255  // Check the SLAG coefficients
256  double *fn_bis = (double*)calloc(N, sizeof(double));
257  flag_sbesselslag(fn_bis, ell, &Kval, 1, N, tau);
258  for (n = 0; n < N; n++){
259  fn_bis[n] = fn_bis[n] * pow(tau, -3.0);
260  printf("> n = %i : fn = %f <-> fn_bis = %f <-> ratio = %16.2e\n", n, fn[n], fn_bis[n], fn_bis[n]/fn[n]);
261  }
262 
263  // Approximate reconstruction
264  double *f_rec = (double*)calloc(N, sizeof(double));
265  flag_spherlaguerre_synthesis(f_rec, fn, nodes, N, N);
266 
267  // SBessel transform
268  double kmin = 0.05;
269  double kmax = 0.3;
270  double *kvalues = (double*)calloc(Nk, sizeof(double));
271  for (n=0; n<Nk; n++)
272  kvalues[n] = kmin + (kmax - kmin)*(double)n/(double)Nk;
273  double *flk = (double*)calloc(Nk, sizeof(double));
274  //flag_spherlaguerre2spherbessel(flk, fn, kvalues, Nk, N, ell, tau);
275 
276  for (n = 0; n < Nk; n++){
277  // printf("> k = %f : flk = %f\n", kvalues[n], flk[n]);
278  }
279 
280 
281  free(f);
282  free(f_rec);
283  free(fn);
284  free(fn_bis);
285  free(flk);
286 }
287 
288 
289 int main(int argc, char *argv[])
290 {
291  const int NREPEAT = 4;
292  const int NSCALE = 5;
293  const double Kval = 0.15;
294  const int ell = 3;
295  const int L = 4;
296  const int N = 64;
297  const int Nk = 40;
298  double tau = flag_spherlaguerre_tau(1.0, N);
299  const double R = 1.0 / tau;
300  const int seed = (int)(10000.0*(double)clock()/(double)CLOCKS_PER_SEC);
301 
302  printf("==========================================================\n");
303  printf("PARAMETERS : ");
304  printf(" L = %i N = %i R = %4.1f seed = %i\n", L, N, R, seed);
305  printf("----------------------------------------------------------\n");
306 
307  //flag_sbesselslag_test_jlK(Kval, ell, Nk, N, R, seed);
308  fflush(NULL);
309 
310  printf("----------------------------------------------------------\n");
311 
312  flag_sbesselslag_test_simple(Nk, N, R, seed);
313  fflush(NULL);
314 
315  printf("==========================================================\n");
316  printf(" L = %i N = %i R = %4.1f seed = %i\n", L, N, R, seed);
317 
318  return 0;
319 }
void flag_sbesselslag(double *sbesselslag, int ell, double *kvalues, int Nk, int N, double tau)
int flag_core_flmn_size(int L, int N)
Definition: flag_core.c:27
int main(int argc, char *argv[])
Definition: flag_fbtest.c:289
double maxerr_cplx(complex double *a, complex double *b, int size)
Definition: flag_fbtest.c:18
void flag_spherlaguerre2spherbessel(double *flk, const double *fn, double *kvalues, int Nk, int N, int ell, double tau)
#define MAX(a, b)
Definition: flag_fbtest.c:16
void flag_sbesselslag_test_jlK(double Kval, int ell, int Nk, int N, double R, int seed)
Definition: flag_fbtest.c:238
int ssht_flm_size(int L)
Definition: flag_core.c:20
void print_flmn(const complex double *flmn, int L, int N)
Definition: flag_fbtest.c:142
void flag_sbesselslag_test_simple(int Nk, int N, double R, int seed)
Definition: flag_fbtest.c:155
double flag_spherlaguerre_tau(double R, int N)
int ssht_fr_size_mw(int L)
Definition: flag_core.c:13
void flag_random_flmn(complex double *flmn, int L, int N, int seed)
Definition: flag_fbtest.c:84
double j_ell(double X, int l)
Definition: flag_core.c:206
void flag_random_flmn_real(complex double *flmn, int L, int N, int seed)
Definition: flag_fbtest.c:93
void flag_spherlaguerre_sampling(double *nodes, double *weights, double tau, int N)
double ran2_dp(int idum)
Definition: flag_fbtest.c:39
int flag_core_f_size_mw(int L, int N)
Definition: flag_core.c:34
double maxerr(double *a, double *b, int size)
Definition: flag_fbtest.c:29
void flag_random_f(complex double *f, int L, int N, int seed)
Definition: flag_fbtest.c:75
void print_f_real(const double *f, int L, int N)
Definition: flag_fbtest.c:129
void flag_spherlaguerre_synthesis(double *f, const double *fn, const double *nodes, int Nnodes, double tau, int N)
void flag_spherlaguerre_analysis(double *fn, const double *f, const double *nodes, const double *weights, double tau, int N)
void print_f(const complex double *f, int L, int N)
Definition: flag_fbtest.c:116