在 fortran77 中使用 fftw 分解 2D FFT(和逆 fft)
Decomposition of 2D FFT (and inverse fft) with fftw in fortran77
[edit 1] 添加了数字以显示原始数据和获得的数据
[编辑 2] 我发现了我的错误,我在 dfftw_plan_many_dft
的调用中使用了 fftw_measure 而不是 fftw_estimate
[编辑 3] 更正了代码中的拼写错误(在 dfftw_execute_dft_r2c 中将 u 替换为 u2d)
我正在尝试使用多个 1D fft 执行数组的 2D fft,而不是使用 fftw 库中已经存在的 2D fft 函数。随后,我需要执行逆二维 fft。
这样做的原因是(将来)我的阵列太大而无法一次加载以执行 2D fft。
我的代码的第一稿目前看起来大致如下:
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_plan_many_dft 的调用中使用了 fftw_measure 而不是 fftw_estimate。
更正给我适当的原始字段。
清除混乱。发生的情况是 FFTW c2r
和 r2c
例程不能保证保留输入数组。他们可以用垃圾覆盖结果。
现在,你可能很幸运,只使用 FFTW_ESTIMATE
而不是 FFTW_MEASURE
,但这不是一个好主意。FFTW_MEASURE
尝试了很多算法,因此也可能会尝试一个不保留输入的。 FFTW_ESTIMATE
不会尝试计算任何内容,也不会覆盖输入。
问题是在执行转换(执行计划)时您的输入可能会被覆盖。只有当 FFT_ESTIMATE
select 是一种为您保留输入的算法时,您才会幸运。这是彩票。
为了确保输入得到保留,除了 FFT_ESTIMATE
或 FFTW_MEASURE
.
之外,您还应该使用 FFTW_INPUT_PRESERVE
您也可以不使用它,而是将输入保存在某处。我认为这通常更好,因为 FFTW_INPUT_PRESERVE
可以(很可能)select 一个较慢的算法。
[edit 1] 添加了数字以显示原始数据和获得的数据
[编辑 2] 我发现了我的错误,我在 dfftw_plan_many_dft
的调用中使用了 fftw_measure 而不是 fftw_estimate[编辑 3] 更正了代码中的拼写错误(在 dfftw_execute_dft_r2c 中将 u 替换为 u2d)
我正在尝试使用多个 1D fft 执行数组的 2D fft,而不是使用 fftw 库中已经存在的 2D fft 函数。随后,我需要执行逆二维 fft。 这样做的原因是(将来)我的阵列太大而无法一次加载以执行 2D fft。
我的代码的第一稿目前看起来大致如下:
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_plan_many_dft 的调用中使用了 fftw_measure 而不是 fftw_estimate。
更正给我适当的原始字段。
清除混乱。发生的情况是 FFTW c2r
和 r2c
例程不能保证保留输入数组。他们可以用垃圾覆盖结果。
现在,你可能很幸运,只使用 FFTW_ESTIMATE
而不是 FFTW_MEASURE
,但这不是一个好主意。FFTW_MEASURE
尝试了很多算法,因此也可能会尝试一个不保留输入的。 FFTW_ESTIMATE
不会尝试计算任何内容,也不会覆盖输入。
问题是在执行转换(执行计划)时您的输入可能会被覆盖。只有当 FFT_ESTIMATE
select 是一种为您保留输入的算法时,您才会幸运。这是彩票。
为了确保输入得到保留,除了 FFT_ESTIMATE
或 FFTW_MEASURE
.
FFTW_INPUT_PRESERVE
您也可以不使用它,而是将输入保存在某处。我认为这通常更好,因为 FFTW_INPUT_PRESERVE
可以(很可能)select 一个较慢的算法。