以下是我为了在一段时间内找到正弦(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可以容纳的最小值。这是我应该担心的事情吗?
答案 0 :(得分:2)
就像@VladimirF已经说过的那样,值的排序与您预期的略有不同。阵列的前半部分保持正频率,后半部分以相反的顺序保持负频率(见this link)。您可能必须检查FFTW使用的符号约定。
准确性问题源于pi
的单精度值和使用cmplx
生成单精度复数(使用关键字参数kind
)。在这种情况下,您可以简单地将实际值分配给复杂变量。应用这两个更改会产生~1e-10
的精度。这可以通过提供更好的pi近似值(即超过10位数)来改善。
E.g。值pi = 3.141592653589793d0
会产生精确度为1e-16
的结果。