在fortran77中用fftw分解二维FFT(和逆FFT)
[编辑1]添加数字以显示原始数据和获得的数据 [编辑2]我发现了我的错误,在调用dfftw\u plan\u many\u dft时,我使用了fftw\u度量而不是fftw\u估计 [edit 3]更正了代码中的一个输入错误(在dfftw\u execute\u dft\u r2c中将u替换为u2d) 我正在尝试使用多个1D fft来执行阵列的2D fft,而不是使用fftw库中已有的2D fft函数。随后,我需要进行二维fft逆运算。 这样做的原因是(将来)我的阵列太大,无法一次性加载以执行2D fft 目前,我的代码初稿大致如下:在fortran77中用fftw分解二维FFT(和逆FFT),fortran,fft,fftw,Fortran,Fft,Fftw,[编辑1]添加数字以显示原始数据和获得的数据 [编辑2]我发现了我的错误,在调用dfftw\u plan\u many\u dft时,我使用了fftw\u度量而不是fftw\u估计 [edit 3]更正了代码中的一个输入错误(在dfftw\u execute\u dft\u r2c中将u替换为u2d) 我正在尝试使用多个1D fft来执行阵列的2D fft,而不是使用fftw库中已有的2D fft函数。随后,我需要进行二维fft逆运算。 这样做的原因是(将来)我的阵列太大,无法一次性加载以执行2
double precision u2d(nx,ny),u2d2(nx,ny)
double complex qhat2d(nx/2+1,ny),qhat2d2(nx/2+1,ny)
integer N(1)
integer howmany, idist, odist, istride, ostride
integer inembed(2), onembed(2)
integer rank
! some function to read the data into u2d
! perform x-fft
N(1) = NX
howmany = NY
inembed(1) = NX
inembed(2) = NY
istride = 1
idist = NX
ostride = 1
odist = (NX/2+1)
onembed(1) = (NX/2+1)
onembed(2) = NY
rank = 1
write(*,*) 'u', u2d(1,1)
CALL dfftw_plan_many_dft_r2c(PLAN,rank,N(1),howmany,
& u2d,inembed,
& istride,idist,
& qhat2d,onembed,
& ostride,odist,FFTW_ESTIMATE) !
CALL dfftw_execute_dft_r2c(PLAN,u2d,qhat2d) ! x-fft
CALL dfftw_destroy_plan(PLAN)
! perform y-fft
N(1) = NY
howmany = (NX/2+1)
inembed(1) = (NX/2+1)
inembed(2) = NY
istride = (NX/2+1)
idist = 1
ostride = (NX/2+1)
odist = 1
onembed(1) = (NX/2+1)
onembed(2) = NY
rank = 1
CALL dfftw_plan_many_dft(PLAN,rank,N(1),howmany,
& qhat2d,inembed,
& istride,idist,
& qhat2d2,onembed,
& ostride,odist,FFTW_FORWARD,
& FFTW_MEASURE) !
CALL dfftw_execute_dft(PLAN,qhat2d,qhat2d2) ! y-fft
CALL dfftw_destroy_plan(PLAN)
! normally here, perform some filtering operation
! but at the moment, I do nothing
! perform inv-y-fft
N(1) = NY
howmany = (NX/2+1)
inembed(1) = (NX/2+1)
inembed(2) = NY
istride = (NX/2+1)
idist = 1
ostride = (NX/2+1)
odist = 1
onembed(1) = (NX/2+1)
onembed(2) = NY
rank = 1
CALL dfftw_plan_many_dft(PLAN,rank,N(1),howmany,
& qhat2d2,inembed,
& istride,idist,
& qhat2d,onembed,
& ostride,odist,FFTW_BACKWARD,
& FFTW_MEASURE) !
CALL dfftw_execute_dft(PLAN,qhat2d2,qhat2d) ! inv-y-fft
CALL dfftw_destroy_plan(PLAN)
! perform inv-x-fft
N(1) = NX ! I'm not too sure about this value here
howmany = NY
inembed(1) = (NX/2+1)
inembed(2) = NY
istride = 1
idist = (NX/2+1)
ostride = 1
odist = NX
onembed(1) = NX
onembed(2) = NY
rank = 1
CALL dfftw_plan_many_dft_c2r(PLAN,rank,N(1),howmany,
& qhat2d,inembed,
& istride,idist,
& u2d2,onembed,
& ostride,odist,FFTW_ESTIMATE) !
CALL dfftw_execute_dft_c2r(PLAN,qhat2d,u2d2) ! x-fft
CALL dfftw_destroy_plan(PLAN)
write(*,*) 'u2d2', u2d2(1,1)
do i=1,nx
do j=1,ny
u2d2(i,j) = u2d2(i,j) / (nx*ny)
enddo
enddo
write(*,*) 'u2d2', u2d2(1,1) ! here the values u2d2(1,1) is different from u2d(1,1)
! some action to write u2d2 to file
end
我希望u2d和u2d2是相同的,但我得到的值相对不同。我在什么地方出错了吗
原始数据和结果如下所示。形状看起来相似,但值相对不同(例如最小值和最大值)
我发现了我的错误,在dfftw\u plan\u many\u dft的调用中,我使用了fftw\u度量而不是fftw\u估计
更正后,我得到了适当的原始字段。我发现了错误,在调用dfftw\u plan\u many\u dft时,我使用了fftw\u度量而不是fftw\u估计
更正后,我将获得相应的原始字段。以清除混淆。发生的情况是,不能保证FFTW
c2r
和r2c
例程保留输入数组。它们可以用垃圾覆盖结果
现在,您可以很幸运地使用FFTW\u ESTIMATE
而不是FFTW\u MEASURE
,但这不是一个好主意。FFTW\u MEASURE
尝试了许多算法,因此可能也尝试了一种不保留输入的算法FFTW_ESTIMATE
不会尝试计算任何内容,也不会覆盖输入
问题在于,在执行转换(执行计划)时,您的输入可能会被覆盖。只有当FFT\u ESTIMATE
选择了一种为您保留输入的算法时,您才会幸运。这是彩票
为了确保输入得到保留,除了FFT\u估计值
或FFTW\u度量值
之外,还应使用FFTW\u输入
您也可以不使用它,而是将输入保存在某个地方。我认为这通常更好,因为
FFTW\u INPUT\u PRESERVE
可以(很可能)选择较慢的算法。来消除混淆。发生的情况是,不能保证FFTWc2r
和r2c
例程保留输入数组。它们可以用垃圾覆盖结果
现在,您可以很幸运地使用FFTW\u ESTIMATE
而不是FFTW\u MEASURE
,但这不是一个好主意。FFTW\u MEASURE
尝试了许多算法,因此可能也尝试了一种不保留输入的算法FFTW_ESTIMATE
不会尝试计算任何内容,也不会覆盖输入
问题在于,在执行转换(执行计划)时,您的输入可能会被覆盖。只有当FFT\u ESTIMATE
选择了一种为您保留输入的算法时,您才会幸运。这是彩票
为了确保输入得到保留,除了FFT\u估计值
或FFTW\u度量值
之外,还应使用FFTW\u输入
您也可以不使用它,而是将输入保存在某个地方。我认为这通常更好,因为
FFTW\u INPUT\u PRESERVE
可以(很可能)选择较慢的算法。因此,如果对同一数据进行前后变换,则会有一个数组长度因子。请参见,例如,或或为什么对复杂数据进行实值DFT(\u r2c
),FFTW会这样做。因此,如果对同一数据进行前向和后向变换,则会有一个数组长度因子。请参见,例如,或或为什么对复杂数据进行实值DFT(\u r2c
),这一点都不重要。重要的是FFTW_PRESERVE_输入,但前提是您不将输入保存到其他地方。@VladimirF查看手册页面,实际上似乎如果使用FFTW_度量,则在创建计划时输入数组将被覆盖。非常混乱的界面…@roygvib是的,你不应该仅仅把输入数组当作intent(in)
,它不是这样的。甚至在转换过程中也没有。那么你应该使用'FFTW\u PRESERVE\u INPUT'。如果以后出于任何目的需要,我强烈建议将输入值保存到其他地方。正如答案所示,仅仅使用FFTW\u估计值是不够的。这可能会隐藏问题,但它可能会在估计选择不保留输入的算法时随时出现。然后,输入将在转换期间而不是在规划期间被覆盖。因此,这个答案是不正确的。是的,更一般地说,我建议以某种方式将计划的创建和实际的转换分开。在我的例子中,我创建了一个模块,在内部为用户处理这个问题。但我认为答案本身是正确的,因为编码“风格”在某种程度上是一个品味问题。尽管如此,我认为如果另外添加一个不同的答案作为替代(更安全的)方式,这应该是非常有用的…@roygvib这是不正确的,您可以使用FFTW_ESTIMATE
并仍然覆盖您的输入。唯一的幸运是计划者选择了一个不进行覆盖的算法,但这纯粹是运气。下一次,在不同的机器上使用相同的代码,它可能会再次失败。这一点都不重要。重要的是FFTW_PRESERVE_输入,但前提是您不将输入保存到其他地方。@VladimirF查看手册页面,实际上似乎如果使用FFTW_度量,则在创建计划时输入数组将被覆盖。非常混乱的界面…@roygvib是的,你