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, batch_axis, 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 integer,
intent(in) :: batch_axis
106 logical,
intent(in) :: is_real
107 integer,
intent(in) :: sign
108 integer,
intent(in) :: flags
109 real(real64),
optional,
target,
intent(in) :: din_(:,:,:,:)
110 complex(real64),
optional,
target,
intent(in) :: cin_(:,:,:,:)
111 complex(real64),
optional,
target,
intent(in) :: cout_(:,:,:,:)
113 real(real64),
pointer,
contiguous :: rin(:,:,:,:)
114 real(real64),
pointer,
contiguous :: rout(:,:,:,:)
115 complex(real64),
pointer,
contiguous :: cin(:,:,:,:)
116 complex(real64),
pointer,
contiguous :: cout(:,:,:,:)
117 logical :: aligned_memory
118 integer(c_int) :: n_r(1:dim)
119 integer(c_int) :: inembed(1:dim), onembed(1:dim)
120 integer(c_int) :: istride, ostride, idist, odist
124 assert(sign == fftw_forward .or. sign == fftw_backward)
125 assert(batch_axis == 1 .or. batch_axis == 4)
127 aligned_memory = .false.
128 if (
present(din_) .or.
present(cin_))
then
129 assert(
present(cout_))
130 assert(
present(din_) .neqv.
present(cin_))
131 aligned_memory = .
true.
133 assert(
present(din_))
135 assert(
present(cin_))
139 n_r(1:dim) = n(dim:1:-1)
140 inembed(1:dim) = n_r(1:dim)
141 onembed(1:dim) = n_r(1:dim)
149 if (batch_axis == 1)
then
154 else if (batch_axis == 4)
then
164 if (sign == fftw_forward)
then
165 if (.not. aligned_memory)
then
166 safe_allocate(rin(1:howmany, 1:n(1), 1:n(2), 1:n(3)))
167 safe_allocate(cout(1:howmany, 1:n(1)/2+1, 1:n(2), 1:n(3)))
173 onembed(dim) = onembed(dim)/2 + 1
174 if (batch_axis == 4)
then
175 idist = product(inembed(1:dim))
176 odist = product(onembed(1:dim))
178 plan = fftw_plan_many_dft_r2c(dim, n_r, howmany, &
179 rin, inembed, istride, idist, &
180 cout, onembed, ostride, odist, &
182 assert(c_associated(plan))
184 if (.not. aligned_memory)
then
185 safe_deallocate_p(rin)
186 safe_deallocate_p(cout)
191 if (.not. aligned_memory)
then
192 safe_allocate(cin(1:howmany, 1:n(1)/2+1, 1:n(2), 1:n(3)))
193 safe_allocate(rout(1:howmany, 1:n(1), 1:n(2), 1:n(3)))
199 inembed(dim) = inembed(dim)/2 + 1
200 if (batch_axis == 4)
then
201 idist = product(inembed(1:dim))
202 odist = product(onembed(1:dim))
204 plan = fftw_plan_many_dft_c2r(dim, n_r, howmany, &
205 cin, inembed, istride, idist, &
206 rout, onembed, ostride, odist, &
208 assert(c_associated(plan))
210 if (.not. aligned_memory)
then
211 safe_deallocate_p(cin)
212 safe_deallocate_p(rout)
218 if (.not. aligned_memory)
then
219 safe_allocate(cin(1:howmany, 1:n(1), 1:n(2), 1:n(3)))
220 safe_allocate(cout(1:howmany, 1:n(1), 1:n(2), 1:n(3)))
222 if (sign == fftw_forward)
then
231 if (batch_axis == 4)
then
232 idist = product(inembed(1:dim))
233 odist = product(onembed(1:dim))
235 plan = fftw_plan_many_dft(dim, n_r, howmany, &
236 cin, inembed, istride, idist, &
237 cout, onembed, ostride, odist, &
239 assert(c_associated(plan))
241 if (.not. aligned_memory)
then
242 safe_deallocate_p(cin)
243 safe_deallocate_p(cout)
254 integer,
intent(in) :: rs_n(:)
255 logical,
intent(in) :: is_real
256 integer,
intent(out) :: fs_n(:)
261 if (is_real) fs_n(1) = rs_n(1)/2 + 1
270 subroutine fftw_alloc_memory(rs_dims, is_real, fs_dims, drs_data, zrs_data, fs_data)
271 integer,
intent(in) :: rs_dims(4)
272 logical,
intent(in) :: is_real
273 integer,
intent(in) :: fs_dims(4)
274 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
275 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
276 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
278 type(c_ptr) :: address
283 address = fftw_alloc_real(int(product(rs_dims), c_size_t))
284 call c_f_pointer(address, drs_data, rs_dims)
286 address = fftw_alloc_complex(int(product(rs_dims), c_size_t))
287 call c_f_pointer(address, zrs_data, rs_dims)
290 address = fftw_alloc_complex(int(product(fs_dims), c_size_t))
291 call c_f_pointer(address, fs_data, fs_dims)
298 logical,
intent(in) :: is_real
299 real(real64),
pointer,
intent(inout) :: drs_data(:,:,:,:)
300 complex(real64),
pointer,
intent(inout) :: zrs_data(:,:,:,:)
301 complex(real64),
pointer,
intent(inout) :: fs_data(:,:,:,:)
306 if (
associated(drs_data))
then
307 call fftw_free(c_loc(drs_data))
311 if (
associated(zrs_data))
then
312 call fftw_free(c_loc(zrs_data))
316 if (
associated(fs_data))
then
317 call fftw_free(c_loc(fs_data))
subroutine, public fftw_free_memory(is_real, drs_data, zrs_data, fs_data)
subroutine, public fftw_prepare_plan(plan, dim, n, howmany, batch_axis, is_real, sign, flags, din_, cin_, cout_)
subroutine, public fftw_get_dims(rs_n, is_real, fs_n)
subroutine, public fftw_alloc_memory(rs_dims, is_real, fs_dims, drs_data, zrs_data, fs_data)
Allocate the FFTW work buffers. The rank-4 dimension arrays (which already carry the batch axis at th...