在Fortran混合输出中使用FFTW的正弦(x)的DFT

时间:2015-02-12 07:03:23

标签: fortran fft fftw dft

以下是我为了在一段时间内找到正弦(x)的DFT而编写的代码。

program fftw_test

implicit none

INTEGER FFTW_MEASURE
    PARAMETER (FFTW_MEASURE=0)
INTEGER FFTW_ESTIMATE
    PARAMETER (FFTW_ESTIMATE=64)
INTEGER FFTW_FORWARD
    PARAMETER (FFTW_FORWARD=-1)

integer, parameter :: n = 8
integer :: i
double complex, dimension(0:n-1) :: input, output
double precision, parameter :: pi = 3.141592653, h = 2.0d0*pi/(n)
integer*8 :: plan

call dfftw_plan_dft_1d(plan, n, input, output, fftw_forward, fftw_measure)

do i = 0, n-1
    input(i) = cmplx(sin(h*i), 0)
end do

call dfftw_execute_dft(plan, input, output)

output = output/n 

output(0) = cmplx(0,0) ! setting oddball wavenumber to be 0

call dfftw_destroy_plan(plan)

do i = -n/2, n/2-1, 1
    write(*, *) i, output(i+(n/2))
end do

end program

我知道FFTW库中的r2c(真实到复杂)功能。但我被建议使用正常的c2c功能。所以我将输入函数定义为具有实部分=正弦(x)和复数部分0的复数。

正弦(x)的DFT应该是fk(-1)= cmplx(0,-0.5)和fk(1)= cmplx(0,0.5)其中fk(k)表示的傅立叶系数k wavenumber

我收到的输出如下。

      -4 (  0.0000000000000000     ,  0.0000000000000000     )
      -3 (  3.2001271327131496E-008,-0.49999998518472011     )
      -2 ( -1.0927847071684482E-008,  1.4901161193847656E-008)
      -1 ( -1.0145577183762535E-008,  1.4815279864022202E-008)
       0 ( -1.0927847071684482E-008,  0.0000000000000000     )
       1 ( -1.0145577183762535E-008, -1.4815279864022202E-008)
       2 ( -1.0927847071684482E-008, -1.4901161193847656E-008)
       3 (  3.2001271327131496E-008, 0.49999998518472011     )

我得到fk(-3)= cmplx(~0,-0.5)和fk(3)= cmplx(~0,0.5)。如果我将网格大小增加到16,32左右,我得到-n / 2 -1和n / 2 -1 wavenumbers,其中包含所需的值而不是-1和1个波数。

这与FFTW将输出存储在输出数组中的方式有​​关吗?或者我在其他地方出错了?

另外,我似乎没有得到“适当的0”。相反,数字的大小为10 ^( - 8),我相信这是我的数据类型double可以容纳的最小值。这是我应该担心的事情吗?

1 个答案:

答案 0 :(得分:2)

就像@VladimirF已经说过的那样,值的排序与您预期的略有不同。阵列的前半部分保持正频率,后半部分以相反的顺序保持负频率(见this link)。您可能必须检查FFTW使用的符号约定。

准确性问题源于pi的单精度值和使用cmplx生成单精度复数(使用关键字参数kind)。在这种情况下,您可以简单地将实际值分配给复杂变量。应用这两个更改会产生~1e-10的精度。这可以通过提供更好的pi近似值(即超过10位数)来改善。

E.g。值pi = 3.141592653589793d0会产生精确度为1e-16的结果。