2004-05-14 23:33:08 +08:00
|
|
|
!---------------------------------------------------------------
|
|
|
|
subroutine scf
|
|
|
|
!---------------------------------------------------------------
|
|
|
|
!
|
|
|
|
! this routine performs the atomic self-consistent procedure
|
|
|
|
! self-interaction-correction allowed
|
|
|
|
!
|
|
|
|
use constants, only: e2
|
|
|
|
use ld1inc
|
|
|
|
implicit none
|
|
|
|
|
|
|
|
logical:: conv
|
|
|
|
integer:: nerr, nstop, n, i, is, id, nin, mch
|
2004-07-14 01:32:44 +08:00
|
|
|
real(kind=dp) :: vnew(ndm,2), rhoc1(ndm), vhn1(ndm), egc(ndm), &
|
|
|
|
rab(ndm), ze2
|
|
|
|
real(kind=dp), allocatable :: vsic(:,:), vsicnew(:)
|
|
|
|
integer, parameter :: maxter=200
|
2004-12-10 23:33:00 +08:00
|
|
|
real(kind=dp), parameter :: thresh=1.0e-10_dp
|
2004-05-14 23:33:08 +08:00
|
|
|
!
|
|
|
|
!
|
|
|
|
ze2 = - zed * e2
|
2004-12-10 23:33:00 +08:00
|
|
|
rhoc1=0.0_dp
|
2004-05-14 23:33:08 +08:00
|
|
|
id=3
|
2004-12-10 23:33:00 +08:00
|
|
|
psi_dir=0.0_dp
|
2004-05-14 23:33:08 +08:00
|
|
|
rab=dx*r
|
|
|
|
!
|
2004-07-14 01:32:44 +08:00
|
|
|
if (isic /= 0) then
|
2004-05-14 23:33:08 +08:00
|
|
|
allocate(vsic(ndm,nwf))
|
|
|
|
allocate(vsicnew(ndm))
|
2004-12-10 23:33:00 +08:00
|
|
|
vsic=0.0_dp
|
2004-05-14 23:33:08 +08:00
|
|
|
id=1
|
|
|
|
endif
|
|
|
|
do iter=1,maxter
|
|
|
|
nerr=0
|
|
|
|
vnew = vpot
|
|
|
|
do n=1,nwf
|
2004-12-10 23:33:00 +08:00
|
|
|
if (oc(n) >= 0.0_dp) then
|
2004-05-14 23:33:08 +08:00
|
|
|
is=isw(n)
|
2004-07-14 01:32:44 +08:00
|
|
|
if (isic /= 0 .and. iter > 1) vnew(:,is)=vsic(:,n)
|
|
|
|
if (rel == 0) then
|
|
|
|
call ascheq (nn(n),ll(n),enl(n),mesh,dx,r,r2, &
|
2004-05-14 23:33:08 +08:00
|
|
|
sqr,vnew(1,is),ze2,thresh,psi(1,n),nstop)
|
2004-07-14 01:32:44 +08:00
|
|
|
elseif (rel == 1) then
|
|
|
|
call lschps (1,zed,exp(dx),dx,mesh,nin,mch, &
|
|
|
|
nn(n),ll(n),enl(n),psi(1,n),r,vnew(1,is))
|
2004-05-14 23:33:08 +08:00
|
|
|
nstop=0
|
2004-07-14 01:32:44 +08:00
|
|
|
elseif (rel == 2) then
|
|
|
|
call dirsol (ndm,mesh,nn(n),ll(n),jj(n),iter,enl(n), &
|
|
|
|
thresh,dx,psi_dir(1,1,n),r,rab,vnew(1,is))
|
2004-05-14 23:33:08 +08:00
|
|
|
psi(:,n)=psi_dir(:,2,n)
|
|
|
|
nstop=0
|
|
|
|
else
|
2004-12-10 23:33:00 +08:00
|
|
|
call errore('scf','relativistic not programmed',1)
|
2004-05-14 23:33:08 +08:00
|
|
|
endif
|
|
|
|
! write(6,*) el(n),enl(n)
|
2004-07-14 01:32:44 +08:00
|
|
|
if (nstop /= 0) write(6,'(4i6)') iter,nn(n),ll(n),nstop
|
2004-05-14 23:33:08 +08:00
|
|
|
nerr=nerr+nstop
|
|
|
|
else
|
2004-12-10 23:33:00 +08:00
|
|
|
enl(n)=0.0_dp
|
|
|
|
psi(:,n)=0.0_dp
|
2004-05-14 23:33:08 +08:00
|
|
|
endif
|
|
|
|
enddo
|
|
|
|
|
|
|
|
if (rel==2) then
|
|
|
|
call charge(ndm,mesh,nwf,2,oc,psi_dir,rho,isw)
|
|
|
|
else
|
|
|
|
call charge(ndm,mesh,nwf,1,oc,psi,rho,isw)
|
|
|
|
endif
|
|
|
|
|
|
|
|
call new_potential(ndm,mesh,r,r2,sqr,dx,zed,vxt, &
|
|
|
|
lsd,.false.,latt,enne,rhoc1,rho,vh,vnew)
|
|
|
|
|
2004-07-14 01:32:44 +08:00
|
|
|
if (isic /= 0) then
|
2004-05-14 23:33:08 +08:00
|
|
|
do n=1,nwf
|
2004-12-10 23:33:00 +08:00
|
|
|
if (oc(n) >= 0.0_dp) then
|
2004-07-14 01:32:44 +08:00
|
|
|
is=isw(n)
|
|
|
|
call sic_correction(n,vhn1,vsicnew,egc)
|
|
|
|
vsicnew(:) = vnew(:,is)-vsicnew(:)
|
|
|
|
call dmixp(mesh,vsicnew,vsic(1,n),beta,tr2,iter,id,eps0,conv)
|
|
|
|
end if
|
2004-05-14 23:33:08 +08:00
|
|
|
enddo
|
|
|
|
endif
|
|
|
|
call vpack(mesh,ndm,nspin,vnew,vpot,1)
|
|
|
|
call dmixp(mesh*nspin,vnew,vpot,beta,tr2,iter,id,eps0,conv)
|
|
|
|
call vpack(mesh,ndm,nspin,vnew,vpot,-1)
|
|
|
|
! write(6,*) iter, eps0
|
|
|
|
|
|
|
|
if (conv) then
|
2004-07-14 01:32:44 +08:00
|
|
|
if (nerr /= 0) call errore('scf','errors in KS equations',-1)
|
2004-05-14 23:33:08 +08:00
|
|
|
goto 45
|
|
|
|
endif
|
|
|
|
enddo
|
2004-07-14 01:32:44 +08:00
|
|
|
call errore('scf','warning: convergence not achieved',-1)
|
|
|
|
45 if (isic /= 0) then
|
2004-05-14 23:33:08 +08:00
|
|
|
deallocate(vsicnew)
|
|
|
|
deallocate(vsic)
|
|
|
|
endif
|
|
|
|
|
|
|
|
return
|
|
|
|
end subroutine scf
|