在fortran77中用fftw分解二维FFT(和逆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

[编辑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

目前,我的代码初稿大致如下:

  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
可以(很可能)选择较慢的算法。

来消除混淆。发生的情况是,不能保证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
可以(很可能)选择较慢的算法。因此,如果对同一数据进行前后变换,则会有一个数组长度因子。请参见,例如,或或为什么对复杂数据进行实值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是的,你