4
1
mirror of https://github.com/pfloos/quack synced 2024-11-13 01:23:59 +01:00
quack/src/MBPT/QP_roots.f90

183 lines
4.7 KiB
Fortran
Raw Normal View History

2020-02-12 21:44:35 +01:00
subroutine QP_roots(nBas,nC,nO,nV,nR,nS,eta,eHF,Omega,rho,eGW)
2020-02-12 12:25:24 +01:00
! Compute all the roots of the QP equation for each orbital
implicit none
include 'parameters.h'
! Input variables
integer,intent(in) :: nBas
integer,intent(in) :: nC
integer,intent(in) :: nO
integer,intent(in) :: nV
integer,intent(in) :: nR
integer,intent(in) :: nS
double precision,intent(in) :: eta
double precision,intent(in) :: eHF(nBas)
double precision,intent(in) :: Omega(nS)
double precision,intent(in) :: rho(nBas,nBas,nS)
! Local variables
integer :: i,j,a,b,x,jb,g
2020-02-12 21:44:35 +01:00
integer,parameter :: nGrid = 100000
double precision,parameter :: wmin = -50d0
double precision,parameter :: wmax = +50d0
2020-02-12 12:25:24 +01:00
double precision :: dw
double precision :: eps
double precision :: left_sign,right_sign
double precision :: left_QP,right_QP
double precision,allocatable :: w(:)
double precision,allocatable :: SigC(:)
double precision,allocatable :: dSigC(:)
integer :: nIt
integer,parameter :: maxIt = 64
double precision,parameter :: thresh = 1d-6
double precision,external :: SigmaC,dSigmaC
2020-02-12 21:44:35 +01:00
double precision :: sig,dsig
double precision :: sat,dsat
2020-02-12 12:25:24 +01:00
double precision :: om
2020-02-12 21:44:35 +01:00
integer :: nRoot
double precision :: Z
double precision :: Ztot
double precision :: QP
! Output variables
double precision,intent(out) :: eGW(nBas)
2020-02-12 12:25:24 +01:00
! Construct grid
allocate(w(nGrid),SigC(nGrid),dSigC(nGrid))
! Minimum and maximum frequency values
dw = (wmax - wmin)/dble(nGrid)
do g=1,nGrid
w(g) = wmin + dble(g)*dw
enddo
! Main loop over the orbitals
do x=nC+1,nBas-nR
SigC(:) = 0d0
dSigC(:) = 0d0
! Loop over grid points
do g=1,nGrid
! Occupied part of the self-energy and spectral weight
do i=nC+1,nO
jb = 0
do j=nC+1,nO
do b=nO+1,nBas-nR
jb = jb + 1
eps = w(g) - eHF(i) + Omega(jb)
SigC(g) = SigC(g) + 2d0*rho(x,i,jb)**2*eps/(eps**2 + eta**2)
dSigC(g) = dSigC(g) - 2d0*rho(x,i,jb)**2*(eps**2 - eta**2)/(eps**2 + eta**2)**2
enddo
enddo
enddo
! Virtual part of the self-energy and spectral weight
do a=nO+1,nBas-nR
jb = 0
do j=nC+1,nO
do b=nO+1,nBas-nR
jb = jb + 1
eps = w(g) - eHF(a) - Omega(jb)
SigC(g) = SigC(g) + 2d0*rho(x,a,jb)**2*eps/(eps**2 + eta**2)
dSigC(g) = dSigC(g) - 2d0*rho(x,a,jb)**2*(eps**2 - eta**2)/(eps**2 + eta**2)**2
enddo
enddo
enddo
enddo
! Find the zeros of the QP equation
nRoot = 0
2020-02-12 21:44:35 +01:00
QP = 0d0
Ztot = 0d0
2020-02-12 12:25:24 +01:00
write(*,*) '-----------------'
write(*,'(A10,I3)') 'Orbital ',x
write(*,*) '-----------------'
write(*,*)
left_QP = w(1) - eHF(x) - SigC(1)
left_sign = sign(1d0,left_QP)
do g=2,nGrid
right_QP = w(g) - eHF(x) - SigC(g)
right_sign = sign(1d0,right_QP)
if(left_sign /= right_sign .and. left_sign == sign(1d0,-1d0)) then
nRoot = nRoot + 1
write(*,'(A20,I6,F10.6,F10.6,I6,F10.6,F10.6,F10.6)') &
'root right here!',g-1,w(g-1),left_QP,g,w(g),right_QP,1d0/(1d0-dSigC(g))
! Run Newton's algorithm to find the root
om = w(g-1)
nIt = 0
2020-02-12 21:44:35 +01:00
sat = 1d0
2020-02-12 12:25:24 +01:00
2020-02-12 21:44:35 +01:00
do while (abs(sat) > thresh .and. nIt < maxIt)
2020-02-12 12:25:24 +01:00
nIt = nIt + 1
2020-02-12 21:44:35 +01:00
sig = SigmaC(x,om,eta,nBas,nC,nO,nV,nR,nS,eHF,Omega,rho)
dsig = dSigmaC(x,om,eta,nBas,nC,nO,nV,nR,nS,eHF,Omega,rho)
sat = om - eHF(x) - sig
dsat = 1d0 - dsig
Z = 1d0/dsat
2020-02-12 12:25:24 +01:00
2020-02-12 21:44:35 +01:00
write(*,'(A3,I3,A1,1X,4F15.9)') 'It.',nIt,':',om,sat,sig,Z
2020-02-12 12:25:24 +01:00
2020-02-12 21:44:35 +01:00
om = om - sat/dsat
2020-02-12 12:25:24 +01:00
end do
2020-02-12 21:44:35 +01:00
if(nIt == maxIt) then
2020-02-12 12:25:24 +01:00
2020-02-12 21:44:35 +01:00
write(*,*) 'Newton root search has not converged!'
else
Ztot = Ztot + Z
QP = QP + Z*om
end if
2020-02-12 12:25:24 +01:00
end if
left_sign = right_sign
left_QP = right_QP
end do
2020-02-12 21:44:35 +01:00
eGW(x) = QP/Ztot
2020-02-12 12:25:24 +01:00
write(*,*)
write(*,'(A32,I3,A1,I3)') 'Number of roots for orbital ',x,':',nRoot
2020-02-12 21:44:35 +01:00
write(*,'(A32,F16.10)') 'Total weight ',Ztot
write(*,'(A32,F16.10)') 'Quasiparticle energy (eV) ',eGW(x)*HaToeV
2020-02-12 12:25:24 +01:00
write(*,*)
end do
end subroutine QP_roots