fftw3: Reversing array dimensions

 
 7.2 Reversing array dimensions
 ==============================
 
 A minor annoyance in calling FFTW from Fortran is that FFTW's array
 dimensions are defined in the C convention (row-major order), while
 Fortran's array dimensions are the opposite convention (column-major
 order).  SeeMulti-dimensional Array Format.  This is just a
 bookkeeping difference, with no effect on performance.  The only
 consequence of this is that, whenever you create an FFTW plan for a
 multi-dimensional transform, you must always _reverse the ordering of
 the dimensions_.
 
    For example, consider the three-dimensional (L x M x N ) arrays:
 
        complex(C_DOUBLE_COMPLEX), dimension(L,M,N) :: in, out
 
    To plan a DFT for these arrays using 'fftw_plan_dft_3d', you could
 do:
 
        plan = fftw_plan_dft_3d(N,M,L, in,out, FFTW_FORWARD,FFTW_ESTIMATE)
 
    That is, from FFTW's perspective this is a N x M x L array.  _No data
 transposition need occur_, as this is _only notation_.  Similarly, to
 use the more generic routine 'fftw_plan_dft' with the same arrays, you
 could do:
 
        integer(C_INT), dimension(3) :: n = [N,M,L]
        plan = fftw_plan_dft_3d(3, n, in,out, FFTW_FORWARD,FFTW_ESTIMATE)
 
    Note, by the way, that this is different from the legacy Fortran
 interface (SeeFortran-interface routines), which automatically
 reverses the order of the array dimension for you.  Here, you are
 calling the C interface directly, so there is no "translation" layer.
 
    An important thing to keep in mind is the implication of this for
 multidimensional real-to-complex transforms (SeeMulti-Dimensional
 DFTs of Real Data).  In C, a multidimensional real-to-complex DFT
 chops the last dimension roughly in half (N x M x L real input goes to N
 x M x L/2+1 complex output).  In Fortran, because the array dimension
 notation is reversed, the _first_ dimension of the complex data is
 chopped roughly in half.  For example consider the 'r2c' transform of L
 x M x N real input in Fortran:
 
        type(C_PTR) :: plan
        real(C_DOUBLE), dimension(L,M,N) :: in
        complex(C_DOUBLE_COMPLEX), dimension(L/2+1,M,N) :: out
        plan = fftw_plan_dft_r2c_3d(N,M,L, in,out, FFTW_ESTIMATE)
        ...
        call fftw_execute_dft_r2c(plan, in, out)
 
    Alternatively, for an in-place r2c transform, as described in the C
 documentation we must _pad_ the _first_ dimension of the real input with
 an extra two entries (which are ignored by FFTW) so as to leave enough
 space for the complex output.  The input is _allocated_ as a 2[L/2+1] x
 M x N array, even though only L x M x N of it is actually used.  In this
 example, we will allocate the array as a pointer type, using
 Allocating aligned memory in Fortran::); this also makes it easy to
 reference the same memory as both a real array and a complex array.
 
        real(C_DOUBLE), pointer :: in(:,:,:)
        complex(C_DOUBLE_COMPLEX), pointer :: out(:,:,:)
        type(C_PTR) :: plan, data
        data = fftw_alloc_complex(int((L/2+1) * M * N, C_SIZE_T))
        call c_f_pointer(data, in, [2*(L/2+1),M,N])
        call c_f_pointer(data, out, [L/2+1,M,N])
        plan = fftw_plan_dft_r2c_3d(N,M,L, in,out, FFTW_ESTIMATE)
        ...
        call fftw_execute_dft_r2c(plan, in, out)
        ...
        call fftw_destroy_plan(plan)
        call fftw_free(data)