Guest User

Untitled

a guest
Jun 26th, 2013
269
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.70 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include <time.h> // for RNG seed
  4. #include <fftw3.h> // for Fourier Transforms
  5. #include <gsl/gsl_rng.h> // for random number generation
  6.  
  7. #define M_PI 3.14159265358979323846264338327
  8.  
  9. void example_FFTW_inplace();
  10. void example_FFTW();
  11. void example_FFTW_GURU();
  12. void example_FFTW_2D();
  13.  
  14. void initialiseData(double *, int, int, int);
  15. void printDataReal(double * , int , int , int );
  16. void printDataFourier(double * , int , int , int );
  17.  
  18. int seed;
  19.  
  20. enum {FALSE, TRUE};
  21.  
  22.  
  23. int main(void)
  24. {
  25. seed = (int) time(NULL);
  26.  
  27. example_FFTW_2D();
  28.  
  29. return 0;
  30. }
  31.  
  32.  
  33.  
  34.  
  35.  
  36. void example_FFTW_2D()
  37. {
  38.  
  39. printf ("\n\n");
  40. printf ("==============================================================\n");
  41. printf ("Example of taking Fourier transforms with FFTW (out of place):\n");
  42. printf ("==============================================================\n");
  43.  
  44.  
  45. // array dimensions
  46. int Nx = 8; int Ny = 8; int Nz = 3;
  47.  
  48. const int dims = Nx * Ny * Nz;
  49.  
  50. // allocate memory
  51. double *input = fftw_alloc_real(dims); // input data (pre Fourier transform)
  52. double *input2 = fftw_alloc_real(dims); // store copy of input data so we can compute accuracy
  53.  
  54.  
  55. const int outdims = Nx * (Ny/2 + 1) * Nz;
  56. fftw_complex *output = fftw_alloc_complex(outdims); // we want to perform the transform out of place (so seperate array for output)
  57.  
  58. #define input(i,j,k) ( input[(k) + Nz * ((j) + Ny * (i))] )
  59. #define input2(i,j,k) ( input2[(k) + Nz * ((j) + Ny * (i))] )
  60.  
  61.  
  62. ////////////////////////////////////////////////////
  63. // setup "plans" for forward and backward transforms
  64. const int rank = 2; const int howmany = Nz;
  65. const int istride = Nz; const int ostride = Nz;
  66. const int idist = 1; const int odist = 1;
  67. int n[] = {Nx, Ny};
  68. int *inembed = NULL, *onembed = NULL;
  69.  
  70.  
  71. fftw_plan fp = fftw_plan_many_dft_r2c(rank, n, howmany,
  72. input, inembed, istride, idist,
  73. output, onembed, ostride, odist,
  74. FFTW_PATIENT);
  75.  
  76. fftw_plan bp = fftw_plan_many_dft_c2r(rank, n, howmany,
  77. output, onembed, ostride, odist,
  78. input, inembed, istride, idist,
  79. FFTW_PATIENT);
  80.  
  81.  
  82.  
  83. ///////////////////////////////////////////
  84. // initialise the data (important that this
  85. // is done after initialisation)
  86. initialiseData(input, Nx, Ny, Nz);
  87. initialiseData(input2, Nx, Ny, Nz);
  88.  
  89. // and print for record
  90. printDataReal(input, Nx, Ny, Nz);
  91.  
  92.  
  93. /////////////////////////////
  94. // take the forward transform
  95. fftw_execute(fp); printf ("FFT complete!\n");
  96.  
  97. // and print for record
  98. printDataFourier((double *) output, Nx, Ny, Nz);
  99.  
  100.  
  101.  
  102.  
  103. /////////////////////////////
  104. // take the backward transform
  105. fftw_execute(bp); printf ("IFFT complete!\n");
  106.  
  107. double maxError = 0.0;
  108.  
  109. for (int i = 0; i < Nx; ++i)
  110. for (int j = 0; j < Ny; ++j)
  111. for (int d = 0; d < Nz; ++d)
  112. {
  113. // remember that FFTW doesn't normalise
  114. input(i,j,d) /= (double) (Nx*Ny);
  115.  
  116. const double error = fabs(input2(i,j,d) - input(i,j,d));
  117. if (error > maxError) maxError = error;
  118. }
  119.  
  120. printDataReal(input, Nx, Ny, Nz);
  121.  
  122. printf ("maximum error after 1 cycle: %.4g\n", maxError);
  123.  
  124. fftw_free(input);
  125. fftw_free(input2);
  126. fftw_free(output);
  127.  
  128.  
  129. // clean up FTTW stuff
  130. fftw_destroy_plan(fp);
  131. fftw_destroy_plan(bp);
  132.  
  133. fftw_cleanup();
  134. }
  135.  
  136.  
  137.  
  138.  
  139.  
  140. void initialiseData(double * input, int Nx, int Ny, int Nz)
  141. {
  142. // initialise random number generator with Mersenne Twister
  143. gsl_rng * rng = gsl_rng_alloc ( gsl_rng_mt19937 );
  144. // change this to try a different seed
  145. gsl_rng_set(rng, seed);
  146.  
  147.  
  148. // setup input data
  149. for (int k = 0; k < Nz; ++k )
  150. for (int i = 0; i < Nx; ++i)
  151. for (int j = 0; j < Ny; ++j)
  152. {
  153.  
  154. if (k == 0)
  155. input(i,j,k) = gsl_rng_uniform(rng);
  156. else
  157. {
  158. const double x = (double) i / (double) Nx;
  159. const double y = (double) j / (double) Ny;
  160.  
  161. input(i,j,k) = cos(2* M_PI * y);
  162. input(i,j,k) += cos(4* M_PI * x);
  163.  
  164. input(i,j,k) *= (k + 1);
  165. }
  166.  
  167. }
  168.  
  169. gsl_rng_free(rng);
  170. }
  171.  
  172. void printDataReal(double * dataToPrint, int Nx, int Ny, int Nz)
  173. {
  174.  
  175. printf ("Data in real space\n");
  176. #define dataToPrint(i,j,k) ( dataToPrint[(k) + Nz * ((j) + Ny * (i))] )
  177.  
  178. // print input data
  179. for (int k = 0; k < Nz; ++k )
  180. {
  181. printf ("\nk = %d\n", k);
  182.  
  183. for (int i = 0; i < Nx; ++i)
  184. {
  185. for (int j = 0; j < Ny; ++j)
  186. printf ("i[%3d][%d][%d] = %.3f\t", i, j, k, dataToPrint(i,j,k));
  187.  
  188. printf ("\n");
  189. }
  190. }
  191.  
  192. printf ("\n\n\n");
  193. }
  194.  
  195.  
  196. void printDataFourier(double * dataToPrint, int Nx, int Ny, int Nz)
  197. {
  198.  
  199. printf ("Data in Fourier space\n");
  200.  
  201. #define dataToPrintRe(qx,qy,k) ( dataToPrint[2*((k) + Nz * ((qy) + (Ny/2 + 1) * (qx))) ] )
  202. #define dataToPrintIm(qx,qy,k) ( dataToPrint[2*((k) + Nz * ((qy) + (Ny/2 + 1) * (qx))) + 1] )
  203.  
  204. // print input data
  205. for (int k = 0; k < Nz; ++k )
  206. {
  207. printf ("\nk = %d\n", k);
  208.  
  209. for (int qx = 0; qx <= Nx/2; ++qx)
  210. {
  211. for (int qy = 0; qy <= Ny/2; ++qy)
  212. printf ("o[%3d][%d][%d] = %.3f + %.3fi\t", qx, qy, k, dataToPrintRe(qx, qy, k), dataToPrintIm(qx, qy, k));
  213.  
  214. printf ("\n");
  215. }
  216. }
  217.  
  218. printf ("\n\n\n");
  219. }
Advertisement
Add Comment
Please, Sign In to add comment