26 use,
intrinsic :: iso_c_binding
27 use,
intrinsic :: ieee_arithmetic
34 use,
intrinsic :: iso_fortran_env
44#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
83 integer,
public,
parameter :: &
88 integer,
public,
parameter :: &
96 integer,
parameter :: &
105 integer,
public ::
type
106 integer,
public :: library
113 type(MPI_Comm) :: comm
114 integer :: rs_n_global(3)
115 integer :: fs_n_global(3)
118 integer :: rs_istart(1:3)
119 integer :: fs_istart(1:3)
122 integer,
public :: stride_rs(1:3)
123 integer,
public :: stride_fs(1:3)
132 real(real64),
contiguous,
pointer,
public :: drs_data(:,:,:,:)
133 complex(real64),
contiguous,
pointer,
public :: zrs_data(:,:,:,:)
134 complex(real64),
contiguous,
pointer,
public :: fs_data(:,:,:,:)
137 real(real32),
contiguous,
pointer,
public :: srs_data(:,:,:,:)
138 complex(real32),
contiguous,
pointer,
public :: crs_data(:,:,:,:)
139 complex(real32),
contiguous,
pointer,
public :: cfs_data(:,:,:,:)
140 logical,
public :: single = .false.
141 type(c_ptr) :: cuda_plan_fw
142 type(c_ptr) :: cuda_plan_bw
144 type(finufft_t),
public :: finufft
146 type(pnfft_t),
public :: pnfft
148 logical,
public :: aligned_memory
195 integer,
parameter :: &
196 CUFFT_R2C = int(z
'2a'), &
210 integer :: ii, fft_default
211#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
303#if ! defined(HAVE_CUDA)
304 call messages_write(
'You have selected the Accelerated FFT, but Octopus was compiled', new_line = .
true.)
309 call messages_write(
'You have selected the accelerated FFT, but acceleration is disabled.')
314#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
315 if (omp_get_max_threads() > 1)
then
320 iret = fftw_init_threads()
325 call fftw_plan_with_nthreads(omp_get_max_threads())
355#if defined(HAVE_OPENMP) && defined(HAVE_FFTW3_THREADS)
356 call fftw_cleanup_threads()
369 subroutine fft_init(this, nn, dim, type, library, optimize, optimize_parity, comm, mpi_grp, use_aligned, &
370 howmany, nthreads, single)
371 type(
fft_t),
intent(inout) :: this
372 integer,
intent(inout) :: nn(3)
373 integer,
intent(in) :: dim
374 integer,
intent(in) ::
type
375 integer,
intent(in) :: library
377 integer,
intent(in) :: optimize_parity(3)
379 type(mpi_comm),
optional,
intent(out) :: comm
380 type(
mpi_grp_t),
optional,
intent(in) :: mpi_grp
381 logical,
optional,
intent(in) :: use_aligned
382 integer,
optional,
intent(in) :: howmany
383 integer,
optional,
intent(in) :: nthreads
384 logical,
optional,
intent(in) :: single
386 integer :: ii, jj, fft_dim, idir, column_size, row_size, n3
387 integer :: n_1, n_2, n_3, nn_temp(3)
390 integer(int64) :: number_points, alloc_size
402 if (
present(mpi_grp)) mpi_grp_ = mpi_grp
406 assert(this%howmany > 0)
409 if (this%single)
then
410 this%aligned_memory = .
true.
416 if (nn(ii) <= 1)
exit
417 fft_dim = fft_dim + 1
420 if (fft_dim == 0)
then
421 message(1) =
"Internal error in fft_init: apparently, a 1x1x1 FFT is required."
435 nn_temp(1:fft_dim) = nn(1:fft_dim)
437 select case (library_)
440 if(any(optimize_parity(1:fft_dim) > 1))
then
441 message(1) =
"Internal error in fft_init: optimize_parity must be negative, 0, or 1."
446 nn_temp(ii) =
fft_size(nn(ii), (/2, 3, 5, 7/), optimize_parity(ii))
451 assert(this%howmany == 1)
461 assert(this%howmany == 1)
465 if (int(nn(ii)/2)*2 /= nn(ii)) nn(ii) = nn(ii) + 1
468 if (fft_dim < 3)
then
474 if (fft_dim < 3 .and. library_ ==
fftlib_pfft)
then
479 if (any(optimize_parity(1:fft_dim) > 1))
then
480 message(1) =
"Internal error in fft_init: optimize_parity must be negative, 0, or 1."
493 do ii = fft_max, 1, -1
495 if (all(nn(1:dim) ==
fft_array(ii)%rs_n_global(1:dim)) .and.
type ==
fft_array(ii)%type &
498 .and. this%howmany ==
fft_array(ii)%howmany &
499 .and. (this%single .eqv.
fft_array(ii)%single) &
500 .and. (this%aligned_memory .eqv.
fft_array(ii)%aligned_memory))
then
506 if (
present(comm)) comm =
fft_array(ii)%comm
516 message(1) =
"Not enough slots for FFTs."
517 message(2) =
"Please increase FFT_MAX in fft.F90 and recompile."
527 fft_array(jj)%rs_n_global(1:dim) = nn(1:dim)
537 fft_array(jj)%aligned_memory = this%aligned_memory
540 select case (library_)
547 ierror = pfft_create_procmesh_2d(mpi_grp_%comm%MPI_VAL, column_size, row_size,
fft_array(jj)%comm%MPI_VAL)
549 if (ierror /= 0)
then
550 message(1) =
"The number of rows and columns in PFFT processor grid is not equal to "
551 message(2) =
"the number of processor in the MPI communicator."
552 message(3) =
"Please check it."
566 if (
present(comm)) comm =
fft_array(jj)%comm
569 select case (library_)
577 if (this%single)
then
581 else if (this%aligned_memory)
then
588 assert(this%howmany == 1)
603 n3 = ceiling(real(2*alloc_size)/real(n_1*n_2))
604 safe_allocate(
fft_array(jj)%drs_data(1:n_1, 1:n_2, 1:n3, 1:1))
614 n3 = ceiling(real(alloc_size)/real(n_3*n_1))
615 safe_allocate(
fft_array(jj)%fs_data(1:n_3, 1:n_1, 1:n3, 1:1))
643 select case (library_)
647 if (this%single)
then
666 fft_dim,
fft_array(jj)%rs_n_global, nthreads=nthreads)
715 call cuda_fft_plan_many(
fft_array(jj)%cuda_plan_fw, this%howmany, &
718 call cuda_fft_plan_many(
fft_array(jj)%cuda_plan_bw, this%howmany, &
722 call cuda_fft_plan_many(
fft_array(jj)%cuda_plan_fw, this%howmany, &
725 call cuda_fft_plan_many(
fft_array(jj)%cuda_plan_bw, this%howmany, &
746 number_points = number_points *
fft_array(jj)%rs_n_global(idir)
755 if (any(nn(1:fft_dim) /= nn_temp(1:fft_dim)))
then
757 call messages_write(
' Inefficient FFT grid. A better grid would be: ')
765 select case (library_)
767 write(
message(1),
'(a)')
"Info: FFT library = PFFT"
768 write(
message(2),
'(a)')
"Info: PFFT processor grid"
769 write(
message(3),
'(a, i9)')
" No. of processors = ", mpi_grp_%size
770 write(
message(4),
'(a, i9)')
" No. of columns in the proc. grid = ", column_size
771 write(
message(5),
'(a, i9)')
" No. of rows in the proc. grid = ", row_size
772 write(
message(6),
'(a, i9)')
" The size of integer is = ", c_intptr_t
797 type(
fft_t),
intent(inout) :: this
801 real(real64),
intent(in) :: xx(:,:)
802 integer,
optional,
intent(in) :: nn(:)
808 assert(
size(xx,2) == 3)
818 xx(1:nn(1),1), xx(1:nn(2),2), xx(1:nn(3),3))
839 type(
fft_t),
intent(inout) :: this
847 message(1) =
"Trying to deallocate FFT that has not been allocated."
856 call fftwf_destroy_plan(
fft_array(ii)%planf)
857 call fftwf_destroy_plan(
fft_array(ii)%planb)
861 call fftw_destroy_plan(
fft_array(ii)%planf)
862 call fftw_destroy_plan(
fft_array(ii)%planb)
864 if (this%aligned_memory)
then
872 call pfft_destroy_plan(
fft_array(ii)%planf)
873 call pfft_destroy_plan(
fft_array(ii)%planb)
875 safe_deallocate_p(
fft_array(ii)%drs_data)
876 safe_deallocate_p(
fft_array(ii)%zrs_data)
881 call cuda_fft_destroy(
fft_array(ii)%cuda_plan_fw)
882 call cuda_fft_destroy(
fft_array(ii)%cuda_plan_bw)
904 type(
fft_t),
intent(in) :: fft_i
905 type(
fft_t),
intent(inout) :: fft_o
909 if (fft_o%slot > 0)
then
912 assert(fft_i%slot >= 1.and.fft_i%slot <= fft_max)
923 function fft_pack(dims3, howmany)
result(dims4)
924 integer,
intent(in) :: dims3(3)
925 integer,
intent(in) :: howmany
928 dims4(1:3) = dims3(1:3)
933 subroutine fft_get_dims(fft, rs_n_global, fs_n_global, rs_n, fs_n, rs_istart, fs_istart)
934 type(
fft_t),
intent(in) :: fft
935 integer,
intent(out) :: rs_n_global(1:3)
936 integer,
intent(out) :: fs_n_global(1:3)
937 integer,
intent(out) :: rs_n(1:3)
938 integer,
intent(out) :: fs_n(1:3)
939 integer,
intent(out) :: rs_istart(1:3)
940 integer,
intent(out) :: fs_istart(1:3)
947 rs_n_global(1:3) =
fft_array(slot)%rs_n_global(1:3)
948 fs_n_global(1:3) =
fft_array(slot)%fs_n_global(1:3)
951 rs_istart(1:3) =
fft_array(slot)%rs_istart(1:3)
952 fs_istart(1:3) =
fft_array(slot)%fs_istart(1:3)
959 pure function pad_feq(ii, nn, mode)
960 integer,
intent(in) :: ii,nn
961 logical,
intent(in) ::
mode
967 if (ii <= nn/2 + 1)
then
984 integer function fft_size(size, factors, parity)
985 integer,
intent(in) :: size
986 integer,
intent(in) :: factors(:)
987 integer,
intent(in) :: parity
991 integer,
allocatable :: exponents(:)
995 nfactors = ubound(factors, dim = 1)
997 safe_allocate(exponents(1:nfactors))
1002 if (nondiv == 1 .and. mod(
fft_size, 2) == parity)
exit
1006 safe_deallocate_a(exponents)
1013 subroutine get_exponents(num, nfactors, factors, exponents, nondiv)
1014 integer,
intent(in) :: num
1015 integer,
intent(in) :: nfactors
1016 integer,
intent(in) :: factors(:)
1017 integer,
intent(out) :: exponents(:)
1018 integer,
intent(out) :: nondiv
1025 do ifactor = 1, nfactors
1026 exponents(ifactor) = 0
1028 if (mod(nondiv, factors(ifactor)) /= 0)
exit
1029 nondiv = nondiv/factors(ifactor)
1030 exponents(ifactor) = exponents(ifactor) + 1
1041 type(
fft_t),
intent(in) :: fft
1043 real(real64) :: fullsize
1047 fullsize = real(fft%howmany, real64)*product(real(fft%fs_n(1:3), real64))
1055 pure subroutine fft_gg_transform(gg_in, temp, periodic_dim, latt, qq, gg, modg2)
1056 integer,
intent(in) :: gg_in(:)
1057 real(real64),
intent(in) :: temp(:)
1058 integer,
intent(in) :: periodic_dim
1060 real(real64),
intent(in) :: qq(:)
1061 real(real64),
intent(out) :: gg(:)
1062 real(real64),
intent(out) :: modg2
1066 gg(1:3) = real(gg_in(1:3), real64)
1067 gg(1:periodic_dim) = gg(1:periodic_dim) + qq(1:periodic_dim)
1068 gg(1:3) = gg(1:3) * temp(1:3)
1069 gg(1:3) = matmul(latt%klattice_primitive(1:3,1:3),gg(1:3))
1070 modg2 = sum(gg(1:3)**2)
1079 type(
fft_t),
intent(in) :: fft
1082 scaling_factor =
m_one
1087 scaling_factor =
m_one/real(
fft_array(fft%slot)%rs_n_global(1), real64)
1088 scaling_factor = scaling_factor/real(
fft_array(fft%slot)%rs_n_global(2), real64)
1089 scaling_factor = scaling_factor/real(
fft_array(fft%slot)%rs_n_global(3), real64)
1100 real(real64) function
fft_get_ecut_from_box(box_dim, fs_istart, latt, gspacing, periodic_dim, qq) result(ecut)
1101 integer,
intent(in) :: box_dim(:)
1102 integer,
intent(in) :: fs_istart(:)
1104 real(real64),
intent(in) :: gspacing(:)
1105 integer,
intent(in) :: periodic_dim
1106 real(real64),
intent(in) :: qq(:)
1108 integer :: lx, ix, iy, iz, idir, idir2, idir3
1109 real(real64) :: dminsq, gg(3), modg2
1110 integer :: box_dim_(3), ixx(3)
1111 integer :: ming(3), maxg(3)
1115 assert(periodic_dim > 0)
1117 box_dim_(1:periodic_dim) = box_dim(1:periodic_dim)
1118 if (periodic_dim < 3) box_dim_(periodic_dim+1:3) = 1
1123 do idir = 1, periodic_dim
1124 do lx = 1, box_dim(idir)
1125 ix = fs_istart(idir) + lx - 1
1127 ming(idir) = min(ming(idir), ixx(idir))
1128 maxg(idir) = max(maxg(idir), ixx(idir))
1130 maxg(idir) = min(abs(ming(idir)), maxg(idir))
1135 do idir = 1, periodic_dim
1136 idir2 = mod(idir, 3)+1
1137 idir3 = mod(idir+1, 3)+1
1140 ixx(idir) = -maxg(idir)
1141 do iy = -maxg(idir2), maxg(idir2)
1143 do iz = -maxg(idir3), maxg(idir3)
1146 dminsq = min(dminsq, sum(gg(1:periodic_dim)**2))
1150 ixx(idir) = maxg(idir)
1151 do iy = -maxg(idir2), maxg(idir2)
1153 do iz = -maxg(idir3), maxg(idir3)
1156 dminsq = min(dminsq, sum(gg(1:periodic_dim)**2))
1167#include "fft_inc.F90"
1170#include "complex.F90"
1171#include "fft_inc.F90"
1174#include "real32.F90"
1175#include "fft_inc.F90"
1178#include "complex32.F90"
1179#include "fft_inc.F90"
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()
type(accel_t), public accel
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
subroutine sfft_forward_single_3d(fft, in, out, norm)
subroutine zfft_forward_accel(fft, in, out)
subroutine dfft_backward_1d(fft, in, out)
integer, parameter cufft_z2d
subroutine get_exponents(num, nfactors, factors, exponents, nondiv)
subroutine, public fft_all_init(namespace)
initialize the table
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...
subroutine sfft_backward_accel(fft, in, out)
subroutine zfft_forward_many_3d(fft, in, out, norm)
subroutine zfft_backward_single_3d(fft, in, out, norm)
subroutine dfft_forward_accel(fft, in, out)
subroutine cfft_forward_single_3d(fft, in, out, norm)
subroutine dfft_forward_single_3d(fft, in, out, norm)
subroutine sfft_forward_many_3d(fft, in, out, norm)
subroutine, public fft_end(this)
subroutine cfft_backward_accel(fft, in, out)
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...
subroutine, public fft_init(this, nn, dim, type, library, optimize, optimize_parity, comm, mpi_grp, use_aligned, howmany, nthreads, single)
integer, public fft_default_lib
integer, parameter cufft_z2z
pure integer function, public pad_feq(ii, nn, mode)
convert between array index and G-vector
subroutine dfft_backward_single_3d(fft, in, out, norm)
subroutine zfft_backward_1d(fft, in, out)
subroutine cfft_backward_single_3d(fft, in, out, norm)
subroutine cfft_forward_many_3d(fft, in, out, norm)
integer, parameter, public fftlib_accel
integer function, dimension(4) fft_pack(dims3, howmany)
Rank-4 data-array shape (dims3, howmany) with the batch as the trailing (batch-last) axis.
subroutine, public fft_all_end()
delete all plans
logical, save, public fft_initialized
integer function fft_size(size, factors, parity)
subroutine fft_operation_count(fft)
subroutine sfft_forward_accel(fft, in, out)
subroutine zfft_backward_accel(fft, in, out)
integer, parameter cufft_c2r
subroutine sfft_backward_many_3d(fft, in, out, norm)
integer, parameter cufft_c2c
integer, parameter, public fft_real
subroutine, public fft_get_dims(fft, rs_n_global, fs_n_global, rs_n, fs_n, rs_istart, fs_istart)
integer, parameter, public fft_complex
integer, save fft_prepare_plan
integer, parameter, public fftlib_nfft
subroutine, public fft_copy(fft_i, fft_o)
subroutine dfft_backward_many_3d(fft, in, out, norm)
type(pnfft_t), save pnfft_options
subroutine cfft_backward_many_3d(fft, in, out, norm)
subroutine zfft_forward_single_3d(fft, in, out, norm)
integer, dimension(fft_max), save fft_refs
subroutine zfft_backward_many_3d(fft, in, out, norm)
subroutine dfft_forward_1d(fft, in, out)
subroutine cfft_forward_accel(fft, in, out)
integer, parameter cufft_d2z
type(fft_t), dimension(fft_max), save fft_array
integer, parameter fft_null
integer, parameter, public fftlib_pnfft
subroutine sfft_backward_single_3d(fft, in, out, norm)
subroutine dfft_forward_many_3d(fft, in, out, norm)
subroutine zfft_forward_1d(fft, in, out)
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 .
integer, parameter, public fftlib_pfft
subroutine dfft_backward_accel(fft, in, out)
integer, parameter, public fftlib_fftw
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...
subroutine, public fftw_free_memory(is_real, drs_data, zrs_data, fs_data)
subroutine, public fftw_get_dims(rs_n, is_real, fs_n)
subroutine, public fftw_prepare_plan_single(plan, dim, n, howmany, is_real, sign, flags, sin_, cin_, cout_)
Single-precision counterpart of fftw_prepare_plan. Only the aligned-memory path is supported (the sin...
subroutine, public fftw_alloc_memory_single(rs_dims, is_real, fs_dims, srs_data, crs_data, cfs_data)
subroutine, public fftw_free_memory_single(is_real, srs_data, crs_data, cfs_data)
subroutine, public fftw_prepare_plan(plan, dim, n, howmany, is_real, sign, flags_, din_, cin_, cout_)
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).
Non-equispaced FFTs through the C interface of the FINUFFT library.
subroutine, public finufft_write_info(finufft)
subroutine, public finufft_read_options(finufft, namespace)
subroutine, public finufft_init(finufft, finufft_options, N, dim, M, nthreads)
subroutine, public finufft_end(finufft)
subroutine, public finufft_precompute(finufft, X1, X2, X3)
Hand the spatial nodes to FINUFFT.
real(real64), parameter, public m_two
real(real64), parameter, public m_huge
real(real64), parameter, public m_half
real(real64), parameter, public m_one
subroutine, public messages_not_implemented(feature, namespace)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_new_line()
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
type(mpi_comm), parameter, public mpi_comm_undefined
used to indicate a communicator has not been initialized
type(mpi_grp_t), public mpi_world
The low level module to work with the PFFT library. http:
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.
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.
subroutine, public pfft_decompose(n_proc, dim1, dim2)
Decompose all available processors in 2D processor grid, most equally possible.
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.
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)
The includes for the PFFT.
The low level module to work with the PNFFT library. http:
subroutine, public pnfft_copy_params(in, out)
subroutine, public pnfft_set_sp_nodes(pnfft, namespace, X)
subroutine, public pnfft_init_plan(pnfft, pnfft_options, comm, fs_n_global, fs_n, fs_istart, rs_n, rs_istart)
subroutine, public pnfft_write_info(pnfft)
subroutine, public pnfft_guru_options(pnfft, namespace)
subroutine, public pnfft_end(pnfft)
subroutine, public pnfft_init_procmesh(pnfft, mpi_grp, comm)
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.