I am currently working on a project where I need to implement a fourier transform and an inverse transform. I was testing a program I modified from an online example; the print or write commands are normally for debugging purposes:
program testit INCLUDE 'fftw3.f' double complex out!, in real in parameter (N=100) dimension in(N), out(N) integer*8 p,p2 integer i,j real x real fact write(*,*)"stuff in data" OPEN(UNIT=12, FILE="input.txt", ACTION="write", STATUS="replace") OPEN(UNIT=20, FILE="dftoutput.txt", ACTION="write", STATUS="replace") x=0 in = 0 do i=1,N/2 in(i)=1 enddo do i=1,N write(*,"(f10.2,1x,f10.2)")in(i) WRITE(12,*)real(in(i)) enddo write(*,*)"create plans" call dfftw_plan_dft_r2c_1d(p ,N,in,out,FFTW_ESTIMATE) call dfftw_plan_dft_c2r_1d(p2,N,in,out,FFTW_ESTIMATE) write(*,*)"do it" call dfftw_execute_dft_r2c(p,in,out) do i=1,N write(*,"(f12.4,1x,f12.4)")out(i) WRITE(20,*)abs(out(i)) enddo write(*,*)"undo it" call dfftw_execute_dft_c2r(p2,in,out) fact=1.0/N do i=1,N write(*,)in(i) write(*,)out(i) enddo write(*,*)"clean up" call dfftw_destroy_plan(p,in,out) call dfftw_destroy_plan(p2,in,out) end program
The real to complex transformation works just fine. The inverse transformation gives wrong values and somehow it modifies both the in and out variables. I do not know what the problem is and I was not able to figure out any answers online. Help is appreciated.
Thanks in advance!
Chad W. Freer
Edit: I was also wondering if there is a similar function to fftshift() and ifftshift() from matlab in the fftw package.
There is a precision issue : on most computers, real refers to single precision 32bit floating point numbers. real*8 can be used to specify double precision floating point numbers, to be consistent with double complex and dfftw_....
For FFTW real to complex transform, if the size of the input is N real*8, then the size of the output is N/2+1 double complex. Since the input is real, coefficients of negative frequencies (higher than N/2+1) are conjugate of positive frequencies, and their computation is avoided.
According to the documentation of FFTW regarding planner flags ,
FFTW_PRESERVE_INPUT specifies that an out-of-place transform must not change its input array. This is ordinarily the default, except for c2r and hc2r (i.e. complex-to-real) transforms for which FFTW_DESTROY_INPUT is the default...
If you wish to save the coefficients in the Fourier space out, either copy the array, or try to use FFTW_PRESERVE_INPUT. The first solution seems the best way to go if you have enough memory.
Order of arguments for FFTW functions is always origin,destination. As the backward transform is performed from out to in :
call dfftw_plan_dft_c2r_1d(p2,N,out,in,FFTW_ESTIMATE) ... call dfftw_execute_dft_c2r(p2,out,in)
Here is a code based on yours, which performs forward and backward fft. It is compiled by gfortran main.f90 -o main -lfftw3 -lm -Wall :
program testit INCLUDE 'fftw3.f' double complex out!, in real*8 in parameter (N=100) dimension in(N), out((N/2+1)) integer*8 p,p2 integer i real x real fact write(*,*)"stuff in data" OPEN(UNIT=12, FILE="input.txt", ACTION="write", STATUS="replace") OPEN(UNIT=20, FILE="dftoutput.txt", ACTION="write", STATUS="replace") x=0 in = 0 do i=1,N/2 in(i)=1 enddo do i=1,N write(*,"(f10.2,1x/)")in(i) WRITE(12,*)real(in(i)) enddo write(*,*)"create plans" call dfftw_plan_dft_r2c_1d(p ,N,in,out,FFTW_ESTIMATE) call dfftw_plan_dft_c2r_1d(p2,N,out,in,FFTW_ESTIMATE) write(*,*)"do it" call dfftw_execute_dft_r2c(p,in,out) do i=1,N/2+1 write(*,"(f12.4,1x,f12.4/)")out(i) WRITE(20,*)abs(out(i)) enddo write(*,*)"undo it" call dfftw_execute_dft_c2r(p2,out,in) fact=1.0/N write(*,*)"input back, except for scaling" do i=1,N write(*,"(f10.2,1x)")in(i) enddo write(*,*)"output may be modified by c2r...except if FFTW_PRESERVE_INPUT is set" do i=1,N/2+1 write(*,"(f10.2,1x,f10.2/)")out(i) enddo write(*,*)"clean up" call dfftw_destroy_plan(p,in,out) call dfftw_destroy_plan(p2,out,in) end program
After the forward fft in->out and the backward fft out->in , in is identical to its initial value, except for a scale factor N.