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