23 use,
intrinsic :: iso_c_binding
32 fftw_execute_dft_c2r, &
33 fftw_execute_dft_r2c, &
40 fftw_plan_many_dft_r2c, &
41 fftw_plan_many_dft_c2r, &
62 public :: fftw_mpi_default_block
64#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
67 fftw_plan_with_nthreads, &
73 include
"fftw3-mpi.f03"
83 use,
intrinsic :: iso_c_binding
100 subroutine fftw_prepare_plan(plan, dim, n, howmany, is_real, sign, flags, din_, cin_, cout_)
101 type(c_ptr),
intent(inout) :: plan
102 integer,
intent(in) :: dim
103 integer,
intent(in) :: n(:)
104 integer(c_int),
intent(in) :: howmany
105 logical,
intent(in) :: is_real
106 integer,
intent(in) :: sign
107 integer,
intent(in) :: flags
108 real(real64),
optional,
target,
intent(in) :: din_(:,:,:,:)
109 complex(real64),
optional,
target,
intent(in) :: cin_(:,:,:,:)
110 complex(real64),
optional,
target,
intent(in) :: cout_(:,:,:,:)
112 real(real64),
pointer,
contiguous :: rin(:,:,:,:)
113 real(real64),
pointer,
contiguous :: rout(:,:,:,:)
114 complex(real64),
pointer,
contiguous :: cin(:,:,:,:)
115 complex(real64),
pointer,
contiguous :: cout(:,:,:,:)
116 logical :: aligned_memory
117 integer(c_int) :: n_r(1:dim)
118 integer(c_int) :: inembed(1:dim), onembed(1:dim)
119 integer(c_int) :: istride, ostride, idist, odist
123 assert(sign == fftw_forward .or. sign == fftw_backward)
125 aligned_memory = .false.
126 if (
present(din_) .or.
present(cin_))
then
127 assert(
present(cout_))
128 assert(
present(din_) .neqv.
present(cin_))
129 aligned_memory = .
true.
131 assert(
present(din_))
133 assert(
present(cin_))
137 n_r(1:dim) = n(dim:1:-1)
138 inembed(1:dim) = n_r(1:dim)
139 onembed(1:dim) = n_r(1:dim)
150 if (sign == fftw_forward)
then
151 if (.not. aligned_memory)
then
152 safe_allocate(rin(1:n(1), 1:n(2), 1:n(3), 1:howmany))
153 safe_allocate(cout(1:n(1)/2+1, 1:n(2), 1:n(3), 1:howmany))
159 onembed(dim) = onembed(dim)/2 + 1
160 idist = product(inembed(1:dim))
161 odist = product(onembed(1:dim))
162 plan = fftw_plan_many_dft_r2c(dim, n_r, howmany, &
163 rin, inembed, istride, idist, &
164 cout, onembed, ostride, odist, &
166 assert(c_associated(plan))
168 if (.not. aligned_memory)
then
169 safe_deallocate_p(rin)
170 safe_deallocate_p(cout)
175 if (.not. aligned_memory)
then
176 safe_allocate(cin(1:n(1)/2+1, 1:n(2), 1:n(3), 1:howmany))
177 safe_allocate(rout(1:n(1), 1:n(2), 1:n(3), 1:howmany))
183 inembed(dim) = inembed(dim)/2 + 1
184 idist = product(inembed(1:dim))
185 odist = product(onembed(1:dim))
186 plan = fftw_plan_many_dft_c2r(dim, n_r, howmany, &
187 cin, inembed, istride, idist, &
188 rout, onembed, ostride, odist, &
190 assert(c_associated(plan))
192 if (.not. aligned_memory)
then
193 safe_deallocate_p(cin)
194 safe_deallocate_p(rout)
200 if (.not. aligned_memory)
then
201 safe_allocate(cin(1:n(1), 1:n(2), 1:n(3), 1:howmany))
202 safe_allocate(cout(1:n(1), 1:n(2), 1:n(3), 1:howmany))
204 if (sign == fftw_forward)
then
213 idist = product(inembed(1:dim))
214 odist = product(onembed(1:dim))
215 plan = fftw_plan_many_dft(dim, n_r, howmany, &
216 cin, inembed, istride, idist, &
217 cout, onembed, ostride, odist, &
219 assert(c_associated(plan))
221 if (.not. aligned_memory)
then
222 safe_deallocate_p(cin)
223 safe_deallocate_p(cout)
234 integer,
intent(in) :: rs_n(:)
235 logical,
intent(in) :: is_real
236 integer,
intent(out) :: fs_n(:)
241 if (is_real) fs_n(1) = rs_n(1)/2 + 1
248 subroutine fftw_alloc_memory(rs_dims, is_real, fs_dims, drs_data, zrs_data, fs_data)
249 integer,
intent(in) :: rs_dims(4)
250 logical,
intent(in) :: is_real
251 integer,
intent(in) :: fs_dims(4)
252 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
253 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
254 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
256 type(c_ptr) :: address
261 address = fftw_alloc_real(int(product(rs_dims), c_size_t))
262 call c_f_pointer(address, drs_data, rs_dims)
264 address = fftw_alloc_complex(int(product(rs_dims), c_size_t))
265 call c_f_pointer(address, zrs_data, rs_dims)
268 address = fftw_alloc_complex(int(product(fs_dims), c_size_t))
269 call c_f_pointer(address, fs_data, fs_dims)
276 logical,
intent(in) :: is_real
277 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
278 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
279 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
284 if (
associated(drs_data))
then
285 call fftw_free(c_loc(drs_data))
289 if (
associated(zrs_data))
then
290 call fftw_free(c_loc(zrs_data))
294 if (
associated(fs_data))
then
295 call fftw_free(c_loc(fs_data))
subroutine, public fftw_free_memory(is_real, drs_data, zrs_data, fs_data)
subroutine, public fftw_get_dims(rs_n, is_real, fs_n)
subroutine, public fftw_prepare_plan(plan, dim, n, howmany, is_real, sign, flags, din_, cin_, cout_)
subroutine, public fftw_alloc_memory(rs_dims, is_real, fs_dims, drs_data, zrs_data, fs_data)
Allocate the FFTW work buffers from the rank-4 (batch-last) dimension arrays (see fft_pack).