Octopus
pnfft.F90
Go to the documentation of this file.
1!! Copyright (C) 2013 Umberto De Giovannini
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
21! TODO(Alex) This is superfluous and should be scrapped
24 use,intrinsic :: iso_c_binding
26 implicit none
27#ifdef HAVE_PNFFT
28 include "pnfft.f03"
29#endif
30end module pnfft_params_oct_m
31
32
35module pnfft_oct_m
36 use debug_oct_m
37 use global_oct_m
38 use io_oct_m
39 use, intrinsic :: iso_fortran_env
41 use math_oct_m
43 use mpi_oct_m
45 use parser_oct_m
46 use pfft_oct_m
49
50 implicit none
51
52 private
53
54 public :: &
55 pnfft_t, &
60 pnfft_end, &
67
68
69 type pnfft_t
70 private
71
72! Parameters
73 integer :: np(3)
74 integer(C_INTPTR_T) :: N_local(3)
75 integer(C_INTPTR_T) :: N(3)
76 integer(C_INTPTR_T) :: Nos(3)
77 integer(C_INTPTR_T), public :: M(3)
78 integer :: M_istart(3)
79 integer(C_INTPTR_T) :: local_M
80 integer :: mm
81 real(real64), public :: sigma
82 integer :: flags
83 logical, public :: set_defaults = .false.
84
85 real(real64), public :: norm
86
87
88 type(MPI_Comm) :: comm
89! Data
90 type(C_PTR) :: plan
91
92 complex(C_DOUBLE_COMPLEX), pointer :: f_lin(:) => null()
93 complex(C_DOUBLE_COMPLEX), pointer :: f(:,:,:) => null()
94 complex(C_DOUBLE_COMPLEX), pointer :: f_hat(:,:,:) => null()
95 real(C_DOUBLE), pointer :: x_lin(:,:) => null()
96 real(C_DOUBLE), pointer :: x(:,:,:,:) => null()
97
98 real(C_DOUBLE) :: lower_border(3)
99 real(C_DOUBLE) :: upper_border(3)
100 real(real64) :: lo_global(3)
101 real(real64) :: up_global(3)
102
103 end type pnfft_t
104
105contains
106
107 ! ---------------------------------------------------------
108 subroutine pnfft_guru_options(pnfft, namespace)
109 type(pnfft_t), intent(inout) :: pnfft
110 type(namespace_t), intent(in) :: namespace
111
112 push_sub(pnfft_guru_options)
113
114
115 !%Variable PNFFTCutoff
116 !%Type integer
117 !%Default 6
118 !%Section Mesh::FFTs
119 !%Description
120 !% Cut-off parameter of the window function.
121 !%End
122 call parse_variable(namespace, 'PNFFTCutoff', 6, pnfft%mm)
123
124 !%Variable PNFFTOversampling
125 !%Type float
126 !%Default 2.0
127 !%Section Mesh::FFTs
128 !%Description
129 !% PNFFT oversampling factor (sigma). This will rule the size of the FFT under the hood.
130 !%End
131 call parse_variable(namespace, 'PNFFTOversampling', m_two, pnfft%sigma)
132
133 pop_sub(pnfft_guru_options)
134 end subroutine pnfft_guru_options
135
136 ! ---------------------------------------------------------
137 subroutine pnfft_init_params(pnfft, pnfft_options, nn, optimize)
138 type(pnfft_t), intent(inout) :: pnfft
139 type(pnfft_t), intent(in) :: pnfft_options
140 integer, intent(in) :: nn(3)
141 logical, optional, intent(in) :: optimize
142
143 integer :: ii, my_nn(3)
144 logical :: optimize_
145
146 push_sub(pnfft_init_params)
147
148 optimize_ = optional_default(optimize, .true.)
149
150 if (.not. pnfft%set_defaults) then
151 !Set defaults
152 pnfft%mm = pnfft_options%mm
153 pnfft%sigma = pnfft_options%sigma
154 end if
155
156 my_nn = 0
157 do ii = 1, 3
158 my_nn(ii) = nn(ii)*int(pnfft%sigma)
159 if (optimize_) call loct_fft_optimize(my_nn(ii), 1) ! ask for an odd number
160 end do
161
162 pnfft%Nos(1:3) = my_nn(1:3)
163
164#ifdef HAVE_PNFFT
165 pnfft%flags = pnfft_malloc_x + pnfft_malloc_f_hat + pnfft_malloc_f + &
166 pnfft_window_kaiser_bessel
167#endif
170 end subroutine pnfft_init_params
173 ! ---------------------------------------------------------
174 subroutine pnfft_init_procmesh(pnfft, mpi_grp, comm)
175 type(pnfft_t), intent(inout) :: pnfft
176 type(mpi_grp_t), intent(in) :: mpi_grp
177 type(mpi_comm), intent(out):: comm
179 integer :: ierror
181 push_sub(pnfft_init_procmesh)
182
183#ifdef HAVE_PNFFT
184 call pnfft_init()
185#endif
186
187 pnfft%np(1:3) = 1
189 call pfft_decompose(mpi_grp%size, pnfft%np(1), pnfft%np(2))
191#ifdef HAVE_PNFFT
192 ierror = pnfft_create_procmesh(2, mpi_grp%comm%MPI_VAL, pnfft%np, comm%MPI_VAL)
193#else
194 ierror = 0
195 comm = mpi_comm_null
196#endif
197
198 if (ierror /= 0) then
199 message(1) = "The number of rows and columns in PNFFT processor grid is not equal to "
200 message(2) = "the number of processor in the MPI communicator."
201 message(3) = "Please check it."
202 call messages_fatal(3)
203 end if
204
205 pop_sub(pnfft_init_procmesh)
206 end subroutine pnfft_init_procmesh
207
208
209 ! ---------------------------------------------------------
210 subroutine pnfft_copy_params(in, out)
211 type(pnfft_t), intent(in) :: in
212 type(pnfft_t), intent(out) :: out
213
214
215 push_sub(pnfft_copy_params)
216
217 out%mm = in%mm
218 out%sigma = in%sigma
219 out%set_defaults = in%set_defaults
220
221 pop_sub(pnfft_copy_params)
222 end subroutine pnfft_copy_params
223
224 ! ---------------------------------------------------------
225 subroutine pnfft_write_info(pnfft)
226 type(pnfft_t), intent(in) :: pnfft
227
228 integer :: idir
229
230 push_sub(pnfft_write_info)
231
233
234 call messages_write("Info: PNFFT parameters")
235 call messages_new_line()
236 call messages_write(" Fourier coefficients N = ")
237 do idir = 1, 3
238 call messages_write(pnfft%N(idir))
239 if (idir < 3) call messages_write(" x ")
240 end do
241 call messages_new_line()
242 call messages_write(" Spatial nodes per process = ")
243 call messages_write(pnfft%local_M)
244 call messages_new_line()
245 call messages_write(" Oversampling factor sigma = ")
246 call messages_write(pnfft%sigma)
247 call messages_new_line()
248 call messages_write(" FFT grid size n = ")
249 do idir = 1, 3
250 call messages_write(pnfft%Nos(idir))
251 if (idir < 3) call messages_write(" x ")
252 end do
253 call messages_new_line()
254 call messages_write(" Real Space cutoff = ")
255 call messages_write(pnfft%mm)
256 call messages_new_line()
257 call messages_write(" Process mesh np = ")
258 do idir = 1, 3
259 call messages_write(pnfft%np(idir))
260 if (idir < 3) call messages_write(" x ")
261 end do
262 call messages_info()
263
264 pop_sub(pnfft_write_info)
265 end subroutine pnfft_write_info
266
267 ! ---------------------------------------------------------
268 subroutine pnfft_init_plan(pnfft, pnfft_options, comm, fs_n_global, fs_n, fs_istart, rs_n, rs_istart)
269 type(pnfft_t), intent(inout) :: pnfft
270 type(pnfft_t), intent(inout) :: pnfft_options
271 type(mpi_comm), intent(in) :: comm
272 integer, intent(in) :: fs_n_global(1:3)
273 integer, intent(out) :: fs_n(1:3)
274 integer, intent(out) :: fs_istart(1:3)
275 integer, intent(out) :: rs_n(1:3)
276 integer, intent(out) :: rs_istart(1:3)
277
278 real(c_double) :: lower_border(3), upper_border(3)
279 real(c_double) :: x_max(3)
280 integer(C_INTPTR_T) :: local_n(3), local_n_start(3), local_m
281 integer(C_INTPTR_T), parameter :: d = 3
282 type(c_ptr) :: cf_hat, cf, cx
283
284
285 push_sub(pnfft_init_plan)
286
287 pnfft%N(1:3) = fs_n_global(1:3)
288
289 call pnfft_init_params(pnfft, pnfft_options, fs_n_global(1:3), optimize = .true.)
290
291 x_max(:) = 0.4_real64
292
293#ifdef HAVE_PNFFT
294 call pnfft_local_size_guru(3, pnfft%N, pnfft%Nos, x_max, pnfft%mm, comm%MPI_VAL, &
295 pnfft_transposed_f_hat, local_n, local_n_start, lower_border, upper_border)
296#else
297 local_n = 0
298 local_n_start = 0
299 lower_border = m_zero
300 upper_border = m_zero
301#endif
302
303 pnfft%comm = comm
304
305 pnfft%lower_border = lower_border
306 pnfft%upper_border = upper_border
307 pnfft%N_local(1:3) = local_n(1:3)
308
309 pnfft%M(1) = pnfft%N_local(2)
310 pnfft%M(2) = pnfft%N_local(3)
311 pnfft%M(3) = pnfft%N_local(1)
312
313 local_m = pnfft%M(1) * pnfft%M(2) * pnfft%M(3)
314
315 fs_n(1) = int(local_n(1))
316 fs_n(2) = int(local_n(3))
317 fs_n(3) = int(local_n(2))
318 fs_istart(1) = int(pnfft%N(1)/2 + local_n_start(1) + 1)
319 fs_istart(2) = int(pnfft%N(3)/2 + local_n_start(3) + 1)
320 fs_istart(3) = int(pnfft%N(2)/2 + local_n_start(2) + 1)
321
322
323 rs_n(1:3) = int(pnfft%M(1:3))
324
325 rs_istart(1) = fs_istart(3)
326 rs_istart(2) = fs_istart(2)
327 rs_istart(3) = fs_istart(1)
328
329 pnfft%M_istart(:) = rs_istart(:)
330
331#ifdef HAVE_PNFFT
332 pnfft%plan = pnfft_init_guru(3, pnfft%N, pnfft%Nos, x_max, local_m, pnfft%mm, &
333 pnfft%flags, pfft_estimate, comm%MPI_VAL)
334#endif
335
336 pnfft%local_M=local_m
337
338#ifdef HAVE_PNFFT
339 ! Get data pointers in C format
340 cf_hat = pnfft_get_f_hat(pnfft%plan)
341 cf = pnfft_get_f(pnfft%plan)
342 cx = pnfft_get_x(pnfft%plan)
343#else
344 cf_hat = c_null_ptr
345 cf = c_null_ptr
346 cx = c_null_ptr
347#endif
348
349 ! Convert data pointers to Fortran format
350 call c_f_pointer(cf_hat, pnfft%f_hat, [local_n(1),local_n(3),local_n(2)])
351 call c_f_pointer(cf, pnfft%f_lin, [pnfft%local_M])
352 call c_f_pointer(cf, pnfft%f, [pnfft%M(1),pnfft%M(2),pnfft%M(3)])
353 call c_f_pointer(cx, pnfft%x_lin, [d, pnfft%local_M])
354 call c_f_pointer(cx, pnfft%x, [d, pnfft%M(1),pnfft%M(2),pnfft%M(3)])
355
356
357
358 write(6,*) mpi_world%rank, "local_N(3) ", local_n
359 write(6,*) mpi_world%rank, "local_N_start(3) ", local_n_start
360 write(6,*) mpi_world%rank, "fs_istart(1:3) ", fs_istart
361 write(6,*) mpi_world%rank, "fs_n(1:3) ", fs_n
362 write(6,*) mpi_world%rank, "rs_istart(1:3) ", rs_istart
363 write(6,*) mpi_world%rank, "rs_n(1:3) ", rs_n
364 write(6,*) mpi_world%rank, "lower_border ", lower_border
365 write(6,*) mpi_world%rank, "upper_border ", upper_border
366 write(6,*) mpi_world%rank, "rs_range ", upper_border(:) - lower_border(:)
367 write(6,*) mpi_world%rank, "local_M ", local_m
368 write(6,*) mpi_world%rank, "pnfft%N_local ", pnfft%N_local
369 write(6,*) mpi_world%rank, "pnfft%M ", pnfft%M
370 write(6,*) mpi_world%rank, "pnfft%M_istart ", pnfft%M_istart
371 write(6,*) mpi_world%rank, "size(pnfft%f_hat)", size(pnfft%f_hat,1), size(pnfft%f_hat,2), size(pnfft%f_hat, 3)
372 write(6,*) mpi_world%rank, "size(pnfft%f) ", size(pnfft%f,1), size(pnfft%f,2), size(pnfft%f,3)
373
374 pop_sub(pnfft_init_plan)
375 end subroutine pnfft_init_plan
376
377 ! ---------------------------------------------------------
378 subroutine pnfft_end(pnfft)
379 type(pnfft_t), intent(inout) :: pnfft
380
381 push_sub(pnfft_end)
382
383#ifdef HAVE_PNFFT
384 call pnfft_finalize(pnfft%plan, pnfft_free_x + pnfft_free_f_hat + pnfft_free_f)
385 call pnfft_cleanup()
386#endif
387
388 nullify(pnfft%f_lin)
389 nullify(pnfft%f)
390 nullify(pnfft%f_hat)
391 nullify(pnfft%x)
392 nullify(pnfft%x_lin)
393
394 pop_sub(pnfft_end)
395 end subroutine pnfft_end
396
397
398 ! ---------------------------------------------------------
399 ! Set the coordinates for the spatial nodes rescaled to
400 ! the 3D torus [-0.5,0.5)
401 ! ---------------------------------------------------------
402 subroutine pnfft_set_sp_nodes(pnfft, namespace, X)
403 type(pnfft_t), intent(inout) :: pnfft
404 type(namespace_t),intent(in) :: namespace
405 real(real64), intent(in) :: x(:,:) !X(i, dim)
406
407 real(real64) :: len(3), cc(3), eps,temp, lo(3), up(3)
408 integer :: ii, idir, i1, i2, i3
409 real(real64), allocatable :: dx(:,:)
410! integer :: j,t
411
412 push_sub(pnfft_set_sp_nodes)
413
414 eps = 1.25_real64 ! the sample nodes must be in [0.5,0.5)
415
416 lo = pnfft%lower_border
417 up = pnfft%upper_border
418
419
420
421 do idir = 1,3
422 len(:) = (maxval(x(:,idir))-minval(x(:,idir)))*eps
423 cc(:) = (minval(x(:,idir))+maxval(x(:,idir)))/m_two
424 end do
425
426
427
428
429 do i1 = 1, int(pnfft%M(1))
430 do i2 = 1, int(pnfft%M(2))
431 do i3 = 1, int(pnfft%M(3))
432 pnfft%x(1, i1,i2,i3) = (x(pnfft%M_istart(1)+i1-1, 1) - cc(1))/len(1)
433 pnfft%x(2, i1,i2,i3) = (x(pnfft%M_istart(2)+i2-1, 2) - cc(2))/len(2)
434 pnfft%x(3, i1,i2,i3) = (x(pnfft%M_istart(3)+i3-1, 3) - cc(3))/len(3)
435
436! pnfft%x_lin(1, pnfft_idx_3to1(pnfft,i1,i2,i3)) = real((X(rs_istart(1)+i1-1, 1) - cc(1))/len(1), C_DOUBLE)
437! pnfft%x_lin(2, pnfft_idx_3to1(pnfft,i1,i2,i3)) = real((X(rs_istart(2)+i2-1, 2) - cc(2))/len(2), C_DOUBLE)
438! pnfft%x_lin(3, pnfft_idx_3to1(pnfft,i1,i2,i3)) = real((X(rs_istart(3)+i3-1, 3) - cc(3))/len(3), C_DOUBLE)
439
440! pnfft%x_lin(1, pnfft_idx_3to1(pnfft,i1,i2,i3)) = &
441! (pnfft%upper_border(1) - pnfft%lower_border(1)) * rand(0) + pnfft%lower_border(1)
442! pnfft%x_lin(2, pnfft_idx_3to1(pnfft,i1,i2,i3)) = &
443! (pnfft%upper_border(2) - pnfft%lower_border(2)) * rand(0) + pnfft%lower_border(2)
444! pnfft%x_lin(3, pnfft_idx_3to1(pnfft,i1,i2,i3)) = &
445! (pnfft%upper_border(3) - pnfft%lower_border(3)) * rand(0) + pnfft%lower_border(3)
446
447! pnfft%x(1, i1,i2,i3) = (pnfft%upper_border(1) - pnfft%lower_border(1)) * rand(0) + pnfft%lower_border(1)
448! pnfft%x(2, i1,i2,i3) = (pnfft%upper_border(2) - pnfft%lower_border(2)) * rand(0) + pnfft%lower_border(2)
449! pnfft%x(3, i1,i2,i3) = (pnfft%upper_border(3) - pnfft%lower_border(3)) * rand(0) + pnfft%lower_border(3)
450
451 temp = (x(pnfft%M_istart(3)+i3-1, 3) - cc(3))/len(3)
452 if (temp > pnfft%upper_border(3) .or. temp < pnfft%lower_border(3)) then
453 write(6,*) mpi_world%rank, "out of bounds x3 = ", temp,"-- ", pnfft%lower_border(3), pnfft%upper_border(3)
454 end if
455
456
457 end do
458
459 temp = (x(pnfft%M_istart(2)+i2-1, 2) - cc(2))/len(2)
460 if (temp > pnfft%upper_border(2) .or. temp < pnfft%lower_border(2)) then
461 write(6,*) mpi_world%rank, "out of bounds x2 = ", temp,"-- ", pnfft%lower_border(2), pnfft%upper_border(2)
462 end if
463
464 end do
465
466 temp = (x(pnfft%M_istart(1)+i1-1, 1) - cc(1))/len(1)
467 if (temp > pnfft%upper_border(1) .or. temp < pnfft%lower_border(1)) then
468 write(6,*) mpi_world%rank, "out of bounds x1 = ", temp,"-- ", pnfft%lower_border(1), pnfft%upper_border(1)
469 end if
470
471 end do
472
474! do j = 1,pnfft%local_M
475! do t=1,3
476! pnfft%x_lin(t,j) = (pnfft%upper_border(t) - pnfft%lower_border(t)) * rand(0) + pnfft%lower_border(t)
477! end do
478! end do
479
480
481 call pnfft_messages_debug(pnfft, namespace)
482
483
484 safe_allocate( dx(1:maxval(pnfft%M(:))-1, 1:3))
485
486
487 ! Set the normalization factor
488 do idir = 1,3
489 do ii = 1, size(x(:,idir))-1
490 dx(ii,idir)= abs(x(ii+1, idir)-x(ii, idir))
491! dX(ii,2)= abs(x2_(ii+1)-x2_(ii))
492! dX(ii,3)= abs(x3_(ii+1)-x3_(ii))
493 end do
494 end do
495
496! pnfft%norm = M_ONE/(minval(dX(:,1)) * minval(dX(:,2)) * minval(dX(:,3)))
497 pnfft%norm = m_one/(pnfft%N(1)*pnfft%N(2)*pnfft%N(3))
498
499 write(6,*) mpi_world%rank, "pnfft%norm", pnfft%norm
500
501 pop_sub(pnfft_set_sp_nodes)
502 end subroutine pnfft_set_sp_nodes
503
504 ! ---------------------------------------------------------
505 subroutine pnfft_messages_debug(pnfft, namespace)
506 type(pnfft_t), intent(in) :: pnfft
507 type(namespace_t), intent(in) :: namespace
508
509 integer :: nn, i1, i2, i3
510 integer :: iunit
511 character(len=3) :: filenum
512#ifdef HAVE_MPI
513 integer :: ierr
514#endif
515
516 push_sub(pnfft_messages_debug)
517
518 if (debug%info) then
519
520 if (mpi_world%is_root()) then
521 call io_mkdir('debug/PNFFT', namespace)
522 end if
523#ifdef HAVE_MPI
524 call mpi_barrier(pnfft%comm, ierr)
525#endif
526
527 nn = mpi_world%rank
528 write(filenum, '(i3.3)') nn
529
530 iunit = io_open('debug/PNFFT/rs_partition.'//filenum, &
531 namespace, action='write')
532
533 do i1 = 1, int(pnfft%M(1))
534 do i2 = 1, int(pnfft%M(2))
535 do i3 = 1, int(pnfft%M(3))
536 write(iunit, '(3f18.8)') pnfft%x(1, i1,i2,i3), pnfft%x(2, i1,i2,i3), pnfft%x(3, i1,i2,i3)
537 end do
538 end do
539 end do
540 call io_close(iunit)
541
542 end if
543
544 pop_sub(pnfft_messages_debug)
545
546 end subroutine pnfft_messages_debug
547
548 !---------------------------------------------------------------------------------
549! integer function pnfft_idx_3to1(pnfft, ix , iy, iz) result(idx)
550! type(pnfft_t), intent(in) :: pnfft
551! integer, intent(in) :: ix
552! integer, intent(in) :: iy
553! integer, intent(in) :: iz
554!
555! idx = (ix-1)*pnfft%M(2)*pnfft%M(3) + (iy-1)*pnfft%M(3) + (iz-1) + 1
556!
557! end function pnfft_idx_3to1
558
559#include "undef.F90"
560#include "real.F90"
561#include "pnfft_inc.F90"
562
563#include "undef.F90"
564#include "complex.F90"
565#include "pnfft_inc.F90"
566
567end module pnfft_oct_m
568
569!! Local Variables:
570!! mode: f90
571!! coding: utf-8
572!! End:
subroutine optimize()
type(debug_t), save, public debug
Definition: debug.F90:158
real(real64), parameter, public m_two
Definition: global.F90:192
real(real64), parameter, public m_zero
Definition: global.F90:190
real(real64), parameter, public m_one
Definition: global.F90:191
Definition: io.F90:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:466
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:360
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:401
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
subroutine, public messages_new_line()
Definition: messages.F90:1118
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:416
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:600
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
The low level module to work with the PFFT library. http:
Definition: pfft.F90:128
subroutine, public pfft_decompose(n_proc, dim1, dim2)
Decompose all available processors in 2D processor grid, most equally possible.
Definition: pfft.F90:152
The includes for the PFFT.
Definition: pfft.F90:117
The low level module to work with the PNFFT library. http:
Definition: pnfft.F90:130
subroutine, public zpnfft_backward(pnfft, in, out)
Definition: pnfft.F90:949
subroutine, public pnfft_copy_params(in, out)
Definition: pnfft.F90:306
subroutine, public pnfft_set_sp_nodes(pnfft, namespace, X)
Definition: pnfft.F90:498
subroutine, public pnfft_init_plan(pnfft, pnfft_options, comm, fs_n_global, fs_n, fs_istart, rs_n, rs_istart)
Definition: pnfft.F90:364
subroutine pnfft_init_params(pnfft, pnfft_options, nn, optimize)
Definition: pnfft.F90:233
subroutine, public pnfft_write_info(pnfft)
Definition: pnfft.F90:321
subroutine, public pnfft_guru_options(pnfft, namespace)
Definition: pnfft.F90:204
subroutine, public pnfft_end(pnfft)
Definition: pnfft.F90:474
subroutine, public dpnfft_forward(pnfft, in, out)
Definition: pnfft.F90:722
subroutine, public zpnfft_forward(pnfft, in, out)
Definition: pnfft.F90:895
subroutine pnfft_messages_debug(pnfft, namespace)
Definition: pnfft.F90:601
subroutine, public dpnfft_backward(pnfft, in, out)
Definition: pnfft.F90:776
subroutine, public pnfft_init_procmesh(pnfft, mpi_grp, comm)
Definition: pnfft.F90:270
The includes for the PNFFT.
Definition: pnfft.F90:118
This is defined even when running serial.
Definition: mpi.F90:144
int true(void)