Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran混沌输出中使用FFTW的正弦(x)DFT_Fortran_Fft_Fftw_Dft - Fatal编程技术网

Fortran混沌输出中使用FFTW的正弦(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

下面是我为求正弦(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波数的傅里叶系数

我收到的输出如下

      -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是常量(初始化)表达式,否则是可执行语句。