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
53 real(real64) function fourier_shell_cutoff(space, cube, mesh, is_wfn, dg)
54 class(space_t), intent(in) :: space
55 type(cube_t), intent(in) :: cube
56 class(mesh_t), intent(in) :: mesh
57 logical, intent(in) :: is_wfn
58 real(real64), optional, intent(out) :: dg(:)
59
60 real(real64) :: dg_(3)
61
62 push_sub(fourier_shell_cutoff)
63
64 ! FIXME: what about anisotropic spacing?
65 dg_(1:3) = m_pi/(cube%rs_n_global(1:3)/2*mesh%spacing(1:3))
66 if (present(dg)) dg(1:3) = dg_(1:3)
67 if (is_wfn .and. space%is_periodic()) then
68 fourier_shell_cutoff = (dg_(1)*(cube%rs_n_global(1)/2-2))**2/m_two
69 else
70 fourier_shell_cutoff = (dg_(1)*(cube%rs_n_global(1)/2))**2/m_two
71 end if
72
73 pop_sub(fourier_shell_cutoff)
74 end function fourier_shell_cutoff
75
76 subroutine fourier_shell_init(this, namespace, space, cube, mesh, kk)
77 type(fourier_shell_t), intent(inout) :: this
78 type(namespace_t), intent(in) :: namespace
79 class(space_t), intent(in) :: space
80 type(cube_t), intent(in) :: cube
81 class(mesh_t), intent(in) :: mesh
82 real(real64), optional, intent(in) :: kk(:)
83
84 integer :: ig, ix, iy, iz, ixx(1:3), imap
85 real(real64) :: dg(1:3), gvec(1:3)
86 real(real64), allocatable :: modg2(:)
87 integer, allocatable :: map(:), ucoords(:, :), ured_gvec(:, :)
88 integer(int64) :: number_points
89
90 push_sub(fourier_shell_init)
91
92 this%ekin_cutoff = fourier_shell_cutoff(space, cube, mesh, present(kk), dg = dg)
93
94 ! make sure we do not run into integer overflow here
95 number_points = cube%rs_n_global(1) * cube%rs_n_global(2)
96 number_points = number_points * cube%rs_n_global(3)
97 if (number_points >= huge(0)) then
98 message(1) = "Error: too many points for the normal cube. Please try to use a distributed FFT."
99 call messages_fatal(1, namespace=namespace)
100 end if
101 safe_allocate(modg2(1:product(cube%rs_n_global(1:3))))
102 safe_allocate(ucoords(1:3, 1:product(cube%rs_n_global(1:3))))
103 safe_allocate(ured_gvec(1:3, 1:product(cube%rs_n_global(1:3))))
104
105 ig = 0
106 ! According to the conventions of plane-wave codes, e.g. Quantum ESPRESSO,
107 ! PARATEC, EPM, and BerkeleyGW, if the FFT grid is even, then neither
108 ! nfft/2 nor -nfft/2 should be a valid G-vector component.
109 do ix = 1, cube%rs_n_global(1)
110 ixx(1) = pad_feq(ix, cube%rs_n_global(1), .true.)
111 if (2 * ixx(1) == cube%rs_n_global(1)) cycle
112 do iy = 1, cube%rs_n_global(2)
113 ixx(2) = pad_feq(iy, cube%rs_n_global(2), .true.)
114 if (2 * ixx(2) == cube%rs_n_global(2)) cycle
115 do iz = 1, cube%rs_n_global(3)
116 ixx(3) = pad_feq(iz, cube%rs_n_global(3), .true.)
117 if (2 * ixx(3) == cube%rs_n_global(3)) cycle
118
119 if (present(kk)) then
120 gvec(1:3) = dg(1:3)*(ixx(1:3) + kk(1:3))
121 else
122 gvec(1:3) = dg(1:3)*ixx(1:3)
123 end if
124
125 if (sum(gvec(1:3)**2)/m_two <= this%ekin_cutoff + 1e-10_real64) then
126 ig = ig + 1
127 ucoords(1:3, ig) = (/ ix, iy, iz /)
128 ured_gvec(1:3, ig) = ixx(1:3)
129 modg2(ig) = sum(gvec(1:3)**2)
130 end if
131
132 end do
133 end do
134 end do
135
136 this%ngvectors = ig
137
138 safe_allocate(this%coords(1:3, 1:this%ngvectors))
139 safe_allocate(this%red_gvec(1:3, 1:this%ngvectors))
140 safe_allocate(map(1:this%ngvectors))
142 do ig = 1, this%ngvectors
143 map(ig) = ig
144 end do
145
146 call sort(modg2(1:this%ngvectors), map)
147
148 do ig = 1, this%ngvectors
149 imap = map(ig)
150 this%coords(1:3, ig) = ucoords(1:3, imap)
151 this%red_gvec(1:3, ig) = ured_gvec(1:3, imap)
152 end do
153
154 safe_deallocate_a(ucoords)
155 safe_deallocate_a(ured_gvec)
156 safe_deallocate_a(modg2)
157 safe_deallocate_a(map)
158
159 pop_sub(fourier_shell_init)
160 end subroutine fourier_shell_init
161
162 ! -----------------------------------------------------
163
164 subroutine fourier_shell_end(this)
165 type(fourier_shell_t), intent(inout) :: this
166
167 push_sub(fourier_shell_end)
168
169 safe_deallocate_a(this%coords)
170 safe_deallocate_a(this%red_gvec)
171
172 pop_sub(fourier_shell_end)
173 end subroutine fourier_shell_end
174
175end module fourier_shell_oct_m
176
177!! Local Variables:
178!! mode: f90
179!! coding: utf-8
180!! End:
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:118
real(real64) function, public fourier_shell_cutoff(space, cube, mesh, is_wfn, dg)
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:189
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:185
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:117
int true(void)