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