Octopus
projector.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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
21module projector_oct_m
22 use accel_oct_m
23 use batch_oct_m
26 use debug_oct_m
27 use global_oct_m
28 use grid_oct_m
30 use ions_oct_m
33 use mesh_oct_m
35 use mpi_oct_m
38 use ps_oct_m
39 use pseudo_oct_m
47
48 implicit none
49
50 private
51 public :: &
70
71 integer, parameter :: MAX_NPROJECTIONS = 4
72 integer, parameter :: MAX_L = 5
73
85
86 type projector_t
87 private
88 integer, public :: type = proj_none
89 integer :: nprojections
90 integer, public :: lmax
91 integer, public :: lloc
92 integer :: nik
93 integer :: reltype
94
95 type(submesh_t), public :: sphere
96
97
100 type(hgh_projector_t), allocatable, public :: hgh_p(:, :)
101 type(kb_projector_t), allocatable, public :: kb_p(:, :)
102 type(rkb_projector_t), allocatable, public :: rkb_p(:, :)
103 real(real64), allocatable, public :: uspp_dij(:, :, :)
104 real(real64), allocatable, public :: uspp_qij(:, :, :)
105 real(real64), allocatable, public :: uspp_qfunc(:, :, :)
106 integer, public :: uspp_qfunc_lmax = -1
107 integer, public :: uspp_qfunc_nbeta = 0
108 complex(real64), allocatable, public :: phase(:, :, :)
109 end type projector_t
110
111contains
112
113 !---------------------------------------------------------
114 logical elemental function projector_is_null(p)
115 type(projector_t), intent(in) :: p
116
117 projector_is_null = (p%type == proj_none)
118 end function projector_is_null
119
120 !---------------------------------------------------------
121 logical elemental function projector_is(p, type)
122 type(projector_t), intent(in) :: p
123 integer, intent(in) :: type
124 projector_is = (p%type == type)
125 end function projector_is
126
127 !---------------------------------------------------------
128 subroutine projector_init(p, pseudo, namespace, dim, reltype)
129 type(projector_t), intent(inout) :: p
130 type(pseudopotential_t), target, intent(in) :: pseudo
131 type(namespace_t), intent(in) :: namespace
132 integer, intent(in) :: dim
133 integer, intent(in) :: reltype
134
135 type(ps_t), pointer :: ps
136
137 push_sub(projector_init)
138
139 ps => pseudo%ps
140
141 p%reltype = reltype
142 p%lmax = ps%lmax
143
144 if (ps%local) then
145 p%type = proj_none
146 pop_sub(projector_init)
147 return
148 end if
149
150 p%lloc = ps%llocal
151
152 p%type = ps%projector_type
153
154 ! reltype is epot_oct_m::proj_reltype, which is either NOREL (0) or SPIN_ORBIT (1);
155 ! the named constants cannot be used here, as epot_oct_m already uses this module.
156 if (p%type == proj_kb .and. reltype == 1) then
157 if (ps%relativistic_treatment == proj_j_dependent) then
158 p%type = proj_rkb
159 else
160 call messages_write("Spin-orbit coupling for species '"//trim(pseudo%get_label())//" is not available.")
161 call messages_warning(namespace=namespace)
162 end if
163 end if
165 select case (p%type)
166 case (proj_kb, proj_rkb, proj_uspp)
167 p%nprojections = ps%kbc
168 case (proj_hgh)
169 p%nprojections = 3
170 case default
171 assert(.false.)
172 end select
173
174 pop_sub(projector_init)
175 end subroutine projector_init
176
177 !---------------------------------------------
178
179 subroutine projector_init_phases(this, dim, std, bnd, kpoints, vec_pot, vec_pot_var)
180 type(projector_t), intent(inout) :: this
181 integer, intent(in) :: dim
182 type(states_elec_dim_t), intent(in) :: std
183 type(boundaries_t), intent(in) :: bnd
184 type(kpoints_t), intent(in) :: kpoints
185 real(real64), optional, allocatable, intent(in) :: vec_pot(:)
186 real(real64), optional, allocatable, intent(in) :: vec_pot_var(:, :)
187
188 integer :: ns, iq, is, ikpoint
189 real(real64) :: kr, kpoint(dim)
190 integer :: nphase, iphase
191 real(real64), allocatable :: diff(:,:)
192
195 ns = this%sphere%np
196 nphase = 1
197 if (bnd%spiralBC) nphase = 3
199 if (.not. allocated(this%phase) .and. ns > 0) then
200 safe_allocate(this%phase(1:ns, 1:nphase, std%kpt%start:std%kpt%end))
201 end if
202
203 ! Construct vectors which translate the submesh point back into the unit cell:
204 ! The positions this%sphere%x can lie outside the unit cell, while
205 ! this%sphere%mesh%x(this%sphere%map(is), 1:ndim) by construction is the periodic image inside the unit cell.
206 ! If a point of the submesh is inside the unit cell, diff(:,is) = 0.
207 safe_allocate(diff(1:dim, 1:ns))
208 !$omp parallel private(ikpoint, kpoint, iphase, is, kr, iq)
209 !$omp do
210 do is = 1, ns
211 diff(:, is) = this%sphere%rel_x(:,is) + this%sphere%center - this%sphere%mesh%x(:, this%sphere%map(is))
212 end do
213
214 do iq = std%kpt%start, std%kpt%end
215 ikpoint = std%get_kpoint_index(iq)
216
217 ! if this fails, it probably means that sb is not compatible with std
218 assert(ikpoint <= kpoints_number(kpoints))
219
220 kpoint = m_zero
221 kpoint(1:dim) = kpoints%get_point(ikpoint)
222
223 do iphase = 1, nphase
224 !$omp do
225 do is = 1, ns
226 ! this is only the correction to the global phase, that can
227 ! appear if the sphere crossed the boundary of the cell. (diff=0 otherwise)
228
229 kr = sum(kpoint(1:dim)*diff(1:dim, is))
230
231 if (present(vec_pot)) then
232 if (allocated(vec_pot)) kr = kr + sum(vec_pot(1:dim)*diff(1:dim, is))
233 end if
234
235 if (present(vec_pot_var)) then
236 if (allocated(vec_pot_var)) kr = kr + sum(vec_pot_var(1:dim, this%sphere%map(is)) &
237 *(this%sphere%rel_x(:, is)+this%sphere%center))
238 end if
239
240 if (bnd%spiralBC .and. iphase > 1) then
241 kr = kr + (2*(iphase-1)-3)*sum(bnd%spiral_q(1:dim)*diff(1:dim, is))
242 end if
243
244 this%phase(is, iphase, iq) = exp(-m_zi*kr)
245 end do
246 !$omp end do nowait
247 end do
248 end do
249 !$omp end parallel
250
251 safe_deallocate_a(diff)
252
253 pop_sub(projector_init_phases)
254
255 end subroutine projector_init_phases
256
257 !---------------------------------------------------------
258 subroutine projector_build(p, ps, so_strength)
259 type(projector_t), intent(inout) :: p
260 class(pseudopotential_t), intent(in) :: ps
261 real(real64), intent(in) :: so_strength
262
263 integer :: ll, mm, ic, ip
264
265 push_sub_with_profile(projector_build)
266
267 select case (p%type)
268
269 case (proj_hgh)
270 safe_allocate(p%hgh_p(0:p%lmax, -p%lmax:p%lmax))
271 do ll = 0, p%lmax
272 if (ll == p%lloc) cycle
273 do mm = -ll, ll
274 call hgh_projector_init(p%hgh_p(ll, mm), p%sphere, p%reltype, ps, ll, mm, so_strength)
275 end do
276 end do
277
278 case (proj_kb, proj_uspp)
279 safe_allocate(p%kb_p(0:p%lmax, -p%lmax:p%lmax))
280 if (p%type == proj_uspp) then
281 safe_allocate(p%uspp_dij(0:p%lmax, 1:ps%ps%kbc, 1:ps%ps%kbc))
282 safe_allocate(p%uspp_qij(0:p%lmax, 1:ps%ps%kbc, 1:ps%ps%kbc))
283 p%uspp_dij = ps%ps%h
284 p%uspp_qij = ps%ps%qij
285 if (allocated(ps%ps%radial_augmentation)) then
286 p%uspp_qfunc_lmax = ps%ps%radial_augmentation_lmax
287 p%uspp_qfunc_nbeta = ps%ps%radial_augmentation_nprojectors
288 safe_allocate(p%uspp_qfunc(1:p%sphere%np, 1:p%uspp_qfunc_nbeta*p%uspp_qfunc_nbeta, 0:p%uspp_qfunc_lmax))
289 do ll = 0, p%uspp_qfunc_lmax
290 do ic = 1, p%uspp_qfunc_nbeta*p%uspp_qfunc_nbeta
291 do ip = 1, p%sphere%np
292 if (p%sphere%r(ip) < spline_range_max(ps%ps%radial_augmentation(ic, ll))) then
293 p%uspp_qfunc(ip, ic, ll) = spline_eval(ps%ps%radial_augmentation(ic, ll), p%sphere%r(ip))
294 else
295 p%uspp_qfunc(ip, ic, ll) = m_zero
296 end if
297 end do
298 end do
299 end do
300 end if
301 end if
302 do ll = 0, p%lmax
303 if (ll == p%lloc) cycle
304 do mm = -ll, ll
305 call kb_projector_init(p%kb_p(ll, mm), p%sphere, ps, ll, mm)
306 end do
307 end do
308
309 case (proj_rkb)
310 safe_allocate(p%rkb_p(1:p%lmax, -p%lmax:p%lmax))
311 do ll = 1, p%lmax
312 if (ll == p%lloc) cycle
313 do mm = -ll, ll
314 call rkb_projector_init(p%rkb_p(ll, mm), p%sphere, ps, ll, mm, so_strength)
315 end do
316 end do
317 ! for rkb, l = 0 is a normal kb
318 if (p%lloc /= 0) then
319 safe_allocate(p%kb_p(1, 1))
320 call kb_projector_init(p%kb_p(1, 1), p%sphere, ps, 0, 0)
321 end if
322
323 end select
324
325 pop_sub_with_profile(projector_build)
326 end subroutine projector_build
327
328 !---------------------------------------------------------
335 subroutine projector_check_discretization(pseudo, sm, namespace)
336 class(pseudopotential_t), target, intent(in) :: pseudo
337 type(submesh_t), intent(in) :: sm
338 type(namespace_t), intent(in) :: namespace
339
340 integer :: ll, mm, ic, ir, nc
341 real(real64) :: rc, dr, rr, norm_rad, norm_grid, dev
342 real(real64), allocatable :: uv(:)
343 type(ps_t), pointer :: ps
344
345 integer, parameter :: quad_points = 2000
347 real(real64), parameter :: norm_dev_warning = 0.05_real64
348
350
351 ps => pseudo%ps
352
353 dev = m_zero
354 safe_allocate(uv(1:max(sm%np, 1)))
355
356 do ll = 0, ps%lmax
357 if (ll == ps%llocal) cycle
358
359 nc = ps%kbc
360 if (ps%projector_type == proj_kb) nc = min(nc, ps%projectors_per_l(ll+1))
361
362 do ic = 1, nc
363 ! Norm^2 of the projector on the radial grid
364 rc = ps%kb(ll, ic)%x_threshold
365 if (rc <= m_epsilon) cycle
366 dr = rc/quad_points
367 norm_rad = m_zero
368 do ir = 1, quad_points
369 rr = (ir - m_half)*dr
370 norm_rad = norm_rad + spline_eval(ps%kb(ll, ic), rr)**2 * rr**2
371 end do
372 norm_rad = norm_rad*dr
373 if (norm_rad <= 1.0e-10_real64) cycle
374
375 ! Norm^2 of the same projector discretized on the grid, for all values of m
376 do mm = -ll, ll
377 call pseudopotential_real_nl_projector(pseudo, sm%np, sm%rel_x, sm%r, ll, mm, ic, uv)
378 norm_grid = dsm_nrm2(sm, uv)**2
379 dev = max(dev, abs(norm_grid - norm_rad)/norm_rad)
380 end do
381 end do
382 end do
383
384 safe_deallocate_a(uv)
385
386 write(message(1), '(a,es9.2)') "Debug: projector discretization error for species '" &
387 //trim(pseudo%get_label())//"' = ", dev
388 call messages_info(1, namespace=namespace, debug_only=.true.)
389
390 if (dev > norm_dev_warning) then
391 write(message(1), '(a)') "The nonlocal projectors of species '"//trim(pseudo%get_label())//"'"
392 write(message(2), '(a)') "are not well resolved on the real-space grid: at least one projector norm"
393 write(message(3), '(a,f8.1,a)') "deviates by ", dev*100, "% from its radial-grid value."
394 write(message(4), '(a)') "This can produce spurious (ghost) states. Please reduce the grid Spacing."
395 call messages_warning(4, namespace=namespace)
396 end if
397
399 end subroutine projector_check_discretization
400
401 !---------------------------------------------------------
402 subroutine projector_end(p)
403 type(projector_t), intent(inout) :: p
404
405 integer :: ll, mm
406
407 push_sub(projector_end)
408
409 call submesh_end(p%sphere)
410
411 select case (p%type)
412 case (proj_hgh)
413 do ll = 0, p%lmax
414 if (ll == p%lloc) cycle
415 do mm = -ll, ll
416 call hgh_projector_end(p%hgh_p(ll, mm))
417 end do
418 end do
419 safe_deallocate_a(p%hgh_p)
420
421 case (proj_kb, proj_uspp)
422 do ll = 0, p%lmax
423 if (ll == p%lloc) cycle
424 do mm = -ll, ll
425 call kb_projector_end(p%kb_p(ll, mm))
426 end do
427 end do
428 safe_deallocate_a(p%kb_p)
429 safe_deallocate_a(p%uspp_dij)
430 safe_deallocate_a(p%uspp_qij)
431 safe_deallocate_a(p%uspp_qfunc)
432
433 case (proj_rkb)
434 do ll = 1, p%lmax
435 if (ll == p%lloc) cycle
436 do mm = -ll, ll
437 call rkb_projector_end(p%rkb_p(ll, mm))
438 end do
439 end do
440 safe_deallocate_a(p%rkb_p)
441 if (p%lloc /= 0) then
442 call kb_projector_end(p%kb_p(1, 1))
443 safe_deallocate_a(p%kb_p)
444 end if
445
446 end select
447
448 p%type = proj_none
449
450 safe_deallocate_a(p%phase)
451
452 pop_sub(projector_end)
453 end subroutine projector_end
454
455#include "undef.F90"
456#include "real.F90"
457#include "projector_inc.F90"
458
459#include "undef.F90"
460#include "complex.F90"
461#include "projector_inc.F90"
462
463end module projector_oct_m
464
465
466
467!! Local Variables:
468!! mode: f90
469!! coding: utf-8
470!! End:
double exp(double __x) __attribute__((__nothrow__
This module implements batches of mesh functions.
Definition: batch.F90:133
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
Module implementing boundary conditions in Octopus.
Definition: boundaries.F90:122
This module implements the underlying real-space grid.
Definition: grid.F90:117
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
/* To use the profiling module, call profiling_in and profiling_out with the label of the region as a...
Definition: profiling.F90:143
real(real64) function, public dprojector_matrix_element(pj, bnd, dim, ik, psia, psib)
dprojector_matrix_element calculates <psia|projector|psib>
Definition: projector.F90:951
subroutine, public projector_build(p, ps, so_strength)
Definition: projector.F90:352
subroutine, public dprojector_commute_r(pj, mesh, bnd, dim, idir, ik, psi, cpsi)
This function calculates |cpsi> += [x, V_nl] |psi>
Definition: projector.F90:1070
logical elemental function, public projector_is(p, type)
Definition: projector.F90:215
subroutine, public dproject_psi(mesh, bnd, pj, npj, dim, psi, ppsi, ik)
dproject_psi calculates the action of a projector on the psi wavefunction. The result is summed up to...
Definition: projector.F90:619
subroutine, public projector_init(p, pseudo, namespace, dim, reltype)
Definition: projector.F90:222
subroutine, public projector_init_phases(this, dim, std, bnd, kpoints, vec_pot, vec_pot_var)
Definition: projector.F90:273
subroutine, public dproject_psi_batch(mesh, bnd, pj, npj, dim, psib, ppsib)
To optimize the application of the non-local operator in parallel, the projectors are applied in step...
Definition: projector.F90:654
complex(real64) function, public zprojector_matrix_element(pj, bnd, dim, ik, psia, psib)
zprojector_matrix_element calculates <psia|projector|psib>
Definition: projector.F90:1659
subroutine, public zprojector_commute_r_allatoms_alldir(pj, ions, mesh, dim, bnd, ik, psi, cpsi)
This function calculates |cpsi> += [x, V_nl] |psi>
Definition: projector.F90:1863
subroutine, public projector_end(p)
Definition: projector.F90:496
subroutine, public zproject_psi(mesh, bnd, pj, npj, dim, psi, ppsi, ik)
zproject_psi calculates the action of a projector on the psi wavefunction. The result is summed up to...
Definition: projector.F90:1327
subroutine, public zproject_psi_batch(mesh, bnd, pj, npj, dim, psib, ppsib)
To optimize the application of the non-local operator in parallel, the projectors are applied in step...
Definition: projector.F90:1362
subroutine, public projector_check_discretization(pseudo, sm, namespace)
Check how well the nonlocal projectors are resolved on the real-space grid.
Definition: projector.F90:429
subroutine, public dprojector_commute_r_allatoms_alldir(pj, ions, mesh, dim, bnd, ik, psi, cpsi)
This function calculates |cpsi> += [x, V_nl] |psi>
Definition: projector.F90:1155
subroutine, public zprojector_commute_r(pj, mesh, bnd, dim, idir, ik, psi, cpsi)
This function calculates |cpsi> += [x, V_nl] |psi>
Definition: projector.F90:1778
logical elemental function, public projector_is_null(p)
Definition: projector.F90:208
Definition: ps.F90:114
integer, parameter, public proj_none
Definition: ps.F90:171
This module handles spin dimensions of the states and the k-point distribution.
The projector data type is intended to hold the local and non-local parts of the pseudopotentials....
Definition: projector.F90:179
int true(void)