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
.