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