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"
95 use,
intrinsic :: ieee_exceptions
97 use,
intrinsic :: iso_c_binding
118 type(c_ptr),
intent(inout) :: plan
119 integer,
intent(in) :: dim
120 integer,
contiguous,
intent(in) :: n(:)
121 integer(c_int),
intent(in) :: howmany
122 logical,
intent(in) :: is_real
123 integer,
intent(in) :: sign
124 integer,
intent(in) :: flags_
125 real(real64),
contiguous,
optional,
target,
intent(in) :: din_(:,:,:,:)
126 complex(real64),
contiguous,
optional,
target,
intent(in) :: cin_(:,:,:,:)
127 complex(real64),
contiguous,
optional,
target,
intent(in) :: cout_(:,:,:,:)
129 real(real64),
pointer,
contiguous :: rin(:,:,:,:)
130 real(real64),
pointer,
contiguous :: rout(:,:,:,:)
131 complex(real64),
pointer,
contiguous :: cin(:,:,:,:)
132 complex(real64),
pointer,
contiguous :: cout(:,:,:,:)
133 logical :: aligned_memory
134 integer(c_int) :: n_r(1:dim)
135 integer(c_int) :: inembed(1:dim), onembed(1:dim)
136 integer(c_int) :: istride, ostride, idist, odist, flags
138 logical :: halting_mode(size(ieee_all))
143 assert(sign == fftw_forward .or. sign == fftw_backward)
148 call ieee_get_halting_mode(ieee_all, halting_mode)
149 call ieee_set_halting_mode(ieee_all, .false.)
152 aligned_memory = .false.
155 if (
present(din_) .or.
present(cin_))
then
156 assert(
present(cout_))
157 assert(
present(din_) .neqv.
present(cin_))
158 aligned_memory = .
true.
160 assert(
present(din_))
162 assert(
present(cin_))
166 flags = flags_ + fftw_unaligned
169 n_r(1:dim) = n(dim:1:-1)
170 inembed(1:dim) = n_r(1:dim)
171 onembed(1:dim) = n_r(1:dim)
182 if (sign == fftw_forward)
then
183 if (.not. aligned_memory)
then
184 safe_allocate(rin(1:n(1), 1:n(2), 1:n(3), 1:howmany))
185 safe_allocate(cout(1:n(1)/2+1, 1:n(2), 1:n(3), 1:howmany))
191 onembed(dim) = onembed(dim)/2 + 1
192 idist = product(inembed(1:dim))
193 odist = product(onembed(1:dim))
194 plan = fftw_plan_many_dft_r2c(dim, n_r, howmany, &
195 rin, inembed, istride, idist, &
196 cout, onembed, ostride, odist, &
198 assert(c_associated(plan))
200 if (.not. aligned_memory)
then
201 safe_deallocate_p(rin)
202 safe_deallocate_p(cout)
207 if (.not. aligned_memory)
then
208 safe_allocate(cin(1:n(1)/2+1, 1:n(2), 1:n(3), 1:howmany))
209 safe_allocate(rout(1:n(1), 1:n(2), 1:n(3), 1:howmany))
215 inembed(dim) = inembed(dim)/2 + 1
216 idist = product(inembed(1:dim))
217 odist = product(onembed(1:dim))
218 plan = fftw_plan_many_dft_c2r(dim, n_r, howmany, &
219 cin, inembed, istride, idist, &
220 rout, onembed, ostride, odist, &
222 assert(c_associated(plan))
224 if (.not. aligned_memory)
then
225 safe_deallocate_p(cin)
226 safe_deallocate_p(rout)
232 if (.not. aligned_memory)
then
233 safe_allocate(cin(1:n(1), 1:n(2), 1:n(3), 1:howmany))
234 safe_allocate(cout(1:n(1), 1:n(2), 1:n(3), 1:howmany))
236 if (sign == fftw_forward)
then
245 idist = product(inembed(1:dim))
246 odist = product(onembed(1:dim))
247 plan = fftw_plan_many_dft(dim, n_r, howmany, &
248 cin, inembed, istride, idist, &
249 cout, onembed, ostride, odist, &
251 assert(c_associated(plan))
253 if (.not. aligned_memory)
then
254 safe_deallocate_p(cin)
255 safe_deallocate_p(cout)
262 call ieee_set_halting_mode(ieee_all, halting_mode)
270 integer,
contiguous,
intent(in) :: rs_n(:)
271 logical,
intent(in) :: is_real
272 integer,
contiguous,
intent(out) :: fs_n(:)
277 if (is_real) fs_n(1) = rs_n(1)/2 + 1
284 subroutine fftw_alloc_memory(rs_dims, is_real, fs_dims, drs_data, zrs_data, fs_data)
285 integer,
intent(in) :: rs_dims(4)
286 logical,
intent(in) :: is_real
287 integer,
intent(in) :: fs_dims(4)
288 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
289 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
290 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
292 type(c_ptr) :: address
297 address = fftw_alloc_real(int(product(rs_dims), c_size_t))
298 call c_f_pointer(address, drs_data, rs_dims)
300 address = fftw_alloc_complex(int(product(rs_dims), c_size_t))
301 call c_f_pointer(address, zrs_data, rs_dims)
304 address = fftw_alloc_complex(int(product(fs_dims), c_size_t))
305 call c_f_pointer(address, fs_data, fs_dims)
312 logical,
intent(in) :: is_real
313 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
314 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
315 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
320 if (
associated(drs_data))
then
321 call fftw_free(c_loc(drs_data))
325 if (
associated(zrs_data))
then
326 call fftw_free(c_loc(zrs_data))
330 if (
associated(fs_data))
then
331 call fftw_free(c_loc(fs_data))
343 type(c_ptr),
intent(inout) :: plan
344 integer,
intent(in) :: dim
345 integer,
contiguous,
intent(in) :: n(:)
346 integer(c_int),
intent(in) :: howmany
347 logical,
intent(in) :: is_real
348 integer,
intent(in) :: sign
349 integer,
intent(in) :: flags
350 real(real32),
contiguous,
optional,
target,
intent(in) :: sin_(:,:,:,:)
351 complex(real32),
contiguous,
optional,
target,
intent(in) :: cin_(:,:,:,:)
352 complex(real32),
contiguous,
optional,
target,
intent(in) :: cout_(:,:,:,:)
354 real(real32),
pointer,
contiguous :: rin(:,:,:,:), rout(:,:,:,:)
355 complex(real32),
pointer,
contiguous :: cin(:,:,:,:), cout(:,:,:,:)
356 integer(c_int) :: n_r(1:dim)
357 integer(c_int) :: inembed(1:dim), onembed(1:dim)
358 integer(c_int) :: istride, ostride, idist, odist
360 logical :: halting_mode(size(ieee_all))
365 assert(sign == fftw_forward .or. sign == fftw_backward)
369 call ieee_get_halting_mode(ieee_all, halting_mode)
370 call ieee_set_halting_mode(ieee_all, .false.)
373 n_r(1:dim) = n(dim:1:-1)
374 inembed(1:dim) = n_r(1:dim)
375 onembed(1:dim) = n_r(1:dim)
380 if (sign == fftw_forward)
then
383 onembed(dim) = onembed(dim)/2 + 1
384 idist = product(inembed(1:dim))
385 odist = product(onembed(1:dim))
386 plan = fftwf_plan_many_dft_r2c(dim, n_r, howmany, &
387 rin, inembed, istride, idist, cout, onembed, ostride, odist, flags)
391 inembed(dim) = inembed(dim)/2 + 1
392 idist = product(inembed(1:dim))
393 odist = product(onembed(1:dim))
394 plan = fftwf_plan_many_dft_c2r(dim, n_r, howmany, &
395 cin, inembed, istride, idist, rout, onembed, ostride, odist, flags)
398 if (sign == fftw_forward)
then
405 idist = product(inembed(1:dim))
406 odist = product(onembed(1:dim))
407 plan = fftwf_plan_many_dft(dim, n_r, howmany, &
408 cin, inembed, istride, idist, cout, onembed, ostride, odist, sign, flags)
410 assert(c_associated(plan))
413 call ieee_set_halting_mode(ieee_all, halting_mode)
421 integer,
intent(in) :: rs_dims(4)
422 logical,
intent(in) :: is_real
423 integer,
intent(in) :: fs_dims(4)
424 real(real32),
pointer,
intent(inout) :: srs_data(:,:,:,:)
425 complex(real32),
pointer,
intent(inout) :: crs_data(:,:,:,:)
426 complex(real32),
pointer,
intent(inout) :: cfs_data(:,:,:,:)
428 type(c_ptr) :: address
433 address = fftwf_alloc_real(int(product(rs_dims), c_size_t))
434 call c_f_pointer(address, srs_data, rs_dims)
436 address = fftwf_alloc_complex(int(product(rs_dims), c_size_t))
437 call c_f_pointer(address, crs_data, rs_dims)
440 address = fftwf_alloc_complex(int(product(fs_dims), c_size_t))
441 call c_f_pointer(address, cfs_data, fs_dims)
448 logical,
intent(in) :: is_real
449 real(real32),
pointer,
intent(inout) :: srs_data(:,:,:,:)
450 complex(real32),
pointer,
intent(inout) :: crs_data(:,:,:,:)
451 complex(real32),
pointer,
intent(inout) :: cfs_data(:,:,:,:)
456 if (
associated(srs_data))
then
457 call fftwf_free(c_loc(srs_data))
461 if (
associated(crs_data))
then
462 call fftwf_free(c_loc(crs_data))
466 if (
associated(cfs_data))
then
467 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).