K
Kazik
Hello,
I'm using FFTW3 library to compute Fourier transform of my data.
Yes, I have read FFTW3 manual. Still I have (probably humiliating)
question/problem.
Firstly, I should probably mention that I am not very familiar with
what you probably call "signal processing". I look at Fourier
transform more from mathematical or physical point of view. So, if I
have a function defined on some interval [-z_max, z_max] (position
space or time domain, whatever), it's natural for me that after
computation of Fourier transform I will have function on interval [-
k_z_max, k_z_max] (momentum space or frequency domain, whatever). Not
from 0 to k_z_max and then suddenly from -k_z_max to 0. Nevertheless,
I thought I have understood the ordering of FFTW. Until I wrote my
code.
So, to make my story short. I would like to compute FFT of one
dimensional array.
Firstly I've defined a grid:
########################################
/* Position grid-z-axis: */
double* z = new double[N];
double zmax = 30;
double dz = (2*zmax)/N;
for(int i=0; i<N; i++){
z = -zmax+(i*dz);
}
/* Momentum grid-z-axis: */
double* pz = new double[N];
double dpz = M_PI/zmax;
double pzmax = (N/2)*dpz;
for(int i=0; i<=N/2; i++){
pz = i*dpz;
}
for(int i=1; i<N/2; i++){
pz[i+N/2] = -pzmax+i*dpz;
}
########################################
Then, arrays and plans:
########################################
fftw_complex *psiX = (fftw_complex*) fftw_malloc(sizeof
(fftw_complex) * N);
fftw_complex *psiK = (fftw_complex*) fftw_malloc(sizeof
(fftw_complex) * N);
fftw_complex *psiX2 = (fftw_complex*) fftw_malloc(sizeof
(fftw_complex) * N);
fftw_plan XtoK_Plan = fftw_plan_dft_1d(N, psiX, psiK, FFTW_FORWARD,
FFTW_PATIENT);
fftw_plan KtoX2_Plan = fftw_plan_dft_1d(N, psiK, psiX2,
FFTW_BACKWARD, FFTW_PATIENT);
########################################
Subsequently I defined two routines:
########################################
/*------------------------------------------------------
* Routine FFTW_1d_Forward computes one-dimensional
* Fourier transform of input array ArrayX (X refers to
* position space). Output: ArrayXintoK (K refers to
* momentum space).
------------------------------------------------------*/
void FFTW_1d_Forward(fftw_complex* ArrayX, fftw_complex* ArrayXintoK,
fftw_plan XtoK_Plan, const double dz, const int N){
for(int i=0; i<N; i++){
ArrayX[0] = ArrayX[0];
ArrayX[1] = ArrayX[1];
}
fftw_execute(XtoK_Plan);
for(int i=0; i<N; i++){
ArrayXintoK[0] *= (dz*pow(-1,i));
ArrayXintoK[1] *= (dz*pow(-1,i));
}
}
/*------------------------------------------------------
* Routine FFTW_1d_Backward computes one-dimensional
* inverse Fourier transform of input array ArrayK (K
* refers to momentum space). Output: ArrayKintoX (X
* refers to position space).
------------------------------------------------------*/
void FFTW_1d_Backward(fftw_complex* ArrayK, fftw_complex* ArrayKintoX,
fftw_plan KtoX_Plan, const double dz, const int N){
for(int i=0; i<N; i++){
ArrayK[0] = ArrayK[0]*pow(-1,i);
ArrayK[1] = ArrayK[1]*pow(-1,i);
}
fftw_execute(KtoX_Plan);
for(int i=0; i<N; i++){
ArrayKintoX[0] /= (1.*N*dz);
ArrayKintoX[1] /= (1.*N*dz);
}
}
########################################
which I used in main() like that:
########################################
FFTW_1d_Forward(psiX, psiK, XtoK_Plan, dz, N);
FFTW_1d_Backward(psiK, psiX2, KtoX2_Plan, dz, N);
########################################
The multipilcations by "dz" and "N*dz" in routines FFTW_1d_Forward and
FFTW_1d_Backward are due to the normalisation of the FFT. The
multiplications by pow(-1,i) follow my experience with Numerical
Recipes (NR) code for FFT. In principle this "-1"s should govern that
the final result is ordered like [-k_z_max, ..., 0, ..., k_z_max], as
far as I understand what is going on.
The problem is that the result of the above code is wrong [in order to
learn FFTW I compare every FFTW-result with NR-result, and this NR-
code gives the correct result for 100%]. In particular I've checked
such a function:
########################################
for(int i=0; i<N; i++){
psiX[0] = exp(-z*z)*(z + 3.*z*z-7.*z*z*z
)*sin(z);
psiX[1] = 0.;
}
########################################
I have chosen such an ugly example on purpose. The nice examples (e.g.
Gaussians) are often misleading.
What I've checked/compared wit NR-result are:
1) FFTW_BACKWARD[ FFTW_FORWARD[ psiX ] ] = psiX
So, this is ok, as it should be.
2) The Plancherel theorem (the conservation of a norm of psiX and
FFTW_FORWARD[ psiX ]) also works perfectly
3) The real part of the FFT_FORWARD[psiX] is exactly the same as I
obtain form NR-program
4) !!! HERE COMES THE PROBLEM !!! :
the imaginary part of FFT_FORWARD[psiX] is mirror-reflected with
respect to "y"-axis (of course I know this by comaprison with NR-
result). So, if only I swapped the "right" and "left" part of the
imaginary part of the array FFT_FORWARD[psiX] (it's called psiK in the
code above), everything would be perfect. HOWEVER, if I did that,
point 1) crashes, i.e. I don't get identity when subsequently apply
FORWARD and BACKWARD.
I feel really lost with this. I've tried "experimentally" many other
ways of ordering, but every time some of the 4 points I mentioned
(actually points 1, 3 and 4) crashes. So, in general the result looks
"not-so-bad" (youi can definitely see that something works) but there
is always some mirror-reflection with respect to "y"-axis or the
result looks like it was globally multiplied by -1, and so on.
I would really appreciate any hints and/or advices. I spent all day
writing the code above but it seems that I failed.
Thank you in advance.
I'm using FFTW3 library to compute Fourier transform of my data.
Yes, I have read FFTW3 manual. Still I have (probably humiliating)
question/problem.
Firstly, I should probably mention that I am not very familiar with
what you probably call "signal processing". I look at Fourier
transform more from mathematical or physical point of view. So, if I
have a function defined on some interval [-z_max, z_max] (position
space or time domain, whatever), it's natural for me that after
computation of Fourier transform I will have function on interval [-
k_z_max, k_z_max] (momentum space or frequency domain, whatever). Not
from 0 to k_z_max and then suddenly from -k_z_max to 0. Nevertheless,
I thought I have understood the ordering of FFTW. Until I wrote my
code.
So, to make my story short. I would like to compute FFT of one
dimensional array.
Firstly I've defined a grid:
########################################
/* Position grid-z-axis: */
double* z = new double[N];
double zmax = 30;
double dz = (2*zmax)/N;
for(int i=0; i<N; i++){
z = -zmax+(i*dz);
}
/* Momentum grid-z-axis: */
double* pz = new double[N];
double dpz = M_PI/zmax;
double pzmax = (N/2)*dpz;
for(int i=0; i<=N/2; i++){
pz = i*dpz;
}
for(int i=1; i<N/2; i++){
pz[i+N/2] = -pzmax+i*dpz;
}
########################################
Then, arrays and plans:
########################################
fftw_complex *psiX = (fftw_complex*) fftw_malloc(sizeof
(fftw_complex) * N);
fftw_complex *psiK = (fftw_complex*) fftw_malloc(sizeof
(fftw_complex) * N);
fftw_complex *psiX2 = (fftw_complex*) fftw_malloc(sizeof
(fftw_complex) * N);
fftw_plan XtoK_Plan = fftw_plan_dft_1d(N, psiX, psiK, FFTW_FORWARD,
FFTW_PATIENT);
fftw_plan KtoX2_Plan = fftw_plan_dft_1d(N, psiK, psiX2,
FFTW_BACKWARD, FFTW_PATIENT);
########################################
Subsequently I defined two routines:
########################################
/*------------------------------------------------------
* Routine FFTW_1d_Forward computes one-dimensional
* Fourier transform of input array ArrayX (X refers to
* position space). Output: ArrayXintoK (K refers to
* momentum space).
------------------------------------------------------*/
void FFTW_1d_Forward(fftw_complex* ArrayX, fftw_complex* ArrayXintoK,
fftw_plan XtoK_Plan, const double dz, const int N){
for(int i=0; i<N; i++){
ArrayX[0] = ArrayX[0];
ArrayX[1] = ArrayX[1];
}
fftw_execute(XtoK_Plan);
for(int i=0; i<N; i++){
ArrayXintoK[0] *= (dz*pow(-1,i));
ArrayXintoK[1] *= (dz*pow(-1,i));
}
}
/*------------------------------------------------------
* Routine FFTW_1d_Backward computes one-dimensional
* inverse Fourier transform of input array ArrayK (K
* refers to momentum space). Output: ArrayKintoX (X
* refers to position space).
------------------------------------------------------*/
void FFTW_1d_Backward(fftw_complex* ArrayK, fftw_complex* ArrayKintoX,
fftw_plan KtoX_Plan, const double dz, const int N){
for(int i=0; i<N; i++){
ArrayK[0] = ArrayK[0]*pow(-1,i);
ArrayK[1] = ArrayK[1]*pow(-1,i);
}
fftw_execute(KtoX_Plan);
for(int i=0; i<N; i++){
ArrayKintoX[0] /= (1.*N*dz);
ArrayKintoX[1] /= (1.*N*dz);
}
}
########################################
which I used in main() like that:
########################################
FFTW_1d_Forward(psiX, psiK, XtoK_Plan, dz, N);
FFTW_1d_Backward(psiK, psiX2, KtoX2_Plan, dz, N);
########################################
The multipilcations by "dz" and "N*dz" in routines FFTW_1d_Forward and
FFTW_1d_Backward are due to the normalisation of the FFT. The
multiplications by pow(-1,i) follow my experience with Numerical
Recipes (NR) code for FFT. In principle this "-1"s should govern that
the final result is ordered like [-k_z_max, ..., 0, ..., k_z_max], as
far as I understand what is going on.
The problem is that the result of the above code is wrong [in order to
learn FFTW I compare every FFTW-result with NR-result, and this NR-
code gives the correct result for 100%]. In particular I've checked
such a function:
########################################
for(int i=0; i<N; i++){
psiX[0] = exp(-z*z)*(z + 3.*z*z-7.*z*z*z
)*sin(z);
psiX[1] = 0.;
}
########################################
I have chosen such an ugly example on purpose. The nice examples (e.g.
Gaussians) are often misleading.
What I've checked/compared wit NR-result are:
1) FFTW_BACKWARD[ FFTW_FORWARD[ psiX ] ] = psiX
So, this is ok, as it should be.
2) The Plancherel theorem (the conservation of a norm of psiX and
FFTW_FORWARD[ psiX ]) also works perfectly
3) The real part of the FFT_FORWARD[psiX] is exactly the same as I
obtain form NR-program
4) !!! HERE COMES THE PROBLEM !!! :
the imaginary part of FFT_FORWARD[psiX] is mirror-reflected with
respect to "y"-axis (of course I know this by comaprison with NR-
result). So, if only I swapped the "right" and "left" part of the
imaginary part of the array FFT_FORWARD[psiX] (it's called psiK in the
code above), everything would be perfect. HOWEVER, if I did that,
point 1) crashes, i.e. I don't get identity when subsequently apply
FORWARD and BACKWARD.
I feel really lost with this. I've tried "experimentally" many other
ways of ordering, but every time some of the 4 points I mentioned
(actually points 1, 3 and 4) crashes. So, in general the result looks
"not-so-bad" (youi can definitely see that something works) but there
is always some mirror-reflection with respect to "y"-axis or the
result looks like it was globally multiplied by -1, and so on.
I would really appreciate any hints and/or advices. I spent all day
writing the code above but it seems that I failed.
Thank you in advance.