1! 2! Copyright (C) 2006 Quantum ESPRESSO group 3! This file is distributed under the terms of the 4! GNU General Public License. See the file `License' 5! in the root directory of the present distribution, 6! or http://www.gnu.org/copyleft/gpl.txt . 7! 8!--------------------------------------------------------------- 9subroutine test_bessel ( ) 10 !--------------------------------------------------------------- 11 ! 12 ! diagonalization of the pseudo-atomic hamiltonian 13 ! in a basis of spherical Bessel functions: j_l (qr) 14 ! with zero boundary conditions at the border R: 15 ! j_l (q_l R) = 0 16 ! The basis sets contains all q_l's up to a kinetic 17 ! energy cutoff Ecut, such that q^2 <= Ecut (in Ry a.u.) 18 ! rm is the radius R of the box 19 ! 20 use io_global, only : stdout 21 use kinds, only : dp 22 use constants, only: pi 23 use ld1inc, only: lmax, lmx, grid 24 use ld1inc, only: ecutmin, ecutmax, decut, rm 25 ! 26 implicit none 27 ! 28 real(kind=dp), parameter :: eps = 1.0d-4 29 real(kind=dp) :: ecut ! kinetic-energy cutoff (equivalent to PW) 30 ! 31 real(kind=dp), allocatable :: q(:,:) ! quantized momenta in the spherical box 32 ! 33 integer :: nswx, & ! max number of quantized momenta q 34 nsw (0:lmx), & ! number of q such that q^2 < Ecut 35 mesh_, & ! mesh_ is such that r (mesh_) <= R 36 ncut, nc 37 ! 38 if ( ecutmin < eps .or. ecutmax < eps .or. ecutmax < ecutmin + eps .or. & 39 decut < eps .or. rm < 5.0_dp ) return 40 ! 41 write (stdout, "(/,5x,14('-'), ' Test with a basis set of Bessel functions ',& 42 & 10('-'),/)") 43 ! 44 write (stdout, "(5x,'Box size (a.u.) : ',f6.1)" ) rm 45 ncut = nint ( ( ecutmax-ecutmin ) / decut ) + 1 46 ! 47 ! we redo everything for each cutoff: not really a smart implementation 48 ! 49 do nc = 1, ncut 50 ! 51 ecut = ecutmin + (nc-1) * decut 52 ! 53 ! estimated max number of q needed for all values of l 54 ! 55 nswx = int ( sqrt ( ecut*rm**2/pi**2 ) ) + lmax + 1 56 ! 57 ! find grid point mesh_ such that r(mesh_) < R 58 ! note that mesh_ must be odd to perform simpson integration 59 ! 60 do mesh_ = 1, grid%mesh 61 if ( grid%r(mesh_) >= rm ) go to 20 62 end do 63 call errore ('test_bessel','r(mesh) < Rmax', mesh_) 6420 continue 65 mesh_ = 2 * ( (mesh_-1) / 2 ) + 1 66 ! 67 ! find quantized momenta q 68 ! 69 allocate ( q ( nswx, 0:lmax ) ) 70 call q_fill ( nswx, lmax, rm, ecut, nsw, q ) 71 ! 72 ! fill and diagonalize Kohn-Sham pseudo-hamiltonian 73 ! 74 write (stdout, "(/5x,'Cutoff (Ry) : ',f6.1)" ) ecut 75 call h_diag ( mesh_, nswx, nsw, lmax, q ) 76 ! 77 deallocate ( q ) 78 ! 79 end do 80 ! 81 write (stdout, "(/,5x,14('-'), ' End of Bessel function test ',24('-'),/)") 82 ! 83end subroutine test_bessel 84! 85!----------------------------------------------------------------------- 86subroutine q_fill ( nswx, lmax, rm, ecut, nsw, q ) 87 !----------------------------------------------------------------------- 88 ! 89 ! find quantized momenta in a box of radius R = rm 90 ! 91 use kinds, only : dp 92 use constants, only : pi 93 implicit none 94 integer, intent(in) :: nswx, lmax 95 real(kind=dp), intent(in) :: rm, ecut 96 integer, intent(out) :: nsw(0:lmax) 97 real(kind=dp), intent(out) :: q(nswx,0:lmax) 98 ! 99 integer :: i, l, iret 100 real(kind=dp), parameter :: eps=1.0d-10 101 real(kind=dp), external :: find_root 102 ! 103 ! l = 0 : j_0 (qR)=0 => q_i = i * (2pi/R) 104 ! 105 do i = 1, nswx 106 q(i,0) = i*pi 107 end do 108 ! 109 ! l > 0 : zeros for j_l (x) are found between two consecutive 110 ! zeros for j_{l-1} (x) 111 ! 112 do l = 1, lmax 113 do i = 1, nswx-l 114 q(i,l) = find_root ( l, q(i,l-1), q(i+1,l-1), eps, iret ) 115 if (iret /= 0) call errore('q_fill','root not found',l) 116 end do 117 end do 118 ! 119 do l = 0, lmax 120 do i = 1, nswx-l 121 q (i,l) = q(i,l) / rm 122 if ( q(i,l)**2 > ecut ) then 123 nsw(l) = i-1 124 goto 20 125 endif 126 enddo 127 call errore('q_fill','nswx is too small',nswx) 12820 continue 129 end do 130 ! 131 return 132end subroutine q_fill 133! 134!----------------------------------------------------------------------- 135function find_root ( l, xt1, xt2, eps, iret ) 136 ! ---------------------------------------------------------------------- 137 ! 138 use kinds, only : dp 139 implicit none 140 ! 141 integer, intent (in) :: l 142 real(kind=dp), intent (in) :: xt1, xt2, eps 143 ! 144 integer, intent (out) :: iret 145 real(kind=dp) :: find_root 146 ! 147 real(kind=dp) :: x1, x2, x0, f1, f2, f0 148 ! 149 x1 = MIN (xt1, xt2) 150 x2 = MAX (xt1, xt2) 151 ! 152 call sph_bes ( 1, 1.0_dp, x1, l, f1 ) 153 call sph_bes ( 1, 1.0_dp, x2, l, f2 ) 154 ! 155 iret = 0 156 ! 157 if ( sign(f1,f2) == f1 ) then 158 find_root = 0.0_dp 159 iret = 1 160 return 161 end if 162! 163 do while ( abs(x2-x1) > eps ) 164 x0 = 0.5*(x1+x2) 165 call sph_bes ( 1, 1.0_dp, x0, l, f0 ) 166 if ( sign(f0,f1) == f0 ) then 167 x1 = x0 168 f1 = f0 169 else 170 x2 = x0 171 f2 = f0 172 end if 173 end do 174 ! 175 find_root = x0 176 ! 177 return 178end function find_root 179! 180!----------------------------------------------------------------------- 181subroutine h_diag ( mesh_, nswx, nsw, lmax, q ) 182 !----------------------------------------------------------------------- 183 ! 184 ! diagonalize the radial Kohn-Sham hamiltonian 185 ! in the basis of spherical bessel functions 186 ! Requires the self-consistent potential from a previous calculation! 187 ! 188 use io_global, only : stdout 189 use kinds, only : dp 190 use ld1inc, only: lmx, grid 191 use ld1inc, only: nbeta, betas, qq, ddd, vpstot, vnl, lls, jjs, & 192 nspin, rel, pseudotype 193 implicit none 194 ! 195 ! input 196 integer, intent (in) :: mesh_, lmax, nswx, nsw(0:lmx) 197 real(kind=dp), intent (in) :: q(nswx,0:lmax) 198 ! local 199 real(kind=dp), allocatable :: & 200 h(:,:), s(:,:), & ! hamiltonian and overlap matrix 201 chi (:,:), enl (:), & ! eigenvectors and eigenvalues 202 s0(:), & ! normalization factors for jl(qr) 203 betajl(:,:), & ! matrix elements for beta 204 betajl_(:,:), & ! work space: \sum_m D_lm beta_m 205 vaux (:), jlq (:,:), work (:) ! more work space 206 real(kind=dp), external :: int_0_inf_dr 207 real(kind=dp) :: j 208 character(len=2), dimension (2) :: spin = (/ 'up', 'dw' /) 209 integer :: n_states = 3, l, n, m, nb, mb, ind, is, nj 210 ! 211 ! 212 allocate ( h (nswx, nswx), s0(nswx), chi (nswx, n_states), enl(nswx) ) 213 allocate ( jlq ( mesh_, nswx ), work (mesh_), vaux (mesh_) ) 214 if ( pseudotype > 2 ) allocate ( s(nswx, nswx) ) 215 ! 216 write(stdout,"( 20x,3(7x,'N = ',i1) )" ) (n, n=1,n_states) 217 ! 218 do l=0,lmax 219 ! 220 ! nj: number of j-components in fully relativistic case 221 ! 222 if ( rel == 2 .and. l > 0 ) then 223 nj=2 224 else 225 nj=1 226 endif 227 ! 228 do n = 1, nsw(l) 229 ! 230 call sph_bes ( mesh_, grid%r, q(n,l), l, jlq(1,n) ) 231 ! 232 ! s0 = < j_l(qr) | j_l (qr) > 233 ! 234 work (:) = ( jlq(:,n) * grid%r(1:mesh_) ) ** 2 235 s0(n) = sqrt ( int_0_inf_dr ( work, grid, mesh_, 2*l+2 ) ) 236 ! 237 end do 238 ! 239 ! vaux is the local + scf potential ( + V_l for semilocal PPs) 240 ! note that nspin = 2 only for lsda; nspin = 1 in all other cases 241 ! 242 do is = 1, nspin 243 ! 244 do ind = 1, nj 245 ! 246 if ( rel == 2 .and. l > 0 ) then 247 j = l + (ind-1.5_dp) ! this is J=L+S 248 else if ( rel == 2 .and. l == 0 ) then 249 j = 0.5_dp 250 else 251 j = 0.0_dp 252 end if 253 ! 254 if (pseudotype == 1) then 255 vaux(:) = vpstot (1:mesh_, is) + vnl (1:mesh_, l, ind) 256 else 257 vaux(:) = vpstot (1:mesh_, is) 258 allocate ( betajl ( nswx, nbeta ), betajl_ ( nswx, nbeta ) ) 259 endif 260 ! 261 h (:,:) = 0.0_dp 262 ! 263 do n = 1, nsw(l) 264 ! 265 ! matrix elements for vaux 266 ! 267 do m = 1, n 268 work (:) = jlq(:,n) * jlq(:,m) * vaux(1:mesh_) * grid%r2(1:mesh_) 269 h(m,n) = int_0_inf_dr ( work, grid, mesh_, 2*l+2 ) & 270 / s0(n) / s0(m) 271 end do 272 ! 273 ! kinetic energy 274 ! 275 h(n,n) = h(n,n) + q(n,l)**2 276 ! 277 ! betajl(q,n) = < beta_n | j_l(qr) > 278 ! 279 if ( pseudotype > 1 ) then 280 do nb = 1, nbeta 281 if ( lls (nb) == l .and. abs(jjs (nb) - j) < 0.001_8 ) then 282 work (:) = jlq(:,n) * betas( 1:mesh_, nb ) * grid%r(1:mesh_) 283 betajl (n, nb) = 1.0_dp / s0(n) * & 284 int_0_inf_dr ( work, grid, mesh_, 2*l+2 ) 285 end if 286 end do 287 end if 288 end do 289 ! 290 ! separable PP 291 ! 292 if ( pseudotype > 1 ) then 293 ! 294 ! betajl_(q,m) = \sum_n D_mn * < beta_n | j_l(qr) > 295 ! 296 betajl_ (:,:) = 0.0_dp 297 do mb = 1, nbeta 298 if ( lls (mb) == l .and. abs(jjs (mb) - j) < 0.001_8 ) then 299 do nb = 1, nbeta 300 if ( lls (nb) == l .and. abs(jjs (nb) - j) < 0.001_8 ) then 301 betajl_ (:, mb) = betajl_ (:, mb) + & 302 ddd (mb,nb,is) * betajl (:, nb) 303 end if 304 end do 305 end if 306 end do 307 ! 308 ! matrix elements for nonlocal (separable) potential 309 ! 310 do n = 1, nsw(l) 311 do m = 1, n 312 do nb = 1, nbeta 313 if ( lls (nb) == l .and. abs(jjs (nb) - j) < 0.001_8 ) then 314 h(m,n) = h(m,n) + betajl_ (m, nb) * betajl (n, nb) 315 end if 316 end do 317 end do 318 end do 319 ! 320 ! US PP 321 ! 322 if ( pseudotype > 2 ) then 323 ! 324 ! betajl_(q,m) = \sum_n D_mn * < beta_n | j_l(qr) > 325 ! 326 betajl_ (:,:) = 0.0_dp 327 do mb = 1, nbeta 328 if ( lls (mb) == l .and. abs(jjs (mb) - j) < 0.001_8 ) then 329 do nb = 1, nbeta 330 if ( lls (nb) == l .and. & 331 abs(jjs (nb) - j) < 0.001_8 ) then 332 betajl_ (:, mb) = betajl_ (:, mb) + & 333 qq (mb,nb) * betajl (:, nb) 334 end if 335 end do 336 end if 337 end do 338 ! 339 ! overlap matrix S 340 ! 341 s (:,:) = 0.0_dp 342 do n = 1, nsw(l) 343 do m = 1, n 344 do nb = 1, nbeta 345 if ( lls (nb) == l .and. & 346 abs(jjs (nb) - j) < 0.001_8 ) then 347 s(m,n) = s(m,n) + betajl_ (m, nb) * betajl (n, nb) 348 end if 349 end do 350 end do 351 s(n,n) = s(n,n) + 1.0_dp 352 end do 353 end if 354 ! 355 deallocate ( betajl_, betajl ) 356 ! 357 end if 358 ! 359 if ( pseudotype > 2 ) then 360 call rdiags ( nsw(l), h, s, nswx, n_states, enl, chi, nswx) 361 else 362 call rdiagd ( nsw(l), h, nswx, n_states, enl, chi, nswx) 363 end if 364 ! 365 if ( nspin == 2 ) then 366 write(stdout, & 367 "( 5x,'E(L=',i1,',spin ',a2,') =',4(f10.4,' Ry') )" ) & 368 l, spin(is), (enl(n), n=1,n_states) 369 else if ( rel == 2 ) then 370 write(stdout, & 371 "( 5x,'E(L=',i1,',J=',f3.1,') =',4(f10.4,' Ry') )" ) & 372 l, j, (enl(n), n=1,n_states) 373 else 374 write(stdout, & 375 "( 5x,'E(L=',i1,') =',5x,4(f10.4,' Ry') )" ) & 376 l, (enl(n), n=1,n_states) 377 end if 378 end do 379 ! 380 end do 381 end do 382 ! 383 if ( pseudotype > 2 ) deallocate ( s ) 384 deallocate ( vaux, work, jlq ) 385 deallocate ( enl, chi, s0, h ) 386 ! 387 return 388end subroutine h_diag 389! 390!------------------------------------------------------------------ 391subroutine rdiagd ( n, h, ldh, m, e, v, ldv ) 392 !------------------------------------------------------------------ 393 ! 394 ! LAPACK driver for eigenvalue problem H*x = ex 395 ! 396 use kinds, only : dp 397 implicit none 398 ! 399 integer, intent (in) :: & 400 n, & ! dimension of the matrix to be diagonalized 401 ldh, & ! leading dimension of h, as declared in the calling pgm 402 m, & ! number of roots to be searched 403 ldv ! leading dimension of the v matrix 404 real(kind=dp), intent (inout) :: & 405 h(ldh,n) ! matrix to be diagonalized, UPPER triangle 406 ! DESTROYED ON OUTPUT 407 real(kind=dp), intent (out) :: e(m), v(ldv,m) ! eigenvalues and eigenvectors 408 ! 409 integer :: mo, lwork, info 410 integer, allocatable :: iwork(:), ifail(:) 411 real(kind=dp) :: vl, vu 412 real(kind=dp), allocatable :: work(:) 413 ! 414 lwork = 8*n 415 allocate ( work (lwork), iwork(5*n), ifail(n) ) 416 v (:,:) = 0.0_dp 417 ! 418 call DSYEVX ( 'V', 'I', 'U', n, h, ldh, vl, vu, 1, m, 0.0_dp, mo, e,& 419 v, ldv, work, lwork, iwork, ifail, info ) 420 ! 421 if ( info > 0) then 422 call errore('rdiagd','failed to converge',info) 423 else if(info < 0) then 424 call errore('rdiagd','illegal arguments',-info) 425 end if 426 deallocate ( ifail, iwork, work ) 427 ! 428 return 429end subroutine rdiagd 430! 431!---------------------------------------------------------------------------- 432SUBROUTINE rdiags( n, h, s, ldh, m, e, v, ldv ) 433 !---------------------------------------------------------------------------- 434 ! 435 ! LAPACK driver for generalized eigenvalue problem H*x = e S*x 436 ! 437 use kinds, only : dp 438 IMPLICIT NONE 439 ! 440 integer, intent (in) :: & 441 n, & ! dimension of the matrix to be diagonalized 442 ldh, & ! leading dimension of h, as declared in the calling pgm 443 m, & ! number of roots to be searched 444 ldv ! leading dimension of the v matrix 445 real(kind=dp), intent (inout) :: & 446 h(ldh,n), & ! matrix to be diagonalized, UPPER triangle 447 s(ldh,n) ! overlap matrix - both destroyed on output 448 ! 449 real(kind=dp), intent (out) :: e(m), v(ldv,m) ! eigenvalues and eigenvectors 450 ! 451 ! ... LOCAL variables 452 ! 453 integer :: mo, lwork, info 454 integer, allocatable :: iwork(:), ifail(:) 455 real(kind=dp), allocatable :: work(:) 456 457 lwork = 8 * n 458 allocate ( work (lwork), iwork(5*n), ifail(n) ) 459 v (:,:) = 0.0_dp 460 ! 461 CALL DSYGVX( 1, 'V', 'I', 'U', n, h, ldh, s, ldh, & 462 0.0_dp, 0.0_dp, 1, m, 0.0_dp, mo, e, v, ldh, work, lwork, & 463 iwork, ifail, info ) 464 ! 465 if ( info > n) then 466 call errore('rdiags','failed to converge (factorization)',info-n) 467 else if(info > 0) then 468 call errore('rdiags','failed to converge: ',info) 469 else if(info < 0) then 470 call errore('rdiags','illegal arguments',-info) 471 end if 472 deallocate ( ifail, iwork, work ) 473 ! 474 return 475 ! 476END SUBROUTINE rdiags 477