Next: FFTW Fortran type reference, Previous: Overview of Fortran interface, Up: Calling FFTW from Modern Fortran

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). See Multi-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 × M × 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 × M × 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 (see Fortran-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 (see Multi-Dimensional DFTs of Real Data). In C, a multidimensional real-to-complex DFT
chops the last dimension roughly in half (N × M × L real input
goes to N × M × L/2+1 complex output). In Fortran, because
the array dimension notation is reversed, the `last`

dimension of
the complex data is chopped roughly in half. For example consider the
‘`r2c`’ transform of L × M × 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] × M × N array, even though only
L × M × N of it is actually used. In this example, we will
allocate the array as a pointer type, using ‘`fftw_alloc`’ to
ensure aligned memory for maximum performance (see 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)