Confusion testing fftw3 - poisson equation 2d test

Posted by user3699736 on Stack Overflow See other posts from Stack Overflow or by user3699736
Published on 2014-06-02T15:23:28Z Indexed on 2014/06/02 15:24 UTC
Read the original article Hit count: 301

Filed under:
|

I am having trouble explaining/understanding the following phenomenon: To test fftw3 i am using the 2d poisson test case:

laplacian(f(x,y)) = - g(x,y) with periodic boundary conditions.

After applying the fourier transform to the equation we obtain : F(kx,ky) = G(kx,ky) /(kx² + ky²) (1)

if i take g(x,y) = sin (x) + sin(y) , (x,y) \in [0,2 \pi] i have immediately f(x,y) = g(x,y)

which is what i am trying to obtain with the fft :

i compute G from g with a forward Fourier transform

From this i can compute the Fourier transform of f with (1).

Finally, i compute f with the backward Fourier transform (without forgetting to normalize by 1/(nx*ny)).

In practice, the results are pretty bad?

(For instance, the amplitude for N = 256 is twice the amplitude obtained with N = 512)

Even worse, if i try g(x,y) = sin(x)*sin(y) , the curve has not even the same form of the solution.

(note that i must change the equation; i divide by two the laplacian in this case : (1) becomes F(kx,ky) = 2*G(kx,ky)/(kx²+ky²)

Here is the code:

/*
* fftw test -- double precision
*/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fftw3.h>
using namespace std;

int main()
{
 int N = 128;
 int i, j ;
 double pi = 3.14159265359;
 double *X, *Y  ; 
 X = (double*) malloc(N*sizeof(double));
   Y = (double*) malloc(N*sizeof(double));
   fftw_complex  *out1, *in2, *out2, *in1;
   fftw_plan     p1, p2;
   double L  = 2.*pi;
   double dx = L/((N - 1)*1.0);

   in1 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );
   out2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );
   out1 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );
   in2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*(N*N) );

   p1 = fftw_plan_dft_2d(N, N, in1, out1, FFTW_FORWARD,FFTW_MEASURE ); 
   p2 = fftw_plan_dft_2d(N, N, in2, out2, FFTW_BACKWARD,FFTW_MEASURE);

   for(i = 0; i < N; i++){
       X[i] = -pi + (i*1.0)*2.*pi/((N - 1)*1.0) ;
       for(j = 0; j < N; j++){
    Y[j] = -pi + (j*1.0)*2.*pi/((N - 1)*1.0) ;
        in1[i*N + j][0] = sin(X[i]) + sin(Y[j]) ; // row major ordering
        //in1[i*N + j][0] = sin(X[i]) * sin(Y[j]) ; // 2nd test case
        in1[i*N + j][1] = 0 ; 
       }
   }

     fftw_execute(p1); // FFT forward 

     for ( i = 0; i < N; i++){   // f = g / ( kx² + ky² )  
       for( j = 0; j < N; j++){
         in2[i*N + j][0] = out1[i*N + j][0]/ (i*i+j*j+1e-16); 
         in2[i*N + j][1] = out1[i*N + j][1]/ (i*i+j*j+1e-16); 
         //in2[i*N + j][0] = 2*out1[i*N + j][0]/ (i*i+j*j+1e-16); // 2nd test case
         //in2[i*N + j][1] = 2*out1[i*N + j][1]/ (i*i+j*j+1e-16); 
       }
     }

     fftw_execute(p2); //FFT backward

     // checking the results computed

     double erl1 = 0.;
     for ( i = 0; i < N; i++) {
       for( j = 0; j < N; j++){
         erl1 += fabs( in1[i*N + j][0] -  out2[i*N + j][0]/N/N )*dx*dx; 
         cout<< i <<" "<< j<<" "<< sin(X[i])+sin(Y[j])<<" "<<  out2[i*N+j][0]/N/N <<" "<< endl; // > output
        }
      }
      cout<< erl1 << endl ;  // L1 error

      fftw_destroy_plan(p1);
      fftw_destroy_plan(p2);
      fftw_free(out1);
      fftw_free(out2);
      fftw_free(in1);
      fftw_free(in2);

      return 0;
    }

I can't find any (more) mistakes in my code (i installed the fftw3 library last week) and i don't see a problem with the maths either but i don't think it's the fft's fault. Hence my predicament. I am all out of ideas and all out of google as well.

Any help solving this puzzle would be greatly appreciated.

note :

compiling : g++ test.cpp -lfftw3 -lm

executing : ./a.out > output

and i use gnuplot in order to plot the curves : (in gnuplot ) splot "output" u 1:2:4 ( for the computed solution )

© Stack Overflow or respective owner

Related posts about c++

Related posts about fftw