quantum-espresso/PW/v_of_rho.f90

687 lines
20 KiB
Fortran

!
! Copyright (C) 2001-2009 Quantum ESPRESSO 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 .
!
!----------------------------------------------------------------------------
SUBROUTINE v_of_rho( rho, rho_core, rhog_core, &
ehart, etxc, vtxc, eth, etotefield, charge, v )
!----------------------------------------------------------------------------
!
! ... This routine computes the Hartree and Exchange and Correlation
! ... potential and energies which corresponds to a given charge density
! ... The XC potential is computed in real space, while the
! ... Hartree potential is computed in reciprocal space.
!
USE kinds, ONLY : DP
USE grid_dimensions, ONLY : nrxx
USE gvect, ONLY : ngm
USE lsda_mod, ONLY : nspin
USE noncollin_module, ONLY : noncolin
USE ions_base, ONLY : nat
USE ldaU, ONLY : lda_plus_U, Hubbard_lmax, Hubbard_l, &
Hubbard_U, Hubbard_alpha
USE funct, ONLY : dft_is_meta
USE scf, ONLY : scf_type
!
IMPLICIT NONE
!
TYPE(scf_type), INTENT(IN) :: rho ! the valence charge
TYPE(scf_type), INTENT(INOUT) :: v ! the scf (Hxc) potential
!!!!!!!!!!!!!!!!! NB: NOTE that in F90 derived data type must be INOUT and
!!!!!!!!!!!!!!!!! not just OUT because otherwise their allocatable or pointer
!!!!!!!!!!!!!!!!! components are NOT defined !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
REAL(DP), INTENT(IN) :: rho_core(nrxx)
! the core charge
COMPLEX(DP), INTENT(IN) :: rhog_core(ngm)
! the core charge in reciprocal space
REAL(DP), INTENT(OUT) :: vtxc, etxc, ehart, eth, charge
! the integral V_xc * rho
! the E_xc energy
! the hartree energy
! the hubbard energy
! the integral of the charge
REAL(DP), INTENT(INOUT) :: etotefield
! electric field energy - inout due to the screwed logic of add_efield
! !
INTEGER :: is
!
CALL start_clock( 'v_of_rho' )
!
! ... calculate exchange-correlation potential
!
if (dft_is_meta()) then
call v_xc_meta( rho, rho_core, rhog_core, etxc, vtxc, v%of_r, v%kin_r )
else
CALL v_xc( rho, rho_core, rhog_core, etxc, vtxc, v%of_r )
endif
!
! ... add a magnetic field (if any)
!
CALL add_bfield( v%of_r, rho%of_r )
!
! ... calculate hartree potential
!
CALL v_h( rho%of_g, ehart, charge, v%of_r )
!
if (lda_plus_u) call v_Hubbard(rho%ns,v%ns,eth)
!
! ... add an electric field
!
DO is = 1, nspin
CALL add_efield(v%of_r(1,is), etotefield, rho%of_r, .false. )
END DO
!
CALL stop_clock( 'v_of_rho' )
!
RETURN
!
END SUBROUTINE v_of_rho
!
SUBROUTINE v_xc_meta( rho, rho_core, rhog_core, etxc, vtxc, v, kedtaur )
!----------------------------------------------------------------------------
!
! ... Exchange-Correlation potential Vxc(r) from n(r)
!
USE kinds, ONLY : DP
USE constants, ONLY : e2, eps8
USE io_global, ONLY : stdout
USE grid_dimensions, ONLY : nrxx
USE gvect, ONLY : ngm
USE lsda_mod, ONLY : nspin
USE cell_base, ONLY : omega
USE spin_orb, ONLY : domag
USE funct, ONLY : xc, xc_spin, get_igcx, get_igcc
USE scf, ONLY : scf_type
USE mp, ONLY : mp_sum
!
IMPLICIT NONE
!
TYPE (scf_type), INTENT(IN) :: rho
REAL(DP), INTENT(IN) :: rho_core(nrxx)
! the core charge
COMPLEX(DP), INTENT(IN) :: rhog_core(ngm)
! input: the core charge in reciprocal space
REAL(DP), INTENT(OUT) :: v(nrxx,nspin), kedtaur(nrxx,nspin), vtxc, etxc
! V_xc potential
! local K energy density
! integral V_xc * rho
! E_xc energy
!
! ... local variables
!
CALL start_clock( 'v_xc_meta' )
!
etxc = 0.D0
vtxc = 0.D0
v(:,:) = 0.D0
!
! IF (get_igcx()==7.AND.get_igcc()==6) THEN
call v_xc_tpss( rho, rho_core, rhog_core, etxc, vtxc, v, kedtaur )
! ELSE
! CALL errore('v_xc_meta','wrong igcx and/or igcc',1)
! ENDIF
CALL stop_clock( 'v_xc_meta' )
RETURN
END SUBROUTINE v_xc_meta
!
SUBROUTINE v_xc_tpss( rho, rho_core, rhog_core, etxc, vtxc, v, kedtaur )
! ===================
!--------------------------------------------------------------------
USE kinds, ONLY : DP
USE gvect, ONLY : g,nl,ngm
USE grid_dimensions, ONLY : nr1, nr2, nr3, nrxx
USE scf, ONLY : scf_type
USE lsda_mod, ONLY : nspin
USE cell_base, ONLY : omega, alat
USE constants, ONLY : e2
USE mp_global, ONLY : intra_pool_comm
USE mp, ONLY : mp_sum
IMPLICIT NONE
!
! input
TYPE (scf_type), INTENT(IN) :: rho
REAL(DP),INTENT(IN) :: rho_core(nrxx)
COMPLEX(DP),INTENT(IN) :: rhog_core(ngm)
REAL(DP),INTENT(OUT) :: etxc, vtxc, v(nrxx,nspin), kedtaur(nrxx,nspin)
! integer nspin , nnr
! real(8) grho(nnr,3,nspin), rho(nnr,nspin),kedtau(nnr,nspin)
! output: excrho: exc * rho ; E_xc = \int excrho(r) d_r
! output: rhor: contains the exchange-correlation potential
REAL(DP) :: zeta, rh
INTEGER :: k, ipol, is
REAL(DP) :: grho2 (2), sx, sc, v1x, v2x, v3x,v1c, v2c, v3c, &
v1xup, v1xdw, v2xup, v2xdw, v1cup, v1cdw ,v2cup(3),v2cdw(3), &
v3xup, v3xdw,grhoup(3),grhodw(3),&
segno, arho, atau, fac
!
REAL(DP), ALLOCATABLE :: grho(:,:,:), h(:,:,:), dh(:)
REAL(DP), ALLOCATABLE :: rhoout(:,:)
COMPLEX(DP), ALLOCATABLE :: rhogsum(:,:)
REAL(DP), PARAMETER :: epsr = 1.0d-6, epsg = 1.0d-10
!
ALLOCATE (grho(3,nrxx,nspin))
ALLOCATE (h(3,nrxx,nspin))
ALLOCATE (rhoout(nrxx,nspin))
ALLOCATE (rhogsum(ngm,nspin))
!
vtxc = 0.d0
etxc = 0.d0
!
! ... calculate the gradient of rho + rho_core in real space
!
rhoout(:,1:nspin)=rho%of_r(:,1:nspin)
rhogsum(:,1:nspin)=rho%of_g(:,1:nspin)
fac = 1.D0 / DBLE( nspin )
!
DO is = 1, nspin
!
rhoout(:,is) = fac * rho_core(:) + rhoout(:,is)
rhogsum(:,is) = fac * rhog_core(:) + rhogsum(:,is)
!
CALL gradrho( nrxx, rhogsum(1,is), ngm, g, nl, grho(1,1,is) )
!
END DO
!
DO k = 1, nrxx
DO is = 1, nspin
grho2 (is) = grho(1,k, is)**2 + grho(2,k,is)**2 + grho(3,k, is)**2
ENDDO
IF (nspin == 1) THEN
!
! This is the spin-unpolarised case
!
arho = ABS (rho%of_r (k, 1) )
segno = SIGN (1.d0, rho%of_r (k, 1) )
atau = rho%kin_r(k,1) / e2 ! kinetic energy density in Hartree
IF (arho.GT.epsr.AND.grho2 (1) .GT.epsg.AND.ABS(atau).GT.epsr) THEN
CALL tpsscxc (arho, grho2(1),atau,sx, sc, v1x, v2x,v3x,v1c, v2c,v3c)
! if (mod(k,100).eq.0) then
! write(6,*) 'PON k=',k
! write(6,*) ' arho,atau=',arho,atau
! write(6,*) ' sx,sc=',sx,sc
! write(6,*) ' v1x,v2x,v3c=',v1x,v2x,v3x
! write(6,*) ' v1c,v2c,v3c=',v1c,v2c,v3c
! endif
v(k, 1) = (v1x + v1c )*e2
kedtaur(k,1)= (v3x + v3c) * 0.5d0 * e2
! h contains D(rho*Exc)/D(|grad rho|) * (grad rho) / |grad rho|
h(:,k,1) = (v2x + v2c)*grho (:,k,1) *e2
etxc = etxc + (sx + sc) * segno *e2
vtxc = vtxc + (v1x+v1c)*e2*arho + 1.5d0*kedtaur(k,1)*rho%kin_r(k,1)
ELSE
h (:, k, 1) = 0.d0
kedtaur(k,1)=0.d0
ENDIF
ELSE
!
! spin-polarised case
!
CALL tpsscx_spin(rho%of_r(k, 1), rho%of_r(k, 2), grho2 (1), grho2 (2), &
rho%kin_r(k,1)/e2,rho%kin_r(k,2)/e2,sx, &
v1xup,v1xdw,v2xup,v2xdw,v3xup,v3xdw)
rh = rho%of_r(k, 1) + rho%of_r(k, 2)
IF (rh.GT.epsr) THEN
zeta = (rho%of_r(k, 1) - rho%of_r(k, 2) ) / rh
DO ipol=1,3
grhoup(ipol)=grho(ipol,k,1)
grhodw(ipol)=grho(ipol,k,2)
END DO
atau = (rho%kin_r(k,1)+rho%kin_r(k,2)) / e2 ! KE-density in Hartree
CALL tpsscc_spin(rh,zeta,grhoup,grhodw, &
atau,sc,v1cup,v1cdw,v2cup,v2cdw,v3c)
ELSE
sc = 0.d0
v1cup = 0.d0
v1cdw = 0.d0
v2cup=0.d0
v2cdw=0.d0
v3c=0.d0
!
ENDIF
!
! first term of the gradient correction : D(rho*Exc)/D(rho)
!
v(k, 1) = (v1xup + v1cup)*e2
v(k, 2) = (v1xdw + v1cdw)*e2
!
! h contains D(rho*Exc)/D(|grad rho|) * (grad rho) / |grad rho|
!
h(:,k,1) = (v2xup*grho(:,k,1) + v2cup(:))*e2
h(:,k,2) = (v2xdw*grho(:,k,2) + v2cdw(:)) *e2
kedtaur(k,1)= (v3xup + v3c) * 0.5d0 * e2
kedtaur(k,2)= (v3xdw + v3c) * 0.5d0 * e2
etxc = etxc + (sx + sc)*e2
vtxc = vtxc + (v1xup+v1cup+v1xdw+v1cdw)*e2*rh
ENDIF
ENDDO
!
ALLOCATE( dh( nrxx ) )
!
! ... second term of the gradient correction :
! ... \sum_alpha (D / D r_alpha) ( D(rho*Exc)/D(grad_alpha rho) )
!
DO is = 1, nspin
!
CALL grad_dot( nrxx, h(1,1,is), ngm, g, nl, alat, dh )
!
v(:,is) = v(:,is) - dh(:)
!
rhoout(:,is)=rhoout(:,is)-fac*rho_core(:)
vtxc = vtxc - SUM( dh(:) * rhoout(:,is) )
!
END DO
DEALLOCATE(dh)
!
vtxc = omega * (vtxc / ( nr1 * nr2 * nr3 ))
etxc = omega * etxc / ( nr1 * nr2 * nr3 )
!
CALL mp_sum( vtxc , intra_pool_comm )
CALL mp_sum( etxc , intra_pool_comm )
DEALLOCATE(grho)
DEALLOCATE(h)
DEALLOCATE(rhoout)
DEALLOCATE(rhogsum)
!
RETURN
!
END SUBROUTINE v_xc_tpss
!----------------------------------------------------------------------------
SUBROUTINE v_xc( rho, rho_core, rhog_core, etxc, vtxc, v )
!----------------------------------------------------------------------------
!
! ... Exchange-Correlation potential Vxc(r) from n(r)
!
USE kinds, ONLY : DP
USE constants, ONLY : e2, eps8
USE io_global, ONLY : stdout
USE grid_dimensions, ONLY : nr1, nr2, nr3, nrxx
USE gvect, ONLY : ngm
USE lsda_mod, ONLY : nspin
USE cell_base, ONLY : omega
USE spin_orb, ONLY : domag
USE funct, ONLY : xc, xc_spin, dft_is_vdW
USE vdW_DF, ONLY : xc_vdW_DF
USE scf, ONLY : scf_type
USE mp_global, ONLY : intra_pool_comm
USE mp, ONLY : mp_sum
!
IMPLICIT NONE
!
TYPE (scf_type), INTENT(IN) :: rho
REAL(DP), INTENT(IN) :: rho_core(nrxx)
! the core charge
COMPLEX(DP), INTENT(IN) :: rhog_core(ngm)
! input: the core charge in reciprocal space
REAL(DP), INTENT(OUT) :: v(nrxx,nspin), vtxc, etxc
! V_xc potential
! integral V_xc * rho
! E_xc energy
!
! ... local variables
!
REAL(DP) :: rhox, arhox, zeta, amag, vs, ex, ec, vx(2), vc(2), rhoneg(2)
! the total charge in each point
! the absolute value of the charge
! the absolute value of the charge
! local exchange energy
! local correlation energy
! local exchange potential
! local correlation potential
INTEGER :: ir, ipol
! counter on mesh points
! counter on nspin
!
REAL(DP), PARAMETER :: vanishing_charge = 1.D-10, &
vanishing_mag = 1.D-20
!
!
CALL start_clock( 'v_xc' )
!
etxc = 0.D0
vtxc = 0.D0
v(:,:) = 0.D0
rhoneg = 0.D0
!
IF ( nspin == 1 .OR. ( nspin == 4 .AND. .NOT. domag ) ) THEN
!
! ... spin-unpolarized case
!
!$omp parallel do private( rhox, arhox, ex, ec, vx, vc ), &
!$omp reduction(+:etxc,vtxc), reduction(-:rhoneg)
DO ir = 1, nrxx
!
rhox = rho%of_r(ir,1) + rho_core(ir)
!
arhox = ABS( rhox )
!
IF ( arhox > vanishing_charge ) THEN
!
CALL xc( arhox, ex, ec, vx(1), vc(1) )
!
v(ir,1) = e2*( vx(1) + vc(1) )
!
etxc = etxc + e2*( ex + ec ) * rhox
!
vtxc = vtxc + v(ir,1) * rho%of_r(ir,1)
!
ENDIF
!
IF ( rho%of_r(ir,1) < 0.D0 ) rhoneg(1) = rhoneg(1) - rho%of_r(ir,1)
!
END DO
!$omp end parallel do
!
ELSE IF ( nspin == 2 ) THEN
!
! ... spin-polarized case
!
!$omp parallel do private( rhox, arhox, zeta, ex, ec, vx, vc ), &
!$omp reduction(+:etxc,vtxc), reduction(-:rhoneg)
DO ir = 1, nrxx
!
rhox = rho%of_r(ir,1) + rho%of_r(ir,2) + rho_core(ir)
!
arhox = ABS( rhox )
!
IF ( arhox > vanishing_charge ) THEN
!
zeta = ( rho%of_r(ir,1) - rho%of_r(ir,2) ) / arhox
!
IF ( ABS( zeta ) > 1.D0 ) zeta = SIGN( 1.D0, zeta )
!
IF ( rho%of_r(ir,1) < 0.D0 ) rhoneg(1) = rhoneg(1) - rho%of_r(ir,1)
IF ( rho%of_r(ir,2) < 0.D0 ) rhoneg(2) = rhoneg(2) - rho%of_r(ir,2)
!
CALL xc_spin( arhox, zeta, ex, ec, vx(1), vx(2), vc(1), vc(2) )
!
v(ir,:) = e2*( vx(:) + vc(:) )
!
etxc = etxc + e2*( ex + ec ) * rhox
!
vtxc = vtxc + v(ir,1) * rho%of_r(ir,1) + v(ir,2) * rho%of_r(ir,2)
!
END IF
!
END DO
!$omp end parallel do
!
ELSE IF ( nspin == 4 ) THEN
!
! ... noncolinear case
!
DO ir = 1,nrxx
!
amag = SQRT( rho%of_r(ir,2)**2 + rho%of_r(ir,3)**2 + rho%of_r(ir,4)**2 )
!
rhox = rho%of_r(ir,1) + rho_core(ir)
!
IF ( rho%of_r(ir,1) < 0.D0 ) rhoneg(1) = rhoneg(1) - rho%of_r(ir,1)
!
arhox = ABS( rhox )
!
IF ( arhox > vanishing_charge ) THEN
!
zeta = amag / arhox
!
IF ( ABS( zeta ) > 1.D0 ) THEN
!
rhoneg(2) = rhoneg(2) + 1.D0 / omega
!
zeta = SIGN( 1.D0, zeta )
!
END IF
!
CALL xc_spin( arhox, zeta, ex, ec, vx(1), vx(2), vc(1), vc(2) )
!
vs = 0.5D0*( vx(1) + vc(1) - vx(2) - vc(2) )
!
v(ir,1) = e2*( 0.5D0*( vx(1) + vc(1) + vx(2) + vc(2 ) ) )
!
IF ( amag > vanishing_mag ) THEN
!
DO ipol = 2, 4
!
v(ir,ipol) = e2 * vs * rho%of_r(ir,ipol) / amag
!
vtxc = vtxc + v(ir,ipol) * rho%of_r(ir,ipol)
!
END DO
!
END IF
!
etxc = etxc + e2*( ex + ec ) * rhox
vtxc = vtxc + v(ir,1) * rho%of_r(ir,1)
!
END IF
!
END DO
!
END IF
!
CALL mp_sum( rhoneg , intra_pool_comm )
!
rhoneg(:) = rhoneg(:) * omega / ( nr1*nr2*nr3 )
!
IF ( rhoneg(1) > eps8 .OR. rhoneg(2) > eps8 ) &
WRITE( stdout,'(/,5X,"negative rho (up, down): ",2E10.3)') rhoneg
!
! ... energy terms, local-density contribution
!
vtxc = omega * vtxc / ( nr1*nr2*nr3 )
etxc = omega * etxc / ( nr1*nr2*nr3 )
!
! ... add gradient corrections (if any)
!
CALL gradcorr( rho%of_r, rho%of_g, rho_core, rhog_core, etxc, vtxc, v )
if (dft_is_vdW()) then
CALL xc_vdW_DF(rho%of_r, rho_core, etxc, vtxc, v)
end if
!
CALL mp_sum( vtxc , intra_pool_comm )
CALL mp_sum( etxc , intra_pool_comm )
!
CALL stop_clock( 'v_xc' )
!
RETURN
!
END SUBROUTINE v_xc
!
!----------------------------------------------------------------------------
SUBROUTINE v_h( rhog, ehart, charge, v )
!----------------------------------------------------------------------------
!
! ... Hartree potential VH(r) from n(G)
!
USE constants, ONLY : fpi, e2
USE kinds, ONLY : DP
USE fft_base, ONLY : dfftp
USE fft_interfaces,ONLY : invfft
USE grid_dimensions, ONLY : nrxx
USE gvect, ONLY : nl, nlm, ngm, gg, gstart
USE lsda_mod, ONLY : nspin
USE cell_base, ONLY : omega, tpiba2
USE control_flags, ONLY : gamma_only
USE mp_global, ONLY: intra_pool_comm
USE mp, ONLY: mp_sum
USE martyna_tuckerman, ONLY : wg_corr_h, do_comp_mt
!
IMPLICIT NONE
!
COMPLEX(DP), INTENT(IN) :: rhog(ngm,nspin)
REAL(DP), INTENT(INOUT) :: v(dfftp%nnr,nspin)
REAL(DP), INTENT(OUT) :: ehart, charge
!
REAL(DP) :: fac
REAL(DP), ALLOCATABLE :: aux1(:,:)
REAL(DP) :: rgtot_re, rgtot_im, eh_corr
INTEGER :: is, ig
COMPLEX(DP), ALLOCATABLE :: aux(:), rgtot(:), vaux(:)
INTEGER :: nt
!
CALL start_clock( 'v_h' )
!
ALLOCATE( aux( dfftp%nnr ), aux1( 2, ngm ) )
charge = 0.D0
!
IF ( gstart == 2 ) THEN
!
charge = omega*REAL( rhog(1,1) )
!
IF ( nspin == 2 ) charge = charge + omega*REAL( rhog(1,2) )
!
END IF
!
CALL mp_sum( charge , intra_pool_comm )
!
! ... calculate hartree potential in G-space (NB: V(G=0)=0 )
!
ehart = 0.D0
aux1(:,:) = 0.D0
!
!$omp parallel do private( fac, rgtot_re, rgtot_im ), reduction(+:ehart)
DO ig = gstart, ngm
!
fac = 1.D0 / gg(ig)
!
rgtot_re = REAL( rhog(ig,1) )
rgtot_im = AIMAG( rhog(ig,1) )
!
IF ( nspin == 2 ) THEN
!
rgtot_re = rgtot_re + REAL( rhog(ig,2) )
rgtot_im = rgtot_im + AIMAG( rhog(ig,2) )
!
END IF
!
ehart = ehart + ( rgtot_re**2 + rgtot_im**2 ) * fac
!
aux1(1,ig) = rgtot_re * fac
aux1(2,ig) = rgtot_im * fac
!
ENDDO
!$omp end parallel do
!
fac = e2 * fpi / tpiba2
!
ehart = ehart * fac
!
aux1 = aux1 * fac
!
IF ( gamma_only ) THEN
!
ehart = ehart * omega
!
ELSE
!
ehart = ehart * 0.5D0 * omega
!
END IF
!
if (do_comp_mt) then
ALLOCATE( vaux( ngm ), rgtot(ngm) )
rgtot(:) = rhog(:,1)
if (nspin==2) rgtot(:) = rgtot(:) + rhog(:,2)
CALL wg_corr_h (omega, ngm, rgtot, vaux, eh_corr)
aux1(1,1:ngm) = aux1(1,1:ngm) + REAL( vaux(1:ngm))
aux1(2,1:ngm) = aux1(2,1:ngm) + AIMAG(vaux(1:ngm))
ehart = ehart + eh_corr
DEALLOCATE( rgtot, vaux )
end if
!
CALL mp_sum( ehart , intra_pool_comm )
!
aux(:) = 0.D0
!
aux(nl(1:ngm)) = CMPLX ( aux1(1,1:ngm), aux1(2,1:ngm), KIND=dp )
!
IF ( gamma_only ) THEN
!
aux(nlm(1:ngm)) = CMPLX ( aux1(1,1:ngm), -aux1(2,1:ngm), KIND=dp )
!
END IF
!
! ... transform hartree potential to real space
!
CALL invfft ('Dense', aux, dfftp)
!
! ... add hartree potential to the xc potential
!
IF ( nspin == 4 ) THEN
!
v(:,1) = v(:,1) + DBLE (aux(:))
!
ELSE
!
DO is = 1, nspin
!
v(:,is) = v(:,is) + DBLE (aux(:))
!
END DO
!
END IF
!
DEALLOCATE( aux, aux1 )
!
CALL stop_clock( 'v_h' )
!
RETURN
!
END SUBROUTINE v_h
!
!-----------------------------------------------------------------------
SUBROUTINE v_hubbard(ns, v_hub, eth)
!-----------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE ions_base, ONLY : nat, ityp
USE ldaU, ONLY : Hubbard_lmax, Hubbard_l, &
Hubbard_U, Hubbard_alpha
USE lsda_mod, ONLY : nspin
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: ns(2*Hubbard_lmax+1,2*Hubbard_lmax+1,nspin,nat)
REAL(DP), INTENT(OUT) :: v_hub(2*Hubbard_lmax+1,2*Hubbard_lmax+1,nspin,nat)
REAL(DP), INTENT(OUT) :: eth
INTEGER :: is, na, nt, m1, m2
!
! Now the contribution to the total energy is computed.
!
eth = 0.d0
v_hub(:,:,:,:) = 0.d0
DO na = 1, nat
nt = ityp (na)
IF (Hubbard_U(nt).NE.0.d0 .OR. Hubbard_alpha(nt).NE.0.d0) THEN
DO is = 1, nspin
DO m1 = 1, 2 * Hubbard_l(nt) + 1
eth = eth + ( Hubbard_alpha(nt) + 0.5D0 * Hubbard_U(nt) ) * &
ns(m1,m1,is,na)
v_hub(m1,m1,is,na) = v_hub(m1,m1,is,na) + &
( Hubbard_alpha(nt) + 0.5D0 * Hubbard_U(nt) )
DO m2 = 1, 2 * Hubbard_l(nt) + 1
eth = eth - 0.5D0 * Hubbard_U(nt) * &
ns(m2,m1,is,na)* ns(m1,m2,is,na)
v_hub(m1,m2,is,na) = v_hub(m1,m2,is,na) - &
Hubbard_U(nt) * ns(m2,m1,is,na)
ENDDO
ENDDO
ENDDO
ENDIF
ENDDO
IF (nspin.EQ.1) eth = 2.d0 * eth
RETURN
END SUBROUTINE v_hubbard