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_dft_1d, &
40 fftw_plan_dft_2d, &
41 fftw_plan_dft_3d, &
42 fftw_plan_dft_r2c_1d, &
43 fftw_plan_dft_r2c_2d, &
44 fftw_plan_dft_r2c_3d, &
45 fftw_plan_dft_c2r_1d, &
46 fftw_plan_dft_c2r_2d, &
47 fftw_plan_dft_c2r_3d, &
48 fftw_plan_r2r_1d, &
49 c_fftw_r2r_kind, &
50 fftw_r2hc, &
51 fftw_hc2r, &
52 fftw_dht, &
53 fftw_redft00, &
54 fftw_redft01, &
55 fftw_redft10, &
56 fftw_redft11, &
57 fftw_rodft00, &
58 fftw_rodft01, &
59 fftw_rodft10, &
60 fftw_rodft11, &
61 fftw_forward, &
62 fftw_backward, &
63 fftw_measure, &
64 fftw_estimate, &
65 fftw_destroy_input, &
66 fftw_unaligned
67#ifdef HAVE_FFTW3_MPI
68 public :: fftw_mpi_default_block
69#endif
70#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
71 public :: &
72 fftw_init_threads, &
73 fftw_plan_with_nthreads, &
74 fftw_cleanup_threads
75#endif
76
77
78#ifdef HAVE_FFTW3_MPI
79 include "fftw3-mpi.f03"
80#else
81 include "fftw3.f03"
82#endif
83end module fftw_params_oct_m
84
85module fftw_oct_m
87 use debug_oct_m
88 use global_oct_m
89 use, intrinsic :: iso_c_binding
92 implicit none
93
94 private
95
96 public :: &
101
102
103contains
104
105 ! ---------------------------------------------------------
106 subroutine fftw_prepare_plan(plan, dim, n, is_real, sign, flags, din_, cin_, cout_)
107 type(c_ptr), intent(inout) :: plan
108 integer, intent(in) :: dim
109 integer, intent(in) :: n(:)
110 logical, intent(in) :: is_real
111 integer, intent(in) :: sign
112 integer, intent(in) :: flags
113 real(real64), optional, target, intent(in) :: din_(:,:,:)
114 complex(real64), optional, target, intent(in) :: cin_(:,:,:)
115 complex(real64), optional, target, intent(in) :: cout_(:,:,:)
116
117 real(real64), pointer :: rin(:,:,:)
118 real(real64), pointer :: rout(:,:,:)
119 complex(real64), pointer :: cin(:,:,:)
120 complex(real64), pointer :: cout(:,:,:)
121 logical :: aligned_memory
122
123 push_sub(fftw_prepare_plan)
124
125 assert(sign == fftw_forward .or. sign == fftw_backward)
126
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.
132 if (is_real) then
133 assert(present(din_))
134 else
135 assert(present(cin_))
136 end if
137 end if
138
139 if (is_real) then
140 if (sign == fftw_forward) then
141 if (.not. aligned_memory) then
142 safe_allocate(rin(1:n(1), 1:n(2), 1:n(3)))
143 safe_allocate(cout(1:n(1)/2+1, 1:n(2), 1:n(3)))
144 else
145 rin => din_
146 cout => cout_
147 end if
148
149 select case (dim)
150 case (1)
151 plan = fftw_plan_dft_r2c_1d(n(1), rin, cout, flags)
152 case (2)
153 plan = fftw_plan_dft_r2c_2d(n(2), n(1),rin, cout, flags)
154 case (3)
155 plan = fftw_plan_dft_r2c_3d(n(3), n(2), n(1), rin, cout, flags)
156 end select
157
158 if (.not. aligned_memory) then
159 safe_deallocate_p(rin)
160 safe_deallocate_p(cout)
161 else
162 nullify(rin, cout)
163 end if
164 else
165 if (.not. aligned_memory) then
166 safe_allocate(cin(1:n(1)/2+1, 1:n(2), 1:n(3)))
167 safe_allocate(rout(1:n(1), 1:n(2), 1:n(3)))
168 else
169 cin => cout_
170 rout => din_
171 end if
172
173 select case (dim)
174 case (1)
175 plan = fftw_plan_dft_c2r_1d(n(1), cin, rout, flags)
176 case (2)
177 plan = fftw_plan_dft_c2r_2d(n(2), n(1), cin, rout, flags)
178 case (3)
179 plan = fftw_plan_dft_c2r_3d(n(3), n(2), n(1), cin, rout, flags)
180 end select
181
182 if (.not. aligned_memory) then
183 safe_deallocate_p(cin)
184 safe_deallocate_p(rout)
185 else
186 nullify(cin,rout)
187 end if
188 end if
189 else
190 if (.not. aligned_memory) then
191 safe_allocate(cin(1:n(1), 1:n(2), 1:n(3)))
192 safe_allocate(cout(1:n(1), 1:n(2), 1:n(3)))
193 else
194 if (sign == fftw_forward) then
195 cin => cin_
196 cout => cout_
197 else
198 cout => cin_
199 cin => cout_
200 end if
201 end if
202
203 select case (dim)
204 case (1)
205 plan = fftw_plan_dft_1d(n(1), cin, cout, sign, flags)
206 case (2)
207 plan = fftw_plan_dft_2d(n(2), n(1), cin, cout, sign, flags)
208 case (3)
209 plan = fftw_plan_dft_3d(n(3), n(2), n(1), cin, cout, sign, flags)
210 end select
211
212 if (.not. aligned_memory) then
213 safe_deallocate_p(cin)
214 safe_deallocate_p(cout)
215 else
216 nullify(cin, cout)
217 end if
218 end if
219
220 pop_sub(fftw_prepare_plan)
221 end subroutine fftw_prepare_plan
222
223 ! ---------------------------------------------------------
224 subroutine fftw_get_dims(rs_n, is_real, fs_n)
225 integer, intent(in) :: rs_n(:)
226 logical, intent(in) :: is_real
227 integer, intent(out) :: fs_n(:)
228
229 push_sub(fftw_get_dims)
230
231 fs_n = rs_n
232 if (is_real) fs_n(1) = rs_n(1)/2 + 1
233
234 pop_sub(fftw_get_dims)
235 end subroutine fftw_get_dims
236
237 ! ---------------------------------------------------------
238 subroutine fftw_alloc_memory(rs_n, is_real, fs_n, drs_data, zrs_data, fs_data)
239 integer, intent(in) :: rs_n(:)
240 logical, intent(in) :: is_real
241 integer, intent(in) :: fs_n(:)
242 real(real64), pointer, intent(inout) :: drs_data(:,:,:)
243 complex(real64), pointer, intent(inout) :: zrs_data(:,:,:)
244 complex(real64), pointer, intent(inout) :: fs_data(:,:,:)
245 type(c_ptr) :: address
246
247 push_sub(fftw_alloc_memory)
248
249 if (is_real) then
250 address = fftw_alloc_real(int(product(rs_n(1:3)), c_size_t))
251 call c_f_pointer(address, drs_data, rs_n)
252 else
253 address = fftw_alloc_complex(int(product(rs_n(1:3)), c_size_t))
254 call c_f_pointer(address, zrs_data, rs_n)
255 end if
256 address = fftw_alloc_complex(int(product(fs_n(1:3)), c_size_t))
257 call c_f_pointer(address, fs_data, fs_n)
258
259 pop_sub(fftw_alloc_memory)
260 end subroutine fftw_alloc_memory
261
262 ! ---------------------------------------------------------
263 subroutine fftw_free_memory(is_real, drs_data, zrs_data, fs_data)
264 logical, intent(in) :: is_real
265 real(real64), pointer, intent(inout) :: drs_data(:,:,:)
266 complex(real64), pointer, intent(inout) :: zrs_data(:,:,:)
267 complex(real64), pointer, intent(inout) :: fs_data(:,:,:)
268
269 push_sub(fftw_free_memory)
270
271 if (is_real) then
272 call fftw_free(c_loc(drs_data))
273 nullify(drs_data)
274 else
275 call fftw_free(c_loc(zrs_data))
276 nullify(zrs_data)
277 end if
278 call fftw_free(c_loc(fs_data))
279 nullify(fs_data)
280
281 pop_sub(fftw_free_memory)
282 end subroutine fftw_free_memory
283
284end module fftw_oct_m
285
286!! Local Variables:
287!! mode: f90
288!! coding: utf-8
289!! End:
subroutine, public fftw_prepare_plan(plan, dim, n, is_real, sign, flags, din_, cin_, cout_)
Definition: fftw.F90:187
subroutine, public fftw_free_memory(is_real, drs_data, zrs_data, fs_data)
Definition: fftw.F90:344
subroutine, public fftw_get_dims(rs_n, is_real, fs_n)
Definition: fftw.F90:305
subroutine, public fftw_alloc_memory(rs_n, is_real, fs_n, drs_data, zrs_data, fs_data)
Definition: fftw.F90:319
int true(void)