Fortran中的FFTW数组顺序

Fortran中的FFTW数组顺序,fortran,fft,fftw,Fortran,Fft,Fftw,我想使用FFTW来计算2D数据集的傅里叶谐波。我想我已经掌握了窍门,但我需要用谐波来“解码”复杂的输出。首先,这是我的玩具代码: PROGRAM FFTW_TEST USE, intrinsic :: iso_c_binding IMPLICIT NONE INTEGER :: i, j, n, m, l, k REAL :: pi2, norm, norm2 REAL(C_DOUBLE), POINTER, DIMENSION(:) :: th

我想使用FFTW来计算2D数据集的傅里叶谐波。我想我已经掌握了窍门,但我需要用谐波来“解码”复杂的输出。首先,这是我的玩具代码:

PROGRAM FFTW_TEST
    USE, intrinsic :: iso_c_binding

    IMPLICIT NONE

    INTEGER :: i, j, n, m, l, k
    REAL    :: pi2, norm, norm2
    REAL(C_DOUBLE), POINTER, DIMENSION(:) :: theta, func
    COMPLEX(C_DOUBLE_COMPLEX), POINTER, DIMENSION(:) :: fmn_1d
    REAL(C_DOUBLE), POINTER, DIMENSION(:,:) :: func_2d, r_2d, i_2d
    COMPLEX(C_DOUBLE_COMPLEX), POINTER, DIMENSION(:,:) :: fmn_2d


    INCLUDE 'fftw3.f03'
    TYPE(C_PTR) :: plan
    TYPE(C_PTR) :: real_1d, complex_1d
    TYPE(C_PTR) :: real_2d, complex_2d

    pi2 = 8.0 * ATAN(1.0)

    !------ 1D Example
    n = 64
    real_1d = FFTW_ALLOC_REAL(INT(n,C_SIZE_T))
    complex_1d = FFTW_ALLOC_COMPLEX(INT(n,C_SIZE_T))
    CALL C_F_POINTER(real_1d, func, [n])
    CALL C_F_POINTER(complex_1d, fmn_1d, [n])
    ALLOCATE(theta(n))

    FORALL(i=1:n) theta(i) = DBLE(i-1)/DBLE(n)
    FORALL(i=1:n) func(i)  = 1.0+2.0*cos(2*pi2*theta(i))-3.0*cos(3*pi2*theta(i)) ! Even Values
!    FORALL(i=1:n) func(i)  = 0.0+2.0*sin(4*pi2*theta(i))-3.0*sin(5*pi2*theta(i)) ! Odd Values

    WRITE(401,*) func(1:n)
    CALL FLUSH(401)

    norm    = n/2
    norm2   = n
    plan = FFTW_PLAN_DFT_R2C_1D(n, func, fmn_1d, FFTW_ESTIMATE)
    CALL FFTW_EXECUTE_DFT_R2C(plan, func, fmn_1d)
    CALL FFTW_DESTROY_PLAN(plan)
    func = REAL(fmn_1d)/norm
    func(1) = 2*func(1)
    WRITE(402,*) func; CALL FLUSH(402)
    func = -AIMAG(fmn_1d)/norm
    func(1) = 2*func(1) ! note should be zero
    WRITE(403,*) func; CALL FLUSH(403)
    plan = FFTW_PLAN_DFT_C2R_1D(n, fmn_1d, func, FFTW_ESTIMATE)
    CALL FFTW_EXECUTE_DFT_C2R(plan, fmn_1d, func)
    CALL FFTW_DESTROY_PLAN(plan)
    WRITE(404,*) func/norm2; CALL FLUSH(404)

    CALL FFTW_FREE(real_1d)
    CALL FFTW_FREE(complex_1d)
    IF (ASSOCIATED(theta)) DEALLOCATE(theta)


    !-------   2D Example
    m=16
    n=8
    real_2d = FFTW_ALLOC_REAL(INT(m*n,C_SIZE_T))
    complex_2d = FFTW_ALLOC_COMPLEX(INT(m*n,C_SIZE_T))
    CALL C_F_POINTER(real_2d, func_2d, [m,n])
    CALL C_F_POINTER(complex_2d, fmn_2d, [m,n])
    PRINT *,LBOUND(func_2d,DIM=1)
    ALLOCATE(fmn_1d(m),r_2d(m,n),i_2d(m,n))
    func_2d = 0.5
    DO i = 1, m
       DO j = 1, n
          DO l = 0, 8
             DO k = -4,4
                func_2d(i,j) = func_2d(i,j) + (l*100+k) * cos(l*pi2*(i-1)/m + k*pi2*(j-1)/n)
             END DO
          END DO
       END DO
       WRITE(501,*) func_2d(i,1:n); CALL FLUSH(501)
    END DO

    ! Note in the m direction we read m=0,1,2,3,4...
    !      in the n direction we read n=0..nx/2,-nx/2+1...-1
    norm    = m*n/2
    norm2   = norm*2
    plan = FFTW_PLAN_DFT_R2C_2D(n, m, func_2d, fmn_2d, FFTW_ESTIMATE)
    CALL FFTW_EXECUTE_DFT_R2C(plan, func_2d, fmn_2d)
    CALL FFTW_DESTROY_PLAN(plan)
    r_2d = REAL(fmn_2d)/norm
    r_2d(1,1) = r_2d(1,1)/2
    DO i = 1, m
       WRITE(502,*) r_2d(i,1:n); CALL FLUSH(502)
    END DO
    i_2d = -AIMAG(fmn_2d)/norm
    i_2d(1,1) = i_2d(1,1)/2
    DO i = 1, m
       WRITE(503,*) i_2d(i,1:n); CALL FLUSH(503)
    END DO
    DO i = 1, m
       DO j = 1, n
          IF (abs(r_2d(i,j))>1.0E-5 .or. ABS(i_2d(i,j))>1.0E-5) &
       WRITE(6,*) i,j,r_2d(i,j),i_2d(i,j)
     END DO
    END DO
    plan = FFTW_PLAN_DFT_C2R_2D(n, m, fmn_2d, func_2d, FFTW_ESTIMATE)
    CALL FFTW_EXECUTE_DFT_C2R(plan, fmn_2d, func_2d)
    CALL FFTW_DESTROY_PLAN(plan)
    DO i = 1, m
       WRITE(504,*) func_2d(i,1:n)/norm2; CALL FLUSH(504)
    END DO

    CALL FFTW_FREE(real_2d)
    CALL FFTW_FREE(complex_2d)
    IF (ASSOCIATED(fmn_1d)) DEALLOCATE(fmn_1d)



END PROGRAM FFTW_TEST
现在我想提取一个函数的谐波,它看起来像: $A{mn}\cos(m\theta+n\phi)$,其中$\theta$和$\phi$是真实的空间网格。首先,获取复杂数组的真实部分似乎是正确的。对于简单函数,谐波似乎是正确的。然而,在最后一个测试用例中,数组似乎具有奇数顺序。这是订购单

m/n
0/0 1/0 2/0 3/0 4/0 5/0 6/0 7/0 8/0 0/1 1/1 2/1 3/1 4/1 5/1 6/1
7/1 8/1 0/2 1/2 2/2 3/2 4/2 5/2 6/2 7/2 8/2 0/3 1/3 2/3 3/3 4/3
5/3 6/3 7/3 8/3 0/4 1/4 2/4 3/4 5/4 6/4 7/4 8/4 ?/? ?/? ?/? ?/?
以下是我希望订购的内容,以供参考:

m/n
0/0 1/0 2/0 3/0 4/0 5/0 6/0 7/0 8/0 -7/0 -6/0 -5/0 -4/0 -3/0 -2/0 -1/0
0/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 -7/1 -6/1 -5/1 -4/1 -3/1 -2/1 -1/1
0/2 1/2 2/2 3/2 4/2 5/2 6/2 7/2 8/2 -7/2 -6/2 -5/2 -4/2 -3/2 -2/2 -1/2
代码似乎只是将数组当作线性数组处理。但我在FFTW文档中看到的不应该是这种情况。数组的一个维度应与沿一个维度和另一个维度的变换相对应。因此,在某种意义上,我们应该能够读出m和n次谐波


有人能解释一下复杂数组应该如何根据谐波和适当的规范化进行排序吗?

注意,
pi2=8.0*ATAN(1.0)
不精确,它只是一个(实际上是默认值)精度。@VladimirF很好,但这里的问题不是FFT的结果缺乏准确性,而是阵列中的数据布局与FFTW文档中记录的不一样。如果我理解正确,那么数组应该从[0,NX/2]开始运行,然后[-NX/2+1,-1]穿过数组的一个维度。但很明显,这似乎是一个包袱。此外,阵列似乎正在进行一些打包。我想理解它,这样我就可以输出模式数形式的频率信息。但请记住,C中的nx是Fortran中的ny。@VladimirF这只能解释如果我们按nx,ny值关闭,但数组似乎移位了2(在线性意义上),它不能解释模式顺序。我尝试过如何传递数组标记,但没有得到一致的结果。