Search code examples
c++fftw

Changing the center of a gaussian using FFTW in C++


For a project I need to propagate a gaussian in real space using the Fourier transform of a gaussian centered at the origin using

What I want to calculate

Here is the latex code, since I can't include images yet

N(x | \mu, \sigma) = F^{-1}{F{ N(x |0, \sigma)} e^{-i\ 2\pi \mu\omega} \right},

where \omega is the frequency in Fourier space.

Now the problem I am having is I don't know how to calculate the frequency for some bin after doing the fft with fftw. Here is the code of what I am trying to do.

int main(){

  int N = 128; //Number of "pixels" in real space
  int N_fft = N/2 + 1;

  double *in, *result, *x;
  fftw_complex *out;
  fftw_plan fw, bw;

  in = (double*) fftw_malloc(sizeof(double) * N);
  x = (double*) malloc(sizeof(double) * N);

  out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N_fft);
  result = (double*) fftw_malloc(sizeof(double) * N);

  fw = fftw_plan_dft_r2c_1d(N, in, out, FFTW_ESTIMATE);
  bw = fftw_plan_dft_c2r_1d(N, out, result, FFTW_ESTIMATE);

  double min_x = -9.0, max_x = 9.0; //Limits in real space

  for (int i=0; i<N; i++){

    x[i] = min_x  + 2*max_x*i / (N - 1);
    in[i] = std::exp(-(x[i]) * (x[i]));
  }

  for (int i=0; i<N_fft; i++){
    out[i][0] = 0.0;
    out[i][1] = 0.0;
  }

  fftw_execute(fw);

  double w;

  fftw_complex z;
  double w_norm;

  for (int i=0; i<N_fft; i++){

    w = -2*M_PI*i / (max_x - min_x); //WHAT I DON'T KNOW

    // Calculating the product with the exponential for translating the gaussian
    z[0] = out[i][0]*std::cos(w) - out[i][1]*std::sin(w);
    z[1] = out[i][0]*std::sin(w) + out[i][0]*std::cos(w);

    out[i][0] = z[0];
    out[i][1] = z[1];
  }

  fftw_execute(bw);

  for (int i=0; i<N; i++){
        
    std::cout << x[i] << " " << result[i]/N << " " << std::exp(-x[i] * x[i]) << std::endl;
  }

  fftw_destroy_plan(fw);
  fftw_free(in);
  fftw_free(out);

  return 0;
}

For the moment I've tried using w-nth = -2*np.pi * 1/(max_x - min_x) * n, which worked in python, but for some reason it doesn't work in c++

Here is the result I am obtaining with c++

result

Here ref is the gaussian centered at 0, the one I obtaing should be centered at 1.0, but that's clearly is not happening.

Here is the latex code, since I can't include images yet

(Here is the latex code, since I can't include images yet)


Solution

  • Generally, the more obvious is the mistake, the more time it takes to find it.

    This was verified here.

    The mistake is simply here:

    z[1] = out[i][0]*std::sin(w) + out[i][0]*std::cos(w);
    

    It should be:

    z[1] = out[i][0]*std::sin(w) + out[i][1]*std::cos(w);
    

    Besides, I don't know why you didn't use N__ft = N, but I guess it is related the way fftw works.

    enter image description here