Octopus
pfft.F90
Go to the documentation of this file.
1!! Copyright (C) 2011 J. Alberdi-Rodriguez, P. Garcia RisueƱo, M. Oliveira
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
23 use, intrinsic :: iso_c_binding
25 implicit none
26
27 private
28
29#ifdef HAVE_PFFT
30
31 ! make public some symbols from the pfft library
32 public :: &
33 pfft_cleanup, &
34 pfft_create_procmesh_2d, &
35 pfft_destroy_plan, &
36 pfft_execute, &
37 pfft_init, &
38 pfft_local_size_many_dft_r2c, &
39 pfft_local_size_many_dft, &
40 pfft_plan_many_dft_c2r, &
41 pfft_plan_many_dft_r2c, &
42 pfft_plan_many_dft, &
43 pfft_int, &
44 pfft_ptrdiff_t, &
45 pfft_float, &
46 pfft_double, &
47 pfft_ldouble, &
48 pfft_unsigned, &
49 pfft_transposed_in, &
50 pfft_transposed_out, &
51 pfft_estimate, &
52 pfft_tune, &
53 pfft_destroy_input, &
54 pfft_measure, &
55 pfft_forward, &
56 pfft_backward
57
61#ifndef HAVE_FFTW3_MPI
62 integer(C_INTPTR_T), parameter :: FFTW_MPI_DEFAULT_BLOCK = 0
63#endif
64 include "pfft.f03"
65#endif
66
67end module pfft_params_oct_m
68
71module pfft_oct_m
72 use debug_oct_m
73 use global_oct_m
74 use, intrinsic :: iso_c_binding
75 use math_oct_m
78
79 implicit none
80
81 private
82
83 public :: &
89
90contains
91
92 ! ---------------------------------------------------------
94 subroutine pfft_decompose(n_proc, dim1, dim2)
95 integer, intent(in) :: n_proc
96 integer, intent(out) :: dim1
97 integer, intent(out) :: dim2
98
99 integer :: np, i
100
101 push_sub(pfft_decompose)
102
103 assert(n_proc > 0)
104
105 dim1 = 1
106 dim2 = 1
107 np = n_proc
108 i = n_proc-1
109
110 if (is_prime(n_proc)) then
111 dim1 = n_proc
112 else
113 do
114 if (i <= 1) exit
115 if (mod(np,i) /= 0.or.(.not. is_prime(i))) then
116 i=i-1
117 cycle
118 end if
119 np=np/i
120 if (dim1 <= dim2) then
121 dim1 = dim1*i
122 else
123 dim2 = dim2*i
124 end if
125 end do
126 end if
127
128 assert(dim1*dim2 == n_proc)
129
130 pop_sub(pfft_decompose)
131 end subroutine pfft_decompose
132
133 ! ---------------------------------------------------------
135 subroutine pfft_prepare_plan_r2c(plan, n, in, out, fft_sign, flags, mpi_comm, howmany)
136 type(C_PTR), intent(out) :: plan
137 integer, intent(in) :: n(:)
138 real(real64), contiguous, pointer, intent(inout) :: in(:,:,:,:)
139 complex(real64), contiguous, pointer, intent(inout) :: out(:,:,:,:)
140 integer, intent(in) :: fft_sign
141 integer, intent(in) :: flags
143 integer, intent(in) :: mpi_comm
144 integer, intent(in) :: howmany
145
146 integer(C_INTPTR_T) :: tmp_n(3)
147#ifdef HAVE_PFFT
148 integer(C_INTPTR_T) :: default_blocks(3)
149#endif
150
152 call profiling_in("PFFT_PLAN_R2C")
153
154#ifdef HAVE_PFFT
155 assert(fft_sign == pfft_forward)
156#endif
157
158 tmp_n(1:3) = n(3:1:-1)
159
160#ifdef HAVE_PFFT
161 ! A per-dimension block of FFTW_MPI_DEFAULT_BLOCK (0) requests the PFFT default block
162 ! distribution (the C NULL/PFFT_DEFAULT_BLOCKS pointer cannot be passed through the
163 ! dimension(*) Fortran interface).
164 default_blocks(1:3) = 0_c_intptr_t
165 ! the three tmp_n arguments are the transform size n == n_in (embed) == n_out (embed)
166 plan = pfft_plan_many_dft_r2c(3, tmp_n, tmp_n, tmp_n, int(howmany, c_intptr_t), &
167 default_blocks, default_blocks, in, out, mpi_comm, fft_sign, &
168 pfft_transposed_out + pfft_measure + pfft_destroy_input + pfft_tune)
169#else
170 plan = c_null_ptr
171#endif
172
173 call profiling_out("PFFT_PLAN_R2C")
174 pop_sub(pfft_prepare_plan_r2c)
175 end subroutine pfft_prepare_plan_r2c
176
177 ! ---------------------------------------------------------
179 subroutine pfft_prepare_plan_c2r(plan, n, in, out, fft_sign, flags, mpi_comm, howmany)
180 type(c_ptr), intent(out) :: plan
181 integer, intent(in) :: n(:)
182 complex(real64), contiguous, pointer, intent(inout) :: in(:,:,:,:)
183 real(real64), contiguous, pointer, intent(inout) :: out(:,:,:,:)
184 integer, intent(in) :: fft_sign
186 integer, intent(in) :: flags
188 integer, intent(in) :: mpi_comm
189 integer, intent(in) :: howmany
190
191 integer(C_INTPTR_T) :: tmp_n(3)
192#ifdef HAVE_PFFT
193 integer(C_INTPTR_T) :: default_blocks(3)
194#endif
195 push_sub(pfft_prepare_plan_c2r)
196 call profiling_in("PFFT_PLAN_C2R")
197
198#ifdef HAVE_PFFT
199 assert(fft_sign == pfft_backward)
200#endif
201
202 tmp_n(1:3) = n(3:1:-1)
203
204#ifdef HAVE_PFFT
205 default_blocks(1:3) = 0_c_intptr_t
206 ! the three tmp_n arguments are the transform size n == n_in (embed) == n_out (embed)
207 plan = pfft_plan_many_dft_c2r(3, tmp_n, tmp_n, tmp_n, int(howmany, c_intptr_t), &
208 default_blocks, default_blocks, in, out, mpi_comm, fft_sign, &
209 pfft_transposed_in + pfft_measure + pfft_destroy_input + pfft_tune)
210#else
211 plan = c_null_ptr
212#endif
213
214 call profiling_out("PFFT_PLAN_C2R")
215 pop_sub(pfft_prepare_plan_c2r)
216 end subroutine pfft_prepare_plan_c2r
217
218 ! ---------------------------------------------------------
220 subroutine pfft_prepare_plan_c2c(plan, n, in, out, fft_sign, flags, mpi_comm, howmany)
221 type(c_ptr), intent(out) :: plan
222 integer, intent(in) :: n(:)
223 complex(real64), contiguous, pointer, intent(inout) :: in(:,:,:,:)
224 complex(real64), contiguous, pointer, intent(inout) :: out(:,:,:,:)
225 integer, intent(in) :: fft_sign
227 integer, intent(in) :: flags
229 integer, intent(in) :: mpi_comm
230 integer, intent(in) :: howmany
231
232#ifdef HAVE_PFFT
233 integer(C_INT) :: pfft_flags
234 integer(C_INTPTR_T) :: default_blocks(3)
235#endif
236 integer(C_INTPTR_T) :: tmp_n(3)
237
238 push_sub(pfft_prepare_plan_c2c)
239
240 tmp_n(1:3) = n(3:1:-1)
241
242#ifdef HAVE_PFFT
243 if (fft_sign == pfft_forward) then
244 pfft_flags = pfft_transposed_out
245 else
246 pfft_flags = pfft_transposed_in
247 end if
248
249 default_blocks(1:3) = 0_c_intptr_t
250 ! the three tmp_n arguments are the transform size n == n_in (embed) == n_out (embed)
251 plan = pfft_plan_many_dft(3, tmp_n, tmp_n, tmp_n, int(howmany, c_intptr_t), &
252 default_blocks, default_blocks, in, out, mpi_comm, fft_sign, pfft_flags)
253#else
254 plan = c_null_ptr
255#endif
256
257 pop_sub(pfft_prepare_plan_c2c)
258 end subroutine pfft_prepare_plan_c2c
259
260 ! ---------------------------------------------------------
261 subroutine pfft_get_dims(rs_n_global, mpi_comm, is_real, alloc_size, fs_n_global, rs_n, fs_n, rs_istart, fs_istart, howmany)
262 integer, intent(in) :: rs_n_global(1:3)
263 integer, intent(in) :: mpi_comm
264 logical, intent(in) :: is_real
265 integer(int64), intent(out) :: alloc_size
266 integer, intent(out) :: fs_n_global(1:3)
267 integer, intent(out) :: rs_n(1:3)
268 integer, intent(out) :: fs_n(1:3)
269 integer, intent(out) :: rs_istart(1:3)
270 integer, intent(out) :: fs_istart(1:3)
271 integer, intent(in) :: howmany
272
273 integer(C_INTPTR_T) :: tmp_alloc_size, tmp_n(3)
274 integer(C_INTPTR_T) :: tmp_rs_n(3), tmp_rs_istart(3)
275 integer(C_INTPTR_T) :: tmp_fs_n(3), tmp_fs_istart(3)
276#ifdef HAVE_PFFT
277 integer(C_INTPTR_T) :: default_blocks(3)
278#endif
279
280 push_sub(pfft_get_dims)
281
282 fs_n_global(1:3) = rs_n_global(1:3)
283 ! if calling the ISO_C_BINDING routines from PFFT, one must take into account that
284 ! the array order is the C array order
285 tmp_n(1:3) = rs_n_global(3:1:-1)
286
287 tmp_alloc_size = 0
288#ifdef HAVE_PFFT
289 ! A per-dimension block of FFTW_MPI_DEFAULT_BLOCK (0) requests the PFFT default block
290 ! distribution (equivalent to passing the C NULL/PFFT_DEFAULT_BLOCKS pointer, which cannot be
291 ! expressed through the dimension(*) Fortran interface). The local grid dims
292 ! (tmp_rs_n/tmp_fs_n) are independent of howmany; tmp_alloc_size is the total local element
293 ! count including the howmany batch.
294 default_blocks(1:3) = 0_c_intptr_t
295 if (is_real) then
296 tmp_alloc_size = pfft_local_size_many_dft_r2c(3, tmp_n, tmp_n, tmp_n, int(howmany, c_intptr_t), &
297 default_blocks, default_blocks, mpi_comm, pfft_transposed_out, &
298 tmp_rs_n, tmp_rs_istart, tmp_fs_n, tmp_fs_istart)
299 fs_n_global(1) = rs_n_global(1)/2 + 1
300 else
301 tmp_alloc_size = pfft_local_size_many_dft(3, tmp_n, tmp_n, tmp_n, int(howmany, c_intptr_t), &
302 default_blocks, default_blocks, mpi_comm, pfft_transposed_out, &
303 tmp_rs_n, tmp_rs_istart, tmp_fs_n, tmp_fs_istart)
304 end if
305#else
306 tmp_rs_n = 0
307 tmp_fs_n = 0
308 tmp_rs_istart = 0
309 tmp_fs_istart = 0
310#endif
311 alloc_size = int(tmp_alloc_size, int64)
312 rs_n(1:3) = int(tmp_rs_n(3:1:-1))
313 fs_n(1:3) = int(tmp_fs_n(3:1:-1))
314 rs_istart(1:3) = int(tmp_rs_istart(3:1:-1)+1)
315 fs_istart(1:3) = int(tmp_fs_istart(3:1:-1)+1)
316
317 pop_sub(pfft_get_dims)
318 end subroutine pfft_get_dims
319
320end module pfft_oct_m
321
322!! Local Variables:
323!! mode: f90
324!! coding: utf-8
325!! End:
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
logical function, public is_prime(n)
Definition: math.F90:952
The low level module to work with the PFFT library. http:
Definition: pfft.F90:128
subroutine, public pfft_prepare_plan_c2c(plan, n, in, out, fft_sign, flags, mpi_comm, howmany)
Octopus subroutine to prepare a PFFT plan real to complex.
Definition: pfft.F90:261
subroutine, public pfft_get_dims(rs_n_global, mpi_comm, is_real, alloc_size, fs_n_global, rs_n, fs_n, rs_istart, fs_istart, howmany)
Definition: pfft.F90:290
subroutine, public pfft_decompose(n_proc, dim1, dim2)
Decompose all available processors in 2D processor grid, most equally possible.
Definition: pfft.F90:152
subroutine, public pfft_prepare_plan_r2c(plan, n, in, out, fft_sign, flags, mpi_comm, howmany)
Octopus subroutine to prepare a PFFT plan real to complex.
Definition: pfft.F90:193
subroutine, public pfft_prepare_plan_c2r(plan, n, in, out, fft_sign, flags, mpi_comm, howmany)
Octopus subroutine to prepare a PFFT plan real to complex.
Definition: pfft.F90:227
The includes for the PFFT.
Definition: pfft.F90:117
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554