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
180
182
183#ifdef HAVE_PNFFT
184 call pnfft_init()
185#endif
187 pnfft%np(1:3) = 1
189 call pfft_decompose(mpi_grp%size, pnfft%np(1), pnfft%np(2))
190
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
231
232
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), d=3, local_m
281 type(c_ptr) :: cf_hat, cf, cx
282
283
284 push_sub(pnfft_init_plan)
285
286 pnfft%N(1:3) = fs_n_global(1:3)
287
288 call pnfft_init_params(pnfft, pnfft_options, fs_n_global(1:3), optimize = .true.)
289
290 x_max(:) = 0.4_real64
291
292#ifdef HAVE_PNFFT
293 call pnfft_local_size_guru(3, pnfft%N, pnfft%Nos, x_max, pnfft%mm, comm%MPI_VAL, &
294 pnfft_transposed_f_hat, local_n, local_n_start, lower_border, upper_border)
295#else
296 local_n = 0
297 local_n_start = 0
298 lower_border = m_zero
299 upper_border = m_zero
300#endif
301
302 pnfft%comm = comm
304 pnfft%lower_border = lower_border
305 pnfft%upper_border = upper_border
306 pnfft%N_local(1:3) = local_n(1:3)
307
308 pnfft%M(1) = pnfft%N_local(2)
309 pnfft%M(2) = pnfft%N_local(3)
310 pnfft%M(3) = pnfft%N_local(1)
311
312 local_m = pnfft%M(1) * pnfft%M(2) * pnfft%M(3)
313
314 fs_n(1) = int(local_n(1))
315 fs_n(2) = int(local_n(3))
316 fs_n(3) = int(local_n(2))
317 fs_istart(1) = int(pnfft%N(1)/2 + local_n_start(1) + 1)
318 fs_istart(2) = int(pnfft%N(3)/2 + local_n_start(3) + 1)
319 fs_istart(3) = int(pnfft%N(2)/2 + local_n_start(2) + 1)
320
321
322 rs_n(1:3) = int(pnfft%M(1:3))
323
324 rs_istart(1) = fs_istart(3)
325 rs_istart(2) = fs_istart(2)
326 rs_istart(3) = fs_istart(1)
327
328 pnfft%M_istart(:) = rs_istart(:)
329
330#ifdef HAVE_PNFFT
331 pnfft%plan = pnfft_init_guru(3, pnfft%N, pnfft%Nos, x_max, local_m, pnfft%mm, &
332 pnfft%flags, pfft_estimate, comm%MPI_VAL)
333#endif
334
335 pnfft%local_M=local_m
336
337#ifdef HAVE_PNFFT
338 ! Get data pointers in C format
339 cf_hat = pnfft_get_f_hat(pnfft%plan)
340 cf = pnfft_get_f(pnfft%plan)
341 cx = pnfft_get_x(pnfft%plan)
342#else
343 cf_hat = c_null_ptr
344 cf = c_null_ptr
345 cx = c_null_ptr
346#endif
347
348 ! Convert data pointers to Fortran format
349 call c_f_pointer(cf_hat, pnfft%f_hat, [local_n(1),local_n(3),local_n(2)])
350 call c_f_pointer(cf, pnfft%f_lin, [pnfft%local_M])
351 call c_f_pointer(cf, pnfft%f, [pnfft%M(1),pnfft%M(2),pnfft%M(3)])
352 call c_f_pointer(cx, pnfft%x_lin, [d, pnfft%local_M])
353 call c_f_pointer(cx, pnfft%x, [d, pnfft%M(1),pnfft%M(2),pnfft%M(3)])
354
355
356
357 write(6,*) mpi_world%rank, "local_N(3) ", local_n
358 write(6,*) mpi_world%rank, "local_N_start(3) ", local_n_start
359 write(6,*) mpi_world%rank, "fs_istart(1:3) ", fs_istart
360 write(6,*) mpi_world%rank, "fs_n(1:3) ", fs_n
361 write(6,*) mpi_world%rank, "rs_istart(1:3) ", rs_istart
362 write(6,*) mpi_world%rank, "rs_n(1:3) ", rs_n
363 write(6,*) mpi_world%rank, "lower_border ", lower_border
364 write(6,*) mpi_world%rank, "upper_border ", upper_border
365 write(6,*) mpi_world%rank, "rs_range ", upper_border(:) - lower_border(:)
366 write(6,*) mpi_world%rank, "local_M ", local_m
367 write(6,*) mpi_world%rank, "pnfft%N_local ", pnfft%N_local
368 write(6,*) mpi_world%rank, "pnfft%M ", pnfft%M
369 write(6,*) mpi_world%rank, "pnfft%M_istart ", pnfft%M_istart
370 write(6,*) mpi_world%rank, "size(pnfft%f_hat)", size(pnfft%f_hat,1), size(pnfft%f_hat,2), size(pnfft%f_hat, 3)
371 write(6,*) mpi_world%rank, "size(pnfft%f) ", size(pnfft%f,1), size(pnfft%f,2), size(pnfft%f,3)
372
373 pop_sub(pnfft_init_plan)
374 end subroutine pnfft_init_plan
375
376 ! ---------------------------------------------------------
377 subroutine pnfft_end(pnfft)
378 type(pnfft_t), intent(inout) :: pnfft
379
380 push_sub(pnfft_end)
381
382#ifdef HAVE_PNFFT
383 call pnfft_finalize(pnfft%plan, pnfft_free_x + pnfft_free_f_hat + pnfft_free_f)
384 call pnfft_cleanup()
385#endif
386
387 nullify(pnfft%f_lin)
388 nullify(pnfft%f)
389 nullify(pnfft%f_hat)
390 nullify(pnfft%x)
391 nullify(pnfft%x_lin)
392
393 pop_sub(pnfft_end)
394 end subroutine pnfft_end
395
396
397 ! ---------------------------------------------------------
398 ! Set the coordinates for the spatial nodes rescaled to
399 ! the 3D torus [-0.5,0.5)
400 ! ---------------------------------------------------------
401 subroutine pnfft_set_sp_nodes(pnfft, namespace, X)
402 type(pnfft_t), intent(inout) :: pnfft
403 type(namespace_t),intent(in) :: namespace
404 real(real64), intent(in) :: x(:,:) !X(i, dim)
405
406 real(real64) :: len(3), cc(3), eps,temp, lo(3), up(3)
407 integer :: ii, idir, i1, i2, i3
408 real(real64), allocatable :: dx(:,:)
409! integer :: j,t
410
411 push_sub(pnfft_set_sp_nodes)
412
413 eps = 1.25_real64 ! the sample nodes must be in [0.5,0.5)
414
415 lo = pnfft%lower_border
416 up = pnfft%upper_border
417
418
419
420 do idir = 1,3
421 len(:) = (maxval(x(:,idir))-minval(x(:,idir)))*eps
422 cc(:) = (minval(x(:,idir))+maxval(x(:,idir)))/m_two
423 end do
424
425
426
427
428 do i1 = 1, int(pnfft%M(1))
429 do i2 = 1, int(pnfft%M(2))
430 do i3 = 1, int(pnfft%M(3))
431 pnfft%x(1, i1,i2,i3) = (x(pnfft%M_istart(1)+i1-1, 1) - cc(1))/len(1)
432 pnfft%x(2, i1,i2,i3) = (x(pnfft%M_istart(2)+i2-1, 2) - cc(2))/len(2)
433 pnfft%x(3, i1,i2,i3) = (x(pnfft%M_istart(3)+i3-1, 3) - cc(3))/len(3)
434
435! 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)
436! 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)
437! 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)
438
439! pnfft%x_lin(1, pnfft_idx_3to1(pnfft,i1,i2,i3)) = &
440! (pnfft%upper_border(1) - pnfft%lower_border(1)) * rand(0) + pnfft%lower_border(1)
441! pnfft%x_lin(2, pnfft_idx_3to1(pnfft,i1,i2,i3)) = &
442! (pnfft%upper_border(2) - pnfft%lower_border(2)) * rand(0) + pnfft%lower_border(2)
443! pnfft%x_lin(3, pnfft_idx_3to1(pnfft,i1,i2,i3)) = &
444! (pnfft%upper_border(3) - pnfft%lower_border(3)) * rand(0) + pnfft%lower_border(3)
445
446! pnfft%x(1, i1,i2,i3) = (pnfft%upper_border(1) - pnfft%lower_border(1)) * rand(0) + pnfft%lower_border(1)
447! pnfft%x(2, i1,i2,i3) = (pnfft%upper_border(2) - pnfft%lower_border(2)) * rand(0) + pnfft%lower_border(2)
448! pnfft%x(3, i1,i2,i3) = (pnfft%upper_border(3) - pnfft%lower_border(3)) * rand(0) + pnfft%lower_border(3)
449
450 temp = (x(pnfft%M_istart(3)+i3-1, 3) - cc(3))/len(3)
451 if (temp > pnfft%upper_border(3) .or. temp < pnfft%lower_border(3)) then
452 write(6,*) mpi_world%rank, "out of bounds x3 = ", temp,"-- ", pnfft%lower_border(3), pnfft%upper_border(3)
453 end if
454
455
456 end do
457
458 temp = (x(pnfft%M_istart(2)+i2-1, 2) - cc(2))/len(2)
459 if (temp > pnfft%upper_border(2) .or. temp < pnfft%lower_border(2)) then
460 write(6,*) mpi_world%rank, "out of bounds x2 = ", temp,"-- ", pnfft%lower_border(2), pnfft%upper_border(2)
461 end if
462
463 end do
464
465 temp = (x(pnfft%M_istart(1)+i1-1, 1) - cc(1))/len(1)
466 if (temp > pnfft%upper_border(1) .or. temp < pnfft%lower_border(1)) then
467 write(6,*) mpi_world%rank, "out of bounds x1 = ", temp,"-- ", pnfft%lower_border(1), pnfft%upper_border(1)
468 end if
469
470 end do
471
472
473! do j = 1,pnfft%local_M
474! do t=1,3
475! pnfft%x_lin(t,j) = (pnfft%upper_border(t) - pnfft%lower_border(t)) * rand(0) + pnfft%lower_border(t)
476! end do
477! end do
478
479
480 call pnfft_messages_debug(pnfft, namespace)
481
482
483 safe_allocate( dx(1:maxval(pnfft%M(:))-1, 1:3))
484
485
486 ! Set the normalization factor
487 do idir = 1,3
488 do ii = 1, size(x(:,idir))-1
489 dx(ii,idir)= abs(x(ii+1, idir)-x(ii, idir))
490! dX(ii,2)= abs(x2_(ii+1)-x2_(ii))
491! dX(ii,3)= abs(x3_(ii+1)-x3_(ii))
492 end do
493 end do
495! pnfft%norm = M_ONE/(minval(dX(:,1)) * minval(dX(:,2)) * minval(dX(:,3)))
496 pnfft%norm = m_one/(pnfft%N(1)*pnfft%N(2)*pnfft%N(3))
497
498 write(6,*) mpi_world%rank, "pnfft%norm", pnfft%norm
499
500 pop_sub(pnfft_set_sp_nodes)
501 end subroutine pnfft_set_sp_nodes
502
503 ! ---------------------------------------------------------
504 subroutine pnfft_messages_debug(pnfft, namespace)
505 type(pnfft_t), intent(in) :: pnfft
506 type(namespace_t), intent(in) :: namespace
507
508 integer :: nn, i1, i2, i3
509 integer :: iunit
510 character(len=3) :: filenum
511#ifdef HAVE_MPI
512 integer :: ierr
513#endif
514
515 push_sub(pnfft_messages_debug)
516
517 if (debug%info) then
518
519 if (mpi_grp_is_root(mpi_world)) then
520 call io_mkdir('debug/PNFFT', namespace)
521 end if
522#ifdef HAVE_MPI
523 call mpi_barrier(pnfft%comm, ierr)
524#endif
525
526 nn = mpi_world%rank
527 write(filenum, '(i3.3)') nn
528
529 iunit = io_open('debug/PNFFT/rs_partition.'//filenum, &
530 namespace, action='write')
531
532 do i1 = 1, int(pnfft%M(1))
533 do i2 = 1, int(pnfft%M(2))
534 do i3 = 1, int(pnfft%M(3))
535 write(iunit, '(3f18.8)') pnfft%x(1, i1,i2,i3), pnfft%x(2, i1,i2,i3), pnfft%x(3, i1,i2,i3)
536 end do
537 end do
538 end do
539 call io_close(iunit)
540
541 end if
542
543 pop_sub(pnfft_messages_debug)
544
545 end subroutine pnfft_messages_debug
546
547 !---------------------------------------------------------------------------------
548! integer function pnfft_idx_3to1(pnfft, ix , iy, iz) result(idx)
549! type(pnfft_t), intent(in) :: pnfft
550! integer, intent(in) :: ix
551! integer, intent(in) :: iy
552! integer, intent(in) :: iz
553!
554! idx = (ix-1)*pnfft%M(2)*pnfft%M(3) + (iy-1)*pnfft%M(3) + (iz-1) + 1
555!
556! end function pnfft_idx_3to1
557
558#include "undef.F90"
559#include "real.F90"
560#include "pnfft_inc.F90"
561
562#include "undef.F90"
563#include "complex.F90"
564#include "pnfft_inc.F90"
565
566end module pnfft_oct_m
567
568!! Local Variables:
569!! mode: f90
570!! coding: utf-8
571!! End:
subroutine optimize()
type(debug_t), save, public debug
Definition: debug.F90:154
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_one
Definition: global.F90:188
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:354
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
subroutine, public messages_new_line()
Definition: messages.F90:1146
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
The low level module to work with the PFFT library. http:
Definition: pfft.F90:164
subroutine, public pfft_decompose(n_proc, dim1, dim2)
Decompose all available processors in 2D processor grid, most equally possible.
Definition: pfft.F90:188
The includes for the PFFT.
Definition: pfft.F90:115
The low level module to work with the PNFFT library. http:
Definition: pnfft.F90:128
subroutine, public zpnfft_backward(pnfft, in, out)
Definition: pnfft.F90:946
subroutine, public pnfft_copy_params(in, out)
Definition: pnfft.F90:304
subroutine, public pnfft_set_sp_nodes(pnfft, namespace, X)
Definition: pnfft.F90:495
subroutine, public pnfft_init_plan(pnfft, pnfft_options, comm, fs_n_global, fs_n, fs_istart, rs_n, rs_istart)
Definition: pnfft.F90:362
subroutine pnfft_init_params(pnfft, pnfft_options, nn, optimize)
Definition: pnfft.F90:231
subroutine, public pnfft_write_info(pnfft)
Definition: pnfft.F90:319
subroutine, public pnfft_guru_options(pnfft, namespace)
Definition: pnfft.F90:202
subroutine, public pnfft_end(pnfft)
Definition: pnfft.F90:471
subroutine, public dpnfft_forward(pnfft, in, out)
Definition: pnfft.F90:719
subroutine, public zpnfft_forward(pnfft, in, out)
Definition: pnfft.F90:892
subroutine pnfft_messages_debug(pnfft, namespace)
Definition: pnfft.F90:598
subroutine, public dpnfft_backward(pnfft, in, out)
Definition: pnfft.F90:773
subroutine, public pnfft_init_procmesh(pnfft, mpi_grp, comm)
Definition: pnfft.F90:268
The includes for the PNFFT.
Definition: pnfft.F90:116
This is defined even when running serial.
Definition: mpi.F90:142
int true(void)