Fortran混沌输出中使用FFTW的正弦(x)DFT
下面是我为求正弦(x)在一个周期内的DFT而编写的代码Fortran混沌输出中使用FFTW的正弦(x)DFT,fortran,fft,fftw,dft,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
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波数的傅里叶系数
我收到的输出如下
-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波数,这些波数是需要的值,而不是-1和1波数
这是否与FFTW在输出数组中存储输出的方式有关?还是我在别的地方出了问题
而且,我似乎没有得到我应该得到的“正确的0”。它是10^(-8)级的数字,我认为这是我的数据类型double所能容纳的最小值。这是我应该担心的吗?就像@VladimirF已经说过的,值的顺序与您可能预期的稍有不同。阵列的前半部分保持正频率,后半部分按相反顺序保持负频率(请参阅)。您可能需要检查FFTW使用的符号约定 精度问题源于
pi
的单精度值以及使用cmplx
生成单精度复数(使用关键字参数kind
)。在这种情况下,您可以简单地将实际值分配给复杂变量。应用这两个更改将产生~1e-10
的精度。这可以通过为pi提供更好的近似值(即超过10位)来改进
例如,
pi=3.141592653589793d0
值产生精度为1e-16
10^(-8)的结果肯定不是一个双精度的最小值。然而,你必须考虑FFT的工作原理,以及这些值与你的最大值的相对差异。建议你使用c2c变换的那个人有一些原因?你还必须考虑到,负频率存储在数组的上半部分。如果你的输入数据是纯实数,那么使用r2c或r2hc(实数到半复数)几乎肯定更有效。在这种情况下,有人会推荐c2c似乎很奇怪。谁不记得pi的小数点后有这么多位使用了pi=acos(-1.0d0)
@VladimirF这是便携式的吗?我记得有一个编译器抱怨通过函数调用进行参数初始化(尽管我不记得是哪个编译器)…Fortran 2008是常量(初始化)表达式,否则是可执行语句。