2004-05-14 23:33:08 +08:00
|
|
|
!
|
2005-03-21 22:33:57 +08:00
|
|
|
! Copyright (C) 2004 PWSCF group
|
|
|
|
! This file is distributed under the terms of the
|
|
|
|
! GNU General Public License. See the file `License'
|
|
|
|
! in the root directory of the present distribution,
|
|
|
|
! or http://www.gnu.org/copyleft/gpl.txt .
|
|
|
|
!
|
|
|
|
!
|
2004-05-14 23:33:08 +08:00
|
|
|
!---------------------------------------------------------------
|
2004-12-10 23:33:00 +08:00
|
|
|
subroutine ascheqps(nn,lam,jam,e,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
thresh,y,beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk)
|
|
|
|
!---------------------------------------------------------------
|
|
|
|
!
|
|
|
|
! numerical integration of the radial schroedinger equation for
|
|
|
|
! bound states in a local potential.
|
|
|
|
! thresh dermines the absolute accuracy for the eigenvalue
|
|
|
|
!
|
|
|
|
! This routine allows a nonlocal potential and a overlap
|
|
|
|
! operator. Therefore it can solve a general schroedinger
|
|
|
|
! equation as in the US pseudopotential case. The other
|
|
|
|
! pseudopotentials are particular cases
|
|
|
|
!
|
2007-06-26 15:38:38 +08:00
|
|
|
use io_global, only : stdout
|
2004-12-10 23:33:00 +08:00
|
|
|
use kinds, only : DP
|
|
|
|
implicit none
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2004-12-10 23:33:00 +08:00
|
|
|
integer :: &
|
|
|
|
nn, & ! main quantum number for node number
|
|
|
|
lam,& ! l angular momentum
|
|
|
|
mesh, & ! size of radial mesh
|
|
|
|
ndm, & ! maximum radial mesh
|
|
|
|
nbeta,& ! number of beta function
|
|
|
|
nwfx, & ! maximum number of beta functions
|
|
|
|
lls(nbeta),&! for each beta the angular momentum
|
|
|
|
ikk(nbeta) ! for each beta the point where it become zero
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2005-12-15 21:34:25 +08:00
|
|
|
real(kind=dp) :: &
|
2004-12-10 23:33:00 +08:00
|
|
|
e,de, & ! output eigenvalue
|
|
|
|
dx, & ! linear delta x for radial mesh
|
|
|
|
jam, & ! j angular momentum
|
|
|
|
r(mesh), & ! radial mesh
|
|
|
|
r2(mesh),& ! square of radial mesh
|
|
|
|
sqr(mesh), &! square root of radial mesh
|
|
|
|
vpot(mesh),&! the local potential
|
|
|
|
thresh, & ! precision of eigenvalue
|
|
|
|
y(mesh), & ! the output solution
|
|
|
|
jjs(nwfx), & ! the j angular momentum
|
|
|
|
beta(ndm,nwfx), & ! the beta functions
|
|
|
|
ddd(nwfx,nwfx),qq(nwfx,nwfx) ! parameters for computing B_ij
|
|
|
|
!
|
|
|
|
! the local variables
|
|
|
|
!
|
|
|
|
integer, parameter :: maxter=100
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2005-12-15 21:34:25 +08:00
|
|
|
real(kind=dp) :: &
|
2004-12-10 23:33:00 +08:00
|
|
|
sqlhf, & ! the term for angular momentum in equation
|
|
|
|
det,detup,detlw,detold, &! the determinant
|
|
|
|
eup0,elw0, & ! limits imposed by node counter
|
|
|
|
eup,elw,eold ! actual energy interval
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2004-12-10 23:33:00 +08:00
|
|
|
integer :: &
|
|
|
|
n, & ! counter on mesh points
|
|
|
|
iter, & ! counter on iteration
|
|
|
|
ns, & ! counter on beta functions
|
|
|
|
ncross,& ! the number of nodes
|
2005-02-11 16:35:54 +08:00
|
|
|
count,& ! counter on energy intervals
|
|
|
|
count0 ! counter on attempts with wrong number of nodes
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2004-12-10 23:33:00 +08:00
|
|
|
logical :: &
|
|
|
|
nosol
|
|
|
|
!
|
|
|
|
! set up constants and allocate variables the
|
|
|
|
!
|
2005-12-15 21:34:25 +08:00
|
|
|
sqlhf=(dble(lam)+0.5_DP)**2
|
2004-12-10 23:33:00 +08:00
|
|
|
!
|
|
|
|
! first try to find the zero with newton method
|
|
|
|
!
|
|
|
|
eold=e
|
|
|
|
eup0=0.0_DP
|
|
|
|
elw0=0.0_DP
|
|
|
|
nosol=.false.
|
2005-02-11 16:35:54 +08:00
|
|
|
count0=0
|
2005-12-15 21:34:25 +08:00
|
|
|
elw = e
|
|
|
|
call compute_det(nn,lam,jam,elw,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk, &
|
|
|
|
detlw)
|
|
|
|
eup=e*0.99_DP
|
|
|
|
call compute_det(nn,lam,jam,eup,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk, &
|
|
|
|
detup)
|
|
|
|
detold=detlw
|
2004-12-10 23:33:00 +08:00
|
|
|
do iter=1,maxter
|
2005-12-15 21:34:25 +08:00
|
|
|
if (detup /= detlw) de=-detlw*(eup-elw)/(detup-detlw)
|
2004-12-10 23:33:00 +08:00
|
|
|
!
|
|
|
|
! if an asintote has been found use bisection
|
|
|
|
!
|
2005-12-15 21:34:25 +08:00
|
|
|
if (abs(de).gt.1.e3_dp*abs(eold)) then
|
2007-06-26 15:38:38 +08:00
|
|
|
! write(stdout,*) 'BISECTION'
|
2005-12-15 21:34:25 +08:00
|
|
|
goto 800
|
|
|
|
endif
|
2004-12-10 23:33:00 +08:00
|
|
|
!
|
|
|
|
! check for convergence
|
|
|
|
!
|
2005-12-15 21:34:25 +08:00
|
|
|
if (abs(de/elw).lt.thresh) then
|
|
|
|
e=elw
|
|
|
|
goto 900
|
|
|
|
endif
|
|
|
|
eup = elw
|
|
|
|
elw = elw + de
|
|
|
|
call compute_det(nn,lam,jam,elw,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk, &
|
|
|
|
detlw)
|
|
|
|
call compute_det(nn,lam,jam,eup,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk, &
|
|
|
|
detup)
|
2004-12-10 23:33:00 +08:00
|
|
|
enddo
|
|
|
|
!
|
|
|
|
! if the program arrives here newton method does not work
|
|
|
|
! try bisection, first bracket the zero
|
|
|
|
!
|
|
|
|
800 e=eold
|
|
|
|
if (eup0 == 0.0_DP) then
|
|
|
|
eup=vpot(mesh)+sqlhf/r2(mesh)
|
|
|
|
else
|
|
|
|
eup=eup0
|
|
|
|
endif
|
|
|
|
if (elw0 == 0.0_DP) then
|
|
|
|
elw=eup
|
|
|
|
do n=1,mesh
|
|
|
|
elw=min(elw,vpot(n)+sqlhf/r2(n))
|
|
|
|
enddo
|
|
|
|
else
|
|
|
|
elw=elw0
|
|
|
|
endif
|
|
|
|
if(e.gt.eup) e=0.9_DP*eup+0.1_DP*elw
|
|
|
|
if(e.lt.elw) e=0.9_DP*elw+0.1_DP*eup
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2004-12-10 23:33:00 +08:00
|
|
|
call compute_det(nn,lam,jam,elw,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk,detlw)
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2004-12-10 23:33:00 +08:00
|
|
|
de=(eup-elw)/51.0_DP
|
|
|
|
do n=1,50
|
|
|
|
eup=elw+de
|
|
|
|
call compute_det(nn,lam,jam,eup,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk, &
|
|
|
|
detup)
|
2007-06-26 15:38:38 +08:00
|
|
|
if (detup*detlw.lt.0.0_DP) write(stdout,*) 'count0 = ', count0
|
2004-12-10 23:33:00 +08:00
|
|
|
if (detup*detlw.lt.0.0_DP) goto 100
|
|
|
|
elw=eup
|
|
|
|
detlw=detup
|
|
|
|
enddo
|
|
|
|
count=0
|
|
|
|
100 continue
|
|
|
|
if(e.gt.eup) e=0.9_DP*eup+0.1_DP*elw
|
|
|
|
if(e.lt.elw) e=0.9_DP*elw+0.1_DP*eup
|
|
|
|
!
|
|
|
|
! and find the detailed value
|
|
|
|
!
|
|
|
|
do iter=1,maxter
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2004-12-10 23:33:00 +08:00
|
|
|
call compute_det(nn,lam,jam,e,mesh,ndm,dx,r,r2,sqr,vpot, &
|
|
|
|
beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk,det)
|
2004-05-14 23:33:08 +08:00
|
|
|
|
2007-06-26 15:38:38 +08:00
|
|
|
! write(stdout,'(i11,3f20.10)') iter,detlw,det,detup
|
|
|
|
! write(stdout,'(''energy'',i5,3f20.10)') iter,elw,e,eup
|
2004-12-10 23:33:00 +08:00
|
|
|
!
|
|
|
|
! convergence check
|
|
|
|
!
|
|
|
|
if (abs((eup-elw)/elw).lt.thresh) goto 900
|
|
|
|
!
|
2005-02-04 02:20:34 +08:00
|
|
|
! treatement of asyntotes
|
2004-12-10 23:33:00 +08:00
|
|
|
!
|
|
|
|
if (abs(det).gt.1.0e4_dp) then
|
|
|
|
if (e.gt.eold) then
|
|
|
|
count=count+1
|
|
|
|
elw=eold
|
|
|
|
detlw=detold
|
|
|
|
eup=e-0.001_DP
|
|
|
|
call compute_det(nn,lam,jam,eup,mesh,ndm,dx, &
|
|
|
|
r,r2,sqr,vpot,beta,ddd,qq,&
|
|
|
|
nbeta,nwfx,lls,jjs,ikk,detup)
|
|
|
|
|
|
|
|
if (count.gt.30) &
|
2005-02-03 17:07:42 +08:00
|
|
|
call errore('ascheqps','too many attempts ',1)
|
2004-12-10 23:33:00 +08:00
|
|
|
goto 100
|
|
|
|
else
|
|
|
|
count=count+1
|
|
|
|
elw=e+0.001_DP
|
|
|
|
eup=eold
|
|
|
|
detup=detold
|
|
|
|
call compute_det(nn,lam,jam,elw,mesh,ndm,dx, &
|
|
|
|
r,r2,sqr,vpot,beta,ddd,qq, &
|
|
|
|
nbeta,nwfx,lls,jjs,ikk,detlw)
|
|
|
|
if (count.gt.6) &
|
2005-02-11 16:35:54 +08:00
|
|
|
call errore('ascheqps','too many attempts ',2)
|
2004-12-10 23:33:00 +08:00
|
|
|
goto 100
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
!
|
|
|
|
! bisection method
|
|
|
|
!
|
|
|
|
if (det*detup.gt.0.0_DP) then
|
|
|
|
detup=det
|
|
|
|
eup=e
|
|
|
|
e=(eup+elw)*0.5_DP
|
|
|
|
else
|
|
|
|
detlw=det
|
|
|
|
elw=e
|
|
|
|
e=(eup+elw)*0.5_DP
|
|
|
|
endif
|
|
|
|
enddo
|
2007-06-26 15:38:38 +08:00
|
|
|
write(stdout,'(5x,"Solution not found in ascheqps for n,l=",2i2)') nn,lam
|
2004-12-10 23:33:00 +08:00
|
|
|
nosol=.true.
|
|
|
|
900 continue
|
|
|
|
!
|
|
|
|
! The eigenvalue has been found, compute the solution
|
|
|
|
!
|
|
|
|
if (e.gt.0.0_DP) then
|
|
|
|
e=0.0_DP
|
|
|
|
y=0.0_DP
|
2007-06-26 15:38:38 +08:00
|
|
|
write(stdout,'(5x,"Solution not found in ascheqps for n,l=",2i2)') nn,lam
|
2004-12-10 23:33:00 +08:00
|
|
|
nosol=.true.
|
|
|
|
else
|
2007-05-21 23:01:15 +08:00
|
|
|
call compute_solution(lam,jam,e,mesh,ndm,dx,r, &
|
2004-12-10 23:33:00 +08:00
|
|
|
r2,sqr,vpot,y,beta,ddd,qq,nbeta,nwfx,lls,jjs,ikk)
|
|
|
|
endif
|
|
|
|
!
|
|
|
|
! count the node number and compare with the required n
|
|
|
|
!
|
|
|
|
if (nosol) return
|
|
|
|
ncross=0
|
|
|
|
do n=1,mesh-1
|
|
|
|
if ( y(n).ne.sign(y(n),y(n+1)) ) then
|
|
|
|
if (abs(y(n+1)).gt.1.e-10_dp) ncross=ncross+1
|
|
|
|
endif
|
|
|
|
enddo
|
|
|
|
if (ncross.gt.nn-lam-1) then
|
|
|
|
eup0=e-1.e-6_dp
|
|
|
|
elseif (ncross.lt.nn-lam-1) then
|
|
|
|
elw0=e+1.e-6_dp
|
|
|
|
else
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
!
|
2005-02-11 16:35:54 +08:00
|
|
|
! if the program arrives here the number of nodes is wrong
|
|
|
|
! try bisection with the new limits
|
2004-12-10 23:33:00 +08:00
|
|
|
!
|
2005-02-11 16:35:54 +08:00
|
|
|
if (count0 > 5) then
|
|
|
|
call errore('ascheqps','too many attempts ',3)
|
|
|
|
else
|
|
|
|
count0 = count0 + 1
|
|
|
|
goto 800
|
|
|
|
end if
|
2004-12-10 23:33:00 +08:00
|
|
|
return
|
|
|
|
end subroutine ascheqps
|