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