Octopus
fftw.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2011 M. Oliveira
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
23 use, intrinsic :: iso_c_binding
24 implicit none
25
26 private
27
28 ! make public some needed symbols from the FFTW library
29 public :: &
30 fftw_cleanup, &
31 fftw_execute_dft, &
32 fftw_execute_dft_c2r, &
33 fftw_execute_dft_r2c, &
34 fftw_execute_r2r, &
35 fftw_destroy_plan, &
36 fftw_alloc_real, &
37 fftw_alloc_complex, &
38 fftw_free, &
39 fftw_plan_many_dft, &
40 fftw_plan_many_dft_r2c, &
41 fftw_plan_many_dft_c2r, &
42 fftw_plan_r2r_1d, &
43 c_fftw_r2r_kind, &
44 fftw_r2hc, &
45 fftw_hc2r, &
46 fftw_dht, &
47 fftw_redft00, &
48 fftw_redft01, &
49 fftw_redft10, &
50 fftw_redft11, &
51 fftw_rodft00, &
52 fftw_rodft01, &
53 fftw_rodft10, &
54 fftw_rodft11, &
55 fftw_forward, &
56 fftw_backward, &
57 fftw_measure, &
58 fftw_estimate, &
59 fftw_destroy_input, &
60 fftw_unaligned
61#ifdef HAVE_FFTW3_MPI
62 public :: fftw_mpi_default_block
63#endif
64#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
65 public :: &
66 fftw_init_threads, &
67 fftw_plan_with_nthreads, &
68 fftw_cleanup_threads
69#endif
70
71
72#ifdef HAVE_FFTW3_MPI
73 include "fftw3-mpi.f03"
74#else
75 include "fftw3.f03"
76#endif
77end module fftw_params_oct_m
78
79module fftw_oct_m
81 use debug_oct_m
82 use global_oct_m
83 use, intrinsic :: iso_c_binding
86 implicit none
87
88 private
89
90 public :: &
95
96
97contains
98
99 ! ---------------------------------------------------------
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_(:,:,:,:)
111
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
120
121 push_sub(fftw_prepare_plan)
122
123 assert(sign == fftw_forward .or. sign == fftw_backward)
124
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.
130 if (is_real) then
131 assert(present(din_))
132 else
133 assert(present(cin_))
134 end if
135 end if
136
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)
140 ! batch-last: each transform is contiguous (istride = 1) and the transforms are a whole grid
141 ! apart (idist = product of the per-transform extents). Because the real and complex grids
142 ! differ in size for r2c/c2r, idist/odist are finalized per branch below, once inembed/onembed
143 ! have been halved.
144 istride = 1_c_int
145 ostride = 1_c_int
146 idist = 1_c_int ! set below
147 odist = 1_c_int ! set below
148
149 if (is_real) then
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))
154 else
155 rin => din_
156 cout => cout_
157 end if
158
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, &
165 flags)
166 assert(c_associated(plan))
167
168 if (.not. aligned_memory) then
169 safe_deallocate_p(rin)
170 safe_deallocate_p(cout)
171 else
172 nullify(rin, cout)
173 end if
174 else
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))
178 else
179 cin => cout_
180 rout => din_
181 end if
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, &
189 flags)
190 assert(c_associated(plan))
191
192 if (.not. aligned_memory) then
193 safe_deallocate_p(cin)
194 safe_deallocate_p(rout)
195 else
196 nullify(cin,rout)
197 end if
198 end if
199 else
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))
203 else
204 if (sign == fftw_forward) then
205 cin => cin_
206 cout => cout_
207 else
208 cout => cin_
209 cin => cout_
210 end if
211 end if
212
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, &
218 sign, flags)
219 assert(c_associated(plan))
220
221 if (.not. aligned_memory) then
222 safe_deallocate_p(cin)
223 safe_deallocate_p(cout)
224 else
225 nullify(cin, cout)
226 end if
227 end if
228
229 pop_sub(fftw_prepare_plan)
230 end subroutine fftw_prepare_plan
231
232 ! ---------------------------------------------------------
233 subroutine fftw_get_dims(rs_n, is_real, fs_n)
234 integer, intent(in) :: rs_n(:)
235 logical, intent(in) :: is_real
236 integer, intent(out) :: fs_n(:)
237
238 push_sub(fftw_get_dims)
239
240 fs_n = rs_n
241 if (is_real) fs_n(1) = rs_n(1)/2 + 1
242
243 pop_sub(fftw_get_dims)
244 end subroutine fftw_get_dims
245
246 ! ---------------------------------------------------------
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(:,:,:,:)
255
256 type(c_ptr) :: address
257
258 push_sub(fftw_alloc_memory)
259
260 if (is_real) then
261 address = fftw_alloc_real(int(product(rs_dims), c_size_t))
262 call c_f_pointer(address, drs_data, rs_dims)
263 else
264 address = fftw_alloc_complex(int(product(rs_dims), c_size_t))
265 call c_f_pointer(address, zrs_data, rs_dims)
266 end if
267
268 address = fftw_alloc_complex(int(product(fs_dims), c_size_t))
269 call c_f_pointer(address, fs_data, fs_dims)
270
271 pop_sub(fftw_alloc_memory)
272 end subroutine fftw_alloc_memory
273
274 ! ---------------------------------------------------------
275 subroutine fftw_free_memory(is_real, drs_data, zrs_data, fs_data)
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(:,:,:,:)
280
281 push_sub(fftw_free_memory)
282
283 if (is_real) then
284 if (associated(drs_data)) then
285 call fftw_free(c_loc(drs_data))
286 nullify(drs_data)
287 end if
288 else
289 if (associated(zrs_data)) then
290 call fftw_free(c_loc(zrs_data))
291 nullify(zrs_data)
292 end if
293 end if
294 if (associated(fs_data)) then
295 call fftw_free(c_loc(fs_data))
296 nullify(fs_data)
297 end if
298
299 pop_sub(fftw_free_memory)
300 end subroutine fftw_free_memory
301
302end module fftw_oct_m
303
304!! Local Variables:
305!! mode: f90
306!! coding: utf-8
307!! End:
subroutine, public fftw_free_memory(is_real, drs_data, zrs_data, fs_data)
Definition: fftw.F90:358
subroutine, public fftw_get_dims(rs_n, is_real, fs_n)
Definition: fftw.F90:316
subroutine, public fftw_prepare_plan(plan, dim, n, howmany, is_real, sign, flags, din_, cin_, cout_)
Definition: fftw.F90:183
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).
Definition: fftw.F90:331
int true(void)