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
84
85 type projector_t
86 private
87 integer, public :: type = proj_none
88 integer :: nprojections
89 integer, public :: lmax
90 integer, public :: lloc
91 integer :: nik
92 integer :: reltype
93
94 type(submesh_t), public :: sphere
95
96
99 type(hgh_projector_t), allocatable, public :: hgh_p(:, :)
100 type(kb_projector_t), allocatable, public :: kb_p(:, :)
101 type(rkb_projector_t), allocatable, public :: rkb_p(:, :)
102 complex(real64), allocatable, public :: phase(:, :, :)
103 end type projector_t
104
105contains
106
107 !---------------------------------------------------------
108 logical elemental function projector_is_null(p)
109 type(projector_t), intent(in) :: p
110
111 projector_is_null = (p%type == proj_none)
112 end function projector_is_null
113
114 !---------------------------------------------------------
115 logical elemental function projector_is(p, type)
116 type(projector_t), intent(in) :: p
117 integer, intent(in) :: type
118 projector_is = (p%type == type)
119 end function projector_is
120
121 !---------------------------------------------------------
122 subroutine projector_init(p, pseudo, namespace, dim, reltype)
123 type(projector_t), intent(inout) :: p
124 type(pseudopotential_t), target, intent(in) :: pseudo
125 type(namespace_t), intent(in) :: namespace
126 integer, intent(in) :: dim
127 integer, intent(in) :: reltype
128
129 type(ps_t), pointer :: ps
130
131 push_sub(projector_init)
132
133 ps => pseudo%ps
134
135 p%reltype = reltype
136 p%lmax = ps%lmax
137
138 if (ps%local) then
139 p%type = proj_none
140 pop_sub(projector_init)
141 return
142 end if
143
144 p%lloc = ps%llocal
145
146 p%type = ps%projector_type
147
148 ! reltype is epot_oct_m::proj_reltype, which is either NOREL (0) or SPIN_ORBIT (1);
149 ! the named constants cannot be used here, as epot_oct_m already uses this module.
150 if (p%type == proj_kb .and. reltype == 1) then
151 if (ps%relativistic_treatment == proj_j_dependent) then
152 p%type = proj_rkb
153 else
154 call messages_write("Spin-orbit coupling for species '"//trim(pseudo%get_label())//" is not available.")
155 call messages_warning(namespace=namespace)
156 end if
157 end if
158
159 select case (p%type)
160 case (proj_kb, proj_rkb)
161 p%nprojections = ps%kbc
162 case (proj_hgh)
163 p%nprojections = 3
164 case default
165 assert(.false.)
166 end select
168 pop_sub(projector_init)
169 end subroutine projector_init
170
171 !---------------------------------------------
172
173 subroutine projector_init_phases(this, dim, std, bnd, kpoints, vec_pot, vec_pot_var)
174 type(projector_t), intent(inout) :: this
175 integer, intent(in) :: dim
176 type(states_elec_dim_t), intent(in) :: std
177 type(boundaries_t), intent(in) :: bnd
178 type(kpoints_t), intent(in) :: kpoints
179 real(real64), optional, allocatable, intent(in) :: vec_pot(:)
180 real(real64), optional, allocatable, intent(in) :: vec_pot_var(:, :)
181
182 integer :: ns, iq, is, ikpoint
183 real(real64) :: kr, kpoint(dim)
184 integer :: nphase, iphase
185 real(real64), allocatable :: diff(:,:)
188
189 ns = this%sphere%np
190 nphase = 1
191 if (bnd%spiralBC) nphase = 3
192
193 if (.not. allocated(this%phase) .and. ns > 0) then
194 safe_allocate(this%phase(1:ns, 1:nphase, std%kpt%start:std%kpt%end))
195 end if
197 ! Construct vectors which translate the submesh point back into the unit cell:
198 ! The positions this%sphere%x can lie outside the unit cell, while
199 ! this%sphere%mesh%x(this%sphere%map(is), 1:ndim) by construction is the periodic image inside the unit cell.
200 ! If a point of the submesh is inside the unit cell, diff(:,is) = 0.
201 safe_allocate(diff(1:dim, 1:ns))
202 !$omp parallel private(ikpoint, kpoint, iphase, is, kr, iq)
203 !$omp do
204 do is = 1, ns
205 diff(:, is) = this%sphere%rel_x(:,is) + this%sphere%center - this%sphere%mesh%x(:, this%sphere%map(is))
206 end do
207
208 do iq = std%kpt%start, std%kpt%end
209 ikpoint = std%get_kpoint_index(iq)
211 ! if this fails, it probably means that sb is not compatible with std
212 assert(ikpoint <= kpoints_number(kpoints))
213
214 kpoint = m_zero
215 kpoint(1:dim) = kpoints%get_point(ikpoint)
216
217 do iphase = 1, nphase
218 !$omp do
219 do is = 1, ns
220 ! this is only the correction to the global phase, that can
221 ! appear if the sphere crossed the boundary of the cell. (diff=0 otherwise)
222
223 kr = sum(kpoint(1:dim)*diff(1:dim, is))
224
225 if (present(vec_pot)) then
226 if (allocated(vec_pot)) kr = kr + sum(vec_pot(1:dim)*diff(1:dim, is))
227 end if
228
229 if (present(vec_pot_var)) then
230 if (allocated(vec_pot_var)) kr = kr + sum(vec_pot_var(1:dim, this%sphere%map(is)) &
231 *(this%sphere%rel_x(:, is)+this%sphere%center))
232 end if
233
234 if (bnd%spiralBC .and. iphase > 1) then
235 kr = kr + (2*(iphase-1)-3)*sum(bnd%spiral_q(1:dim)*diff(1:dim, is))
236 end if
237
238 this%phase(is, iphase, iq) = exp(-m_zi*kr)
239 end do
240 !$omp end do nowait
241 end do
242 end do
243 !$omp end parallel
244
245 safe_deallocate_a(diff)
246
247 pop_sub(projector_init_phases)
248
249 end subroutine projector_init_phases
250
251 !---------------------------------------------------------
252 subroutine projector_build(p, ps, so_strength)
253 type(projector_t), intent(inout) :: p
254 class(pseudopotential_t), intent(in) :: ps
255 real(real64), intent(in) :: so_strength
256
257 integer :: ll, mm
258
259 push_sub(projector_build)
260
261 select case (p%type)
262
263 case (proj_hgh)
264 safe_allocate(p%hgh_p(0:p%lmax, -p%lmax:p%lmax))
265 do ll = 0, p%lmax
266 if (ll == p%lloc) cycle
267 do mm = -ll, ll
268 call hgh_projector_init(p%hgh_p(ll, mm), p%sphere, p%reltype, ps, ll, mm, so_strength)
269 end do
270 end do
271
272 case (proj_kb)
273 safe_allocate(p%kb_p(0:p%lmax, -p%lmax:p%lmax))
274 do ll = 0, p%lmax
275 if (ll == p%lloc) cycle
276 do mm = -ll, ll
277 call kb_projector_init(p%kb_p(ll, mm), p%sphere, ps, ll, mm)
278 end do
279 end do
280
281 case (proj_rkb)
282 safe_allocate(p%rkb_p(1:p%lmax, -p%lmax:p%lmax))
283 do ll = 1, p%lmax
284 if (ll == p%lloc) cycle
285 do mm = -ll, ll
286 call rkb_projector_init(p%rkb_p(ll, mm), p%sphere, ps, ll, mm, so_strength)
287 end do
288 end do
289 ! for rkb, l = 0 is a normal kb
290 if (p%lloc /= 0) then
291 safe_allocate(p%kb_p(1, 1))
292 call kb_projector_init(p%kb_p(1, 1), p%sphere, ps, 0, 0)
293 end if
294
295 end select
296
297 pop_sub(projector_build)
298 end subroutine projector_build
299
300 !---------------------------------------------------------
307 subroutine projector_check_discretization(pseudo, sm, namespace)
308 class(pseudopotential_t), target, intent(in) :: pseudo
309 type(submesh_t), intent(in) :: sm
310 type(namespace_t), intent(in) :: namespace
311
312 integer :: ll, mm, ic, ir, nc
313 real(real64) :: rc, dr, rr, norm_rad, norm_grid, dev
314 real(real64), allocatable :: uv(:)
315 type(ps_t), pointer :: ps
316
317 integer, parameter :: quad_points = 2000
319 real(real64), parameter :: norm_dev_warning = 0.05_real64
320
322
323 ps => pseudo%ps
324
325 dev = m_zero
326 safe_allocate(uv(1:max(sm%np, 1)))
327
328 do ll = 0, ps%lmax
329 if (ll == ps%llocal) cycle
330
331 nc = ps%kbc
332 if (ps%projector_type == proj_kb) nc = min(nc, ps%projectors_per_l(ll+1))
333
334 do ic = 1, nc
335 ! Norm^2 of the projector on the radial grid
336 rc = ps%kb(ll, ic)%x_threshold
337 if (rc <= m_epsilon) cycle
338 dr = rc/quad_points
339 norm_rad = m_zero
340 do ir = 1, quad_points
341 rr = (ir - m_half)*dr
342 norm_rad = norm_rad + spline_eval(ps%kb(ll, ic), rr)**2 * rr**2
343 end do
344 norm_rad = norm_rad*dr
345 if (norm_rad <= 1.0e-10_real64) cycle
346
347 ! Norm^2 of the same projector discretized on the grid, for all values of m
348 do mm = -ll, ll
349 call pseudopotential_real_nl_projector(pseudo, sm%np, sm%rel_x, sm%r, ll, mm, ic, uv)
350 norm_grid = dsm_nrm2(sm, uv)**2
351 dev = max(dev, abs(norm_grid - norm_rad)/norm_rad)
352 end do
353 end do
354 end do
355
356 safe_deallocate_a(uv)
357
358 write(message(1), '(a,es9.2)') "Debug: projector discretization error for species '" &
359 //trim(pseudo%get_label())//"' = ", dev
360 call messages_info(1, namespace=namespace, debug_only=.true.)
361
362 if (dev > norm_dev_warning) then
363 write(message(1), '(a)') "The nonlocal projectors of species '"//trim(pseudo%get_label())//"'"
364 write(message(2), '(a)') "are not well resolved on the real-space grid: at least one projector norm"
365 write(message(3), '(a,f8.1,a)') "deviates by ", dev*100, "% from its radial-grid value."
366 write(message(4), '(a)') "This can produce spurious (ghost) states. Please reduce the grid Spacing."
367 call messages_warning(4, namespace=namespace)
368 end if
369
371 end subroutine projector_check_discretization
372
373 !---------------------------------------------------------
374 subroutine projector_end(p)
375 type(projector_t), intent(inout) :: p
376
377 integer :: ll, mm
378
379 push_sub(projector_end)
380
381 call submesh_end(p%sphere)
382
383 select case (p%type)
384 case (proj_hgh)
385 do ll = 0, p%lmax
386 if (ll == p%lloc) cycle
387 do mm = -ll, ll
388 call hgh_projector_end(p%hgh_p(ll, mm))
389 end do
390 end do
391 safe_deallocate_a(p%hgh_p)
392
393 case (proj_kb)
394 do ll = 0, p%lmax
395 if (ll == p%lloc) cycle
396 do mm = -ll, ll
397 call kb_projector_end(p%kb_p(ll, mm))
398 end do
399 end do
400 safe_deallocate_a(p%kb_p)
401
402 case (proj_rkb)
403 do ll = 1, p%lmax
404 if (ll == p%lloc) cycle
405 do mm = -ll, ll
406 call rkb_projector_end(p%rkb_p(ll, mm))
407 end do
408 end do
409 safe_deallocate_a(p%rkb_p)
410 if (p%lloc /= 0) then
411 call kb_projector_end(p%kb_p(1, 1))
412 safe_deallocate_a(p%kb_p)
413 end if
414
415 end select
416
417 p%type = proj_none
418
419 safe_deallocate_a(p%phase)
420
421 pop_sub(projector_end)
422 end subroutine projector_end
423
424#include "undef.F90"
425#include "real.F90"
426#include "projector_inc.F90"
427
428#include "undef.F90"
429#include "complex.F90"
430#include "projector_inc.F90"
431
432end module projector_oct_m
433
434
435
436!! Local Variables:
437!! mode: f90
438!! coding: utf-8
439!! End:
double exp(double __x) __attribute__((__nothrow__
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
Module implementing boundary conditions in Octopus.
Definition: boundaries.F90:124
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
real(real64) function, public dprojector_matrix_element(pj, bnd, dim, ik, psia, psib)
dprojector_matrix_element calculates <psia|projector|psib>
Definition: projector.F90:922
subroutine, public projector_build(p, ps, so_strength)
Definition: projector.F90:348
subroutine, public dprojector_commute_r(pj, mesh, bnd, dim, idir, ik, psi, cpsi)
This function calculates |cpsi> += [x, V_nl] |psi>
Definition: projector.F90:1041
logical elemental function, public projector_is(p, type)
Definition: projector.F90:211
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:590
subroutine, public projector_init(p, pseudo, namespace, dim, reltype)
Definition: projector.F90:218
subroutine, public projector_init_phases(this, dim, std, bnd, kpoints, vec_pot, vec_pot_var)
Definition: projector.F90:269
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:625
complex(real64) function, public zprojector_matrix_element(pj, bnd, dim, ik, psia, psib)
zprojector_matrix_element calculates <psia|projector|psib>
Definition: projector.F90:1630
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:1834
subroutine, public projector_end(p)
Definition: projector.F90:470
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:1298
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:1333
subroutine, public projector_check_discretization(pseudo, sm, namespace)
Check how well the nonlocal projectors are resolved on the real-space grid.
Definition: projector.F90:403
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:1126
subroutine, public zprojector_commute_r(pj, mesh, bnd, dim, idir, ik, psi, cpsi)
This function calculates |cpsi> += [x, V_nl] |psi>
Definition: projector.F90:1749
logical elemental function, public projector_is_null(p)
Definition: projector.F90:204
Definition: ps.F90:116
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:180
int true(void)