26 use,
intrinsic :: iso_fortran_env
46 real(real64) :: ekin_cutoff
47 integer,
allocatable :: coords(:, :)
48 integer,
allocatable :: red_gvec(:, :)
60 real(real64) function fourier_shell_cutoff(space, cube, mesh, is_wfn, dg)
61 class(space_t),
intent(in) :: space
62 type(cube_t),
intent(in) :: cube
63 class(mesh_t),
intent(in) :: mesh
64 logical,
intent(in) :: is_wfn
65 real(real64),
optional,
intent(out) :: dg(:)
67 real(real64) :: dg_(3), gbound(3)
69 push_sub(fourier_shell_cutoff)
71 dg_(1:3) =
m_two *
m_pi/(cube%rs_n_global(1:3)*mesh%spacing(1:3))
72 if (
present(dg)) dg(1:3) = dg_(1:3)
73 if (is_wfn .and. space%is_periodic())
then
78 gbound(1:3) = dg_(1:3)*(cube%rs_n_global(1:3)/2-2)
80 gbound(1:3) = dg_(1:3)*(cube%rs_n_global(1:3)/2)
82 fourier_shell_cutoff = minval(gbound(1:3)**2)/
m_two
84 pop_sub(fourier_shell_cutoff)
88 type(fourier_shell_t),
intent(inout) :: this
89 type(namespace_t),
intent(in) :: namespace
90 class(space_t),
intent(in) :: space
91 type(cube_t),
intent(in) :: cube
92 class(mesh_t),
intent(in) :: mesh
93 real(real64),
optional,
intent(in) :: kk(:)
95 integer :: ig, ix, iy, iz, ixx(1:3), imap
96 real(real64) :: dg(1:3), gvec(1:3)
97 real(real64),
allocatable :: modg2(:)
98 integer,
allocatable :: map(:), ucoords(:, :), ured_gvec(:, :)
99 integer(int64) :: number_points
106 number_points = cube%rs_n_global(1) * cube%rs_n_global(2)
107 number_points = number_points * cube%rs_n_global(3)
108 if (number_points >= huge(0))
then
109 message(1) =
"Error: too many points for the normal cube. Please try to use a distributed FFT."
110 call messages_fatal(1, namespace=namespace)
112 safe_allocate(modg2(1:product(cube%rs_n_global(1:3))))
113 safe_allocate(ucoords(1:3, 1:product(cube%rs_n_global(1:3))))
114 safe_allocate(ured_gvec(1:3, 1:product(cube%rs_n_global(1:3))))
120 do ix = 1, cube%rs_n_global(1)
121 ixx(1) = pad_feq(ix, cube%rs_n_global(1), .
true.)
122 if (2 * ixx(1) == cube%rs_n_global(1)) cycle
123 do iy = 1, cube%rs_n_global(2)
124 ixx(2) = pad_feq(iy, cube%rs_n_global(2), .
true.)
125 if (2 * ixx(2) == cube%rs_n_global(2)) cycle
126 do iz = 1, cube%rs_n_global(3)
127 ixx(3) = pad_feq(iz, cube%rs_n_global(3), .
true.)
128 if (2 * ixx(3) == cube%rs_n_global(3)) cycle
130 if (
present(kk))
then
131 gvec(1:3) = dg(1:3)*(ixx(1:3) + kk(1:3))
133 gvec(1:3) = dg(1:3)*ixx(1:3)
135 gvec(1:3) = matmul(cube%latt%klattice_primitive(1:3, 1:3), gvec(1:3))
137 if (sum(gvec(1:3)**2)/m_two <= this%ekin_cutoff + 1e-10_real64)
then
139 ucoords(1:3, ig) = (/ ix, iy, iz /)
140 ured_gvec(1:3, ig) = ixx(1:3)
141 modg2(ig) = sum(gvec(1:3)**2)
150 safe_allocate(this%coords(1:3, 1:this%ngvectors))
151 safe_allocate(this%red_gvec(1:3, 1:this%ngvectors))
152 safe_allocate(map(1:this%ngvectors))
154 do ig = 1, this%ngvectors
158 call sort(modg2(1:this%ngvectors), map)
160 do ig = 1, this%ngvectors
162 this%coords(1:3, ig) = ucoords(1:3, imap)
163 this%red_gvec(1:3, ig) = ured_gvec(1:3, imap)
166 safe_deallocate_a(ucoords)
167 safe_deallocate_a(ured_gvec)
168 safe_deallocate_a(modg2)
169 safe_deallocate_a(map)
181 safe_deallocate_a(this%coords)
182 safe_deallocate_a(this%red_gvec)
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
real(real64) function, public fourier_shell_cutoff(space, cube, mesh, is_wfn, dg)
Compute the cutoff in Fourier space given a lattice and a spacing.
subroutine, public fourier_shell_init(this, namespace, space, cube, mesh, kk)
subroutine, public fourier_shell_end(this)
real(real64), parameter, public m_two
real(real64), parameter, public m_pi
some mathematical constants
This module defines the meshes, which are used in Octopus.
This module is intended to contain "only mathematical" functions and procedures.