Octopus
fourier_shell.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2011 M. Marques, A. Castro, A. Rubio, G. Bertsch, M. Oliveira
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22 use cube_oct_m
23 use debug_oct_m
24 use fft_oct_m
25 use global_oct_m
26 use, intrinsic :: iso_fortran_env
27 use mesh_oct_m
31 use space_oct_m
32 use sort_oct_m
33
34 implicit none
35
36 private
37 public :: &
42
44 ! Components are public by default
45 integer :: ngvectors
46 real(real64) :: ekin_cutoff
47 integer, allocatable :: coords(:, :)
48 integer, allocatable :: red_gvec(:, :)
49 end type fourier_shell_t
50
51contains
52
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(:)
66
67 real(real64) :: dg_(3), gbound(3)
68
69 push_sub(fourier_shell_cutoff)
70
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
74 ! Note from Alex: -2 margin: the n_i = N_i/2 plane is excluded for even grids, and G+k with a
75 ! reduced k-point shift of up to 1/2 must remain representable
76 ! Apparently -2 can still miss lying on the sphere cutoff, but
77 ! changing to Nᵢ/2 − 1 will change the G-vector count in existing BGW output
78 gbound(1:3) = dg_(1:3)*(cube%rs_n_global(1:3)/2-2)
79 else
80 gbound(1:3) = dg_(1:3)*(cube%rs_n_global(1:3)/2)
81 end if
82 fourier_shell_cutoff = minval(gbound(1:3)**2)/m_two
83
84 pop_sub(fourier_shell_cutoff)
85 end function fourier_shell_cutoff
86
87 subroutine fourier_shell_init(this, namespace, space, cube, mesh, kk)
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(:)
94
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
100
101 push_sub(fourier_shell_init)
102
103 this%ekin_cutoff = fourier_shell_cutoff(space, cube, mesh, present(kk), dg = dg)
104
105 ! make sure we do not run into integer overflow here
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)
111 end if
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))))
115
116 ig = 0
117 ! According to the conventions of plane-wave codes, e.g. Quantum ESPRESSO,
118 ! PARATEC, EPM, and BerkeleyGW, if the FFT grid is even, then neither
119 ! nfft/2 nor -nfft/2 should be a valid G-vector component.
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
129
130 if (present(kk)) then
131 gvec(1:3) = dg(1:3)*(ixx(1:3) + kk(1:3))
132 else
133 gvec(1:3) = dg(1:3)*ixx(1:3)
134 end if
135 gvec(1:3) = matmul(cube%latt%klattice_primitive(1:3, 1:3), gvec(1:3))
136
137 if (sum(gvec(1:3)**2)/m_two <= this%ekin_cutoff + 1e-10_real64) then
138 ig = ig + 1
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)
142 end if
144 end do
145 end do
146 end do
147
148 this%ngvectors = ig
149
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))
153
154 do ig = 1, this%ngvectors
155 map(ig) = ig
156 end do
157
158 call sort(modg2(1:this%ngvectors), map)
159
160 do ig = 1, this%ngvectors
161 imap = map(ig)
162 this%coords(1:3, ig) = ucoords(1:3, imap)
163 this%red_gvec(1:3, ig) = ured_gvec(1:3, imap)
164 end do
165
166 safe_deallocate_a(ucoords)
167 safe_deallocate_a(ured_gvec)
168 safe_deallocate_a(modg2)
169 safe_deallocate_a(map)
170
171 pop_sub(fourier_shell_init)
172 end subroutine fourier_shell_init
173
174 ! -----------------------------------------------------
175
176 subroutine fourier_shell_end(this)
177 type(fourier_shell_t), intent(inout) :: this
178
179 push_sub(fourier_shell_end)
180
181 safe_deallocate_a(this%coords)
182 safe_deallocate_a(this%red_gvec)
183
184 pop_sub(fourier_shell_end)
185 end subroutine fourier_shell_end
186
187end module fourier_shell_oct_m
188
189!! Local Variables:
190!! mode: f90
191!! coding: utf-8
192!! End:
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:120
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
Definition: global.F90:202
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:198
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:119
int true(void)