fortran complex to real fftw issue

匿名 (未验证) 提交于 2019-12-03 02:38:01

问题:

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.

回答1:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!