Octopus
fft.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 J. Alberdi-Rodriguez, P. Garcia RisueƱo, 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
25module fft_oct_m
26 use, intrinsic :: iso_c_binding
27 use, intrinsic :: ieee_arithmetic
28
29 use accel_oct_m
30 use fftw_oct_m
32 use debug_oct_m
33 use global_oct_m
34 use, intrinsic :: iso_fortran_env
39 use mpi_oct_m
41#ifdef HAVE_NFFT
42 use nfft_oct_m
43#endif
44#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
45 use omp_lib
46#endif
47 use parser_oct_m
48 use pfft_oct_m
50 use pnfft_oct_m
52 use types_oct_m
55
56 implicit none
57
58 private
59 public :: &
60 fft_t, &
63 fft_init, &
65 fft_end, &
66 fft_copy, &
68 pad_feq, &
76
77
79 integer, public, parameter :: &
80 FFT_NONE = 0, &
81 fft_real = 1, &
82 fft_complex = 2
83
84 integer, public, parameter :: &
85 FFTLIB_NONE = 0, &
86 fftlib_fftw = 1, &
87 fftlib_pfft = 2, &
88 fftlib_accel = 3, &
89 fftlib_nfft = 4, &
90 fftlib_pnfft = 5
91
92 integer, parameter :: &
93 FFT_MAX = 10, &
94 fft_null = -1
95
96
97 type fft_t
98 private
99 integer :: slot = 0
100
101 integer, public :: type
102 integer, public :: library
103 integer :: howmany
108
109 type(MPI_Comm) :: comm
110 integer :: rs_n_global(3)
111 integer :: fs_n_global(3)
112 integer :: rs_n(3)
113 integer :: fs_n(3)
114 integer :: rs_istart(1:3)
115 integer :: fs_istart(1:3)
116
118 integer, public :: stride_rs(1:3)
119 integer, public :: stride_fs(1:3)
121 type(c_ptr) :: planf
122 type(c_ptr) :: planb
123 !integer(ptrdiff_t_kind) :: pfft_planf !< PFFT plan for forward transform
124 !integer(ptrdiff_t_kind) :: pfft_planb !< PFFT plan for backward transform
125
128 real(real64), contiguous, pointer, public :: drs_data(:,:,:,:)
129 complex(real64), contiguous, pointer, public :: zrs_data(:,:,:,:)
130 complex(real64), contiguous, pointer, public :: fs_data(:,:,:,:)
131 type(c_ptr) :: cuda_plan_fw
132 type(c_ptr) :: cuda_plan_bw
133#ifdef HAVE_NFFT
134 type(nfft_t), public :: nfft
135#endif
136 type(pnfft_t), public :: pnfft
137
138 logical, public :: aligned_memory
139 end type fft_t
140
141 interface dfft_forward
143 end interface dfft_forward
144
145 interface zfft_forward
147 end interface zfft_forward
148
149 interface dfft_backward
151 end interface dfft_backward
152
153 interface zfft_backward
155 end interface zfft_backward
156
157 logical, save, public :: fft_initialized = .false.
158 integer, save :: fft_refs(FFT_MAX)
159 type(fft_t), save :: fft_array(FFT_MAX)
160 logical :: fft_optimize
161 integer, save :: fft_prepare_plan
162 integer, public :: fft_default_lib = -1
163#ifdef HAVE_NFFT
164 type(nfft_t), save :: nfft_options
165#endif
166 type(pnfft_t), save :: pnfft_options
167
168 integer, parameter :: &
169 CUFFT_R2C = int(z'2a'), &
170 cufft_c2r = int(z'2c'), &
171 cufft_c2c = int(z'29'), &
172 cufft_d2z = int(z'6a'), &
173 cufft_z2d = int(z'6c'), &
174 cufft_z2z = int(z'69')
175
176contains
177
178 ! ---------------------------------------------------------
180 subroutine fft_all_init(namespace)
181 type(namespace_t), intent(in) :: namespace
182
183 integer :: ii, fft_default
184#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
185 integer :: iret
186#endif
188 push_sub(fft_all_init)
189
190 fft_initialized = .true.
191
192 !%Variable FFTOptimize
193 !%Type logical
194 !%Default yes
195 !%Section Mesh::FFTs
196 !%Description
197 !% Should <tt>octopus</tt> optimize the FFT dimensions?
198 !% This means that the mesh to which FFTs are applied is not taken to be as small
199 !% as possible: some points may be added to each direction in order to get a "good number"
200 !% for the performance of the FFT algorithm.
201 !% The best FFT grid dimensions are given by <math>2^a 3^b 5^c 7^d 11^e 13^f</math>
202 !% where <math>a,b,c,d</math> are arbitrary and <math>e,f</math> are 0 or 1.
203 !% (<a href=http://www.fftw.org/doc/Complex-DFTs.html>ref</a>).
204 !% In some cases, namely when using
205 !% the split-operator, or Suzuki-Trotter propagators, this option should be turned off.
206 !% For spatial FFTs in periodic directions, the grid is never optimized, but a warning will
207 !% be written if the number is not good, with a suggestion of a better one to use, so you
208 !% can try a different spacing if you want to get a good number.
209 !%End
210 call parse_variable(namespace, 'FFTOptimize', .true., fft_optimize)
211 do ii = 1, fft_max
212 fft_refs(ii) = fft_null
213 end do
215 !%Variable FFTPreparePlan
216 !%Type integer
217 !%Default fftw_measure
218 !%Section Mesh::FFTs
219 !%Description
220 !% The FFTs are performed in octopus with the help of <a href=http://www.fftw.org>FFTW</a> and similar packages.
221 !% Before doing the actual computations, this package prepares a "plan", which means that
222 !% the precise numerical strategy to be followed to compute the FFT is machine/compiler-dependent,
223 !% and therefore the software attempts to figure out which is this precise strategy (see the
224 !% FFTW documentation for details). This plan preparation, which has to be done for each particular
225 !% FFT shape, can be done exhaustively and carefully (slow), or merely estimated. Since this is
226 !% a rather critical numerical step, by default it is done carefully, which implies a longer initial
227 !% initialization, but faster subsequent computations. You can change this behaviour by changing
228 !% this <tt>FFTPreparePlan</tt> variable, and in this way you can force FFTW to do a fast guess or
229 !% estimation of which is the best way to perform the FFT.
230 !%Option fftw_measure 0
231 !% This plan implies a longer initialization, but involves a more careful analysis
232 !% of the strategy to follow, and therefore more efficient FFTs. A side effect of the runtime
233 !% choices is that this plan can introduce slight numerical fluctuations between runs.
234 !%Option fftw_estimate 64
235 !% This is the "fast initialization" scheme, in which the plan is merely guessed from "reasonable"
236 !% assumptions. This is the default option, as it guarantees stable results
237 !%Option fftw_patient 32
238 !% It is like fftw_measure, but considers a wider range of algorithms and often produces a
239 !% "more optimal" plan (especially for large transforms), but at the expense of several times
240 !% longer planning time (especially for large transforms).
241 !%Option fftw_exhaustive 8
242 !% It is like fftw_patient, but considers an even wider range of algorithms,
243 !% including many that we think are unlikely to be fast, to produce the most optimal
244 !% plan but with a substantially increased planning time.
245 !%End
246 call parse_variable(namespace, 'FFTPreparePlan', fftw_estimate, fft_prepare_plan)
247 if (.not. varinfo_valid_option('FFTPreparePlan', fft_prepare_plan)) then
248 call messages_input_error(namespace, 'FFTPreparePlan')
249 end if
250
251 !%Variable FFTLibrary
252 !%Type integer
253 !%Section Mesh::FFTs
254 !%Default fftw
255 !%Description
256 !% (experimental) You can select the FFT library to use.
257 !%Option fftw 1
258 !% Uses FFTW3 library.
259 !%Option pfft 2
260 !% (experimental) Uses PFFT library, which has to be linked.
261 !%Option accel 3
262 !% Uses a GPU accelerated library. This only
263 !% works if Octopus was compiled with HIP, or CUDA support.
264 !%End
265 fft_default = fftlib_fftw
266 if(accel_is_enabled()) then
267 fft_default = fftlib_accel
268 end if
269 call parse_variable(namespace, 'FFTLibrary', fft_default, fft_default_lib)
270
271 if (.not. varinfo_valid_option('FFTLibrary', fft_default_lib)) then
272 call messages_input_error(namespace, 'FFTLibrary')
273 endif
274
275 if (fft_default_lib == fftlib_accel) then
276#if ! defined(HAVE_CUDA)
277 call messages_write('You have selected the Accelerated FFT, but Octopus was compiled', new_line = .true.)
278 call messages_write('without CUDA support.')
279 call messages_fatal()
280#endif
281 if (.not. accel_is_enabled()) then
282 call messages_write('You have selected the accelerated FFT, but acceleration is disabled.')
283 call messages_fatal()
284 end if
285 end if
286
287#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
288 if (omp_get_max_threads() > 1) then
289
290 call messages_write('Info: Initializing Multi-threaded FFTW')
291 call messages_info()
292
293 iret = fftw_init_threads()
294 if (iret == 0) then
295 call messages_write('Initialization of FFTW3 threads failed.')
296 call messages_fatal()
297 end if
298 call fftw_plan_with_nthreads(omp_get_max_threads())
299
300 end if
301#endif
302#ifdef HAVE_NFFT
303 call nfft_guru_options(nfft_options, namespace)
304#endif
305 call pnfft_guru_options(pnfft_options, namespace)
306
307 pop_sub(fft_all_init)
308 end subroutine fft_all_init
309
310
311 ! ---------------------------------------------------------
313 subroutine fft_all_end()
314 integer :: ii
315
316 push_sub(fft_all_end)
317
318 do ii = 1, fft_max
319 if (fft_refs(ii) /= fft_null) then
320 call fft_end(fft_array(ii))
321 end if
322 end do
323
324#ifdef HAVE_PFFT
325 call pfft_cleanup()
326#endif
327
328#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
329 call fftw_cleanup_threads()
330#else
331 call fftw_cleanup()
332#endif
333
334 fft_initialized = .false.
335
336 pop_sub(fft_all_end)
337 end subroutine fft_all_end
338
339 ! ---------------------------------------------------------
340 subroutine fft_init(this, nn, dim, type, library, optimize, optimize_parity, comm, mpi_grp, use_aligned, &
341 howmany)
342 type(fft_t), intent(inout) :: this
343 integer, intent(inout) :: nn(3)
344 integer, intent(in) :: dim
345 integer, intent(in) :: type
346 integer, intent(in) :: library
347 logical, intent(in) :: optimize(3)
348 integer, intent(in) :: optimize_parity(3)
350 type(mpi_comm), optional, intent(out) :: comm
351 type(mpi_grp_t), optional, intent(in) :: mpi_grp
352 logical, optional, intent(in) :: use_aligned
353 integer, optional, intent(in) :: howmany
354
355 integer :: ii, jj, fft_dim, idir, column_size, row_size, n3
356 integer :: n_1, n_2, n_3, nn_temp(3)
357 integer :: library_
358 type(mpi_grp_t) :: mpi_grp_
359 integer(int64) :: number_points, alloc_size
360
361#ifdef HAVE_PFFT
362 integer :: ierror
363#endif
364
365 push_sub(fft_init)
366
367 assert(fft_initialized)
368 assert(type == fft_real .or. type == fft_complex)
369
370 mpi_grp_ = mpi_world
371 if (present(mpi_grp)) mpi_grp_ = mpi_grp
372
373 this%aligned_memory = optional_default(use_aligned, .false.)
374 this%howmany = optional_default(howmany, 1)
375 assert(this%howmany > 0)
376
377 ! First, figure out the dimensionality of the FFT.
378 fft_dim = 0
379 do ii = 1, dim
380 if (nn(ii) <= 1) exit
381 fft_dim = fft_dim + 1
382 end do
383
384 if (fft_dim == 0) then
385 message(1) = "Internal error in fft_init: apparently, a 1x1x1 FFT is required."
386 call messages_fatal(1)
387 end if
388
389 if (fft_dim > 3) call messages_not_implemented('FFT for dimension > 3')
391 library_ = library
392
393 nn_temp(1:fft_dim) = nn(1:fft_dim)
394
395 select case (library_)
396 case (fftlib_accel)
397 ! FFT optimization
398 if(any(optimize_parity(1:fft_dim) > 1)) then
399 message(1) = "Internal error in fft_init: optimize_parity must be negative, 0, or 1."
400 call messages_fatal(1)
401 end if
402
403 do ii = 1, fft_dim
404 nn_temp(ii) = fft_size(nn(ii), (/2, 3, 5, 7/), optimize_parity(ii))
405 if (fft_optimize .and. optimize(ii)) nn(ii) = nn_temp(ii)
406 end do
407
408 case (fftlib_nfft)
409 assert(this%howmany == 1) ! TODO: NFFT does not support howmany > 1
411 do ii = 1, fft_dim
412 !NFFT likes even grids
413 !The underlying FFT grids are optimized inside the nfft_init routine
414 if (int(nn(ii)/2)*2 /= nn(ii) .and. (fft_optimize .and. optimize(ii)))&
415 nn(ii)=nn(ii)+1
416 end do
417
418 case (fftlib_pnfft)
419 assert(this%howmany == 1) ! TODO: PNFFT does not support howmany > 1
420
421 do ii = 1, fft_dim
422 !also PNFFT likes even grids
423 if (int(nn(ii)/2)*2 /= nn(ii)) nn(ii) = nn(ii) + 1
424 end do
425
426 if (fft_dim < 3) then
427 call messages_not_implemented('PNFFT support for dimension < 3')
428 end if
429
430 case default
431
432 if (fft_dim < 3 .and. library_ == fftlib_pfft) then
433 call messages_not_implemented('PFFT support for dimension < 3')
434 end if
435
436 ! FFT optimization
437 if (any(optimize_parity(1:fft_dim) > 1)) then
438 message(1) = "Internal error in fft_init: optimize_parity must be negative, 0, or 1."
439 call messages_fatal(1)
440 end if
441
442 do ii = 1, fft_dim
443 call loct_fft_optimize(nn_temp(ii), optimize_parity(ii))
444 if (fft_optimize .and. optimize(ii)) nn(ii) = nn_temp(ii)
445 end do
446
447 end select
448
449 ! find out if fft has already been allocated
450 jj = 0
451 do ii = fft_max, 1, -1
452 if (fft_refs(ii) /= fft_null) then
453 if (all(nn(1:dim) == fft_array(ii)%rs_n_global(1:dim)) .and. type == fft_array(ii)%type &
454 .and. library_ == fft_array(ii)%library .and. library_ /= fftlib_nfft &
455 .and. library_ /= fftlib_pnfft &
456 .and. this%howmany == fft_array(ii)%howmany &
457 .and. this%aligned_memory .eqv. fft_array(ii)%aligned_memory) then
458
459 ! NFFT and PNFFT plans are always allocated from scratch since they
460 ! are very likely to be different
461 this = fft_array(ii) ! return a copy
462 fft_refs(ii) = fft_refs(ii) + 1 ! increment the ref count
463 if (present(comm)) comm = fft_array(ii)%comm ! also return the MPI communicator
464 pop_sub(fft_init)
465 return
466 end if
467 else
468 jj = ii
469 end if
470 end do
471
472 if (jj == 0) then
473 message(1) = "Not enough slots for FFTs."
474 message(2) = "Please increase FFT_MAX in fft.F90 and recompile."
475 call messages_fatal(2)
476 end if
477
478 ! jj now contains an empty slot
479 fft_refs(jj) = 1
480 fft_array(jj)%slot = jj
481 fft_array(jj)%type = type
482 fft_array(jj)%library = library_
483 fft_array(jj)%howmany = this%howmany
484 fft_array(jj)%rs_n_global(1:dim) = nn(1:dim)
485 fft_array(jj)%rs_n_global(dim+1:) = 1
486 nullify(fft_array(jj)%drs_data)
487 nullify(fft_array(jj)%zrs_data)
488 nullify(fft_array(jj)%fs_data)
489
490 fft_array(jj)%aligned_memory = this%aligned_memory
491
492 ! Initialize parallel communicator
493 select case (library_)
494 case (fftlib_pfft)
495#ifdef HAVE_PFFT
496 call pfft_init()
497
498 call pfft_decompose(mpi_grp_%size, column_size, row_size)
499
500 ierror = pfft_create_procmesh_2d(mpi_grp_%comm%MPI_VAL, column_size, row_size, fft_array(jj)%comm%MPI_VAL)
501
502 if (ierror /= 0) then
503 message(1) = "The number of rows and columns in PFFT processor grid is not equal to "
504 message(2) = "the number of processor in the MPI communicator."
505 message(3) = "Please check it."
506 call messages_fatal(3)
507 end if
508#endif
509
510 case (fftlib_pnfft)
511#ifdef HAVE_PNFFT
512 call pnfft_init_procmesh(fft_array(jj)%pnfft, mpi_grp_, fft_array(jj)%comm)
513#endif
514 case default
515 fft_array(jj)%comm = mpi_comm_undefined
516
517 end select
518
519 if (present(comm)) comm = fft_array(jj)%comm
520
521 ! Get dimentions of arrays
522 select case (library_)
523 case (fftlib_fftw)
524 call fftw_get_dims(fft_array(jj)%rs_n_global, type == fft_real, fft_array(jj)%fs_n_global)
525 fft_array(jj)%rs_n = fft_array(jj)%rs_n_global
526 fft_array(jj)%fs_n = fft_array(jj)%fs_n_global
527 fft_array(jj)%rs_istart = 1
528 fft_array(jj)%fs_istart = 1
529
530 if (this%aligned_memory) then
531 call fftw_alloc_memory(fft_pack(fft_array(jj)%rs_n_global, this%howmany), type == fft_real, &
532 fft_pack(fft_array(jj)%fs_n_global, this%howmany), &
533 fft_array(jj)%drs_data, fft_array(jj)%zrs_data, fft_array(jj)%fs_data)
534 end if
535
536 case (fftlib_pfft)
537 assert(this%howmany == 1) ! PFFT does not support howmany > 1
538#ifdef HAVE_PFFT
539 call pfft_get_dims(fft_array(jj)%rs_n_global, fft_array(jj)%comm%MPI_VAL, type == fft_real, &
540 alloc_size, fft_array(jj)%fs_n_global, fft_array(jj)%rs_n, &
541 fft_array(jj)%fs_n, fft_array(jj)%rs_istart, fft_array(jj)%fs_istart)
542#endif
543
544 ! Allocate memory. Note that PFFT may need extra memory space
545 ! and that in fourier space the function will be transposed. PFFT runs unbatched, so the
546 ! rank-4 arrays keep the pre-batching rank-3 sizing with the trailing batch axis fixed to 1.
547 if (type == fft_real) then
548 n_1 = max(1, fft_array(jj)%rs_n(1))
549 n_2 = max(1, fft_array(jj)%rs_n(2))
550 n_3 = max(1, fft_array(jj)%rs_n(3))
551
552 n3 = ceiling(real(2*alloc_size)/real(n_1*n_2))
553 safe_allocate(fft_array(jj)%drs_data(1:n_1, 1:n_2, 1:n3, 1:1))
554 else
555 n3 = ceiling(real(alloc_size)/real(fft_array(jj)%rs_n(1)*fft_array(jj)%rs_n(2)))
556 safe_allocate(fft_array(jj)%zrs_data(1:fft_array(jj)%rs_n(1), 1:fft_array(jj)%rs_n(2), 1:n3, 1:1))
557 end if
558
559 n_1 = max(1, fft_array(jj)%fs_n(1))
560 n_2 = max(1, fft_array(jj)%fs_n(2))
561 n_3 = max(1, fft_array(jj)%fs_n(3))
562
563 n3 = ceiling(real(alloc_size)/real(n_3*n_1))
564 safe_allocate(fft_array(jj)%fs_data(1:n_3, 1:n_1, 1:n3, 1:1))
565
566 case (fftlib_accel)
567 call fftw_get_dims(fft_array(jj)%rs_n_global, (type == fft_real), fft_array(jj)%fs_n_global)
568 fft_array(jj)%rs_n = fft_array(jj)%rs_n_global
569 fft_array(jj)%fs_n = fft_array(jj)%fs_n_global
570 fft_array(jj)%rs_istart = 1
571 fft_array(jj)%fs_istart = 1
572
573 case (fftlib_nfft)
574 fft_array(jj)%fs_n_global = fft_array(jj)%rs_n_global
575 fft_array(jj)%rs_n = fft_array(jj)%rs_n_global
576 fft_array(jj)%fs_n = fft_array(jj)%fs_n_global
577 fft_array(jj)%rs_istart = 1
578 fft_array(jj)%fs_istart = 1
579
580 case (fftlib_pnfft)
581 fft_array(jj)%fs_n_global = fft_array(jj)%rs_n_global
582 fft_array(jj)%rs_n = fft_array(jj)%rs_n_global
583 fft_array(jj)%fs_n = fft_array(jj)%fs_n_global
584 fft_array(jj)%rs_istart = 1
585 fft_array(jj)%fs_istart = 1
586 ! indices partition is performed together with the plan preparation
587
588
589 end select
590
591 ! Prepare plans
592 select case (library_)
593 case (fftlib_fftw)
594 if (.not. this%aligned_memory) then
595 call fftw_prepare_plan(fft_array(jj)%planf, fft_dim, fft_array(jj)%rs_n_global, this%howmany, &
596 type == fft_real, fftw_forward, fft_prepare_plan+fftw_unaligned)
597 call fftw_prepare_plan(fft_array(jj)%planb, fft_dim, fft_array(jj)%rs_n_global, this%howmany, &
598 type == fft_real, fftw_backward, fft_prepare_plan+fftw_unaligned)
599 else
600 if (type == fft_real) then
601 call fftw_prepare_plan(fft_array(jj)%planf, fft_dim, fft_array(jj)%rs_n_global, this%howmany, &
602 type == fft_real, fftw_forward, fft_prepare_plan, &
603 din_=fft_array(jj)%drs_data, cout_=fft_array(jj)%fs_data)
604 call fftw_prepare_plan(fft_array(jj)%planb, fft_dim, fft_array(jj)%rs_n_global, this%howmany, &
605 type == fft_real, fftw_backward, fft_prepare_plan, &
606 din_=fft_array(jj)%drs_data, cout_=fft_array(jj)%fs_data)
607 else
608 call fftw_prepare_plan(fft_array(jj)%planf, fft_dim, fft_array(jj)%rs_n_global, this%howmany, &
609 type == fft_real, fftw_forward, fft_prepare_plan, &
610 cin_=fft_array(jj)%zrs_data, cout_=fft_array(jj)%fs_data)
611 call fftw_prepare_plan(fft_array(jj)%planb, fft_dim, fft_array(jj)%rs_n_global, this%howmany, &
612 type == fft_real, fftw_backward, fft_prepare_plan, &
613 cin_=fft_array(jj)%zrs_data, cout_=fft_array(jj)%fs_data)
614 end if
615 end if
616
617 case (fftlib_nfft)
618#ifdef HAVE_NFFT
619 call nfft_copy_info(this%nfft,fft_array(jj)%nfft) !copy default parameters set in the calling routine
620 call nfft_init(fft_array(jj)%nfft, nfft_options, fft_array(jj)%rs_n_global, &
621 fft_dim, fft_array(jj)%rs_n_global, optimize = .true.)
622#endif
623 case (fftlib_pfft)
624#ifdef HAVE_PFFT
625 if (type == fft_real) then
626 call pfft_prepare_plan_r2c(fft_array(jj)%planf, fft_array(jj)%rs_n_global, fft_array(jj)%drs_data, &
627 fft_array(jj)%fs_data, fftw_forward, fft_prepare_plan, fft_array(jj)%comm%MPI_VAL)
628 call pfft_prepare_plan_c2r(fft_array(jj)%planb, fft_array(jj)%rs_n_global, fft_array(jj)%fs_data, &
629 fft_array(jj)%drs_data, fftw_backward, fft_prepare_plan, fft_array(jj)%comm%MPI_VAL)
630 else
631 call pfft_prepare_plan_c2c(fft_array(jj)%planf, fft_array(jj)%rs_n_global, fft_array(jj)%zrs_data, &
632 fft_array(jj)%fs_data, fftw_forward, fft_prepare_plan, fft_array(jj)%comm%MPI_VAL)
633 call pfft_prepare_plan_c2c(fft_array(jj)%planb, fft_array(jj)%rs_n_global, fft_array(jj)%fs_data, &
634 fft_array(jj)%zrs_data, fftw_backward, fft_prepare_plan, fft_array(jj)%comm%MPI_VAL)
635 end if
636#endif
637 case (fftlib_pnfft)
638#ifdef HAVE_PNFFT
639 call pnfft_copy_params(this%pnfft, fft_array(jj)%pnfft) ! pass default parameters like in NFFT
640
641 ! NOTE:
642 ! PNFFT (likewise NFFT) breaks the symmetry between real space and Fourier space
643 ! by allowing the possibility to have an unstructured grid in rs and by
644 ! using different parallelizations (the rs is transposed w.r.t. fs).
645 ! Octopus, in fourier_space_m, uses the convention for which the mapping
646 ! between rs and fs is done with a forward transform (and fs->rs with backward).
647 ! This is exactly the opposite of the definitions used by all the libraries
648 ! performing FFTs (PNFFT and NFFT included) [see e.g. M. Frigo, and S. G. Johnson, Proc.
649 ! IEEE 93, 216-231 (2005)].
650 ! While this leads to no problem on ordinary ffts where fs and rs can be exchanged
651 ! it does makes a fundamental difference for PNFFT (for some reason I don`t know NFFT
652 ! is still symmetric).
653 ! Therefore, in order to perform rs->fs tranforms with PNFFT one should use the
654 ! backward transform.
655
656 call pnfft_init_plan(fft_array(jj)%pnfft, pnfft_options, comm, fft_array(jj)%fs_n_global, &
657 fft_array(jj)%fs_n, fft_array(jj)%fs_istart, fft_array(jj)%rs_n, fft_array(jj)%rs_istart)
658#endif
659 case (fftlib_accel)
660
661 fft_array(jj)%stride_rs(1) = 1
662 fft_array(jj)%stride_fs(1) = 1
663 do ii = 2, fft_dim
664 fft_array(jj)%stride_rs(ii) = fft_array(jj)%stride_rs(ii - 1)*fft_array(jj)%rs_n(ii - 1)
665 fft_array(jj)%stride_fs(ii) = fft_array(jj)%stride_fs(ii - 1)*fft_array(jj)%fs_n(ii - 1)
666 end do
667
668#ifdef HAVE_CUDA
669 if (type == fft_real) then
670 call cuda_fft_plan_many(fft_array(jj)%cuda_plan_fw, this%howmany, &
671 fft_array(jj)%rs_n_global(3), fft_array(jj)%rs_n_global(2), fft_array(jj)%rs_n_global(1), cufft_d2z, &
672 accel%cuda_stream)
673 call cuda_fft_plan_many(fft_array(jj)%cuda_plan_bw, this%howmany, &
674 fft_array(jj)%rs_n_global(3), fft_array(jj)%rs_n_global(2), fft_array(jj)%rs_n_global(1), cufft_z2d, &
675 accel%cuda_stream)
676 else
677 call cuda_fft_plan_many(fft_array(jj)%cuda_plan_fw, this%howmany, &
678 fft_array(jj)%rs_n_global(3), fft_array(jj)%rs_n_global(2), fft_array(jj)%rs_n_global(1), cufft_z2z, &
679 accel%cuda_stream)
680 call cuda_fft_plan_many(fft_array(jj)%cuda_plan_bw, this%howmany, &
681 fft_array(jj)%rs_n_global(3), fft_array(jj)%rs_n_global(2), fft_array(jj)%rs_n_global(1), cufft_z2z, &
682 accel%cuda_stream)
683 end if
684#endif
685
686 case default
687 call messages_write('Invalid FFT library.')
688 call messages_fatal()
689 end select
690
691 this = fft_array(jj)
692
693 ! Write information
694 if (.not. (library_ == fftlib_nfft .or. library_ == fftlib_pnfft)) then
695 call messages_write('Info: FFT grid dimensions =')
696 number_points = 1
697 do idir = 1, dim
698 call messages_write(fft_array(jj)%rs_n_global(idir))
699 if (idir < dim) call messages_write(" x ")
700 ! do the multiplication in a integer(int64) to avoid overflow for large grids
701 number_points = number_points * fft_array(jj)%rs_n_global(idir)
702 end do
703 call messages_new_line()
704
705 call messages_write(' Total grid size =')
706 call messages_write(number_points)
707 call messages_write(' (')
708 call messages_write(number_points*8.0_real64, units = unit_megabytes, fmt = '(f9.1)')
709 call messages_write(' )')
710 if (any(nn(1:fft_dim) /= nn_temp(1:fft_dim))) then
711 call messages_new_line()
712 call messages_write(' Inefficient FFT grid. A better grid would be: ')
713 do idir = 1, fft_dim
714 call messages_write(nn_temp(idir))
715 end do
716 end if
717 call messages_info()
718 end if
719
720 select case (library_)
721 case (fftlib_pfft)
722 write(message(1),'(a)') "Info: FFT library = PFFT"
723 write(message(2),'(a)') "Info: PFFT processor grid"
724 write(message(3),'(a, i9)') " No. of processors = ", mpi_grp_%size
725 write(message(4),'(a, i9)') " No. of columns in the proc. grid = ", column_size
726 write(message(5),'(a, i9)') " No. of rows in the proc. grid = ", row_size
727 write(message(6),'(a, i9)') " The size of integer is = ", c_intptr_t
728 call messages_info(6)
729
730 case (fftlib_pnfft)
731#ifdef HAVE_PNFFT
732 call messages_write("Info: FFT library = PNFFT")
733 call messages_info()
734 call pnfft_write_info(fft_array(jj)%pnfft)
735#endif
736 case (fftlib_nfft)
737#ifdef HAVE_NFFT
738 call messages_write("Info: FFT library = NFFT")
739 call messages_info()
740 call nfft_write_info(fft_array(jj)%nfft)
741#endif
742 end select
743
744 pop_sub(fft_init)
745 end subroutine fft_init
746
747 ! ---------------------------------------------------------
751 subroutine fft_init_stage1(this, namespace, XX, nn)
752 type(fft_t), intent(inout) :: this
755 type(namespace_t), intent(in) :: namespace
756 real(real64), intent(in) :: xx(:,:)
757 integer, optional, intent(in) :: nn(:)
758
759 integer :: slot
760
761 push_sub(fft_init_stage1)
762
763 assert(size(xx,2) == 3)
764
765 slot = this%slot
766 select case (fft_array(slot)%library)
767 case (fftlib_fftw)
768 !Do nothing
769 case (fftlib_nfft)
770#ifdef HAVE_NFFT
771 assert(present(nn))
772 call nfft_precompute(fft_array(slot)%nfft, &
773 xx(1:nn(1),1), xx(1:nn(2),2), xx(1:nn(3),3))
774#endif
775 case (fftlib_pfft)
776 !Do nothing
777 case (fftlib_accel)
778 !Do nothing
779 case (fftlib_pnfft)
780#ifdef HAVE_PNFFT
781 call pnfft_set_sp_nodes(fft_array(slot)%pnfft, namespace, xx)
782#endif
783 case default
784 call messages_write('Invalid FFT library.')
785 call messages_fatal()
786 end select
787
788
789
790 pop_sub(fft_init_stage1)
791 end subroutine fft_init_stage1
792 ! ---------------------------------------------------------
793 subroutine fft_end(this)
794 type(fft_t), intent(inout) :: this
795
796 integer :: ii
797
798 push_sub(fft_end)
800 ii = this%slot
801 if (fft_refs(ii) == fft_null) then
802 message(1) = "Trying to deallocate FFT that has not been allocated."
803 call messages_warning(1)
804 else
805 if (fft_refs(ii) > 1) then
806 fft_refs(ii) = fft_refs(ii) - 1
807 else
808 select case (fft_array(ii)%library)
809 case (fftlib_fftw)
810 call fftw_destroy_plan(fft_array(ii)%planf)
811 call fftw_destroy_plan(fft_array(ii)%planb)
812
813 if (this%aligned_memory) then
814 call fftw_free_memory(this%type == fft_real, &
815 fft_array(ii)%drs_data, fft_array(ii)%zrs_data, fft_array(ii)%fs_data)
816 end if
817
818 case (fftlib_pfft)
819#ifdef HAVE_PFFT
820 call pfft_destroy_plan(fft_array(ii)%planf)
821 call pfft_destroy_plan(fft_array(ii)%planb)
822#endif
823 safe_deallocate_p(fft_array(ii)%drs_data)
824 safe_deallocate_p(fft_array(ii)%zrs_data)
825 safe_deallocate_p(fft_array(ii)%fs_data)
826
827 case (fftlib_accel)
828#ifdef HAVE_CUDA
829 call cuda_fft_destroy(fft_array(ii)%cuda_plan_fw)
830 call cuda_fft_destroy(fft_array(ii)%cuda_plan_bw)
831#endif
832
833 case (fftlib_nfft)
834#ifdef HAVE_NFFT
835 call nfft_end(fft_array(ii)%nfft)
836#endif
837 case (fftlib_pnfft)
838#ifdef HAVE_PNFFT
839 call pnfft_end(fft_array(ii)%pnfft)
840#endif
841 end select
842 fft_refs(ii) = fft_null
843 end if
844 end if
845 this%slot = 0
846
847 pop_sub(fft_end)
848 end subroutine fft_end
849
850 ! ---------------------------------------------------------
851 subroutine fft_copy(fft_i, fft_o)
852 type(fft_t), intent(in) :: fft_i
853 type(fft_t), intent(inout) :: fft_o
854
855 push_sub(fft_copy)
856
857 if (fft_o%slot > 0) then
858 call fft_end(fft_o)
859 end if
860 assert(fft_i%slot >= 1.and.fft_i%slot <= fft_max)
861 assert(fft_refs(fft_i%slot) > 0)
862
863 fft_o = fft_i
864 fft_refs(fft_i%slot) = fft_refs(fft_i%slot) + 1
865
866 pop_sub(fft_copy)
867 end subroutine fft_copy
868
869 ! ---------------------------------------------------------
871 function fft_pack(dims3, howmany) result(dims4)
872 integer, intent(in) :: dims3(3)
873 integer, intent(in) :: howmany
874 integer :: dims4(4)
875
876 dims4(1:3) = dims3(1:3)
877 dims4(4) = howmany
878 end function fft_pack
879
880 ! ---------------------------------------------------------
881 subroutine fft_get_dims(fft, rs_n_global, fs_n_global, rs_n, fs_n, rs_istart, fs_istart)
882 type(fft_t), intent(in) :: fft
883 integer, intent(out) :: rs_n_global(1:3)
884 integer, intent(out) :: fs_n_global(1:3)
885 integer, intent(out) :: rs_n(1:3)
886 integer, intent(out) :: fs_n(1:3)
887 integer, intent(out) :: rs_istart(1:3)
888 integer, intent(out) :: fs_istart(1:3)
889
890 integer :: slot
891
892 push_sub(fft_get_dims)
893
894 slot = fft%slot
895 rs_n_global(1:3) = fft_array(slot)%rs_n_global(1:3)
896 fs_n_global(1:3) = fft_array(slot)%fs_n_global(1:3)
897 rs_n(1:3) = fft_array(slot)%rs_n(1:3)
898 fs_n(1:3) = fft_array(slot)%fs_n(1:3)
899 rs_istart(1:3) = fft_array(slot)%rs_istart(1:3)
900 fs_istart(1:3) = fft_array(slot)%fs_istart(1:3)
901
902 pop_sub(fft_get_dims)
903 end subroutine fft_get_dims
904
905 ! ---------------------------------------------------------
907 pure function pad_feq(ii, nn, mode)
908 integer, intent(in) :: ii,nn
909 logical, intent(in) :: mode
910 integer :: pad_feq
911
912 ! no push_sub: called too frequently
914 if (mode) then ! index to frequency number
915 if (ii <= nn/2 + 1) then
916 pad_feq = ii - 1
917 else
918 pad_feq = ii - nn - 1
919 end if
920 else ! frequency number to index
921 if (ii >= 0) then
922 pad_feq = ii + 1
923 else
924 pad_feq = ii + nn + 1
925 end if
926 end if
927
928 end function pad_feq
929
930 ! -------------------------------------------------------
931
932 integer function fft_size(size, factors, parity)
933 integer, intent(in) :: size
934 integer, intent(in) :: factors(:)
935 integer, intent(in) :: parity
936
937 integer :: nfactors
938 integer :: nondiv
939 integer, allocatable :: exponents(:)
940
941 push_sub(fft_size)
942
943 nfactors = ubound(factors, dim = 1)
944
945 safe_allocate(exponents(1:nfactors))
946
947 fft_size = size
948 do
949 call get_exponents(fft_size, nfactors, factors, exponents, nondiv)
950 if (nondiv == 1 .and. mod(fft_size, 2) == parity) exit
951 fft_size = fft_size + 1
952 end do
953
954 safe_deallocate_a(exponents)
955
956 pop_sub(fft_size)
957 end function fft_size
958
959 ! -------------------------------------------------------
960
961 subroutine get_exponents(num, nfactors, factors, exponents, nondiv)
962 integer, intent(in) :: num
963 integer, intent(in) :: nfactors
964 integer, intent(in) :: factors(:)
965 integer, intent(out) :: exponents(:)
966 integer, intent(out) :: nondiv
968 integer :: ifactor
969
970 push_sub(get_exponents)
971
972 nondiv = num
973 do ifactor = 1, nfactors
974 exponents(ifactor) = 0
975 do
976 if (mod(nondiv, factors(ifactor)) /= 0) exit
977 nondiv = nondiv/factors(ifactor)
978 exponents(ifactor) = exponents(ifactor) + 1
979 end do
980 end do
981
982 pop_sub(get_exponents)
983 end subroutine get_exponents
984
985
986 ! ----------------------------------------------------------
987
988 subroutine fft_operation_count(fft)
989 type(fft_t), intent(in) :: fft
990
991 real(real64) :: fullsize
992
993 push_sub(fft_operation_count)
995 fullsize = real(fft%howmany, real64)*product(real(fft%fs_n(1:3), real64))
996 call profiling_count_operations(5.0_real64*fullsize*log(fullsize)/log(m_two))
997
998 pop_sub(fft_operation_count)
999 end subroutine fft_operation_count
1000
1003 pure subroutine fft_gg_transform(gg_in, temp, periodic_dim, latt, qq, gg, modg2)
1004 integer, intent(in) :: gg_in(:)
1005 real(real64), intent(in) :: temp(:)
1006 integer, intent(in) :: periodic_dim
1007 type(lattice_vectors_t), intent(in) :: latt
1008 real(real64), intent(in) :: qq(:)
1009 real(real64), intent(out) :: gg(:)
1010 real(real64), intent(out) :: modg2
1011
1012 ! no PUSH_SUB, called too frequently
1013
1014 gg(1:3) = real(gg_in(1:3), real64)
1015 gg(1:periodic_dim) = gg(1:periodic_dim) + qq(1:periodic_dim)
1016 gg(1:3) = gg(1:3) * temp(1:3)
1017 gg(1:3) = matmul(latt%klattice_primitive(1:3,1:3),gg(1:3))
1018 modg2 = sum(gg(1:3)**2)
1019
1020 end subroutine fft_gg_transform
1021
1022 ! ----------------------------------------------------------
1023
1026 real(real64) pure function fft_scaling_factor(fft) result(scaling_factor)
1027 type(fft_t), intent(in) :: fft
1028
1029 ! for the moment this factor is handled by the backwards transform for most libraries
1030 scaling_factor = m_one
1031
1032 select case (fft_array(fft%slot)%library)
1033 case (fftlib_accel)
1034#ifdef HAVE_CUDA
1035 scaling_factor = m_one/real(fft_array(fft%slot)%rs_n_global(1), real64)
1036 scaling_factor = scaling_factor/real(fft_array(fft%slot)%rs_n_global(2), real64)
1037 scaling_factor = scaling_factor/real(fft_array(fft%slot)%rs_n_global(3), real64)
1038#endif
1039 end select
1040
1041 end function fft_scaling_factor
1042
1043 ! ----------------------------------------------------------
1046 !
1047 ! Inspired by the routine bounds from Abinit
1048 real(real64) function fft_get_ecut_from_box(box_dim, fs_istart, latt, gspacing, periodic_dim, qq) result(ecut)
1049 integer, intent(in) :: box_dim(:)
1050 integer, intent(in) :: fs_istart(:)
1051 type(lattice_vectors_t), intent(in) :: latt
1052 real(real64), intent(in) :: gspacing(:)
1053 integer, intent(in) :: periodic_dim
1054 real(real64), intent(in) :: qq(:)
1055
1056 integer :: lx, ix, iy, iz, idir, idir2, idir3
1057 real(real64) :: dminsq, gg(3), modg2
1058 integer :: box_dim_(3), ixx(3)
1059 integer :: ming(3), maxg(3)
1060
1061 ! no PUSH_SUB, called too frequently
1062
1063 assert(periodic_dim > 0)
1064
1065 box_dim_(1:periodic_dim) = box_dim(1:periodic_dim)
1066 if (periodic_dim < 3) box_dim_(periodic_dim+1:3) = 1
1067
1068 ! We first need to remove asymmetric planes for the case of even FFT grids
1069 ming = 1
1070 maxg = 1
1071 do idir = 1, periodic_dim
1072 do lx = 1, box_dim(idir)
1073 ix = fs_istart(idir) + lx - 1
1074 ixx(idir) = pad_feq(ix, box_dim(idir), .true.)
1075 ming(idir) = min(ming(idir), ixx(idir))
1076 maxg(idir) = max(maxg(idir), ixx(idir))
1077 end do
1078 maxg(idir) = min(abs(ming(idir)), maxg(idir))
1079 end do
1080
1081 ! Given the boundaries, we can search the min distance, which gives us the the cutoff energy
1082 dminsq = m_huge
1083 do idir = 1, periodic_dim
1084 idir2 = mod(idir, 3)+1
1085 idir3 = mod(idir+1, 3)+1
1086
1087 ! Negative plane
1088 ixx(idir) = -maxg(idir)
1089 do iy = -maxg(idir2), maxg(idir2)
1090 ixx(idir2) = iy
1091 do iz = -maxg(idir3), maxg(idir3)
1092 ixx(idir3) = iz
1093 call fft_gg_transform(ixx, gspacing, periodic_dim, latt, qq, gg, modg2)
1094 dminsq = min(dminsq, sum(gg(1:periodic_dim)**2))
1095 end do
1096 end do
1097 ! Positive plane
1098 ixx(idir) = maxg(idir)
1099 do iy = -maxg(idir2), maxg(idir2)
1100 ixx(idir2) = iy
1101 do iz = -maxg(idir3), maxg(idir3)
1102 ixx(idir3) = iz
1103 call fft_gg_transform(ixx, gspacing, periodic_dim, latt, qq, gg, modg2)
1104 dminsq = min(dminsq, sum(gg(1:periodic_dim)**2))
1105 end do
1106 end do
1107 end do
1108
1109 ecut = m_half * dminsq
1110
1111 end function fft_get_ecut_from_box
1112
1113#include "undef.F90"
1114#include "real.F90"
1115#include "fft_inc.F90"
1116
1117#include "undef.F90"
1118#include "complex.F90"
1119#include "fft_inc.F90"
1120
1121end module fft_oct_m
1122
1123!! Local Variables:
1124!! mode: f90
1125!! coding: utf-8
1126!! End:
subroutine optimize()
if write to the Free Software Franklin Fifth USA !If the compiler accepts long Fortran it is better to use that and build all the preprocessor definitions in one line In !this the debuggers will provide the right line numbers !If the compiler accepts line number then CARDINAL and ACARDINAL !will put them just a new line or a ampersand plus a new line !These macros should be used in macros that span several lines They should by !put immedialty before a line where a compilation error might occur and at the !end of the macro !Note that the cardinal and newline words are substituted by the program !preprocess pl by the ampersand and by a real new line just before compilation !The assertions are ignored if the code is compiled in not debug mode(NDEBUG ! is defined). Otherwise it is merely a logical assertion that
double log(double __x) __attribute__((__nothrow__
pure logical function, public accel_is_enabled()
Definition: accel.F90:403
type(accel_t), public accel
Definition: accel.F90:251
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:120
subroutine zfft_forward_accel(fft, in, out)
Definition: fft.F90:1636
subroutine dfft_backward_1d(fft, in, out)
Definition: fft.F90:1449
integer, parameter cufft_z2d
Definition: fft.F90:263
subroutine get_exponents(num, nfactors, factors, exponents, nondiv)
Definition: fft.F90:968
subroutine, public fft_all_init(namespace)
initialize the table
Definition: fft.F90:276
subroutine, public fft_init(this, nn, dim, type, library, optimize, optimize_parity, comm, mpi_grp, use_aligned, howmany)
Definition: fft.F90:412
real(real64) function, public fft_get_ecut_from_box(box_dim, fs_istart, latt, gspacing, periodic_dim, qq)
Given an fft box (fixed by the real-space grid), it returns the cutoff energy of the sphere that fits...
Definition: fft.F90:1055
subroutine zfft_forward_many_3d(fft, in, out, norm)
Definition: fft.F90:1572
subroutine zfft_backward_single_3d(fft, in, out, norm)
Definition: fft.F90:1675
subroutine dfft_forward_accel(fft, in, out)
Definition: fft.F90:1288
subroutine dfft_forward_single_3d(fft, in, out, norm)
Definition: fft.F90:1188
subroutine, public fft_end(this)
Definition: fft.F90:800
real(real64) pure function, public fft_scaling_factor(fft)
This function returns the factor required to normalize a function after a forward and backward transf...
Definition: fft.F90:1033
integer, parameter cufft_z2z
Definition: fft.F90:263
pure integer function, public pad_feq(ii, nn, mode)
convert between array index and G-vector
Definition: fft.F90:914
subroutine dfft_backward_single_3d(fft, in, out, norm)
Definition: fft.F90:1327
subroutine zfft_backward_1d(fft, in, out)
Definition: fft.F90:1797
integer, parameter, public fftlib_accel
Definition: fft.F90:179
integer function, dimension(4) fft_pack(dims3, howmany)
Rank-4 data-array shape (dims3, howmany) with the batch as the trailing (batch-last) axis.
Definition: fft.F90:878
subroutine, public fft_all_end()
delete all plans
Definition: fft.F90:391
integer function fft_size(size, factors, parity)
Definition: fft.F90:939
subroutine fft_operation_count(fft)
Definition: fft.F90:995
subroutine zfft_backward_accel(fft, in, out)
Definition: fft.F90:1777
integer, parameter cufft_c2r
Definition: fft.F90:263
integer, parameter cufft_c2c
Definition: fft.F90:263
integer, parameter, public fft_real
Definition: fft.F90:174
subroutine, public fft_get_dims(fft, rs_n_global, fs_n_global, rs_n, fs_n, rs_istart, fs_istart)
Definition: fft.F90:888
integer, parameter, public fft_complex
Definition: fft.F90:174
integer, parameter, public fftlib_nfft
Definition: fft.F90:179
subroutine, public fft_copy(fft_i, fft_o)
Definition: fft.F90:858
subroutine dfft_backward_many_3d(fft, in, out, norm)
Definition: fft.F90:1352
subroutine zfft_forward_single_3d(fft, in, out, norm)
Definition: fft.F90:1547
subroutine zfft_backward_many_3d(fft, in, out, norm)
Definition: fft.F90:1700
subroutine dfft_forward_1d(fft, in, out)
Definition: fft.F90:1309
integer, parameter cufft_d2z
Definition: fft.F90:263
integer, parameter fft_null
Definition: fft.F90:187
integer, parameter, public fftlib_pnfft
Definition: fft.F90:179
subroutine dfft_forward_many_3d(fft, in, out, norm)
Definition: fft.F90:1213
subroutine zfft_forward_1d(fft, in, out)
Definition: fft.F90:1657
pure subroutine, public fft_gg_transform(gg_in, temp, periodic_dim, latt, qq, gg, modg2)
Convert FFT grid index into the Cartesian reciprocal-space vector .
Definition: fft.F90:1010
integer, parameter, public fftlib_pfft
Definition: fft.F90:179
subroutine dfft_backward_accel(fft, in, out)
Definition: fft.F90:1429
integer, parameter, public fftlib_fftw
Definition: fft.F90:179
subroutine, public fft_init_stage1(this, namespace, XX, nn)
Some fft-libraries (only NFFT for the moment) need an additional precomputation stage that depends on...
Definition: fft.F90:758
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
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_huge
Definition: global.F90:218
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_new_line()
Definition: messages.F90:1089
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:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
type(mpi_comm), parameter, public mpi_comm_undefined
used to indicate a communicator has not been initialized
Definition: mpi.F90:138
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
subroutine, public nfft_write_info(nfft)
Definition: nfft.F90:325
subroutine, public nfft_end(nfft)
Definition: nfft.F90:388
subroutine, public nfft_init(nfft, nfft_options, N, dim, M, optimize)
Definition: nfft.F90:259
subroutine, public nfft_copy_info(in, out)
Definition: nfft.F90:402
subroutine, public nfft_precompute(nfft, X1, X2, X3)
Definition: nfft.F90:431
subroutine, public nfft_guru_options(nfft, namespace)
Definition: nfft.F90:192
The low level module to work with the PFFT library. http:
Definition: pfft.F90:128
subroutine, public pfft_prepare_plan_r2c(plan, n, in, out, fft_sign, flags, mpi_comm)
Octopus subroutine to prepare a PFFT plan real to complex.
Definition: pfft.F90:193
subroutine, public pfft_prepare_plan_c2c(plan, n, in, out, fft_sign, flags, mpi_comm)
Octopus subroutine to prepare a PFFT plan real to complex.
Definition: pfft.F90:261
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_c2r(plan, n, in, out, fft_sign, flags, mpi_comm)
Octopus subroutine to prepare a PFFT plan real to complex.
Definition: pfft.F90:227
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)
Definition: pfft.F90:288
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 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, 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 pnfft_init_procmesh(pnfft, mpi_grp, comm)
Definition: pnfft.F90:270
This module defines the unit system, used for input and output.
type(unit_t), public unit_megabytes
For large amounts of data (natural code units are bytes)
This is defined even when running serial.
Definition: mpi.F90:144
int true(void)