Octopus
ps_psf.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 ps_psf_oct_m
22 use atomic_oct_m
23 use debug_oct_m
24 use global_oct_m
25 use io_oct_m
26 use, intrinsic :: iso_fortran_env
27 use logrid_oct_m
33
34 implicit none
35
36 private
37 public :: &
38 ps_psf_t, &
40 ps_psf_end, &
43
44 type ps_psf_t
45 ! Components are public by default
46 type(ps_psf_file_t), private :: psf_file
47 type(ps_in_grid_t) :: ps_grid
48
49 type(valconf_t) :: conf
50 real(real64), allocatable, private :: eigen(:, :)
51 integer, private :: ispin
52 end type ps_psf_t
53
54contains
55
56 ! ---------------------------------------------------------
57 subroutine ps_psf_init(pstm, ispin, filename, namespace)
58 type(ps_psf_t), intent(inout) :: pstm
59 integer, intent(in) :: ispin
60 character(len=*), intent(in) :: filename
61 type(namespace_t), intent(in) :: namespace
62
63 character(len=MAX_PATH_LEN) :: fullpath
64 integer :: iunit
65 logical :: found, ascii
66
67 push_sub(ps_psf_init)
68
69 ! Sets the spin components
70 pstm%ispin = ispin
71
72 ! Find out where the hell the file is.
73
74 found = .false.
75
76 assert(trim(filename) /= '')
77
78 ascii = .true.
79 fullpath = trim(filename)
80 inquire(file = fullpath, exist = found)
81
82 if (.not. found) then
83 message(1) = "Pseudopotential file '" // trim(fullpath) // " not found"
84 call messages_fatal(1, namespace=namespace)
85 end if
86
87 if (ascii) then
88 iunit = io_open(fullpath, action='read', form='formatted', status='old')
89 else
90 iunit = io_open(fullpath, action='read', form='unformatted', status='old')
91 end if
92 call ps_psf_file_read(iunit, ascii, pstm%psf_file, namespace)
93 call io_close(iunit)
94
95 ! Fills the valence configuration data.
96 call build_valconf(pstm%psf_file, ispin, pstm%conf, namespace)
97
98 ! Hack
99 if (mod(pstm%psf_file%nr, 2) == 0) pstm%psf_file%nr = pstm%psf_file%nr - 1
100
101 call file_to_grid(pstm%psf_file, pstm%ps_grid)
102
103 pop_sub(ps_psf_init)
104 end subroutine ps_psf_init
105
106
107 ! ---------------------------------------------------------
108 subroutine ps_psf_end(ps_psf)
109 type(ps_psf_t), intent(inout) :: ps_psf
110
111 push_sub(ps_psf_end)
112
113 safe_deallocate_a(ps_psf%eigen)
114 call ps_in_grid_end(ps_psf%ps_grid)
115 call ps_psf_file_end(ps_psf%psf_file)
116
117 pop_sub(ps_psf_end)
118 end subroutine ps_psf_end
119
120
121 ! ---------------------------------------------------------
122 subroutine build_valconf(psf_file, ispin, conf, namespace)
123 type(ps_psf_file_t), intent(in) :: psf_file
124 integer, intent(in) :: ispin
125 type(valconf_t), intent(out) :: conf
126 type(namespace_t), intent(in) :: namespace
127
128 character(len=1) :: char1(6), char2
129 character(len=256) :: r_fmt
130 integer :: l
131
132 push_sub(build_valconf)
133
134 conf%symbol = psf_file%namatm
135 conf%p = psf_file%npotd
136 write(char2,'(i1)') conf%p
138 select case (psf_file%irel)
139 case ('nrl')
140 write(r_fmt, '(3a)') '(', char2, '(i1,a1,f5.2,10x))'
141 read(psf_file%title, r_fmt) &
142 (conf%n(l), char1(l), conf%occ(l,1), l = 1, conf%p)
143 case ('isp')
144 write(r_fmt, '(3a)') '(', char2, '(i1,a1,f4.2,1x,f4.2,6x))'
145 read(psf_file%title, r_fmt) &
146 (conf%n(l), char1(l), conf%occ(l,1), conf%occ(l,2), l = 1, conf%p)
147 case ('rel')
148 write(r_fmt, '(3a)') '(', char2, '(i1,a1,f5.2,10x))'
149 read(psf_file%title, r_fmt) &
150 (conf%n(l), char1(l), conf%occ(l,1), l = 1, conf%p)
151 end select
152
153 do l = 1, conf%p
154 select case (char1(l))
155 case ('s')
156 conf%l(l) = 0
157 case ('p')
158 conf%l(l) = 1
159 case ('d')
160 conf%l(l) = 2
161 case ('f')
162 conf%l(l) = 3
163 case default
164 message(1) = 'Error reading pseudopotential file.'
165 call messages_fatal(1, namespace=namespace)
166 end select
167 end do
168
169 if (ispin == 2 .and. psf_file%irel /= 'isp') then
171 end if
172
173 pop_sub(build_valconf)
174 end subroutine build_valconf
175
176 !----------------------------------------------------------------
177 subroutine file_to_grid(psf_file, ps_grid)
178 type(ps_psf_file_t), intent(in) :: psf_file
179 type(ps_in_grid_t), intent(out) :: ps_grid
180
181 integer :: nrval
182
183 push_sub(file_to_grid)
184
185 ! Initializes the pseudo in the logarithmic grid.
186 call ps_in_grid_init(ps_grid, &
187 logrid_psf, psf_file%a, psf_file%b, psf_file%nr, &
188 psf_file%npotd, psf_file%npotu)
189
190 nrval = ps_grid%g%nrval
191
192 ps_grid%zval = psf_file%zval
193 ps_grid%vps(1:nrval,:) = psf_file%vps(1:nrval,:)
194 ps_grid%chcore(1:nrval) = psf_file%chcore(1:nrval)
195 if (ps_grid%so_no_l_channels > 0) then
196 ps_grid%so_vps(1:nrval,:) = psf_file%vso(1:nrval,:)
197 end if
198
199 ps_grid%core_corrections = .true.
200 if (trim(psf_file%icore) == 'nc') ps_grid%core_corrections = .false.
202 pop_sub(file_to_grid)
203 end subroutine file_to_grid
204
205
206 ! ---------------------------------------------------------
207 subroutine ps_psf_process(ps_psf, namespace, lmax, lloc)
208 type(ps_psf_t), intent(inout) :: ps_psf
209 type(namespace_t), intent(in) :: namespace
210 integer, intent(in) :: lmax, lloc
211
212 push_sub(psf_process)
213
214 ! get the pseudoatomic eigenfunctions
215 safe_allocate(ps_psf%eigen(1:ps_psf%psf_file%npotd, 1:3))
216 call solve_schroedinger(ps_psf%psf_file, namespace, ps_psf%ps_grid%g, &
217 ps_psf%conf, ps_psf%ispin, ps_psf%ps_grid%rphi, ps_psf%eigen)
218
219 ! check norm of rphi
220 call ps_in_grid_check_rphi(ps_psf%ps_grid, namespace)
221
222 ! Fix the local potential. Final argument is the core radius
223 call ps_in_grid_vlocal(ps_psf%ps_grid, lloc, m_three, namespace)
224
225 ! Calculate kb cosines and norms
226 call ps_in_grid_kb_cosines(ps_psf%ps_grid, lloc)
227
228 ! Ghost analysis.
229 call ghost_analysis(ps_psf%psf_file, ps_psf%ps_grid, ps_psf%ps_grid%g, namespace, ps_psf%eigen, lmax)
230
231 ! Define the KB-projector cut-off radii
232 call ps_in_grid_cutoff_radii(ps_psf%ps_grid, lloc)
233
234 ! Calculate KB-projectors
235 call ps_in_grid_kb_projectors(ps_psf%ps_grid)
236
237 pop_sub(psf_process)
238 end subroutine ps_psf_process
239
240 ! ---------------------------------------------------------
241 subroutine ps_psf_get_eigen(ps_psf, eigen)
242 type(ps_psf_t), intent(in) :: ps_psf
243 real(real64), intent(out) :: eigen(:,:)
244
245 integer :: i
246
247 push_sub(ps_psf_get_eigen)
248
249 do i = 1, ps_psf%conf%p
250 if (ps_psf%ispin == 1) then
251 eigen(i, 1) = ps_psf%eigen(i, 1)
252 else
253 eigen(i, 1:2) = ps_psf%eigen(i, 2:3)
254 end if
255 end do
256
257 pop_sub(ps_psf_get_eigen)
258 end subroutine ps_psf_get_eigen
259
260 ! ---------------------------------------------------------
261 subroutine solve_schroedinger(psf_file, namespace, g, conf, ispin, rphi, eigen)
262 type(ps_psf_file_t), intent(inout) :: psf_file
263 type(namespace_t), intent(in) :: namespace
264 type(logrid_t), intent(in) :: g
265 type(valconf_t), intent(in) :: conf
266 integer, intent(in) :: ispin
267 real(real64), intent(out) :: rphi(:,:,:), eigen(:,:)
268
269
270 character(len=3) :: functl
271 integer :: iter, ir, is, l, nnode, nprin, ierr
272 real(real64) :: vtot, diff, a2b4
273 real(real64), allocatable :: ve(:, :), rho(:, :), prev(:, :)
274
275 ! These variables are in double precision, even if the single-precision version of
276 ! octopus is compiled, because they are passed to egofv.
277 real(real64) :: e, z, dr, rmax
278 real(real64), allocatable :: s(:), hato(:), gg(:), y(:)
279
280 push_sub(solve_schroedinger)
281
282 ! Allocation.
283 safe_allocate(s(1:g%nrval))
284 safe_allocate(hato(1:g%nrval))
285 safe_allocate(gg(1:g%nrval))
286 safe_allocate(y(1:g%nrval))
287 safe_allocate(ve(1:g%nrval, 1:ispin))
288 safe_allocate(rho(1:g%nrval, 1:ispin))
289 safe_allocate(prev(1:g%nrval, 1:ispin))
290 s = m_zero
291 hato = m_zero
292 gg = m_zero
293 y = m_zero
294 ve = m_zero
295 rho = m_zero
296 prev = m_zero
297
298 ! These numerical parameters have to be fixed for egofv to work.
299 s(:) = g%drdi(:)**2
300 a2b4 = m_fourth*psf_file%a**2
301
302 ! ionic pseudopotential if core-correction for Hartree
303 if ((psf_file%icore == 'pche') .or. (psf_file%icore == 'fche')) then
304 call vhrtre(psf_file%chcore, ve(:, 1), g%rofi, g%drdi, g%s, g%nrval, g%a)
305 do l = 1, psf_file%npotd
306 psf_file%vps(:, l) = psf_file%vps(:, l) + ve(:, 1)
307 end do
308 end if
309
310 ! Calculation of the valence screening potential from the density:
311 ! ve(1:nrval) is the hartree+xc potential created by the pseudo -
312 ! valence charge distribution (everything in Rydbergs, and Bohrs)
313 rho(1:g%nrval, 1) = psf_file%rho_val(1:g%nrval)
314 select case (psf_file%icorr)
315 case ('pb')
316 functl = 'GGA'
317 case default
318 functl = 'LDA'
319 end select
320
321 call atomhxc(namespace, functl, g, 1, rho(:, 1:1), ve(:, 1:1), psf_file%chcore)
322
323 ! Calculation of the pseudo-wavefunctions.
324 ! rphi(1:nrval, 1:conf%p, :) : radial pseudo-wavefunctions. They are normalized so that
325 ! int dr {rphi^2} = 1. Thus its units are Bohr^(-1/2).
326 ! eigen(1:conf%p, :) : eigenvalues, in Rydbergs.
327 do l = 1, psf_file%npotd
328 do ir = 2, g%nrval
329 vtot = psf_file%vps(ir, l) + ve(ir, 1) + real((l-1)*l, real64)/(g%r2ofi(ir))
330 hato(ir) = vtot*s(ir) + a2b4
331 end do
332 hato(1) = first_point_extrapolate(g%rofi, hato)
333
334 nnode = 1
335 nprin = l
336 e = -((psf_file%zval/real(nprin, real64) )**2)
337 z = psf_file%zval
338 dr = -1.0e5_real64
339 rmax = g%rofi(g%nrval)
340
341 call egofv(namespace, hato, s, g%nrval, e, gg, y, l-1, z, &
342 real(g%a, real64) , real(g%b, real64) , rmax, nprin, nnode, dr, ierr)
343
344 if (ierr /= 0) then
345 write(message(1),'(a)') 'The algorithm that calculates atomic wavefunctions could not'
346 write(message(2),'(a)') 'do its job. The program will terminate, since the wavefunctions'
347 write(message(3),'(a)') 'are needed. Change the pseudopotential or improve the code.'
348 call messages_fatal(3, namespace=namespace)
349 end if
350 eigen(l, 1) = e
351
352 rphi(:, l, 1) = gg(:) * sqrt(g%drdi(:))
353
354 end do
355
356 ! Make a copy of the wavefunctions.
357 rphi(:, :, 2) = rphi(:, :, 1)
358
359 ! And now, for the spin-polarized case...
360 spin_polarized: if (ispin == 2) then
361
362 rho = m_zero ! Here information from previous calculation could be used, but
363 prev = m_zero ! to save code lines, let us start from scratch.
364 diff = 1.0e5_real64
365 iter = 0
366 self_consistent: do
367 prev = rho
368 iter = iter + 1
369
370 spin: do is = 1, ispin
371 ang: do l = 1, psf_file%npotd
372 do ir = 2, g%nrval
373 vtot = psf_file%vps(ir, l) + ve(ir, is) + real((l-1)*l, real64)/g%r2ofi(ir)
374 hato(ir) = vtot*s(ir) + a2b4
375 end do
376 hato(1) = first_point_extrapolate(g%rofi, hato)
377
378 nnode = 1
379 nprin = l
380 e = -((psf_file%zval/real(nprin, real64) )**2)
381 z = psf_file%zval
382 dr = -1.0e5_real64
383 rmax = g%rofi(g%nrval)
384
385 call egofv(namespace, hato, s, g%nrval, e, gg, y, l-1, z, &
386 real(g%a, real64) , real(g%b, real64) , rmax, nprin, nnode, dr, ierr)
387
388 if (ierr /= 0) then
389 write(message(1),'(a)') 'The algorithm that calculates atomic wavefunctions could not'
390 write(message(2),'(a)') 'do its job. The program will terminate, since the wavefunctions'
391 write(message(3),'(a)') 'are needed. Change the pseudopotential or improve the code.'
392 call messages_fatal(3, namespace=namespace)
393 end if
394 eigen(l, 1 + is) = e
395
396 rphi(:, l, 1 + is) = gg(:) * sqrt(g%drdi(:))
397 end do ang
398 end do spin
399
400 rho = m_zero
401 do is = 1, ispin
402 do l = 1, psf_file%npotd
403 rho(:, is) = rho(:, is) + conf%occ(l, is)*rphi(:, l, 1 + is)**2
404 end do
405 end do
406
407 diff = m_zero
408 do is = 1, ispin
409 diff = diff + sqrt(sum(g%drdi(:) * (rho(:, is) - prev(:, is))**2))
410 end do
411
412 if (diff < m_epsilon*1e2_real64) exit self_consistent
413 if (iter > 1) rho = m_half * rho + m_half * prev
414
415 !write(message(1),'(a,i4,a,e10.2)') ' Iter =', iter, '; Diff =', diff
416 !call messages_info(1, namespace=namespace)
417
418 call atomhxc(namespace, functl, g, 2, rho, ve, psf_file%chcore)
419 end do self_consistent
420
421 end if spin_polarized
422
423 ! Exit this...
424 safe_deallocate_a(s)
425 safe_deallocate_a(hato)
426 safe_deallocate_a(gg)
427 safe_deallocate_a(y)
428 safe_deallocate_a(ve)
429 safe_deallocate_a(rho)
430 safe_deallocate_a(prev)
431
432 pop_sub(solve_schroedinger)
433 end subroutine solve_schroedinger
434
435
436 ! ---------------------------------------------------------
437 subroutine ghost_analysis(psf_file, ps_grid, g, namespace, eigen, lmax)
438 type(ps_psf_file_t), intent(in) :: psf_file
439 type(ps_in_grid_t), intent(in) :: ps_grid
440 type(logrid_t), intent(in) :: g
441 type(namespace_t), intent(in) :: namespace
442 real(real64), intent(in) :: eigen(:,:)
443 integer, intent(in) :: lmax
444
445 character(len=3) :: functl
446 integer :: ir, l, nnode, nprin, ighost, ierr
447 real(real64) :: vtot, a2b4
448 real(real64), allocatable :: ve(:), elocal(:,:)
449
450 real(real64) :: z, e, dr, rmax
451 real(real64), allocatable :: hato(:), s(:), gg(:), y(:)
452
453 push_sub(ghost_analysis)
454
455 safe_allocate(ve(1:g%nrval))
456 safe_allocate(s(1:g%nrval))
457 safe_allocate(hato(1:g%nrval))
458 safe_allocate(gg(1:g%nrval))
459 safe_allocate(y(1:g%nrval))
460 safe_allocate(elocal(1:2, 1:lmax+1))
461
462 select case (psf_file%icorr)
463 case ('pb')
464 functl = 'GGA'
465 case default
466 functl = 'LDA'
467 end select
468
469 call atomhxc(namespace, functl, g, 1, psf_file%rho_val(:), ve(:), ps_grid%chcore(:))
470
471 ! calculate eigenvalues of the local potential for ghost analysis
472 s(:) = g%drdi(:)**2
473 a2b4 = m_fourth*g%a**2
474
475 do l = 1, lmax+1
476 do ir = 2, g%nrval
477 vtot = ps_grid%vlocal(ir) + ve(ir) + real((l-1)*l, real64)/(g%r2ofi(ir))
478 hato(ir) = vtot*s(ir) + a2b4
479 end do
480 hato(1) = first_point_extrapolate(g%rofi, hato)
481
482 do nnode = 1, 2
483 nprin = l
484 e = -(ps_grid%zval/real(nprin, real64) )**2
485 z = ps_grid%zval
486 dr = -1.0e5_real64
487 rmax = g%rofi(g%nrval)
488
489 call egofv(namespace, hato, s, g%nrval, e, gg, y, l, z, &
490 real(g%a, real64) , real(g%b, real64) , rmax, nprin, nnode, dr, ierr)
491
492 elocal(nnode, l) = e
493 end do
494 end do
495
496 ! Ghost analysis
497 do l = 1, lmax+1
498 ighost = -1
499
500 if (ps_grid%dkbcos(l) > m_zero) then
501 if (eigen(l, 1) > elocal(2, l)) then
502 ighost = 1
503 end if
504 else if (ps_grid%dkbcos(l) < m_zero) then
505 if (eigen(l, 1) > elocal(1, l)) then
506 ighost = 1
507 end if
508 end if
509
510 if (ighost >= 0) then
511 write(message(1), '(a,i2)') "Ghost state found for l = ", l
512 call messages_warning(1, namespace=namespace)
513 end if
514 end do
515
516 safe_deallocate_a(hato)
517 safe_deallocate_a(gg)
518 safe_deallocate_a(y)
519 safe_deallocate_a(elocal)
520 safe_deallocate_a(s)
521 safe_deallocate_a(ve)
522
523 pop_sub(ghost_analysis)
524 end subroutine ghost_analysis
525
526end module ps_psf_oct_m
527
528!! Local Variables:
529!! mode: f90
530!! coding: utf-8
531!! End:
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public atomhxc(namespace, functl, g, nspin, dens, v, extra)
Definition: atomic.F90:253
subroutine, public valconf_unpolarized_to_polarized(conf)
Definition: atomic.F90:233
subroutine, public vhrtre(rho, v, r, drdi, srdrdi, nr, a)
VHRTRE CONSTRUCTS THE ELECTROSTATIC POTENTIAL DUE TO A SUPPLIED ! ELECTRON DENSITY....
Definition: atomic.F90:627
subroutine, public egofv(namespace, h, s, n, e, g, y, l, z, a, b, rmax, nprin, nnode, dr, ierr)
egofv determines the eigenenergy and wavefunction corresponding ! to a particular l,...
Definition: atomic.F90:765
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_fourth
Definition: global.F90:196
real(real64), parameter, public m_epsilon
Definition: global.F90:203
real(real64), parameter, public m_half
Definition: global.F90:193
real(real64), parameter, public m_three
Definition: global.F90:190
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
integer, parameter, public logrid_psf
log grid used in Troullier-Martins code
Definition: logrid.F90:135
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:543
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public ps_in_grid_kb_projectors(ps)
KB-projectors kb = (vps - vlocal) |phi> * dknorm.
Definition: ps_in_grid.F90:284
subroutine, public ps_in_grid_end(ps)
Definition: ps_in_grid.F90:208
subroutine, public ps_in_grid_cutoff_radii(ps, lloc)
Definition: ps_in_grid.F90:358
subroutine, public ps_in_grid_init(ps, flavor, a, b, nrval, no_l, so_no_l)
Definition: ps_in_grid.F90:169
subroutine, public ps_in_grid_kb_cosines(ps, lloc)
KB-cosines and KB-norms: dkbcos stores the KB "cosines:" || (v_l - v_local) phi_l ||^2 / < (v_l - v_l...
Definition: ps_in_grid.F90:313
subroutine, public ps_in_grid_vlocal(ps, l_loc, rcore, namespace)
Definition: ps_in_grid.F90:238
real(real64) function, public first_point_extrapolate(x, y, high_order)
Definition: ps_in_grid.F90:437
subroutine, public ps_in_grid_check_rphi(ps, namespace)
checks normalization of the pseudo wavefunctions
Definition: ps_in_grid.F90:412
subroutine, public ps_psf_file_end(psf)
subroutine, public ps_psf_file_read(unit, ascii, psf, namespace)
subroutine, public ps_psf_init(pstm, ispin, filename, namespace)
Definition: ps_psf.F90:151
subroutine, public ps_psf_process(ps_psf, namespace, lmax, lloc)
Definition: ps_psf.F90:301
subroutine solve_schroedinger(psf_file, namespace, g, conf, ispin, rphi, eigen)
Definition: ps_psf.F90:355
subroutine ghost_analysis(psf_file, ps_grid, g, namespace, eigen, lmax)
Definition: ps_psf.F90:531
subroutine build_valconf(psf_file, ispin, conf, namespace)
Definition: ps_psf.F90:216
subroutine, public ps_psf_get_eigen(ps_psf, eigen)
Definition: ps_psf.F90:335
subroutine, public ps_psf_end(ps_psf)
Definition: ps_psf.F90:202
subroutine file_to_grid(psf_file, ps_grid)
Definition: ps_psf.F90:271
int true(void)