quantum-espresso/Modules/correlation_lda_lsda.f90

1005 lines
32 KiB
Fortran

!
! Copyright (C) 2001-2014 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 .
!
MODULE corr_lda !<GPU:corr_lda=>corr_lda_gpu>
CONTAINS
!-------------------------------------------------------------------------
SUBROUTINE pz( rs, iflag, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! LDA parametrization from Monte Carlo DATA:
!
!! * iflag=1: J.P. Perdew and A. Zunger, PRB 23, 5048 (1981);
!! * iflag=2: G. Ortiz and P. Ballone, PRB 50, 1391 (1994).
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: iflag !<GPU:VALUE>
!! see routine comments
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP) :: a(2), b(2), c(2), d(2), gc(2), b1(2), b2(2)
REAL(DP) :: lnrs, rs12, ox, dox
!
DATA a / 0.0311d0, 0.031091d0 /, b / -0.048d0, -0.046644d0 /, &
c / 0.0020d0, 0.00419d0 /, d / -0.0116d0, -0.00983d0 /
!
DATA gc / -0.1423d0, -0.103756d0 /, b1 / 1.0529d0, 0.56371d0 /, &
b2 / 0.3334d0, 0.27358d0 /
!
IF ( rs < 1.0d0 ) THEN
!
! high density formula
lnrs = LOG(rs)
!
ec = a(iflag)*lnrs + b(iflag) + c(iflag)*rs*lnrs + d(iflag)*rs
!
vc = a(iflag)*lnrs + ( b(iflag) - a(iflag)/3.d0 ) + 2.d0/3.d0 * &
c(iflag)*rs*lnrs + ( 2.d0*d(iflag) - c(iflag) )/3.d0*rs
ELSE
!
! interpolation formula
rs12 = SQRT(rs)
!
ox = 1.d0 + b1(iflag)*rs12 + b2(iflag)*rs
dox = 1.d0 + 7.d0/6.d0*b1(iflag)*rs12 + 4.d0/3.d0*b2(iflag)*rs
!
ec = gc(iflag)/ox
vc = ec*dox/ox
!
ENDIF
!
RETURN
!
END SUBROUTINE pz
!
!
!-----------------------------------------------------------------------
SUBROUTINE pzKZK( rs, ec, vc, vol ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! LDA parametrization from Monte Carlo DATA:
!
!! * iflag=1: J.P. Perdew and A. Zunger, PRB 23, 5048 (1981)
!! * iflag=2: G. Ortiz and P. Ballone, PRB 50, 1391 (1994)
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
REAL(DP) :: vol !<GPU:VALUE>
!! volume element
!
! ... local variables
!
INTEGER :: iflag, kr
REAL(DP) :: ec0(2), vc0(2), ec0p
REAL(DP) :: a(2), b(2), c(2), d(2), gc(2), b1(2), b2(2)
REAL(DP) :: lnrs, rs12, ox, dox, lnrsk, rsk
REAL(DP) :: a1, grs, g1, g2, g3, g4, dL, gh, gl, grsp
REAL(DP) :: f3, f2, f1, f0, pi
REAL(DP) :: D1, D2, D3, P1, P2, ry2h
!
DATA a / 0.0311_DP, 0.031091_DP /, b / -0.048_DP, -0.046644_DP /, &
c / 0.0020_DP, 0.00419_DP /, d / -0.0116_DP, -0.00983_DP /
!
DATA gc / -0.1423_DP, -0.103756_DP /, b1 / 1.0529_DP, 0.56371_DP /, &
b2 / 0.3334_DP, 0.27358_DP /
!
DATA a1 / -2.2037_DP /, g1 / 0.1182_DP/, g2 / 1.1656_DP/, g3 / -5.2884_DP/, &
g4 / -1.1233_DP /
!
DATA ry2h / 0.5_DP /
!
iflag = 1
pi = 4.d0 * ATAN(1.d0)
dL = vol**(1.d0/3.d0)
gh = 0.5d0 * dL / (2.d0 * pi)**(1.d0/3.d0)
gl = dL * (3.d0 / 2.d0 / pi)**(1.d0/3.d0)
!
rsk = gh
!
DO kr = 1, 2
!
lnrsk = LOG(rsk)
IF (rsk < 1.0d0) THEN
! high density formula
ec0(kr) = a(iflag) *lnrsk + b(iflag) + c(iflag) * rsk * lnrsk + d(iflag) * rsk
vc0(kr) = a(iflag) * lnrsk + (b(iflag) - a(iflag) / 3.d0) + 2.d0 / &
3.d0 * c (iflag) * rsk * lnrsk + (2.d0 * d (iflag) - c (iflag) ) &
/ 3.d0 * rsk
!
ELSE
! interpolation formula
rs12 = SQRT(rsk)
ox = 1.d0 + b1 (iflag) * rs12 + b2 (iflag) * rsk
dox = 1.d0 + 7.d0 / 6.d0 * b1 (iflag) * rs12 + 4.d0 / 3.d0 * &
b2 (iflag) * rsk
ec0(kr) = gc (iflag) / ox
vc0(kr) = ec0(kr) * dox / ox
!
ENDIF
!
grs = g1 * rsk * lnrsk + g2 * rsk + g3 * rsk**1.5d0 + g4 * rsk**2.d0
grsp = g1 * lnrsk + g1 + g2 + 1.5d0 * g3 * rsk**0.5d0 + 2.d0 * g4 * rsk
!
ec0(kr) = ec0(kr) + (-a1 * rsk / dL**2.d0 + grs / dL**3.d0) * ry2h
vc0(kr) = vc0(kr) + (-2.d0 * a1 * rsk / dL**2.d0 / 3.d0 + &
grs / dL**3.d0 - grsp * rsk / 3.d0 / dL**3.d0) * ry2h
!
rsk = rs
!
ENDDO
!
lnrs = LOG(rs)
!
IF (rs <= gh) THEN
ec = ec0(2)
vc = vc0(2)
ELSE
IF ( rs <= gl ) THEN
ec0p = 3.d0 * (ec0(1) - vc0(1)) / gh
P1 = 3.d0 * ec0(1) - gh * ec0p
P2 = ec0p
D1 = gl - gh
D2 = gl**2.d0 - gh**2.d0
D3 = gl**3.d0 - gh**3.d0
f2 = 2.d0 * gl**2.d0 * P2 * D1 + D2 * P1
f2 = f2 / (-(2.d0*gl*D1)**2.d0 + 4.d0*gl*D1*D2 - D2**2.d0 )
f3 = - (P2 + 2.d0*D1*f2) / (3.d0 * D2)
f1 = - (P1 + D2 * f2) / (2.d0 * D1)
f0 = - gl * (gl * f2 + 2.d0 * f1) / 3.d0
!
ec = f3 * rs**3.d0 + f2 * rs**2.d0 + f1 * rs + f0
vc = f2 * rs**2.d0 / 3.d0 + f1 * 2.d0 * rs / 3.d0 + f0
ELSE
ec = 0.d0
vc = 0.d0
ENDIF
ENDIF
!
!
RETURN
!
END SUBROUTINE pzKZK
!
!
!-----------------------------------------------------------------------
SUBROUTINE vwn( rs, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! S.H. Vosko, L. Wilk, and M. Nusair, Can. J. Phys. 58, 1200 (1980).
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP), PARAMETER :: a = 0.0310907d0, b = 3.72744d0, &
c = 12.9352d0, x0 = -0.10498d0
REAL(DP) :: q, f1, f2, f3, rs12, fx, qx, tx, tt
!
!
q = SQRT( 4.d0*c - b*b )
f1 = 2.d0*b/q
f2 = b*x0 / ( x0*x0 + b*x0 + c )
f3 = 2.d0*( 2.d0 * x0 + b ) / q
!
rs12 = SQRT(rs)
fx = rs + b*rs12 + c
qx = ATAN( q / (2.d0*rs12 + b) )
!
ec = a * ( LOG( rs/fx ) + f1*qx - f2*( LOG( (rs12 - x0)**2 / fx) &
+ f3*qx) )
!
tx = 2.d0*rs12 + b
tt = tx*tx + q*q
!
vc = ec - rs12*a / 6.d0*( 2.d0 / rs12 - tx/fx - 4.d0*b/tt - f2 * &
(2.d0 / (rs12 - x0) - tx/fx - 4.d0*(2.d0 * x0 + b)/tt) )
!
RETURN
!
END SUBROUTINE vwn
!
!
!-----------------------------------------------------------------------
SUBROUTINE vwn1_rpa( rs, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! S.H. Vosko, L. Wilk, and M. Nusair, Can. J. Phys. 58, 1200 (1980).
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP), PARAMETER :: a = 0.0310907_DP, b = 13.0720_DP, &
c = 42.7198_DP, x0 = -0.409286_DP
REAL(DP) :: q, f1, f2, f3, rs12, fx, qx, tx, tt
!
q = SQRT(4.d0*c - b*b)
f1 = 2.d0*b/q
f2 = b*x0 / (x0*x0 + b*x0 + c)
f3 = 2.d0 * (2.d0 * x0 + b) / q
!
rs12 = SQRT(rs)
fx = rs + b * rs12 + c
qx = ATAN(q / (2.d0 * rs12 + b) )
!
ec = a*( LOG(rs/fx) + f1*qx - f2*(LOG((rs12 - x0)**2/fx) + f3*qx) )
!
tx = 2.d0*rs12 + b
tt = tx*tx + q*q
!
vc = ec - rs12*a/6.d0*( 2.d0/rs12 - tx/fx - 4.d0*b/tt - f2 * &
(2.d0/(rs12 - x0) - tx/fx - 4.d0*(2.d0*x0 + b)/tt) )
!
!
RETURN
!
END SUBROUTINE vwn1_rpa
!
!
!-----------------------------------------------------------------------
SUBROUTINE lyp( rs, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! C. Lee, W. Yang, and R.G. Parr, PRB 37, 785 (1988).
!! LDA part only.
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP), PARAMETER :: a=0.04918d0, b=0.132d0*2.87123400018819108d0
REAL(DP), PARAMETER :: pi43=1.61199195401647d0
! pi43=(4pi/3)^(1/3)
REAL(DP), PARAMETER :: c=0.2533d0*pi43, d=0.349d0*pi43
REAL(DP) :: ecrs, ox
!
!
ecrs = b*EXP( -c*rs )
ox = 1.d0 / (1.d0 + d*rs)
!
ec = - a*ox*(1.d0 + ecrs)
vc = ec - rs/3.d0*a*ox*( d*ox + ecrs*(d*ox + c) )
!
RETURN
!
END SUBROUTINE lyp
!
!
!-----------------------------------------------------------------------
SUBROUTINE pw( rs, iflag, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! * iflag=1: J.P. Perdew and Y. Wang, PRB 45, 13244 (1992)
!! * iflag=2: G. Ortiz and P. Ballone, PRB 50, 1391 (1994)
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
INTEGER, INTENT(IN) :: iflag !<GPU:VALUE>
!! see routine comments
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP), PARAMETER :: a=0.031091d0, b1=7.5957d0, b2=3.5876d0, c0=a, &
c1=0.046644d0, c2=0.00664d0, c3=0.01043d0, d0=0.4335d0, &
d1=1.4408d0
REAL(DP) :: lnrs, rs12, rs32, rs2, om, dom, olog
REAL(DP) :: a1(2), b3(2), b4(2)
DATA a1 / 0.21370d0, 0.026481d0 /, b3 / 1.6382d0, -0.46647d0 /, &
b4 / 0.49294d0, 0.13354d0 /
!
! high- and low-density formulae implemented but not used in PW case
! (reason: inconsistencies in PBE/PW91 functionals).
!
IF ( rs < 1d0 .AND. iflag == 2 ) THEN
!
! high density formula
lnrs = LOG(rs)
ec = c0 * lnrs - c1 + c2 * rs * lnrs - c3 * rs
vc = c0 * lnrs - (c1 + c0 / 3.d0) + 2.d0 / 3.d0 * c2 * rs * &
lnrs - (2.d0 * c3 + c2) / 3.d0 * rs
!
ELSEIF ( rs > 100.d0 .AND. iflag == 2 ) THEN
!
! low density formula
ec = - d0 / rs + d1 / rs**1.5d0
vc = - 4.d0 / 3.d0 * d0 / rs + 1.5d0 * d1 / rs**1.5d0
!
ELSE
!
! interpolation formula
rs12 = SQRT(rs)
rs32 = rs * rs12
rs2 = rs**2
om = 2.d0*a*( b1*rs12 + b2*rs + b3(iflag) * rs32 + b4(iflag)*rs2 )
dom = 2.d0*a*( 0.5d0 * b1 * rs12 + b2 * rs + 1.5d0 * b3(iflag) * &
rs32 + 2.d0 * b4(iflag) * rs2 )
olog = LOG( 1.d0 + 1.0d0 / om )
!
ec = - 2.d0 * a * (1.d0 + a1(iflag) * rs) * olog
vc = - 2.d0 * a * (1.d0 + 2.d0 / 3.d0 * a1(iflag) * rs) &
* olog - 2.d0 / 3.d0 * a * (1.d0 + a1(iflag) * rs) * dom / &
(om * (om + 1.d0) )
!
ENDIF
!
!
RETURN
!
END SUBROUTINE pw
!
!
!-----------------------------------------------------------------------
SUBROUTINE wignerc( rs, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! Wigner correlation.
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP) :: rho13 !rho13=rho^(1/3)
REAL(DP), PARAMETER :: pi34 = 0.6203504908994d0
! pi34 = (3/4pi)^(1/3)
!
!
rho13 = pi34 / rs
vc = - rho13 * ( (0.943656d0 + 8.8963d0 * rho13) / (1.d0 + &
12.57d0 * rho13)**2 )
ec = - 0.738d0 * rho13 * ( 0.959d0 / (1.d0 + 12.57d0 * rho13) )
!
RETURN
!
END SUBROUTINE wignerc
!
!
!-----------------------------------------------------------------------
SUBROUTINE hl( rs, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! L. Hedin and B.I. Lundqvist, J. Phys. C 4, 2064 (1971).
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP) :: a, x
!
!
a = LOG(1.0d0 + 21.d0/rs)
x = rs / 21.0d0
ec = a + (x**3 * a - x*x) + x/2.d0 - 1.0d0/3.0d0
ec = - 0.0225d0 * ec
vc = - 0.0225d0 * a
!
RETURN
!
END SUBROUTINE hl
!
!
!-----------------------------------------------------------------------
SUBROUTINE gl( rs, ec, vc ) !<GPU:DEVICE>
!---------------------------------------------------------------------
!! O. Gunnarsson and B. I. Lundqvist, PRB 13, 4274 (1976).
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP) :: x
REAL(DP), PARAMETER :: c=0.0333d0, r=11.4d0
! c=0.0203, r=15.9 for the paramagnetic case
!
x = rs / r
vc = - c * LOG(1.d0 + 1.d0 / x)
ec = - c * ( (1.d0 + x**3) * LOG(1.d0 + 1.d0 / x) - 1.0d0 / &
3.0d0 + x * (0.5d0 - x) )
!
RETURN
!
END SUBROUTINE gl
!
!
! ... LSDA
!
!-----------------------------------------------------------------------
SUBROUTINE pz_polarized( rs, ec, vc ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! J.P. Perdew and A. Zunger, PRB 23, 5048 (1981).
!! spin-polarized energy and potential.
!
USE kinds, ONLY : DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc
!! correlation potential
!
! ... local variables
!
REAL(DP), PARAMETER :: a=0.01555d0, b=-0.0269d0, c=0.0007d0, &
d=-0.0048d0, gc=-0.0843d0, b1=1.3981d0, b2=0.2611d0
REAL(DP) :: lnrs, rs12, ox, dox
REAL(DP), PARAMETER :: xcprefact=0.022575584d0, pi34=0.6203504908994d0
! REAL(DP) :: betha, etha, csi, prefact
!
!
IF ( rs < 1.0d0 ) THEN
! high density formula
lnrs = LOG(rs)
ec = a * lnrs + b + c * rs * lnrs + d * rs
vc = a * lnrs + (b - a / 3.d0) + 2.d0 / 3.d0 * c * rs * lnrs + &
(2.d0 * d-c) / 3.d0 * rs
ELSE
! interpolation formula
rs12 = SQRT(rs)
ox = 1.d0 + b1 * rs12 + b2 * rs
dox = 1.d0 + 7.d0 / 6.d0 * b1 * rs12 + 4.d0 / 3.d0 * b2 * rs
ec = gc / ox
vc = ec * dox / ox
ENDIF
!
! IF ( lxc_rel ) THEN
! betha = prefact * pi34 / rs
! etha = DSQRT( 1 + betha**2 )
! csi = betha + etha
! prefact = 1.0D0 - (3.0D0/2.0D0) * ( (betha*etha - LOG(csi))/betha**2 )**2
! ec = ec * prefact
! vc = vc * prefact
! ENDIF
!
RETURN
!
END SUBROUTINE pz_polarized
!
!
!-----------------------------------------------------------------------
SUBROUTINE pz_spin( rs, zeta, ec, vc_up, vc_dw ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! Perdew and Zunger, PRB 23, 5048 (1981). Spin polarized case.
!
USE kinds, ONLY : DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(IN) :: zeta
!! zeta = (rho_up - rho_dw) / rho_tot
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc_up, vc_dw
!! correlation potential (up, down)
!
! ... local variables
!
REAL(DP) :: ecu, vcu, ecp, vcp
REAL(DP) :: fz, dfz
REAL(DP), PARAMETER :: p43=4.0d0/3.d0, third=1.d0/3.d0
!
! unpolarized part (Perdew-Zunger formula)
CALL pz( rs, 1, ecu, vcu ) !<GPU:pz=>pz_d>
!
! polarization contribution
CALL pz_polarized( rs, ecp, vcp ) !<GPU:pz_polarized=>pz_polarized_d>
!
fz = ( (1.0d0 + zeta)**p43 + (1.d0 - zeta)**p43 - 2.d0) / &
(2.d0**p43 - 2.d0)
dfz = p43 * ( (1.0d0 + zeta)**third- (1.d0 - zeta)**third) &
/ (2.d0**p43 - 2.d0)
!
ec = ecu + fz * (ecp - ecu)
vc_up = vcu + fz * (vcp - vcu) + (ecp - ecu) * dfz * ( 1.d0 - zeta)
vc_dw = vcu + fz * (vcp - vcu) + (ecp - ecu) * dfz * (-1.d0 - zeta)
!
RETURN
!
END SUBROUTINE pz_spin
!
!-------------------------------------------------------------------------------
SUBROUTINE vwn_spin( rs, zeta, ec, vc_up, vc_dw ) !<GPU:DEVICE>
!------------------------------------------------------------------------------
!! S.H. Vosko, L. Wilk, and M. Nusair. Spin polarized case.
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(IN) :: zeta
!! zeta = (rho_up - rho_dw) / rho_tot
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc_up, vc_dw
!! correlation potential (up, down)
!
! ... local variables
!
REAL(DP) :: zeta3, zeta4, trup, trdw, trup13, trdw13, fz, dfz, fzz4
REAL(DP) :: SQRTrs, ecP, ecF, ac, De, vcP, vcF, dac, dec1, dec2
REAL(DP) :: cfz, cfz1, cfz2, iddfz0
!
! parameters: e_c/para, e_c/ferro, alpha_c
REAL(DP), PARAMETER :: &
A(3) = (/ 0.0310907_DP, 0.01554535_DP, -0.01688686394039_DP /), &
x0(3) = (/ -0.10498_DP, -0.32500_DP, -0.0047584_DP /), &
b(3) = (/3.72744_DP, 7.06042_DP, 1.13107_DP /), &
c(3) = (/ 12.9352_DP, 18.0578_DP, 13.0045_DP /),&
Q(3) = (/ 6.15199081975908_DP, 4.73092690956011_DP, 7.12310891781812_DP /), &
tbQ(3) = (/ 1.21178334272806_DP, 2.98479352354082_DP, 0.31757762321188_DP /), &
fx0(3) = (/ 12.5549141492_DP, 15.8687885_DP, 12.99914055888256_DP /), &
bx0fx0(3) = (/ -0.03116760867894_DP, -0.14460061018521_DP, -0.00041403379428_DP /)
!
! N.B.: A is expressed in Hartree
! Q = SQRT(4*c - b^2)
! tbQ = 2*b/Q
! fx0 = X(x_0) = x_0^2 + b*x_0 + c
! bx0fx0 = b*x_0/X(x_0)
!
!
! coefficients for f(z), df/dz, ddf/ddz(0)
cfz = 2.0_DP**(4.0_DP/3.0_DP) - 2.0_DP
cfz1 = 1.0_DP / cfz
cfz2 = 4.0_DP/3.0_DP * cfz1
iddfz0 = 9.0_DP / 8.0_DP *cfz
!
SQRTrs = SQRT(rs)
zeta3 = zeta**3
zeta4 = zeta3*zeta
trup = 1.0_DP + zeta
trdw = 1.0_DP - zeta
trup13 = trup**(1.0_DP/3.0_DP)
trdw13 = trdw**(1.0_DP/3.0_DP)
fz = cfz1 * (trup13*trup + trdw13*trdw - 2.0_DP) ! f(zeta)
dfz = cfz2 * (trup13 - trdw13) ! df / dzeta
!
CALL padefit_ParSet1( sqrtrs, 1, ecP, vcP ) ! ecF = e_c Paramagnetic !<GPU:padefit_ParSet1=>padefit_ParSet1_d>
CALL padefit_ParSet1( sqrtrs, 2, ecF, vcF ) ! ecP = e_c Ferromagnetic !<GPU:padefit_ParSet1=>padefit_ParSet1_d>
CALL padefit_ParSet1( sqrtrs, 3, ac, dac ) ! ac = "spin stiffness" !<GPU:padefit_ParSet1=>padefit_ParSet1_d>
!
ac = ac * iddfz0
dac = dac * iddfz0
De = ecF - ecP - ac ! e_c[F]-e_c[P]-alpha_c/(ddf/ddz(z=0))
fzz4 = fz * zeta4
ec = ecP + ac * fz + De * fzz4
!
dec1 = vcP + dac*fz + (vcF - vcP - dac) * fzz4 ! e_c - (r_s/3)*(de_c/dr_s)
dec2 = ac*dfz + De*(4.0_DP*zeta3*fz + zeta4*dfz) ! de_c/dzeta
!
vc_up = dec1 + (1.0_DP - zeta)*dec2 ! v_c[s] = e_c - (r_s/3)*(de_c/dr_s)
vc_dw = dec1 - (1.0_DP + zeta)*dec2 ! + [sign(s)-zeta]*(de_c/dzeta)
!
END SUBROUTINE
!
!
!----
SUBROUTINE padefit_ParSet1( x, i, fit, dfit ) !<GPU:DEVICE>
!----
!! It implements formula [4.4] in:
!! S.H. Vosko, L. Wilk, and M. Nusair, Can. J. Phys. 58, 1200 (1980)
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP) :: x
!! input: x is SQRT(r_s)
INTEGER :: i
!! input: i is the index of the fit
REAL(DP) :: fit
!! output: Pade fit calculated in x [eq. 4.4]
REAL(DP) :: dfit
!! output: dfit/drho = fit - (rs/3)*dfit/drs = ec - (x/6)*dfit/dx
!
! ... local variables
!
REAL(DP), PARAMETER :: &
A(3) = (/ 0.0310907d0, 0.01554535d0, -0.01688686394039d0 /), &
x0(3) = (/ -0.10498d0, -0.32500d0, -0.0047584d0 /), &
b(3) = (/3.72744d0, 7.06042d0, 1.13107d0 /), &
c(3) = (/ 12.9352d0, 18.0578d0, 13.0045d0 /),&
Q(3) = (/ 6.15199081975908d0, 4.73092690956011d0, 7.12310891781812d0 /), &
tbQ(3) = (/ 1.21178334272806d0, 2.98479352354082d0, 0.31757762321188d0 /), &
fx0(3) = (/ 12.5549141492d0, 15.8687885d0, 12.99914055888256d0 /), &
bx0fx0(3) = (/ -0.03116760867894d0, -0.14460061018521d0, -0.00041403379428d0 /)
REAL(DP) :: sqx, xx0, Qtxb, atg, fx
REAL(DP) :: txb, txbfx, itxbQ
!
sqx = x * x ! x^2 = r_s
xx0 = x - x0(i) ! x - x_0
Qtxb = Q(i) / (2.0_DP*x + b(i)) ! Q / (2x+b)
atg = ATAN(Qtxb) ! tan^-1(Q/(2x+b))
fx = sqx + b(i)*x + c(i) ! X(x) = x^2 + b*x + c
!
fit = A(i) * ( LOG(sqx/fx) + tbQ(i)*atg - &
bx0fx0(i) * ( LOG(xx0*xx0/fx) + (tbQ(i) + 4.0_DP*x0(i)/Q(i)) * atg ) )
!
txb = 2.0_DP*x + b(i)
txbfx = txb / fx
itxbQ = 1.0_DP / (txb*txb + Q(i)*Q(i))
!
dfit = fit - A(i) / 3.0_DP + A(i)*x/6.0_DP * ( txbfx + 4.0_DP*b(i)*itxbQ + &
bx0fx0(i) * ( 2.0_DP/xx0 - txbfx - 4.0_DP*(b(i)+2.0_DP*x0(i))*itxbQ ) )
!
END SUBROUTINE
SUBROUTINE padefit_ParSet2( x, i, fit, dfit ) !<GPU:DEVICE>
!----
!! It implements formula [4.4] in:
!! S.H. Vosko, L. Wilk, and M. Nusair, Can. J. Phys. 58, 1200 (1980)
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP) :: x
!! input: x is SQRT(r_s)
INTEGER :: i
!! input: i is the index of the fit
REAL(DP) :: fit
!! output: Pade fit calculated in x [eq. 4.4]
REAL(DP) :: dfit
!! output: dfit/drho = fit - (rs/3)*dfit/drs = ec - (x/6)*dfit/dx
!
! ... local variables
!
REAL(DP), PARAMETER :: &
A(3) = (/ 0.0310907_DP, 0.01554535_DP, -0.01688686394039_DP /), &
x0(3) = (/ -0.409286_DP, -0.743294_DP, -0.228344_DP /), &
b(3) = (/ 13.0720_DP, 20.1231_DP, 1.06835_DP /), &
c(3) = (/ 42.7198_DP, 101.578_DP, 11.4813_DP /),&
Q(3) = (/ 0.044899888641577_DP, 1.171685277708971_DP, 6.692072046645942_DP /), &
tbQ(3) = (/ 582.273159042780890_DP, 34.348984975465861_DP, 0.319288254087299_DP /), &
fx0(3) = (/ 37.537128437796000_DP, 87.173106479036008_DP, 11.289489669936000_DP /), &
bx0fx0(3) = (/ -0.142530524167984_DP, -0.171582499414508_DP, -0.021608710360898_DP /)
REAL(DP) :: sqx, xx0, Qtxb, atg, fx
REAL(DP) :: txb, txbfx, itxbQ
!
sqx = x * x ! x^2 = r_s
xx0 = x - x0(i) ! x - x_0
Qtxb = Q(i) / (2.0_DP*x + b(i)) ! Q / (2x+b)
atg = ATAN(Qtxb) ! tan^-1(Q/(2x+b))
fx = sqx + b(i)*x + c(i) ! X(x) = x^2 + b*x + c
!
fit = A(i) * ( LOG(sqx/fx) + tbQ(i)*atg - &
bx0fx0(i) * ( LOG(xx0*xx0/fx) + (tbQ(i) + 4.0_DP*x0(i)/Q(i)) * atg ) )
!
txb = 2.0_DP*x + b(i)
txbfx = txb / fx
itxbQ = 1.0_DP / (txb*txb + Q(i)*Q(i))
!
dfit = fit - A(i) / 3.0_DP + A(i)*x/6.0_DP * ( txbfx + 4.0_DP*b(i)*itxbQ + &
bx0fx0(i) * ( 2.0_DP/xx0 - txbfx - 4.0_DP*(b(i)+2.0_DP*x0(i))*itxbQ ) )
!
END SUBROUTINE
!
!
!-----------------------------------------------------------------------------------------
SUBROUTINE vwn1_rpa_spin( rs, zeta, ec, vc_up, vc_dw ) !<GPU:DEVICE>
!---------------------------------------------------------------------------------------
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(IN) :: zeta
!! zeta = (rho_up - rho_dw)/rho_tot
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc_up, vc_dw
!! correlation potential (up, down)
!
! ... local variables
!
REAL(DP) :: zeta3, zeta4, trup, trdw, trup13, trdw13, fz, dfz, fzz4
REAL(DP) :: SQRTrs, ecP, ecF, ac, De, vcP, vcF, dac, dec1, dec2
REAL(DP) :: cfz, cfz1, cfz2, iddfz0
!
! PARAMETERs: e_c/para, e_c/ferro, alpha_c
REAL(DP), PARAMETER :: &
A(3) = (/ 0.0310907_DP, 0.01554535_DP, -0.01688686394039_DP /), &
x0(3) = (/ -0.409286_DP, -0.743294_DP, -0.228344_DP /), &
b(3) = (/ 13.0720_DP, 20.1231_DP, 1.06835_DP /), &
c(3) = (/ 42.7198_DP, 101.578_DP, 11.4813_DP /),&
Q(3) = (/ 0.044899888641577_DP, 1.171685277708971_DP, 6.692072046645942_DP /), &
tbQ(3) = (/ 582.273159042780890_DP, 34.348984975465861_DP, 0.319288254087299_DP /), &
fx0(3) = (/ 37.537128437796000_DP, 87.173106479036008_DP, 11.289489669936000_DP /), &
bx0fx0(3) = (/ -0.142530524167984_DP, -0.171582499414508_DP, -0.021608710360898_DP /)
! N.B.: A is expressed in Hartree
! Q = SQRT(4*c - b^2)
! tbQ = 2*b/Q
! fx0 = X(x_0) = x_0^2 + b*x_0 + c
! bx0fx0 = b*x_0/X(x_0)
!
!
! coefficients for f(z), df/dz, ddf/ddz(0)
cfz = 2.0_DP**(4.0_DP/3.0_DP) - 2.0_DP
cfz1 = 1.0_DP / cfz
cfz2 = 4.0_DP/3.0_DP * cfz1
iddfz0 = 9.0_DP / 8.0_DP *cfz
!
SQRTrs = SQRT(rs)
zeta3 = zeta**3
zeta4 = zeta3*zeta
trup = 1.0_DP + zeta
trdw = 1.0_DP - zeta
trup13 = trup**(1.0_DP/3.0_DP)
trdw13 = trdw**(1.0_DP/3.0_DP)
fz = cfz1 * (trup13*trup + trdw13*trdw - 2.0_DP) ! f(zeta)
dfz = cfz2 * (trup13 - trdw13) ! df / dzeta
!
CALL padefit_ParSet2( sqrtrs, 1, ecP, vcP ) ! ecF = e_c Paramagnetic !<GPU:padefit_ParSet2=>padefit_ParSet2_d>
CALL padefit_ParSet2( sqrtrs, 2, ecF, vcF ) ! ecP = e_c Ferromagnetic !<GPU:padefit_ParSet2=>padefit_ParSet2_d>
CALL padefit_ParSet2( sqrtrs, 3, ac, dac ) ! ac = "spin stiffness" !<GPU:padefit_ParSet2=>padefit_ParSet2_d>
!
ac = ac * iddfz0
dac = dac * iddfz0
De = ecF - ecP - ac ! e_c[F]-e_c[P]-alpha_c/(ddf/ddz(z=0))
fzz4 = fz * zeta4
ec = ecP + ac * fz + De * fzz4
!
dec1 = vcP + dac*fz + (vcF - vcP - dac) * fzz4 ! e_c - (r_s/3)*(de_c/dr_s)
dec2 = ac*dfz + De*(4.0_DP*zeta3*fz + zeta4*dfz) ! de_c/dzeta
!
vc_up = dec1 + (1.0_DP - zeta)*dec2 ! v_c[s] = e_c - (r_s/3)*(de_c/dr_s)
vc_dw = dec1 - (1.0_DP + zeta)*dec2 ! +[sign(s)-zeta]*(de_c/dzeta)
!
END SUBROUTINE
!
!
!-----------------------------------------------------------------------
SUBROUTINE pw_spin( rs, zeta, ec, vc_up, vc_dw ) !<GPU:DEVICE>
!-----------------------------------------------------------------------
!! J.P. Perdew and Y. Wang, PRB 45, 13244 (1992).
!
USE kinds, ONLY : DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
!! Wigner-Seitz radius
REAL(DP), INTENT(IN) :: zeta
!! zeta = (rho_up - rho_dw)/rho_tot
REAL(DP), INTENT(OUT) :: ec
!! correlation energy
REAL(DP), INTENT(OUT) :: vc_up, vc_dw
!! correlation potential (up, down)
!
! ... local variables
!
REAL(DP) :: rs12, rs32, rs2, zeta2, zeta3, zeta4, fz, dfz
REAL(DP) :: om, dom, olog, epwc, vpwc
REAL(DP) :: omp, domp, ologp, epwcp, vpwcp
REAL(DP) :: oma, doma, ologa, alpha, vpwca
!
! xc parameters, unpolarised
REAL(DP), PARAMETER :: a = 0.031091d0, a1 = 0.21370d0, b1 = 7.5957d0, b2 = &
3.5876d0, b3 = 1.6382d0, b4 = 0.49294d0, c0 = a, c1 = 0.046644d0, &
c2 = 0.00664d0, c3 = 0.01043d0, d0 = 0.4335d0, d1 = 1.4408d0
! xc parameters, polarised
REAL(DP), PARAMETER :: ap = 0.015545d0, a1p = 0.20548d0, b1p = 14.1189d0, b2p &
= 6.1977d0, b3p = 3.3662d0, b4p = 0.62517d0, c0p = ap, c1p = &
0.025599d0, c2p = 0.00319d0, c3p = 0.00384d0, d0p = 0.3287d0, d1p &
= 1.7697d0
! xc PARAMETERs, antiferro
REAL(DP), PARAMETER :: aa = 0.016887d0, a1a = 0.11125d0, b1a = 10.357d0, b2a = &
3.6231d0, b3a = 0.88026d0, b4a = 0.49671d0, c0a = aa, c1a = &
0.035475d0, c2a = 0.00188d0, c3a = 0.00521d0, d0a = 0.2240d0, d1a &
= 0.3969d0
REAL(DP), PARAMETER :: fz0 = 1.709921d0
!
! if (rs < 0.5d0) then
! high density formula (not implemented)
!
! elseif (rs > 100.d0) then
! low density formula (not implemented)
!
! else
! interpolation formula
!
zeta2 = zeta * zeta
zeta3 = zeta2 * zeta
zeta4 = zeta3 * zeta
rs12 = SQRT(rs)
rs32 = rs * rs12
rs2 = rs**2
!
! unpolarised
om = 2.d0 * a * (b1 * rs12 + b2 * rs + b3 * rs32 + b4 * rs2)
dom = 2.d0 * a * (0.5d0 * b1 * rs12 + b2 * rs + 1.5d0 * b3 * rs32 &
+ 2.d0 * b4 * rs2)
olog = LOG(1.d0 + 1.0d0 / om)
epwc = - 2.d0 * a * (1.d0 + a1 * rs) * olog
vpwc = - 2.d0 * a * (1.d0 + 2.d0 / 3.d0 * a1 * rs) * olog - 2.d0 / &
3.d0 * a * (1.d0 + a1 * rs) * dom / (om * (om + 1.d0) )
!
! polarized
omp = 2.d0 * ap * (b1p * rs12 + b2p * rs + b3p * rs32 + b4p * rs2)
domp = 2.d0 * ap * (0.5d0 * b1p * rs12 + b2p * rs + 1.5d0 * b3p * &
rs32 + 2.d0 * b4p * rs2)
ologp = LOG(1.d0 + 1.0d0 / omp)
epwcp = - 2.d0 * ap * (1.d0 + a1p * rs) * ologp
vpwcp = - 2.d0 * ap * (1.d0 + 2.d0 / 3.d0 * a1p * rs) * ologp - &
2.d0 / 3.d0 * ap * (1.d0 + a1p * rs) * domp / (omp * (omp + 1.d0))
!
! antiferro
oma = 2.d0 * aa * (b1a * rs12 + b2a * rs + b3a * rs32 + b4a * rs2)
doma = 2.d0 * aa * ( 0.5d0 * b1a * rs12 + b2a * rs + 1.5d0 * b3a * &
rs32 + 2.d0 * b4a * rs2 )
ologa = LOG( 1.d0 + 1.0d0/oma )
alpha = 2.d0 * aa * (1.d0 + a1a*rs) * ologa
vpwca = + 2.d0 * aa * (1.d0 + 2.d0/3.d0 * a1a * rs) * ologa + &
2.d0 / 3.d0 * aa * (1.d0 + a1a*rs) * doma / (oma * (oma + 1.d0))
!
!
fz = ( (1.d0 + zeta)**(4.d0 / 3.d0) + (1.d0 - zeta)**(4.d0 / &
3.d0) - 2.d0) / (2.d0** (4.d0 / 3.d0) - 2.d0)
dfz = ( (1.d0 + zeta)**(1.d0 / 3.d0) - (1.d0 - zeta)**(1.d0 / &
3.d0) ) * 4.d0 / (3.d0 * (2.d0** (4.d0 / 3.d0) - 2.d0) )
!
!
ec = epwc + alpha * fz * (1.d0 - zeta4) / fz0 + (epwcp - epwc) &
* fz * zeta4
!
vc_up = vpwc + vpwca * fz * (1.d0 - zeta4) / fz0 + (vpwcp - vpwc) &
* fz * zeta4 + (alpha / fz0 * (dfz * (1.d0 - zeta4) - 4.d0 * fz * &
zeta3) + (epwcp - epwc) * (dfz * zeta4 + 4.d0 * fz * zeta3) ) &
* (1.d0 - zeta)
!
vc_dw = vpwc + vpwca * fz * (1.d0 - zeta4) / fz0 + (vpwcp - vpwc) &
* fz * zeta4 - (alpha / fz0 * (dfz * (1.d0 - zeta4) - 4.d0 * fz * &
zeta3) + (epwcp - epwc) * (dfz * zeta4 + 4.d0 * fz * zeta3) ) &
* (1.d0 + zeta)
!
RETURN
!
END SUBROUTINE pw_spin
!
!
!-----------------------------------------------------------------------------
SUBROUTINE lsd_lyp( rho, zeta, elyp, vlyp_up, vlyp_dw ) !<GPU:DEVICE>
!==--------------------------------------------------------------==
!== C. LEE, W. YANG, AND R.G. PARR, PRB 37, 785 (1988) ==
!== THIS IS ONLY THE LDA PART ==
!==--------------------------------------------------------------==
!
USE kinds, ONLY: DP
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rho
!! total charge density
REAL(DP), INTENT(IN) :: zeta
!! zeta = (rho_up - rho_dw)/rho_tot
REAL(DP), INTENT(OUT) :: elyp
!! correlation energy
REAL(DP), INTENT(OUT) :: vlyp_up, vlyp_dw
!! correlation potential (up, down)
!
! ... local variables
!
REAL(DP) :: ra,rb,rm3,dr,e1,or,dor,e2,de1a,de1b,de2a,de2b
REAL(DP), PARAMETER :: small=1.D-24, a=0.04918D0, b=0.132D0, &
c=0.2533D0, d=0.349D0, cf=2.87123400018819108D0
!==--------------------------------------------------------------==
ra = rho*0.5D0*(1.D0+zeta)
ra = MAX(ra,small)
rb = rho*0.5D0*(1.D0-zeta)
rb = MAX(rb,small)
!
rm3= rho**(-1.D0/3.D0)
dr = (1.D0+d*rm3)
!
e1 = 4.D0*a*ra*rb/rho/dr
or = EXP(-c*rm3)/dr*rm3**11.D0
dor= -1.D0/3.D0*rm3**4*or*(11.D0/rm3-c-d/dr)
e2 = 2.D0**(11.D0/3.D0)*cf*a*b*or*ra*rb*(ra**(8.d0/3.d0)+ rb**(8.d0/3.d0))
!
elyp = (-e1-e2)/rho
!
de1a = -e1*(1.D0/3.D0*d*rm3**4/dr+1./ra-1./rho)
de1b = -e1*(1.D0/3.D0*d*rm3**4/dr+1./rb-1./rho)
de2a = -2.D0**(11.D0/3.D0)*cf*a*b*(dor*ra*rb*(ra**(8.d0/3.d0)+ &
rb**(8.d0/3.d0))+or*rb*(11.d0/3.d0*ra**(8.d0/3.d0)+ &
rb**(8.d0/3.d0)))
de2b = -2.D0**(11.D0/3.D0)*cf*a*b*(dor*ra*rb*(ra**(8.d0/3.d0)+ &
rb**(8.d0/3.d0))+or*ra*(11.d0/3.d0*rb**(8.d0/3.d0)+ &
ra**(8.d0/3.d0)))
!
vlyp_up = de1a + de2a
vlyp_dw = de1b + de2b
!==--------------------------------------------------------------==
!
RETURN
!
END SUBROUTINE lsd_lyp
END MODULE