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, &
45 fftwf_execute_dft_c2r, &
46 fftwf_execute_dft_r2c, &
49 fftwf_alloc_complex, &
51 fftwf_plan_many_dft, &
52 fftwf_plan_many_dft_r2c, &
53 fftwf_plan_many_dft_c2r, &
73 public :: fftw_mpi_default_block
75#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
78 fftw_plan_with_nthreads, &
84 include
"fftw3-mpi.f03"
94 use,
intrinsic :: iso_c_binding
114 subroutine fftw_prepare_plan(plan, dim, n, howmany, is_real, sign, flags_, din_, cin_, cout_)
115 type(c_ptr),
intent(inout) :: plan
116 integer,
intent(in) :: dim
117 integer,
contiguous,
intent(in) :: n(:)
118 integer(c_int),
intent(in) :: howmany
119 logical,
intent(in) :: is_real
120 integer,
intent(in) :: sign
121 integer,
intent(in) :: flags_
122 real(real64),
contiguous,
optional,
target,
intent(in) :: din_(:,:,:,:)
123 complex(real64),
contiguous,
optional,
target,
intent(in) :: cin_(:,:,:,:)
124 complex(real64),
contiguous,
optional,
target,
intent(in) :: cout_(:,:,:,:)
126 real(real64),
pointer,
contiguous :: rin(:,:,:,:)
127 real(real64),
pointer,
contiguous :: rout(:,:,:,:)
128 complex(real64),
pointer,
contiguous :: cin(:,:,:,:)
129 complex(real64),
pointer,
contiguous :: cout(:,:,:,:)
130 logical :: aligned_memory
131 integer(c_int) :: n_r(1:dim)
132 integer(c_int) :: inembed(1:dim), onembed(1:dim)
133 integer(c_int) :: istride, ostride, idist, odist, flags
137 assert(sign == fftw_forward .or. sign == fftw_backward)
139 aligned_memory = .false.
142 if (
present(din_) .or.
present(cin_))
then
143 assert(
present(cout_))
144 assert(
present(din_) .neqv.
present(cin_))
145 aligned_memory = .
true.
147 assert(
present(din_))
149 assert(
present(cin_))
153 flags = flags_ + fftw_unaligned
156 n_r(1:dim) = n(dim:1:-1)
157 inembed(1:dim) = n_r(1:dim)
158 onembed(1:dim) = n_r(1:dim)
169 if (sign == fftw_forward)
then
170 if (.not. aligned_memory)
then
171 safe_allocate(rin(1:n(1), 1:n(2), 1:n(3), 1:howmany))
172 safe_allocate(cout(1:n(1)/2+1, 1:n(2), 1:n(3), 1:howmany))
178 onembed(dim) = onembed(dim)/2 + 1
179 idist = product(inembed(1:dim))
180 odist = product(onembed(1:dim))
181 plan = fftw_plan_many_dft_r2c(dim, n_r, howmany, &
182 rin, inembed, istride, idist, &
183 cout, onembed, ostride, odist, &
185 assert(c_associated(plan))
187 if (.not. aligned_memory)
then
188 safe_deallocate_p(rin)
189 safe_deallocate_p(cout)
194 if (.not. aligned_memory)
then
195 safe_allocate(cin(1:n(1)/2+1, 1:n(2), 1:n(3), 1:howmany))
196 safe_allocate(rout(1:n(1), 1:n(2), 1:n(3), 1:howmany))
202 inembed(dim) = inembed(dim)/2 + 1
203 idist = product(inembed(1:dim))
204 odist = product(onembed(1:dim))
205 plan = fftw_plan_many_dft_c2r(dim, n_r, howmany, &
206 cin, inembed, istride, idist, &
207 rout, onembed, ostride, odist, &
209 assert(c_associated(plan))
211 if (.not. aligned_memory)
then
212 safe_deallocate_p(cin)
213 safe_deallocate_p(rout)
219 if (.not. aligned_memory)
then
220 safe_allocate(cin(1:n(1), 1:n(2), 1:n(3), 1:howmany))
221 safe_allocate(cout(1:n(1), 1:n(2), 1:n(3), 1:howmany))
223 if (sign == fftw_forward)
then
232 idist = product(inembed(1:dim))
233 odist = product(onembed(1:dim))
234 plan = fftw_plan_many_dft(dim, n_r, howmany, &
235 cin, inembed, istride, idist, &
236 cout, onembed, ostride, odist, &
238 assert(c_associated(plan))
240 if (.not. aligned_memory)
then
241 safe_deallocate_p(cin)
242 safe_deallocate_p(cout)
253 integer,
contiguous,
intent(in) :: rs_n(:)
254 logical,
intent(in) :: is_real
255 integer,
contiguous,
intent(out) :: fs_n(:)
260 if (is_real) fs_n(1) = rs_n(1)/2 + 1
267 subroutine fftw_alloc_memory(rs_dims, is_real, fs_dims, drs_data, zrs_data, fs_data)
268 integer,
intent(in) :: rs_dims(4)
269 logical,
intent(in) :: is_real
270 integer,
intent(in) :: fs_dims(4)
271 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
272 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
273 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
275 type(c_ptr) :: address
280 address = fftw_alloc_real(int(product(rs_dims), c_size_t))
281 call c_f_pointer(address, drs_data, rs_dims)
283 address = fftw_alloc_complex(int(product(rs_dims), c_size_t))
284 call c_f_pointer(address, zrs_data, rs_dims)
287 address = fftw_alloc_complex(int(product(fs_dims), c_size_t))
288 call c_f_pointer(address, fs_data, fs_dims)
295 logical,
intent(in) :: is_real
296 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
297 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
298 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
303 if (
associated(drs_data))
then
304 call fftw_free(c_loc(drs_data))
308 if (
associated(zrs_data))
then
309 call fftw_free(c_loc(zrs_data))
313 if (
associated(fs_data))
then
314 call fftw_free(c_loc(fs_data))
326 type(c_ptr),
intent(inout) :: plan
327 integer,
intent(in) :: dim
328 integer,
contiguous,
intent(in) :: n(:)
329 integer(c_int),
intent(in) :: howmany
330 logical,
intent(in) :: is_real
331 integer,
intent(in) :: sign
332 integer,
intent(in) :: flags
333 real(real32),
contiguous,
optional,
target,
intent(in) :: sin_(:,:,:,:)
334 complex(real32),
contiguous,
optional,
target,
intent(in) :: cin_(:,:,:,:)
335 complex(real32),
contiguous,
optional,
target,
intent(in) :: cout_(:,:,:,:)
337 real(real32),
pointer,
contiguous :: rin(:,:,:,:), rout(:,:,:,:)
338 complex(real32),
pointer,
contiguous :: cin(:,:,:,:), cout(:,:,:,:)
339 integer(c_int) :: n_r(1:dim)
340 integer(c_int) :: inembed(1:dim), onembed(1:dim)
341 integer(c_int) :: istride, ostride, idist, odist
345 assert(sign == fftw_forward .or. sign == fftw_backward)
347 n_r(1:dim) = n(dim:1:-1)
348 inembed(1:dim) = n_r(1:dim)
349 onembed(1:dim) = n_r(1:dim)
354 if (sign == fftw_forward)
then
357 onembed(dim) = onembed(dim)/2 + 1
358 idist = product(inembed(1:dim))
359 odist = product(onembed(1:dim))
360 plan = fftwf_plan_many_dft_r2c(dim, n_r, howmany, &
361 rin, inembed, istride, idist, cout, onembed, ostride, odist, flags)
365 inembed(dim) = inembed(dim)/2 + 1
366 idist = product(inembed(1:dim))
367 odist = product(onembed(1:dim))
368 plan = fftwf_plan_many_dft_c2r(dim, n_r, howmany, &
369 cin, inembed, istride, idist, rout, onembed, ostride, odist, flags)
372 if (sign == fftw_forward)
then
379 idist = product(inembed(1:dim))
380 odist = product(onembed(1:dim))
381 plan = fftwf_plan_many_dft(dim, n_r, howmany, &
382 cin, inembed, istride, idist, cout, onembed, ostride, odist, sign, flags)
384 assert(c_associated(plan))
391 integer,
intent(in) :: rs_dims(4)
392 logical,
intent(in) :: is_real
393 integer,
intent(in) :: fs_dims(4)
394 real(real32),
pointer,
intent(inout) :: srs_data(:,:,:,:)
395 complex(real32),
pointer,
intent(inout) :: crs_data(:,:,:,:)
396 complex(real32),
pointer,
intent(inout) :: cfs_data(:,:,:,:)
398 type(c_ptr) :: address
403 address = fftwf_alloc_real(int(product(rs_dims), c_size_t))
404 call c_f_pointer(address, srs_data, rs_dims)
406 address = fftwf_alloc_complex(int(product(rs_dims), c_size_t))
407 call c_f_pointer(address, crs_data, rs_dims)
410 address = fftwf_alloc_complex(int(product(fs_dims), c_size_t))
411 call c_f_pointer(address, cfs_data, fs_dims)
418 logical,
intent(in) :: is_real
419 real(real32),
pointer,
intent(inout) :: srs_data(:,:,:,:)
420 complex(real32),
pointer,
intent(inout) :: crs_data(:,:,:,:)
421 complex(real32),
pointer,
intent(inout) :: cfs_data(:,:,:,:)
426 if (
associated(srs_data))
then
427 call fftwf_free(c_loc(srs_data))
431 if (
associated(crs_data))
then
432 call fftwf_free(c_loc(crs_data))
436 if (
associated(cfs_data))
then
437 call fftwf_free(c_loc(cfs_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_single(plan, dim, n, howmany, is_real, sign, flags, sin_, cin_, cout_)
Single-precision counterpart of fftw_prepare_plan. Only the aligned-memory path is supported (the sin...
subroutine, public fftw_alloc_memory_single(rs_dims, is_real, fs_dims, srs_data, crs_data, cfs_data)
subroutine, public fftw_free_memory_single(is_real, srs_data, crs_data, cfs_data)
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).