Chris@82: Chris@82: Chris@82: Chris@82: Chris@82:
Chris@82:Chris@82: Next: Accessing the wisdom API from Fortran, Previous: Plan execution in Fortran, Up: Calling FFTW from Modern Fortran [Contents][Index]
Chris@82:In order to obtain maximum performance in FFTW, you should store your
Chris@82: data in arrays that have been specially aligned in memory (see SIMD alignment and fftw_malloc). Enforcing alignment also permits you to
Chris@82: safely use the new-array execute functions (see New-array Execute Functions) to apply a given plan to more than one pair of in/out
Chris@82: arrays. Unfortunately, standard Fortran arrays do not provide
Chris@82: any alignment guarantees. The only way to allocate aligned
Chris@82: memory in standard Fortran is to allocate it with an external C
Chris@82: function, like the fftw_alloc_real
and
Chris@82: fftw_alloc_complex
functions. Fortunately, Fortran 2003 provides
Chris@82: a simple way to associate such allocated memory with a standard Fortran
Chris@82: array pointer that you can then use normally.
Chris@82:
We therefore recommend allocating all your input/output arrays using Chris@82: the following technique: Chris@82:
Chris@82:pointer
, arr
, to your array of the desired type
Chris@82: and dimensions. For example, real(C_DOUBLE), pointer :: a(:,:)
Chris@82: for a 2d real array, or complex(C_DOUBLE_COMPLEX), pointer ::
Chris@82: a(:,:,:)
for a 3d complex array.
Chris@82:
Chris@82: integer(C_SIZE_T)
. You can either declare a variable of this
Chris@82: type, e.g. integer(C_SIZE_T) :: sz
, to store the number of
Chris@82: elements to allocate, or you can use the int(..., C_SIZE_T)
Chris@82: intrinsic function. e.g. set sz = L * M * N
or use
Chris@82: int(L * M * N, C_SIZE_T)
for an L × M × N
Chris@82: array.
Chris@82:
Chris@82: type(C_PTR) :: p
to hold the return value from
Chris@82: FFTW’s allocation routine. Set p = fftw_alloc_real(sz)
for a real array, or p = fftw_alloc_complex(sz)
for a complex array.
Chris@82:
Chris@82: arr
with the allocated memory p
Chris@82: using the standard c_f_pointer
subroutine: call
Chris@82: c_f_pointer(p, arr, [...dimensions...])
, where
Chris@82: [...dimensions...])
are an array of the dimensions of the array
Chris@82: (in the usual Fortran order). e.g. call c_f_pointer(p, arr,
Chris@82: [L,M,N])
for an L × M × N
Chris@82: array. (Alternatively, you can
Chris@82: omit the dimensions argument if you specified the shape explicitly
Chris@82: when declaring arr
.) You can now use arr
as a usual
Chris@82: multidimensional array.
Chris@82:
Chris@82: call
Chris@82: fftw_free(p)
on p
.
Chris@82:
Chris@82: For example, here is how we would allocate an L × M Chris@82: 2d real array: Chris@82:
Chris@82:real(C_DOUBLE), pointer :: arr(:,:) Chris@82: type(C_PTR) :: p Chris@82: p = fftw_alloc_real(int(L * M, C_SIZE_T)) Chris@82: call c_f_pointer(p, arr, [L,M]) Chris@82: ...use arr and arr(i,j) as usual... Chris@82: call fftw_free(p) Chris@82:
and here is an L × M × N Chris@82: 3d complex array: Chris@82:
Chris@82:complex(C_DOUBLE_COMPLEX), pointer :: arr(:,:,:) Chris@82: type(C_PTR) :: p Chris@82: p = fftw_alloc_complex(int(L * M * N, C_SIZE_T)) Chris@82: call c_f_pointer(p, arr, [L,M,N]) Chris@82: ...use arr and arr(i,j,k) as usual... Chris@82: call fftw_free(p) Chris@82:
See Reversing array dimensions for an example allocating a Chris@82: single array and associating both real and complex array pointers with Chris@82: it, for in-place real-to-complex transforms. Chris@82:
Chris@82:Chris@82: Next: Accessing the wisdom API from Fortran, Previous: Plan execution in Fortran, Up: Calling FFTW from Modern Fortran [Contents][Index]
Chris@82: