master updated

This commit is contained in:
fabrizio22 2019-05-08 12:08:43 +02:00
parent 28609e4f8b
commit 5e5884bf6a
19 changed files with 1798 additions and 1130 deletions

View File

@ -372,23 +372,22 @@ subroutine exch_corr_wrapper(nnr, nspin, grhor, rhor, etxc, v, h)
use kinds, only: DP
use funct, only: dft_is_gradient, get_igcc, &
gcxc, gcx_spin, gcc_spin, gcc_spin_more, init_lda_xc
use xc_lda_lsda, only : xc, xc_spin
use xc_lda_lsda, only : xc
implicit none
integer, intent(in) :: nnr
integer, intent(in) :: nspin
real(DP), intent(in) :: grhor( 3, nnr, nspin )
real(DP) :: h( nnr, nspin, nspin )
real(DP), intent(in) :: rhor( nnr, nspin )
real(DP) :: v( nnr, nspin )
real(DP), intent(in) :: grhor(3,nnr,nspin)
real(DP) :: h(nnr,nspin,nspin)
real(DP), intent(in) :: rhor(nnr,nspin)
real(DP) :: v(nnr,nspin)
real(DP) :: etxc
integer :: ir, is, k
real(DP) :: rup, rdw, ex, ec
real(DP), dimension(nnr) :: rhox_v,arhox_v,zeta_v
real(DP), dimension(nnr) :: ex_v, ec_v
real(DP), dimension(nnr,nspin) :: vx_v, vc_v
real(DP) :: rh, grh2, zeta
real(DP) :: rup, rdw
real(DP), dimension(nnr) :: ex, ec
real(DP), dimension(nnr,nspin) :: rhox, vx, vc
real(DP) :: rh, grh2, zeta, zetas
real(DP) :: sx, sc, v1x, v2x, v1c, v2c
real(DP) :: rhox, arhox, e2
real(DP) :: e2
real(DP) :: grho2(2), arho, segno
real(DP) :: v1xup, v1xdw, v2xup, v2xdw
real(DP) :: v1cup, v1cdw
@ -404,20 +403,18 @@ subroutine exch_corr_wrapper(nnr, nspin, grhor, rhor, etxc, v, h)
e2 = 1.0d0
etxc = 0.0d0
!
call init_lda_xc()
CALL init_lda_xc()
!
if( nspin == 1 ) then
IF ( nspin == 1 ) THEN
!
! spin-unpolarized case
!
arhox_v(:) = abs(rhor(:,nspin))
CALL xc( nnr, 1, 1, rhor, ex, ec, vx, vc )
!
CALL xc( nnr, arhox_v, ex_v, ec_v, vx_v, vc_v )
v(:,1) = e2 * (vx(:,1) + vc(:,1) )
etxc = e2 * SUM( (ex + ec)*rhor(:,1) )
!
v(:,nspin) = e2 * (vx_v(:,1) + vc_v(:,1) )
etxc = e2 * SUM( (ex_v + ec_v)*rhor(:,nspin) )
!
else
ELSE
!
! spin-polarized case
!
@ -425,30 +422,26 @@ subroutine exch_corr_wrapper(nnr, nspin, grhor, rhor, etxc, v, h)
neg(2) = 0
neg(3) = 0
!
do ir = 1, nnr
rhox_v(ir) = rhor(ir,1) + rhor(ir,2)
arhox_v(ir) = abs(rhox_v(ir))
if ( arhox_v(ir) > 1.D-30 ) then
zeta_v(ir) = ( rhor(ir,1) - rhor(ir,2) ) / arhox_v(ir)
if (abs(zeta_v(ir)) > 1.d0) then
neg(3) = neg(3) + 1
zeta_v(ir) = sign(1.d0,zeta_v(ir))
endif
if (rhor(ir,1) < 0.d0) neg(1) = neg(1) + 1
if (rhor(ir,2) < 0.d0) neg(2) = neg(2) + 1
endif
enddo
rhox(:,1) = rhor(:,1) + rhor(:,2)
rhox(:,2) = rhor(:,1) - rhor(:,2)
!
call xc_spin( nnr, arhox_v, zeta_v, ex_v, ec_v, vx_v, vc_v )
CALL xc( nnr, 2, 2, rhox, ex, ec, vx, vc )
!
do ir = 1, nnr
do is = 1, nspin
v(ir,is) = e2 * (vx_v(ir,is) + vc_v(ir,is) )
enddo
etxc = etxc + e2 * (ex_v(ir) + ec_v(ir)) * rhox_v(ir)
enddo
DO ir = 1, nnr
!
DO is = 1, nspin
v(ir,is) = e2 * (vx(ir,is) + vc(ir,is))
ENDDO
etxc = etxc + e2 * (ex(ir) + ec(ir)) * rhox(ir,1)
!
zetas = rhox(ir,2) / rhox(ir,1)
IF (rhor(ir,1) < 0.d0) neg(1) = neg(1) + 1
IF (rhor(ir,2) < 0.d0) neg(2) = neg(2) + 1
IF (ABS(zetas) > 1.d0) neg(3) = neg(3) + 1
!
ENDDO
!
endif
ENDIF
if( debug_xc ) then
open(unit=17,form='unformatted')

View File

@ -8,7 +8,7 @@
!-----------------------------------------------------------------------
SUBROUTINE setup_dmuxc
!-----------------------------------------------------------------------
!! This subroutine computes dmuxc (derivative of the XC potential)
!! This subroutine computes dmuxc (derivative of the XC potential).
!
USE kinds, ONLY : DP
USE eqv, ONLY : dmuxc
@ -17,6 +17,7 @@ SUBROUTINE setup_dmuxc
USE scf, ONLY : rho, rho_core
USE noncollin_module, ONLY : noncolin, nspin_mag
USE spin_orb, ONLY : domag
USE funct, ONLY : init_lda_xc
!
IMPLICIT NONE
!
@ -30,48 +31,54 @@ SUBROUTINE setup_dmuxc
!
ns = 1
IF ( lsda ) ns = 2
ALLOCATE(rho_aux(dfftp%nnr,ns))
IF ( (.NOT. lsda) .AND. noncolin .AND. domag ) ns = 4
!
ALLOCATE( rho_aux(dfftp%nnr,ns) )
!
dmuxc(:,:,:) = 0.d0
!
CALL init_lda_xc()
!
IF ( lsda ) THEN
!
rho_aux(:,1) = ( rho%of_r(:,1) + rho%of_r(:,2) + rho_core(:) ) * 0.5d0
rho_aux(:,2) = ( rho%of_r(:,1) - rho%of_r(:,2) + rho_core(:) ) * 0.5d0
CALL dmxc_spin(dfftp%nnr, rho_aux, dmuxc )
!
!
rho_aux(:,1) = ( rho%of_r(:,1) + rho%of_r(:,2) + rho_core(:) )*0.5_DP
rho_aux(:,2) = ( rho%of_r(:,1) - rho%of_r(:,2) + rho_core(:) )*0.5_DP
!
CALL dmxc( dfftp%nnr, 2, rho_aux, dmuxc )
!
ELSE
!
IF ( noncolin .AND. domag ) THEN
!
rho_aux(:,1) = rho%of_r (:,1) + rho_core(:)
CALL dmxc_nc( dfftp%nnr, rho_aux(:,1), rho%of_r(:,2:4), dmuxc )
!
ELSE
!
ALLOCATE(sign_r(dfftp%nnr))
rho_aux(:,1) = rho%of_r(:,1) + rho_core(:)
sign_r = 1.0_DP
DO ir = 1, dfftp%nnr
IF ( rho_aux(ir,1) < -1.d-30 ) THEN
sign_r(ir) = -1.0_DP
rho_aux(ir,1) = -rho_aux(ir,1)
ELSEIF ( rho_aux(ir,1) < 1.d-30 .AND.rho_aux(ir,1) > -1.d-30 ) THEN
sign_r(ir) = 0.0_DP
rho_aux(ir,1) = 0.5_DP
ENDIF
ENDDO
!
CALL dmxc( dfftp%nnr, rho_aux(:,1), dmuxc(:,1,1) )
dmuxc(:,1,1) = dmuxc(:,1,1)*sign_r(:)
!
DEALLOCATE(sign_r)
!
ENDIF
!
!
IF ( noncolin .AND. domag ) THEN
!
rho_aux(:,1) = rho%of_r(:,1) + rho_core(:)
rho_aux(:,2:4) = rho%of_r(:,2:4)
CALL dmxc( dfftp%nnr, 4, rho_aux, dmuxc )
!
ELSE
!
ALLOCATE(sign_r(dfftp%nnr))
rho_aux(:,1) = rho%of_r(:,1) + rho_core(:)
sign_r = 1.0_DP
DO ir = 1, dfftp%nnr
IF ( rho_aux(ir,1) < -1.d-30 ) THEN
sign_r(ir) = -1.0_DP
rho_aux(ir,1) = -rho_aux(ir,1)
ELSEIF ( rho_aux(ir,1) < 1.d-30 .AND.rho_aux(ir,1) > -1.d-30 ) THEN
sign_r(ir) = 0.0_DP
rho_aux(ir,1) = 0.5_DP
ENDIF
ENDDO
!
CALL dmxc( dfftp%nnr, 1, rho_aux, dmuxc )
dmuxc(:,1,1) = dmuxc(:,1,1)*sign_r(:)
!
DEALLOCATE(sign_r)
!
ENDIF
!
ENDIF
!
DEALLOCATE(rho_aux)
DEALLOCATE( rho_aux )
!
CALL stop_clock ('setup_dmuxc')
!

View File

@ -5,13 +5,170 @@
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!---------------------------------------------------------------------
SUBROUTINE dmxc( length, sr_d, rho_in, dmuxc )
!---------------------------------------------------------------------
!! Wrapper routine. Calls dmxc-driver routines from internal libraries
!! or from the external one 'libxc', depending on the input choice.
!
! Only two possibilities in the present version (LDA only):
! 1) iexch libxc + icorr libxc
! 2) iexch qe + icorr qe
!
USE kinds, ONLY: DP
#if defined(__LIBXC)
USE xc_f90_types_m
USE xc_f90_lib_m
USE xc_lda_lsda
#endif
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: length
!! length of the I/O arrays
INTEGER, INTENT(IN) :: sr_d
!! number of spin components
REAL(DP), INTENT(IN) :: rho_in(length,sr_d)
!! charge density
REAL(DP), INTENT(OUT) :: dmuxc(length,sr_d,sr_d)
!! the derivative of the xc potential
!
! ... local variables
!
#if defined(__LIBXC)
TYPE(xc_f90_pointer_t) :: xc_func
TYPE(xc_f90_pointer_t) :: xc_info1, xc_info2
INTEGER :: pol_unpol
REAL(DP), ALLOCATABLE :: rho_lxc(:)
REAL(DP), ALLOCATABLE :: dmxc_lxc(:), dmex_lxc(:), dmcr_lxc(:)
LOGICAL :: exch_lxc_avail, corr_lxc_avail
#endif
!
INTEGER :: ir, length_lxc, length_dlxc
REAL(DP), PARAMETER :: small = 1.E-10_DP, rho_trash = 0.5_DP
!
!
#if defined(__LIBXC)
!
IF (libxc_switches(1)==1 .AND. libxc_switches(2)==1) THEN
!
length_lxc = length*sr_d
!
! ... set libxc input
SELECT CASE( sr_d )
CASE( 1 )
!
ALLOCATE( rho_lxc(length_lxc) )
pol_unpol = 1
rho_lxc = rho_in(:,1)
!
CASE( 2 )
!
ALLOCATE( rho_lxc(length_lxc) )
pol_unpol = 2
DO ir = 1, length
rho_lxc(2*ir-1) = rho_in(ir,1)
rho_lxc(2*ir) = rho_in(ir,2)
ENDDO
!
CASE( 4 )
!
! ... libxc version not available for non-collinear case with domag...
!
!
CALL dmxc_nc( length, rho_in(:,1), rho_in(:,2:4), dmuxc ) !da sistemare riconversione indici in qe da libxc
!
RETURN
!
CASE DEFAULT
!
CALL errore( 'dmxc', 'Wrong number of spin dimensions', 1 )
!
END SELECT
!
length_dlxc = length
IF (pol_unpol == 2) length_dlxc = length*3
!
!
ALLOCATE( dmex_lxc(length_dlxc), dmcr_lxc(length_dlxc), &
dmxc_lxc(length_dlxc) )
!
! ... DERIVATIVE FOR EXCHANGE
CALL xc_f90_func_init( xc_func, xc_info1, iexch_l, pol_unpol )
CALL xc_f90_lda_fxc( xc_func, length, rho_lxc(1), dmex_lxc(1) )
CALL xc_f90_func_end( xc_func )
!
! ... DERIVATIVE FOR CORRELATION
CALL xc_f90_func_init( xc_func, xc_info2, icorr_l, pol_unpol )
CALL xc_f90_lda_fxc( xc_func, length, rho_lxc(1), dmcr_lxc(1) )
CALL xc_f90_func_end( xc_func )
!
dmxc_lxc = (dmex_lxc + dmcr_lxc)*2.0_DP
!
IF (sr_d == 1) THEN
dmuxc(:,1,1) = dmxc_lxc(:)
ELSEIF (sr_d == 2) THEN
DO ir = 1, length
dmuxc(ir,1,1) = dmxc_lxc(3*ir-2)
dmuxc(ir,1,2) = dmxc_lxc(3*ir-1)
dmuxc(ir,2,1) = dmxc_lxc(3*ir-1)
dmuxc(ir,2,2) = dmxc_lxc(3*ir)
ENDDO
ENDIF
!
DEALLOCATE( dmex_lxc, dmcr_lxc, dmxc_lxc )
DEALLOCATE( rho_lxc )
!
ELSEIF (libxc_switches(1)==0 .AND. libxc_switches(2)==0 ) THEN
!
IF ( sr_d == 1 ) CALL dmxc_lda( length, rho_in(:,1), dmuxc(:,1,1) )
IF ( sr_d == 2 ) CALL dmxc_lsda( length, rho_in, dmuxc )
!
ELSE
!
CALL errore( 'dmxc', 'Derivative of exchange and correlation terms &
& must be both qe or both libxc.', 3 )
!
ENDIF
!
#else
!
SELECT CASE( sr_d )
CASE( 1 )
!
CALL dmxc_lda( length, rho_in(:,1), dmuxc(:,1,1) )
!
CASE( 2 )
!
CALL dmxc_lsda( length, rho_in, dmuxc )
!
CASE( 4 )
!
CALL dmxc_nc( length, rho_in(:,1), rho_in(:,2:4), dmuxc )
!
CASE DEFAULT
!
CALL errore( 'xc_LDA', 'Wrong ns input', 2 )
!
END SELECT
!
#endif
!
!
RETURN
!
END SUBROUTINE
!
!
!
!-----------------------------------------------------------------------
SUBROUTINE dmxc( length, rho_in, dmuxc )
SUBROUTINE dmxc_lda( length, rho_in, dmuxc )
!---------------------------------------------------------------------
!! Computes the derivative of the xc potential with respect to the
!! local density.
!
USE xc_lda_lsda, ONLY: xc, iexch_l, icorr_l
USE xc_lda_lsda, ONLY: xc_lda, iexch_l, icorr_l
USE funct, ONLY: init_lda_xc
USE kinds, ONLY: DP
!
@ -26,70 +183,77 @@ SUBROUTINE dmxc( length, rho_in, dmuxc )
!
! ... local variables
!
REAL(DP), DIMENSION(length) :: ex, vx
REAL(DP), ALLOCATABLE, DIMENSION(:) :: rs, rho, dr
REAL(DP), ALLOCATABLE, DIMENSION(:) :: ex, vx
REAL(DP), ALLOCATABLE, DIMENSION(:) :: rhoaux, dr
REAL(DP), ALLOCATABLE, DIMENSION(:) :: ec, vc
!
REAL(DP), EXTERNAL :: dpz
INTEGER :: iflg, ir
REAL(DP) :: rs, ex_s, vx_s
REAL(DP) :: dpz
INTEGER :: iflg, ir, i1, i2, f1, f2
!
REAL(DP), PARAMETER :: small = 1.E-30_DP, e2 = 2.0_DP, &
pi34 = 0.75_DP / 3.141592653589793_DP, third = 1.0_DP /3.0_DP, &
rho_trash = 0.5_DP, rs_trash = 1.0_DP
!
CALL init_lda_xc()
REAL(DP), PARAMETER :: small = 1.E-30_DP, e2 = 2.0_DP, &
pi34 = 0.75_DP/3.141592653589793_DP, &
third=1.0_DP/3.0_DP, rho_trash=0.5_DP, &
rs_trash = 1.0_DP
!
dmuxc = 0.0_DP
!
! ... first case: analytical derivatives available
!
IF (iexch_l == 1 .AND. icorr_l == 1) THEN
!
ALLOCATE( rs(length) )
!
rs = rs_trash
WHERE ( rho_in > small ) rs = (pi34 / rho_in)**third
!
! ... exchange
CALL slater( length, rs, ex, vx )
dmuxc = vx / (3.0_DP * rho_in)
!
! ... correlation
!
!$omp parallel do private( rs, ex_s, vx_s)
DO ir = 1, length
!
IF ( rho_in(ir) > small ) THEN
rs = (pi34 / rho_in(ir))**third
ELSE
dmuxc(ir) = 0.0_DP
CYCLE
ENDIF
!
CALL slater( rs, ex_s, vx_s )
dmuxc(ir) = vx_s / (3.0_DP * rho_in(ir))
!
iflg = 2
if (rs(ir) < 1.0_DP) iflg = 1
dmuxc(ir) = dmuxc(ir) + dpz(rs(ir), iflg)
if (rs < 1.0_DP) iflg = 1
dmuxc(ir) = dmuxc(ir) + dpz( rs, iflg )
!
ENDDO
!
WHERE ( rho_in < small ) dmuxc = 0.0_DP
!
DEALLOCATE( rs )
!$omp end parallel do
!
ELSE
!
! ... second case: numerical derivatives
!
ALLOCATE( ec(length), vc(length) )
ALLOCATE( dr(length), rho(length) )
ALLOCATE( ex(2*length), vx(2*length) )
ALLOCATE( ec(2*length), vc(2*length) )
ALLOCATE( dr(length), rhoaux(2*length) )
!
rho = rho_in
WHERE ( rho_in < small ) rho = rho_trash
!
i1 = 1 ; f1 = length !two blocks: [ rho+dr ]
i2 = length+1 ; f2 = 2*length ! [ rho-dr ]
!
dr(:) = MIN( 1.E-6_DP, 1.E-4_DP * rho(:) )
!WHERE ( rho_in < small ) rho = rho_trash
!
CALL xc( length, rho+dr, ex, ec, vx, vc )
dr = 0.0_DP
WHERE ( rho_in > small ) dr = MIN( 1.E-6_DP, 1.E-4_DP * rho_in )
!
dmuxc = vx + vc
rhoaux(i1:f1) = rho_in+dr
rhoaux(i2:f2) = rho_in-dr
!
CALL xc( length, rho-dr, ex, ec, vx, vc )
CALL xc_lda( length*2, rhoaux, ex, ec, vx, vc )
!
dmuxc = (dmuxc - vx - vc) / (2.0_DP * dr)
dmuxc(:) = (vx(i1:f1) + vc(i1:f1) - vx(i2:f2) - vc(i2:f2)) / &
(2.0_DP * dr(:))
!
!
DEALLOCATE( ex, vx )
DEALLOCATE( ec, vc )
DEALLOCATE( dr, rho )
DEALLOCATE( dr, rhoaux )
!
WHERE ( rho_in < small ) dmuxc = 0.0_DP
! however a higher threshold is already present in xc()
! however a higher threshold is already present in xc_lda()
!
ENDIF
!
@ -99,181 +263,174 @@ SUBROUTINE dmxc( length, rho_in, dmuxc )
!
RETURN
!
END SUBROUTINE dmxc
END SUBROUTINE dmxc_lda
!
!
!-----------------------------------------------------------------------
SUBROUTINE dmxc_spin( length, rho, dmuxc )
SUBROUTINE dmxc_lsda( length, rho_in, dmuxc )
!-----------------------------------------------------------------------
!! Computes the derivative of the xc potential with respect to the
!! local density in the spin-polarized case.
!
USE funct, ONLY: init_lda_xc
USE kinds, ONLY: DP
USE xc_lda_lsda, ONLY: xc_spin, iexch_l, icorr_l
USE xc_lda_lsda, ONLY: xc_lsda, iexch_l, icorr_l
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: length
!! length of the input/output arrays
REAL(DP), INTENT(IN), DIMENSION(length,2) :: rho
REAL(DP), INTENT(IN), DIMENSION(length,2) :: rho_in
!! spin-up and spin-down charge density
REAL(DP), INTENT(OUT), DIMENSION(length,2,2) :: dmuxc
!! u-u, u-d, d-u, d-d derivatives of the XC functional
!
! ... local variables
!
REAL(DP), DIMENSION(length) :: zeta, rhotot
REAL(DP), DIMENSION(length) :: aux1, null_v
REAL(DP), DIMENSION(length) :: rhotot, zeta, zeta_eff
REAL(DP), DIMENSION(length) :: null_v
!
REAL(DP), ALLOCATABLE, DIMENSION(:) :: rs, zeta_eff, ds
REAL(DP), ALLOCATABLE, DIMENSION(:) :: ecu, ecp, aux2
REAL(DP), ALLOCATABLE, DIMENSION(:) :: vcu, vcp
REAL(DP), ALLOCATABLE, DIMENSION(:,:) :: vx, vc
REAL(DP), ALLOCATABLE, DIMENSION(:) :: aux1, aux2, dr, dz
REAL(DP), ALLOCATABLE, DIMENSION(:) :: rhoaux, zetaux
REAL(DP), ALLOCATABLE, DIMENSION(:,:) :: vx, vc, vxc
REAL(DP) :: ecu, ecp, ex_s
REAL(DP) :: vcu, vcp, vx_s
!
REAL(DP) :: fz, fz1, fz2, dmcu, dmcp, aa, bb, cc
REAL(DP) :: rs, zeta_s
!
REAL(DP), EXTERNAL :: dpz, dpz_polarized
REAL(DP) :: dpz, dpz_polarized
!
INTEGER :: ir, is, iflg
INTEGER :: i1, i2, i3, i4
INTEGER :: f1, f2, f3, f4
!
REAL(DP), PARAMETER :: small = 1.E-30_DP, e2 = 2.0_DP, &
pi34 = 0.75_DP / 3.141592653589793_DP, third = 1.0_DP/3.0_DP, &
p43 = 4.0_DP / 3.0_DP, p49 = 4.0_DP / 9.0_DP, m23 = -2.0_DP / 3.0_DP, &
rho_trash = 0.5_DP, zeta_trash = 0.5_DP
REAL(DP), PARAMETER :: small = 1.E-30_DP, e2 = 2.0_DP, &
pi34 = 0.75_DP/3.141592653589793_DP, &
third = 1.0_DP/3.0_DP, p43 = 4.0_DP/3.0_DP, &
p49 = 4.0_DP/9.0_DP, m23 = -2.0_DP/3.0_DP, &
rho_trash = 0.5_DP, zeta_trash = 0.5_DP
!
dmuxc = 0.0_DP
null_v = 1.0_DP
zeta = zeta_trash
rhotot(:) = rho(:,1) + rho(:,2)
!
CALL init_lda_xc()
!
WHERE (rhotot <= small)
rhotot = rho_trash
null_v = 0.0_DP
ELSEWHERE
zeta(:) = (rho(:,1) - rho(:,2)) / rhotot(:)
END WHERE
!
WHERE (ABS(zeta) > 1.0_DP)
zeta = zeta_trash
null_v = 0.0_DP
END WHERE
rhotot(:) = rho_in(:,1) + rho_in(:,2)
!
IF (iexch_l == 1 .AND. icorr_l == 1) THEN
!
! first case: analytical derivative available
!
ALLOCATE( rs(length) )
ALLOCATE( vcu(length), vcp(length), vx(length,1) )
ALLOCATE( ecu(length), ecp(length) )
!
! ... exchange
!
rs(:) = ( pi34 / (2.0_DP * rho(:,1)) )**third
CALL slater( length, rs, aux1, vx(:,1) )
!
dmuxc(:,1,1) = vx(:,1) / (3.0_DP * rho(:,1))
!
rs(:) = ( pi34 / (2.0_DP * rho(:,2)) )**third
CALL slater( length, rs, aux1, vx(:,1) )
!
dmuxc(:,2,2) = vx(:,1) / (3.0_DP * rho(:,2))
!
! ... correlation
!
rs = (pi34 / rhotot)**third
!
CALL pz( length, rs, 1, ecu, vcu )
CALL pz_polarized( length, rs, ecp, vcp )
! ... first case: analytical derivative available
!
!$omp parallel do private( rs, ex_s, vx_s, ecu, vcu, ecp, vcp, dmcu, dmcp, aa, bb, cc )
DO ir = 1, length
fz = ( (1.0_DP + zeta(ir))**p43 + (1.0_DP - zeta(ir))**p43 - 2.0_DP ) &
/ (2.0_DP**p43 - 2.0_DP)
fz1 = p43 * ( (1.0_DP + zeta(ir))**third - (1.0_DP - zeta(ir))**third) &
/ (2.0_DP**p43 - 2.0_DP)
fz2 = p49 * ( (1.0_DP + zeta(ir))**m23 + (1.0_DP - zeta(ir))**m23 ) &
/ (2.0_DP**p43 - 2.0_DP)
!
IF (rhotot(ir) < small) CYCLE
zeta_s = (rho_in(ir,1) - rho_in(ir,2)) / rhotot(ir)
IF (ABS(zeta_s) > 1.0_DP) CYCLE
!
! ... exchange
!
rs = ( pi34 / (2.0_DP * rho_in(ir,1)) )**third
CALL slater( rs, ex_s, vx_s )
!
dmuxc(ir,1,1) = vx_s / (3.0_DP * rho_in(ir,1))
!
rs = ( pi34 / (2.0_DP * rho_in(ir,2)) )**third
CALL slater( rs, ex_s, vx_s )
!
dmuxc(ir,2,2) = vx_s / (3.0_DP * rho_in(ir,2))
!
! ... correlation
!
rs = (pi34 / rhotot(ir))**third
!
CALL pz( rs, 1, ecu, vcu )
CALL pz_polarized( rs, ecp, vcp )
!
fz = ( (1.0_DP + zeta_s)**p43 + (1.0_DP - zeta_s)**p43 - 2.0_DP ) &
/ (2.0_DP**p43 - 2.0_DP)
fz1 = p43 * ( (1.0_DP + zeta_s)**third - (1.0_DP - zeta_s)**third) &
/ (2.0_DP**p43 - 2.0_DP)
fz2 = p49 * ( (1.0_DP + zeta_s)**m23 + (1.0_DP - zeta_s)**m23) &
/ (2.0_DP**p43 - 2.0_DP)
!
iflg = 2
IF (rs(ir) < 1.0_DP) iflg = 1
IF (rs < 1.0_DP) iflg = 1
!
dmcu = dpz( rs(ir), iflg )
dmcp = dpz_polarized( rs(ir), iflg )
dmcu = dpz( rs, iflg )
dmcp = dpz_polarized( rs, iflg )
!
aa = dmcu + fz * (dmcp - dmcu)
bb = 2.0_DP * fz1 * (vcp(ir) - vcu(ir) - (ecp(ir) - ecu(ir)) ) / rhotot(ir)
cc = fz2 * (ecp(ir) - ecu(ir)) / rhotot(ir)
bb = 2.0_DP * fz1 * (vcp - vcu - (ecp - ecu) ) / rhotot(ir)
cc = fz2 * (ecp - ecu) / rhotot(ir)
!
dmuxc(ir,1,1) = dmuxc(ir,1,1) + aa + (1.0_DP - zeta(ir)) * bb + &
(1.0_DP - zeta(ir))**2 * cc
dmuxc(ir,2,1) = dmuxc(ir,2,1) + aa + (-zeta(ir)) * bb + &
(zeta(ir)**2 - 1.0_DP) * cc
dmuxc(ir,1,1) = dmuxc(ir,1,1) + aa + (1.0_DP - zeta_s) * bb + &
(1.0_DP - zeta_s)**2 * cc
dmuxc(ir,2,1) = dmuxc(ir,2,1) + aa + (-zeta_s) * bb + &
(zeta_s**2 - 1.0_DP) * cc
dmuxc(ir,1,2) = dmuxc(ir,2,1)
dmuxc(ir,2,2) = dmuxc(ir,2,2) + aa - (1.0_DP + zeta(ir)) * bb + &
(1.0_DP + zeta(ir))**2 * cc
dmuxc(ir,2,2) = dmuxc(ir,2,2) + aa - (1.0_DP + zeta_s) * bb + &
(1.0_DP + zeta_s)**2 * cc
ENDDO
!
DEALLOCATE( rs )
DEALLOCATE( vcu, vcp, vx )
DEALLOCATE( ecu, ecp )
!$omp end parallel do
!
ELSE
!
ALLOCATE( vx(length,2), vc(length,2) )
ALLOCATE( aux2(length) )
ALLOCATE( zeta_eff(length), ds(length) )
!
! ... here ds=drho
ds(:) = MIN( 1.E-6_DP, 1.E-4_DP * rhotot(:) )
ALLOCATE( vx(4*length,2) , vc(4*length,2), vxc(2*length,2) )
ALLOCATE( rhoaux(4*length), zetaux(4*length) )
ALLOCATE( aux1(4*length) , aux2(4*length) )
ALLOCATE( dr(length), dz(length) )
!
CALL xc_spin( length, rhotot+ds, zeta, aux1, aux2, vx, vc )
i1 = 1 ; f1 = length ! four blocks: [ rho+dr , zeta ]
i2 = f1+1 ; f2 = 2*length ! [ rho-dr , zeta ]
i3 = f2+1 ; f3 = 3*length ! [ rho , zeta+dz ]
i4 = f3+1 ; f4 = 4*length ! [ rho , zeta-dz ]
!
dmuxc(:,1,1) = vx(:,1) + vc(:,1)
dmuxc(:,2,2) = vx(:,2) + vc(:,2)
!
CALL xc_spin( length, rhotot-ds, zeta, aux1, aux2, vx, vc )
dz(:) = 1.E-6_DP ! dz(:) = MIN( 1.d-6, 1.d-4*ABS(zeta(:)) )
!
dmuxc(:,1,1) = (dmuxc(:,1,1) - vx(:,1) - vc(:,1)) / (2.0_DP * ds(:))
dmuxc(:,2,1) = dmuxc(:,1,1)
dmuxc(:,2,2) = (dmuxc(:,2,2) - vx(:,2) - vc(:,2)) / (2.0_DP * ds(:))
dmuxc(:,1,2) = dmuxc(:,2,2)
! ... THRESHOLD STUFF
DO ir = 1, length
zeta_s=zeta_trash
IF (rhotot(ir) <= small) THEN
rhotot(ir)=rho_trash ; null_v(ir) = 0.0_DP
ENDIF
IF (rhotot(ir) > small) zeta_s = (rho_in(ir,1) - rho_in(ir,2)) / rhotot(ir)
zeta(ir) = zeta_s
! ... If zeta is too close to +-1, the derivative is computed at a slightly
! smaller zeta
zeta_eff(ir) = SIGN( MIN( ABS(zeta_s), (1.0_DP-2.0_DP*dz(ir)) ), zeta_s )
IF (ABS(zeta_s) > 1.0_DP) null_v(ir) = 0.0_DP
ENDDO
!
! ... now ds=dzeta
ds(:) = 1.E-6_DP
! ds() = min (1.d-6, 1.d-4 * abs(zeta(:)) )
dr(:) = MIN( 1.E-6_DP, 1.E-4_DP * rhotot(:) )
!
! ... If zeta is too close to +-1, the derivative is computed at a slightly
! smaller zeta
rhoaux(i1:f1) = rhotot + dr ; zetaux(i1:f1) = zeta
rhoaux(i2:f2) = rhotot - dr ; zetaux(i2:f2) = zeta
rhoaux(i3:f3) = rhotot ; zetaux(i3:f3) = zeta_eff + dz
rhoaux(i4:f4) = rhotot ; zetaux(i4:f4) = zeta_eff - dz
!
zeta_eff(:) = SIGN( MIN( ABS(zeta(:)), (1.0_DP-2.0_DP*ds(:)) ), zeta(:) )
!
CALL xc_spin( length, rhotot, zeta_eff+ds, aux1, aux2, vx, vc )
CALL xc_lsda( length*4, rhoaux, zetaux, aux1, aux2, vx, vc )
!
aux1 = 1.0_DP / rhotot / (2.0_DP*ds)
!
dmuxc(:,1,1) = ( vx(i1:f1,1) + vc(i1:f1,1) - vx(i2:f2,1) - vc(i2:f2,1) ) / (2.0_DP*dr)
dmuxc(:,2,2) = ( vx(i1:f1,2) + vc(i1:f1,2) - vx(i2:f2,2) - vc(i2:f2,2) ) / (2.0_DP*dr)
!
aux1(i1:f1) = 1.0_DP / rhotot(:) / (2.0_DP*dz(:))
aux1(i2:f2) = aux1(i1:f1)
DO is = 1, 2
vx(:,is) = (vx(:,is) + vc(:,is)) * aux1(:) ! vx as workspace here..
vxc(i1:f2,is) = ( vx(i3:f4,is) + vc(i3:f4,is) ) * aux1(i1:f2)
ENDDO
dmuxc(:,1,1) = dmuxc(:,1,1) + vx(:,1) * (1.0_DP-zeta(:))
dmuxc(:,1,2) = dmuxc(:,1,2) + vx(:,2) * (1.0_DP-zeta(:))
dmuxc(:,2,1) = dmuxc(:,2,1) - vx(:,1) * (1.0_DP+zeta(:))
dmuxc(:,2,2) = dmuxc(:,2,2) - vx(:,2) * (1.0_DP+zeta(:))
!
CALL xc_spin( length, rhotot, zeta_eff-ds, aux1, aux2, vx, vc )
dmuxc(:,2,1) = dmuxc(:,1,1) - (vxc(i1:f1,1) - vxc(i2:f2,1)) * (1.0_DP+zeta)
dmuxc(:,1,2) = dmuxc(:,2,2) + (vxc(i1:f1,2) - vxc(i2:f2,2)) * (1.0_DP-zeta)
dmuxc(:,1,1) = dmuxc(:,1,1) + (vxc(i1:f1,1) - vxc(i2:f2,1)) * (1.0_DP-zeta)
dmuxc(:,2,2) = dmuxc(:,2,2) - (vxc(i1:f1,2) - vxc(i2:f2,2)) * (1.0_DP+zeta)
!
aux1 = 1.0_DP / rhotot / (2.0_DP*ds)
DO is=1,2
vx(:,is) = (vx(:,is) + vc(:,is)) * aux1(:) ! ..and here
ENDDO
dmuxc(:,1,1) = dmuxc(:,1,1) - vx(:,1) * (1.0_DP-zeta(:))
dmuxc(:,1,2) = dmuxc(:,1,2) - vx(:,2) * (1.0_DP-zeta(:))
dmuxc(:,2,1) = dmuxc(:,2,1) + vx(:,1) * (1.0_DP+zeta(:))
dmuxc(:,2,2) = dmuxc(:,2,2) + vx(:,2) * (1.0_DP+zeta(:))
!
DEALLOCATE( vx, vc )
DEALLOCATE( aux2 )
DEALLOCATE( zeta_eff, ds )
DEALLOCATE( vx, vc, vxc )
DEALLOCATE( rhoaux, zetaux )
DEALLOCATE( aux1, aux2 )
DEALLOCATE( dr, dz )
!
ENDIF
!
@ -286,15 +443,16 @@ SUBROUTINE dmxc_spin( length, rho, dmuxc )
!
RETURN
!
END SUBROUTINE dmxc_spin
END SUBROUTINE dmxc_lsda
!
!
!-----------------------------------------------------------------------
SUBROUTINE dmxc_nc( length, rho_in, m, dmuxc )
!-----------------------------------------------------------------------
!! Computes the derivative of the xc potential with respect to the
!! local density and magnetization in the non-collinear case.
!
USE xc_lda_lsda, ONLY: xc_spin
USE xc_lda_lsda, ONLY: xc_lsda
USE funct, ONLY: init_lda_xc
USE kinds, ONLY: DP
!
@ -311,20 +469,22 @@ SUBROUTINE dmxc_nc( length, rho_in, m, dmuxc )
!
! ... local variables
!
REAL(DP), DIMENSION(length) :: rho, amag, zeta
REAL(DP), DIMENSION(length) :: zeta_eff, ds, null_v, null_m
REAL(DP), DIMENSION(length) :: vs, aux1, aux2
REAL(DP), DIMENSION(length,2) :: vx, vxm, vxp
REAL(DP), DIMENSION(length,2) :: vc, vcm, vcp
REAL(DP), DIMENSION(length) :: dvxc_rho, dbx_rho, dby_rho, dbz_rho
REAL(DP), DIMENSION(length) :: rhotot, amag, zeta, zeta_eff, dr, dz
REAL(DP), ALLOCATABLE, DIMENSION(:) :: rhoaux, zetaux
REAL(DP), DIMENSION(length) :: vs
INTEGER, DIMENSION(length) :: null_v
REAL(DP), ALLOCATABLE, DIMENSION(:) :: aux1, aux2
REAL(DP), ALLOCATABLE, DIMENSION(:,:) :: vx, vc
REAL(DP), DIMENSION(length) :: dvxc_rho, dbx_rho, dby_rho, dbz_rho
!
REAL(DP) :: dvxc_mx, dvxc_my, dvxc_mz, &
dbx_mx, dbx_my, dbx_mz, &
dby_mx, dby_my, dby_mz, &
dbz_mx, dbz_my, dbz_mz
REAL(DP) :: rnull
REAL(DP) :: rnull, zeta_s
!
INTEGER :: i
INTEGER :: i1, i2, i3, i4, i5, i
INTEGER :: f1, f2, f3, f4, f5
!
REAL(DP), PARAMETER :: small = 1.E-30_DP, e2 = 2.0_DP, &
rho_trash = 0.5_DP, zeta_trash = 0.5_DP, &
@ -332,133 +492,129 @@ SUBROUTINE dmxc_nc( length, rho_in, m, dmuxc )
!
dmuxc = 0.0_DP
!
rho = rho_in
ALLOCATE( rhoaux(length*5), zetaux(length*5) )
ALLOCATE( aux1(length*5), aux2(length*5) )
ALLOCATE( vx(length*5,2), vc(length*5,2) )
!
rhotot = rho_in
zeta = zeta_trash
amag = amag_trash
null_v = 1.0_DP
null_m = 1.0_DP
null_v = 1
!
CALL init_lda_xc()
i1 = 1 ; f1 = length ! five blocks: [ rho , zeta ]
i2 = f1+1 ; f2 = 2*length ! [ rho+dr , zeta ]
i3 = f2+1 ; f3 = 3*length ! [ rho-dr , zeta ]
i4 = f3+1 ; f4 = 4*length ! [ rho , zeta+dz ]
i5 = f4+1 ; f5 = 5*length ! [ rho , zeta-dz ]
!
WHERE (rho_in <= small)
rho = rho_trash
null_v = 0.0_DP
ELSEWHERE
amag = SQRT( m(:,1)**2 + m(:,2)**2 + m(:,3)**2 )
zeta = amag / rho
END WHERE
!
WHERE (ABS(zeta) > 1.0_DP)
zeta = zeta_trash
null_v = 0.0_DP
END WHERE
!
CALL xc_spin( length, rho, zeta, aux1, aux2, vx, vc )
!
vs = 0.5_DP*( vx(:,1)+vc(:,1)-vx(:,2)-vc(:,2) )
!
! ... here ds=drho
ds = MIN( 1.E-6_DP, 1.E-4_DP * rho )
!
CALL xc_spin( length, rho-ds, zeta, aux1, aux2, vxm, vcm )
!
CALL xc_spin( length, rho+ds, zeta, aux1, aux2, vxp, vcp )
!
dvxc_rho = ((vxp(:,1) + vcp(:,1) - vxm(:,1) - vcm(:,1)) + &
(vxp(:,2) + vcp(:,2) - vxm(:,2) - vcm(:,2))) / (4.0_DP*ds)
!
WHERE (amag < 1.E-10_DP)
rho = 0.5_DP
zeta = 0.5_DP
amag = 0.025_DP
null_m = 0.0_DP
END WHERE
!
!
aux2(:) = vxp(:,1) + vcp(:,1) - vxm(:,1) - vcm(:,1) - &
( vxp(:,2) + vcp(:,2) - vxm(:,2) - vcm(:,2) )
!
dbx_rho(:) = aux2 * m(:,1) / (4.0_DP*ds*amag)
dby_rho(:) = aux2 * m(:,2) / (4.0_DP*ds*amag)
dbz_rho(:) = aux2 * m(:,3) / (4.0_DP*ds*amag)
!
! ... now ds=dzeta
ds = 1.0E-6_DP
! ds = min (1.d-6, 1.d-4 * abs (zeta) )
!
! ... If zeta is too close to +-1, the derivative is computed at a slightly
! smaller zeta
dz = 1.0E-6_DP !dz = MIN( 1.d-6, 1.d-4*ABS(zeta) )
!
DO i = 1, length
zeta_eff(i) = SIGN( MIN( ABS( zeta(i) ), ( 1.0_DP - 2.0_DP*ds(i) ) ) , zeta(i) )
zeta_s = zeta_trash
IF (rhotot(i) <= small) THEN
rhotot(i) = rho_trash ; null_v(i) = 0.0_DP
ENDIF
amag(i) = SQRT( m(i,1)**2 + m(i,2)**2 + m(i,3)**2 )
IF (rhotot(i) > small) zeta_s = amag(i) / rhotot(i)
zeta(i) = zeta_s
zeta_eff(i) = SIGN( MIN( ABS(zeta_s), (1.0_DP-2.0_DP*dz(i)) ), zeta_s )
IF (ABS(zeta_s) > 1.0_DP) null_v(i) = 0
ENDDO
!
CALL xc_spin( length, rho, zeta_eff-ds, aux1, aux2, vxm, vcm )
dr = MIN( 1.E-6_DP, 1.E-4_DP * rhotot )
!
rhoaux(i1:f1) = rhotot ; zetaux(i1:f1) = zeta
rhoaux(i2:f2) = rhotot + dr ; zetaux(i2:f2) = zeta
rhoaux(i3:f3) = rhotot - dr ; zetaux(i3:f3) = zeta
rhoaux(i4:f4) = rhotot ; zetaux(i4:f4) = zeta_eff + dz
rhoaux(i5:f5) = rhotot ; zetaux(i5:f5) = zeta_eff - dz
!
CALL xc_spin( length, rho, zeta_eff+ds, aux1, aux2, vxp, vcp )
!
! ... The variables are rho and m, so zeta depends on rho
CALL xc_lsda( length*5, rhoaux, zetaux, aux1, aux2, vx, vc )
!
aux1(:) = vxp(:,1) + vcp(:,1) - vxm(:,1) - vcm(:,1) + &
vxp(:,2) + vcp(:,2) - vxm(:,2) - vcm(:,2)
aux2(:) = vxp(:,1) + vcp(:,1) - vxm(:,1) - vcm(:,1) - &
( vxp(:,2) + vcp(:,2) - vxm(:,2) - vcm(:,2) )
!
dvxc_rho = dvxc_rho - aux1 * zeta/rho / (4.0_DP*ds) * null_m
dbx_rho(:) = dbx_rho - aux2 * m(:,1) * zeta/rho / (4.0_DP*ds*amag)
dby_rho(:) = dby_rho - aux2 * m(:,2) * zeta/rho / (4.0_DP*ds*amag)
dbz_rho(:) = dbz_rho - aux2 * m(:,3) * zeta/rho / (4.0_DP*ds*amag)
vs(:) = 0.5_DP*( vx(i1:f1,1)+vc(i1:f1,1)-vx(i1:f1,2)-vc(i1:f1,2) )
!
dmuxc(:,1,1) = dvxc_rho * null_v
dmuxc(:,2,1) = dbx_rho * null_v
dmuxc(:,3,1) = dby_rho * null_v
dmuxc(:,4,1) = dbz_rho * null_v
dvxc_rho(:) = ((vx(i2:f2,1) + vc(i2:f2,1) - vx(i3:f3,1) - vc(i3:f3,1)) + &
(vx(i2:f2,2) + vc(i2:f2,2) - vx(i3:f3,2) - vc(i3:f3,2))) / (4.0_DP*dr)
!
aux2(1:length) = vx(i2:f2,1) + vc(i2:f2,1) - vx(i3:f3,1) - vc(i3:f3,1) - &
( vx(i2:f2,2) + vc(i2:f2,2) - vx(i3:f3,2) - vc(i3:f3,2) )
!
! ... Here the derivatives with respect to m
dbx_rho(:) = aux2(1:length) * m(:,1) / (4.0_DP*dr*amag)
dby_rho(:) = aux2(1:length) * m(:,2) / (4.0_DP*dr*amag)
dbz_rho(:) = aux2(1:length) * m(:,3) / (4.0_DP*dr*amag)
!
aux1(1:length) = vx(i4:f4,1) + vc(i4:f4,1) - vx(i5:f5,1) - vc(i5:f5,1) + &
vx(i4:f4,2) + vc(i4:f4,2) - vx(i5:f5,2) - vc(i5:f5,2)
aux2(1:length) = vx(i4:f4,1) + vc(i4:f4,1) - vx(i5:f5,1) - vc(i5:f5,1) - &
( vx(i4:f4,2) + vc(i4:f4,2) - vx(i5:f5,2) - vc(i5:f5,2) )
!
DO i = 1, length
!
IF ( null_v(i) == 0 ) THEN
dmuxc(i,:,:) = 0.0_DP
CYCLE
ENDIF
!
IF (amag(i) <= 1.E-10_DP) THEN
dmuxc(i,1,1) = dvxc_rho(i)
CYCLE
ENDIF
!
dvxc_rho(i) = dvxc_rho(i) - aux1(i) * zeta(i)/rhotot(i) / (4.0_DP*dz(i))
dbx_rho(i) = dbx_rho(i) - aux2(i) * m(i,1) * zeta(i)/rhotot(i) / (4.0_DP*dz(i)*amag(i))
dby_rho(i) = dby_rho(i) - aux2(i) * m(i,2) * zeta(i)/rhotot(i) / (4.0_DP*dz(i)*amag(i))
dbz_rho(i) = dbz_rho(i) - aux2(i) * m(i,3) * zeta(i)/rhotot(i) / (4.0_DP*dz(i)*amag(i))
!
dmuxc(i,1,1) = dvxc_rho(i)
dmuxc(i,2,1) = dbx_rho(i)
dmuxc(i,3,1) = dby_rho(i)
dmuxc(i,4,1) = dbz_rho(i)
!
! ... Here the derivatives with respect to m
!
rnull = null_v(i)
!
dvxc_mx = aux1(i) * m(i,1) / rho(i) / (4.0_DP*ds(i)*amag(i))
dvxc_my = aux1(i) * m(i,2) / rho(i) / (4.0_DP*ds(i)*amag(i))
dvxc_mz = aux1(i) * m(i,3) / rho(i) / (4.0_DP*ds(i)*amag(i))
dvxc_mx = aux1(i) * m(i,1) / rhotot(i) / (4.0_DP*dz(i)*amag(i))
dvxc_my = aux1(i) * m(i,2) / rhotot(i) / (4.0_DP*dz(i)*amag(i))
dvxc_mz = aux1(i) * m(i,3) / rhotot(i) / (4.0_DP*dz(i)*amag(i))
!
dbx_mx = (aux2(i) * m(i,1) * m(i,1) * amag(i)/rho(i) / (4.0_DP*ds(i)) + &
dbx_mx = (aux2(i) * m(i,1) * m(i,1) * amag(i)/rhotot(i) / (4.0_DP*dz(i)) + &
vs(i) * (m(i,2)**2+m(i,3)**2)) / amag(i)**3
dbx_my = (aux2(i) * m(i,1) * m(i,2) * amag(i)/rho(i) / (4.0_DP*ds(i)) - &
dbx_my = (aux2(i) * m(i,1) * m(i,2) * amag(i)/rhotot(i) / (4.0_DP*dz(i)) - &
vs(i) * m(i,1) * m(i,2) ) / amag(i)**3
dbx_mz = (aux2(i) * m(i,1) * m(i,3) * amag(i)/rho(i) / (4.0_DP*ds(i)) - &
dbx_mz = (aux2(i) * m(i,1) * m(i,3) * amag(i)/rhotot(i) / (4.0_DP*dz(i)) - &
vs(i) * m(i,1) * m(i,3) ) / amag(i)**3
!
dby_mx = dbx_my
dby_my = (aux2(i) * m(i,2) * m(i,2) * amag(i)/rho(i) / (4.0_DP*ds(i)) + &
dby_my = (aux2(i) * m(i,2) * m(i,2) * amag(i)/rhotot(i) / (4.0_DP*dz(i)) + &
vs(i) * (m(i,1)**2 + m(i,3)**2)) / amag(i)**3
dby_mz = (aux2(i) * m(i,2) * m(i,3) * amag(i)/rho(i) / (4.0_DP*ds(i)) - &
dby_mz = (aux2(i) * m(i,2) * m(i,3) * amag(i)/rhotot(i) / (4.0_DP*dz(i)) - &
vs(i) * m(i,2) * m(i,3)) / amag(i)**3
!
dbz_mx = dbx_mz
dbz_my = dby_mz
dbz_mz = (aux2(i) * m(i,3) * m(i,3) * amag(i)/rho(i) / (4.0_DP*ds(i)) + &
dbz_mz = (aux2(i) * m(i,3) * m(i,3) * amag(i)/rhotot(i) / (4.0_DP*dz(i)) + &
vs(i)*(m(i,1)**2 + m(i,2)**2)) / amag(i)**3
!
! ... assigns values to dmuxc and sets to zero trash points
!
dmuxc(i,1,2) = dvxc_mx * rnull
dmuxc(i,1,3) = dvxc_my * rnull
dmuxc(i,1,4) = dvxc_mz * rnull
dmuxc(i,1,2) = dvxc_mx
dmuxc(i,1,3) = dvxc_my
dmuxc(i,1,4) = dvxc_mz
!
dmuxc(i,2,2) = dbx_mx * rnull
dmuxc(i,2,3) = dbx_my * rnull
dmuxc(i,2,4) = dbx_mz * rnull
dmuxc(i,2,2) = dbx_mx
dmuxc(i,2,3) = dbx_my
dmuxc(i,2,4) = dbx_mz
!
dmuxc(i,3,2) = dby_mx * rnull
dmuxc(i,3,3) = dby_my * rnull
dmuxc(i,3,4) = dby_mz * rnull
dmuxc(i,3,2) = dby_mx
dmuxc(i,3,3) = dby_my
dmuxc(i,3,4) = dby_mz
!
dmuxc(i,4,2) = dbz_mx * rnull
dmuxc(i,4,3) = dbz_my * rnull
dmuxc(i,4,4) = dbz_mz * rnull
dmuxc(i,4,2) = dbz_mx
dmuxc(i,4,3) = dbz_my
dmuxc(i,4,4) = dbz_mz
!
ENDDO
!
@ -466,6 +622,96 @@ SUBROUTINE dmxc_nc( length, rho_in, m, dmuxc )
!
dmuxc = e2 * dmuxc
!
DEALLOCATE( rhoaux, zetaux)
DEALLOCATE( aux1, aux2 )
DEALLOCATE( vx, vc )
!
RETURN
!
END SUBROUTINE dmxc_nc
!
!
!-----------------------------------------------------------------------
FUNCTION dpz( rs, iflg )
!-----------------------------------------------------------------------
!! Derivative of the correlation potential with respect to local density
!! Perdew and Zunger parameterization of the Ceperley-Alder functional.
!
USE kinds, ONLY: DP
USE constants, ONLY: pi, fpi
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
INTEGER, INTENT(IN) :: iflg
REAL(DP) :: dpz
!
! ... local variables
! a,b,c,d,gc,b1,b2 are the parameters defining the functional
!
REAL(DP), PARAMETER :: a = 0.0311d0, b = -0.048d0, c = 0.0020d0, &
d = -0.0116d0, gc = -0.1423d0, b1 = 1.0529d0, b2 = 0.3334d0,&
a1 = 7.0d0 * b1 / 6.d0, a2 = 4.d0 * b2 / 3.d0
REAL(DP) :: x, den, dmx, dmrs
!
IF (iflg == 1) THEN
dmrs = a / rs + 2.d0 / 3.d0 * c * (LOG(rs) + 1.d0) + &
(2.d0 * d-c) / 3.d0
ELSE
x = SQRT(rs)
den = 1.d0 + x * (b1 + x * b2)
dmx = gc * ( (a1 + 2.d0 * a2 * x) * den - 2.d0 * (b1 + 2.d0 * &
b2 * x) * (1.d0 + x * (a1 + x * a2) ) ) / den**3
dmrs = 0.5d0 * dmx / x
ENDIF
!
dpz = - fpi * rs**4.d0 / 9.d0 * dmrs
!
RETURN
!
END FUNCTION dpz
!
!
!-----------------------------------------------------------------------
FUNCTION dpz_polarized( rs, iflg )
!-----------------------------------------------------------------------
!! Derivative of the correlation potential with respect to local density
!! Perdew and Zunger parameterization of the Ceperley-Alder functional. |
!! Spin-polarized case.
!
USE kinds, ONLY: DP
USE constants, ONLY: pi, fpi
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rs
INTEGER, INTENT(IN) :: iflg
REAL(DP) :: dpz_polarized
!
! ... local variables
!
! a,b,c,d,gc,b1,b2 are the parameters defining the functional
!
REAL(DP), PARAMETER :: a=0.01555_DP, b=-0.0269_DP, c=0.0007_DP, &
d=-0.0048_DP, gc=-0.0843_DP, b1=1.3981_DP,&
b2=0.2611_DP, a1=7.0_DP*b1/6._DP, a2=4._DP*b2/3._DP
REAL(DP) :: x, den, dmx, dmrs
!
!
IF (iflg == 1) THEN
dmrs = a/rs + 2._DP/3._DP * c * (LOG(rs) + 1._DP) + &
(2._DP*d - c)/3._DP
ELSE
x = SQRT(rs)
den = 1._DP + x * (b1 + x*b2)
dmx = gc * ( (a1 + 2._DP * a2 * x) * den - 2._DP * (b1 + 2._DP * &
b2 * x) * (1._DP + x * (a1 + x*a2) ) ) / den**3
dmrs = 0.5d0 * dmx/x
ENDIF
!
dpz_polarized = - fpi * rs**4._DP / 9._DP * dmrs
!
!
RETURN
!
END FUNCTION dpz_polarized

View File

@ -75,6 +75,7 @@ module funct
! PRIVATE variables defining the DFT functional
!
PRIVATE :: dft, iexch, icorr, igcx, igcc, imeta, inlc
PRIVATE :: qe_or_libxc
PRIVATE :: discard_input_dft
PRIVATE :: isgradient, ismeta, ishybrid
PRIVATE :: exx_fraction, exx_started
@ -314,6 +315,9 @@ module funct
!
integer, parameter:: notset = -1
!
! switches to decide between qe (1) and libxc (2) routines
integer :: qe_or_libxc(2)
!
! internal indices for exchange-correlation
! iexch: type of exchange
! icorr: type of correlation
@ -407,6 +411,14 @@ CONTAINS
do l = 1, len
dftout (l:l) = capital (dft_(l:l) )
enddo
!
!
! PROVISIONAL: it should be put as an environment variable or something
qe_or_libxc(:)=0
#if defined(__LIBXC)
qe_or_libxc(1)=1
qe_or_libxc(2)=1
#endif
!
! ----------------------------------------------
! FIRST WE CHECK ALL THE SHORT NAMES
@ -416,6 +428,7 @@ CONTAINS
! special cases : PZ (LDA is equivalent to PZ)
IF (('PZ' .EQ. TRIM(dftout) ).OR.('LDA' .EQ. TRIM(dftout) )) THEN
dft_defined = set_dft_values(1,1,0,0,0,0)
! speciale cases : PW ( LDA with PW correlation )
ELSE IF ( 'PW' .EQ. TRIM(dftout)) THEN
dft_defined = set_dft_values(1,4,0,0,0,0)
@ -671,9 +684,9 @@ CONTAINS
igcc = matching (dftout, ngcc,gradc)
imeta = matching (dftout,nmeta, meta)
inlc = matching (dftout, ncnl, nonlocc)
endif
! ----------------------------------------------------------------
! Last check
! No more defaults, the code exits if the dft is not defined
@ -805,24 +818,86 @@ CONTAINS
end subroutine set_auxiliary_flags
!
!-----------------------------------------------------------------------
logical function set_dft_values (i1,i2,i3,i4,i5,i6)
logical function set_dft_values(i1,i2,i3,i4,i5,i6)
!-----------------------------------------------------------------------
!
implicit none
integer :: i1,i2,i3,i4,i5,i6
!
iexch=i1
icorr=i2
igcx =i3
igcc =i4
inlc =i5
imeta=i6
!
set_dft_values = .true.
!
return
!
end function set_dft_values
!
!
!--------------------------------------------------------------------------
FUNCTION qe_to_libxc_index( index_qe, term )
!-----------------------------------------------------------------------
!! PROVISIONAL: converts q-e indexes of functionals into libxc ones,
!! when possible.
!! In the next commit this will be done directly in 'funct.f90' and
!! including all the cases available.
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: index_qe
!! index of q-e functional term
CHARACTER(LEN=*), INTENT(IN) :: term
!! which term to consider
INTEGER :: qe_to_libxc_index
!! index converted in libxc notation
!
! ... exchange term
IF (term .EQ. 'exch_LDA') THEN
!
qe_or_libxc(1) = 1
!
SELECT CASE( index_qe )
CASE( 1 )
qe_to_libxc_index = 1
CASE DEFAULT
qe_to_libxc_index = -1
qe_or_libxc(1) = 0
END SELECT
!
! ... correlation term
ELSEIF (term .EQ. 'corr_LDA') THEN
!
qe_or_libxc(2) = 1
!
SELECT CASE( index_qe )
CASE( 1 ) !pz
qe_to_libxc_index = 9
CASE( 5 ) !wigner
qe_to_libxc_index = 2
CASE( 2 ) !vwn
qe_to_libxc_index = 7
CASE( 4 ) !pw
qe_to_libxc_index = 12
CASE DEFAULT
qe_to_libxc_index = -1
qe_or_libxc(2) = 0
END SELECT
!
ELSE
!
CALL errore( 'qe_to_libxc_index', 'ERROR: option not available', 3 )
!
ENDIF
!
RETURN
!
END FUNCTION qe_to_libxc_index
!
!
!-----------------------------------------------------------------------
subroutine enforce_input_dft (dft_, nomsg)
!
@ -2844,16 +2919,21 @@ end subroutine tau_xc_array_spin
SUBROUTINE init_lda_xc()
!! Gets from inside parameters needed to initialize lda xc-drivers.
!
USE kinds, ONLY: DP
USE xc_lda_lsda, ONLY: iexch_l, icorr_l, &
exx_started_l, is_there_finite_size_corr, &
exx_fraction_l, finite_size_cell_volume_l
USE kinds, ONLY: DP
USE xc_lda_lsda, ONLY: libxc_switches, iexch_l, icorr_l, &
exx_started_l, is_there_finite_size_corr, &
exx_fraction_l, finite_size_cell_volume_l
!
IMPLICIT NONE
!
! use qe or libxc for the different terms (0: qe, 1: libxc)
libxc_switches(:) = qe_or_libxc(:)
!
! exchange-correlation indexes
iexch_l = get_iexch()
IF (libxc_switches(1)==1) iexch_l = qe_to_libxc_index( iexch, 'exch_LDA' )
icorr_l = get_icorr()
IF (libxc_switches(2)==1) icorr_l = qe_to_libxc_index( icorr, 'corr_LDA' )
!
! hybrid exchange vars
exx_started_l = exx_is_active()
@ -2861,7 +2941,8 @@ SUBROUTINE init_lda_xc()
IF ( exx_started ) exx_fraction_l = get_exx_fraction()
!
! finite size correction vars
CALL get_finite_size_cell_volume( is_there_finite_size_corr, finite_size_cell_volume_l )
CALL get_finite_size_cell_volume( is_there_finite_size_corr, &
finite_size_cell_volume_l )
!
RETURN
!

View File

@ -447,8 +447,7 @@ subroutine ggac( rho, grho, sc, v1c, v2c )
!
USE kinds, ONLY : DP
implicit none
integer, parameter :: length=1 !^^^ PROVISIONAL (xc-lib)
real(DP), dimension(length) :: rs, ec, vc
real(DP) :: rs, ec, vc
real(DP) :: rho, grho, sc, v1c, v2c
real(DP) :: al, pa, pb, pc, pd, cx, cxc0, cc0
parameter (al = 0.09d0, pa = 0.023266d0, pb = 7.389d-6, pc = &
@ -465,36 +464,36 @@ subroutine ggac( rho, grho, sc, v1c, v2c )
real(DP) :: h0, dh0, ddh0, ee, cn, dcn, cna, dcna, cnb, dcnb, h1, &
dh1, ddh1
!
rs(1) = pi34 / rho**third
rs2 = rs(1) * rs(1)
rs3 = rs(1) * rs2
rs = pi34 / rho**third
rs2 = rs * rs
rs3 = rs * rs2
!
call pw( length, rs, 1, ec, vc )
call pw( rs, 1, ec, vc )
!
kf = xkf / rs(1)
kf = xkf / rs
ks = xks * sqrt(kf)
t = sqrt(grho) / (2.d0 * ks * rho)
expe = exp( - 2.d0 * al * ec(1) / (be * be) )
expe = exp( - 2.d0 * al * ec / (be * be) )
af = 2.d0 * al / be * (1.d0 / (expe-1.d0) )
bf = expe * (vc(1) - ec(1))
bf = expe * (vc - ec)
y = af * t * t
xy = (1.d0 + y) / (1.d0 + y + y * y)
qy = y * y * (2.d0 + y) / (1.d0 + y + y * y) **2
s1 = 1.d0 + 2.d0 * al / be * t * t * xy
h0 = be * be / (2.d0 * al) * log(s1)
dh0 = be * t * t / s1 * ( - 7.d0 / 3.d0 * xy - qy * (af * bf / &
be-7.d0 / 3.d0) )
be-7.d0 / 3.d0) )
ddh0 = be / (2.d0 * ks * ks * rho) * (xy - qy) / s1
ee = - 100.d0 * (ks / kf * t) **2
cna = cxc0 + pa * rs(1) + pb * rs2
dcna = pa * rs(1) + 2.d0 * pb * rs2
cnb = 1.d0 + pc * rs(1) + pd * rs2 + 1.d4 * pb * rs3
dcnb = pc * rs(1) + 2.d0 * pd * rs2 + 3.d4 * pb * rs3
cna = cxc0 + pa * rs + pb * rs2
dcna = pa * rs + 2.d0 * pb * rs2
cnb = 1.d0 + pc * rs + pd * rs2 + 1.d4 * pb * rs3
dcnb = pc * rs + 2.d0 * pd * rs2 + 3.d4 * pb * rs3
cn = cna / cnb - cx
dcn = dcna / cnb - cna * dcnb / (cnb * cnb)
h1 = nu * (cn - cc0 - 3.d0 / 7.d0 * cx) * t * t * exp(ee)
dh1 = - third * (h1 * (7.d0 + 8.d0 * ee) + nu * t * t * exp(ee) &
* dcn)
* dcn)
ddh1 = 2.d0 * h1 * (1.d0 + ee) * rho / grho
sc = rho * (h0 + h1)
v1c = h0 + h1 + dh0 + dh1
@ -774,29 +773,28 @@ subroutine pbec(rho, grho, iflag, sc, v1c, v2c)
real(DP), parameter :: third = 1.d0 / 3.d0, pi34 = 0.6203504908994d0
real(DP), parameter :: xkf = 1.919158292677513d0, xks = 1.128379167095513d0
! pi34=(3/4pi)^(1/3), xkf=(9 pi/4)^(1/3), xks= sqrt(4/pi)
integer, parameter :: length=1 !^^^ PROVISIONAL
real(DP), dimension(length) :: rs, ec, vc
real(DP) :: rs, ec, vc
!
real(DP) :: kf, ks, t, expe, af, bf, y, xy, qy
real(DP) :: s1, h0, dh0, ddh0, sc2D, v1c2D, v2c2D
!
rs(1) = pi34 / rho**third
rs = pi34 / rho**third
!
call pw( length, rs, 1, ec, vc )
call pw( rs, 1, ec, vc )
!
kf = xkf / rs(1)
ks = xks * sqrt (kf)
t = sqrt (grho) / (2.d0 * ks * rho)
expe = exp ( - ec(1) / ga)
kf = xkf / rs
ks = xks * sqrt(kf)
t = sqrt(grho) / (2.d0 * ks * rho)
expe = exp( - ec / ga)
af = be(iflag) / ga * (1.d0 / (expe-1.d0) )
bf = expe * (vc(1) - ec(1))
bf = expe * (vc - ec)
y = af * t * t
xy = (1.d0 + y) / (1.d0 + y + y * y)
qy = y * y * (2.d0 + y) / (1.d0 + y + y * y) **2
s1 = 1.d0 + be(iflag) / ga * t * t * xy
h0 = ga * log (s1)
h0 = ga * log(s1)
dh0 = be(iflag) * t * t / s1 * ( - 7.d0 / 3.d0 * xy - qy * (af * bf / &
be(iflag)-7.d0 / 3.d0) )
be(iflag)-7.d0 / 3.d0) )
ddh0 = be(iflag) / (2.d0 * ks * ks * rho) * (xy - qy) / s1
sc = rho * h0
v1c = h0 + dh0
@ -1352,46 +1350,6 @@ subroutine wcx (rho, grho, sx, v1x, v2x)
return
end subroutine wcx
!
!-----------------------------------------------------------------------
function dpz(rs, iflg)
!-----------------------------------------------------------------------
! derivative of the correlation potential with respect to local density
! Perdew and Zunger parameterization of the Ceperley-Alder functional
!
use kinds, only: DP
USE constants, ONLY: pi, fpi
!
implicit none
!
real(DP), intent(in) :: rs
integer, intent(in) :: iflg
real(DP) :: dpz
!
! local variables
! a,b,c,d,gc,b1,b2 are the parameters defining the functional
!
real(DP), parameter :: a = 0.0311d0, b = -0.048d0, c = 0.0020d0, &
d = -0.0116d0, gc = -0.1423d0, b1 = 1.0529d0, b2 = 0.3334d0,&
a1 = 7.0d0 * b1 / 6.d0, a2 = 4.d0 * b2 / 3.d0
real(DP) :: x, den, dmx, dmrs
!
!
if (iflg == 1) then
dmrs = a / rs + 2.d0 / 3.d0 * c * (log (rs) + 1.d0) + &
(2.d0 * d-c) / 3.d0
else
x = sqrt (rs)
den = 1.d0 + x * (b1 + x * b2)
dmx = gc * ( (a1 + 2.d0 * a2 * x) * den - 2.d0 * (b1 + 2.d0 * &
b2 * x) * (1.d0 + x * (a1 + x * a2) ) ) / den**3
dmrs = 0.5d0 * dmx / x
endif
!
dpz = - fpi * rs**4.d0 / 9.d0 * dmrs
return
!
end function dpz
!----------------------------------------------------------------------
!
! HSE (wPBE) stabbing starts HERE
!

View File

@ -101,9 +101,8 @@ subroutine ggac_spin(rho, zeta, grho, sc, v1cup, v1cdw, v2c)
implicit none
real(DP) :: rho, zeta, grho, sc, v1cup, v1cdw, v2c
!
integer, parameter :: length=1 !^^^ PROVISIONAL
real(dp), dimension(length) :: rs , zeta_v, ec
real(dp), dimension(length,2) :: vc
real(dp) :: rs, ec
real(dp) :: vc(2)
!
real(DP) :: al, pa, pb, pc, pd, cx, cxc0, cc0
parameter (al = 0.09d0, pa = 0.023266d0, pb = 7.389d-6, pc = &
@ -121,16 +120,14 @@ subroutine ggac_spin(rho, zeta, grho, sc, v1cup, v1cdw, v2c)
ddh1, fz, fz2, fz3, fz4, dfz, bfup, bfdw, dh0up, dh0dw, dh0zup, &
dh0zdw, dh1zup, dh1zdw
!
rs(1) = pi34 / rho**third
rs2 = rs(1) * rs(1)
rs3 = rs(1) * rs2
rs = pi34 / rho**third
rs2 = rs * rs
rs3 = rs * rs2
!
zeta_v(1) = zeta
call pw_spin( rs, zeta, ec, vc )
!
call pw_spin( length, rs, zeta_v, ec, vc )
!
kf = xkf / rs(1)
ks = xks * sqrt (kf)
kf = xkf / rs
ks = xks * sqrt(kf)
fz = 0.5d0 * ( (1.d0 + zeta) ** (2.d0 / 3.d0) + (1.d0 - zeta) ** ( &
2.d0 / 3.d0) )
fz2 = fz * fz
@ -138,35 +135,35 @@ subroutine ggac_spin(rho, zeta, grho, sc, v1cup, v1cdw, v2c)
fz4 = fz3 * fz
dfz = ( (1.d0 + zeta) ** ( - 1.d0 / 3.d0) - (1.d0 - zeta) ** ( - &
1.d0 / 3.d0) ) / 3.d0
t = sqrt (grho) / (2.d0 * fz * ks * rho)
expe = exp ( - 2.d0 * al * ec(1) / (fz3 * be * be) )
t = sqrt(grho) / (2.d0 * fz * ks * rho)
expe = exp( - 2.d0 * al * ec / (fz3 * be * be) )
af = 2.d0 * al / be * (1.d0 / (expe-1.d0) )
bfup = expe * (vc(1,1) - ec(1)) / fz3
bfdw = expe * (vc(1,2) - ec(1)) / fz3
bfup = expe * (vc(1) - ec) / fz3
bfdw = expe * (vc(2) - ec) / fz3
y = af * t * t
xy = (1.d0 + y) / (1.d0 + y + y * y)
qy = y * y * (2.d0 + y) / (1.d0 + y + y * y) **2
qy = y * y * (2.d0 + y) / (1.d0 + y + y * y)**2
s1 = 1.d0 + 2.d0 * al / be * t * t * xy
h0 = fz3 * be * be / (2.d0 * al) * log (s1)
h0 = fz3 * be * be / (2.d0 * al) * log(s1)
dh0up = be * t * t * fz3 / s1 * ( - 7.d0 / 3.d0 * xy - qy * &
(af * bfup / be-7.d0 / 3.d0) )
dh0dw = be * t * t * fz3 / s1 * ( - 7.d0 / 3.d0 * xy - qy * &
(af * bfdw / be-7.d0 / 3.d0) )
dh0zup = (3.d0 * h0 / fz - be * t * t * fz2 / s1 * (2.d0 * xy - &
qy * (3.d0 * af * expe * ec(1) / fz3 / be+2.d0) ) ) * dfz * (1.d0 - &
qy * (3.d0 * af * expe * ec / fz3 / be+2.d0) ) ) * dfz * (1.d0 - &
zeta)
dh0zdw = - (3.d0 * h0 / fz - be * t * t * fz3 / s1 * (2.d0 * xy - &
qy * (3.d0 * af * expe * ec(1) / fz3 / be+2.d0) ) ) * dfz * (1.d0 + &
qy * (3.d0 * af * expe * ec / fz3 / be+2.d0) ) ) * dfz * (1.d0 + &
zeta)
ddh0 = be * fz / (2.d0 * ks * ks * rho) * (xy - qy) / s1
ee = - 100.d0 * fz4 * (ks / kf * t) **2
cna = cxc0 + pa * rs(1) + pb * rs2
dcna = pa * rs(1) + 2.d0 * pb * rs2
cnb = 1.d0 + pc * rs(1) + pd * rs2 + 1.d4 * pb * rs3
dcnb = pc * rs(1) + 2.d0 * pd * rs2 + 3.d4 * pb * rs3
cna = cxc0 + pa * rs + pb * rs2
dcna = pa * rs + 2.d0 * pb * rs2
cnb = 1.d0 + pc * rs + pd * rs2 + 1.d4 * pb * rs3
dcnb = pc * rs + 2.d0 * pd * rs2 + 3.d4 * pb * rs3
cn = cna / cnb - cx
dcn = dcna / cnb - cna * dcnb / (cnb * cnb)
h1 = nu * (cn - cc0 - 3.d0 / 7.d0 * cx) * fz3 * t * t * exp (ee)
h1 = nu * (cn - cc0 - 3.d0 / 7.d0 * cx) * fz3 * t * t * exp(ee)
dh1 = - third * (h1 * (7.d0 + 8.d0 * ee) + fz3 * nu * t * t * exp &
(ee) * dcn)
ddh1 = 2.d0 * h1 * (1.d0 + ee) * rho / grho
@ -192,9 +189,8 @@ subroutine pbec_spin (rho, zeta, grho, iflag, sc, v1cup, v1cdw, v2c)
integer, intent(in) :: iflag
real(DP) :: rho, zeta, grho, sc, v1cup, v1cdw, v2c
!
integer, parameter :: length=1 !^^^PROVISIONAL
real(dp), dimension(length) :: rs , zeta_v, ec
real(dp), dimension(length,2) :: vc
real(dp) :: rs, ec
real(dp) :: vc(2)
!
real(DP) :: ga, be(2)
parameter (ga = 0.031091d0)
@ -208,12 +204,11 @@ subroutine pbec_spin (rho, zeta, grho, iflag, sc, v1cup, v1cdw, v2c)
real(DP) :: fz, fz2, fz3, fz4, dfz, bfup, bfdw, dh0up, dh0dw, &
dh0zup, dh0zdw
!
rs(1) = pi34 / rho**third
zeta_v(1) = zeta
rs = pi34 / rho**third
!
call pw_spin( length, rs, zeta_v, ec, vc )
call pw_spin( rs, zeta, ec, vc )
!
kf = xkf / rs(1)
kf = xkf / rs
ks = xks * sqrt(kf)
fz = 0.5d0 * ( (1.d0 + zeta) ** (2.d0 / 3.d0) + (1.d0 - zeta) ** ( &
2.d0 / 3.d0) )
@ -223,10 +218,10 @@ subroutine pbec_spin (rho, zeta, grho, iflag, sc, v1cup, v1cdw, v2c)
dfz = ( (1.d0 + zeta) ** ( - 1.d0 / 3.d0) - (1.d0 - zeta) ** ( - &
1.d0 / 3.d0) ) / 3.d0
t = sqrt(grho) / (2.d0 * fz * ks * rho)
expe = exp( - ec(1) / (fz3 * ga) )
expe = exp( - ec / (fz3 * ga) )
af = be(iflag) / ga * (1.d0 / (expe-1.d0) )
bfup = expe * (vc(1,1) - ec(1)) / fz3
bfdw = expe * (vc(1,2) - ec(1)) / fz3
bfup = expe * (vc(1) - ec) / fz3
bfdw = expe * (vc(2) - ec) / fz3
y = af * t * t
xy = (1.d0 + y) / (1.d0 + y + y * y)
qy = y * y * (2.d0 + y) / (1.d0 + y + y * y) **2
@ -237,10 +232,10 @@ subroutine pbec_spin (rho, zeta, grho, iflag, sc, v1cup, v1cdw, v2c)
dh0dw = be(iflag) * t * t * fz3 / s1 * ( - 7.d0 / 3.d0 * xy - qy * &
(af * bfdw / be(iflag)-7.d0 / 3.d0) )
dh0zup = (3.d0 * h0 / fz - be(iflag) * t * t * fz2 / s1 * (2.d0 * xy - &
qy * (3.d0 * af * expe * ec(1) / fz3 / be(iflag)+2.d0) ) ) * dfz * (1.d0 - zeta)
qy * (3.d0 * af * expe * ec / fz3 / be(iflag)+2.d0) ) ) * dfz * (1.d0 - zeta)
dh0zdw = - (3.d0 * h0 / fz - be(iflag) * t * t * fz2 / s1 * (2.d0 * xy - &
qy * (3.d0 * af * expe * ec(1) / fz3 / be(iflag)+2.d0) ) ) * dfz * (1.d0 + zeta)
qy * (3.d0 * af * expe * ec / fz3 / be(iflag)+2.d0) ) ) * dfz * (1.d0 + zeta)
!
ddh0 = be(iflag) * fz / (2.d0 * ks * ks * rho) * (xy - qy) / s1
sc = rho * h0
v1cup = h0 + dh0up + dh0zup
@ -249,44 +244,3 @@ subroutine pbec_spin (rho, zeta, grho, iflag, sc, v1cup, v1cdw, v2c)
return
end subroutine pbec_spin
!
!-----------------------------------------------------------------------
function dpz_polarized (rs, iflg)
!-----------------------------------------------------------------------
! derivative of the correlation potential with respect to local density
! Perdew and Zunger parameterization of the Ceperley-Alder functional
! spin-polarized case
!
USE kinds, only : DP
USE constants, ONLY : pi, fpi
!
implicit none
!
real(DP), intent (in) :: rs
integer, intent(in) :: iflg
real(DP) :: dpz_polarized
!
! local variables
! a,b,c,d,gc,b1,b2 are the parameters defining the functional
!
real(DP), parameter :: a = 0.01555d0, b = -0.0269d0, c = 0.0007d0, &
d = -0.0048d0, gc = -0.0843d0, b1 = 1.3981d0, b2 = 0.2611d0,&
a1 = 7.0d0 * b1 / 6.d0, a2 = 4.d0 * b2 / 3.d0
real(DP) :: x, den, dmx, dmrs
!
!
if (iflg == 1) then
dmrs = a / rs + 2.d0 / 3.d0 * c * (log (rs) + 1.d0) + &
(2.d0 * d-c) / 3.d0
else
x = sqrt (rs)
den = 1.d0 + x * (b1 + x * b2)
dmx = gc * ( (a1 + 2.d0 * a2 * x) * den - 2.d0 * (b1 + 2.d0 * &
b2 * x) * (1.d0 + x * (a1 + x * a2) ) ) / den**3
dmrs = 0.5d0 * dmx / x
endif
!
dpz_polarized = - fpi * rs**4.d0 / 9.d0 * dmrs
return
!
end function dpz_polarized

View File

@ -119,8 +119,7 @@ subroutine metax(rho,grho2,tau,ex,v1x,v2x,v3x)
! OUTPUT
real(DP) :: ex,v1x,v2x,v3x
! LOCAL
integer, parameter :: length=1 !^^^ PROVISIONAL
real(DP), dimension(length) :: rs, vx_unif, ex_unif
real(DP) :: rs, vx_unif, ex_unif
! ex_unif: lda \epsilon_x(rho)
! ec_unif: lda \epsilon_c(rho)
real(DP) :: small, pi34, third
@ -139,11 +138,11 @@ subroutine metax(rho,grho2,tau,ex,v1x,v2x,v3x)
v3x=0.0_DP
return
endif
rs(1) = pi34/rho**third
call slater( length, rs, ex_unif, vx_unif )
rs = pi34/rho**third
call slater( rs, ex_unif, vx_unif )
call metaFX(rho,grho2,tau,fx,f1x,f2x,f3x)
ex =rho*ex_unif(1)
v1x=vx_unif(1)*fx + ex*f1x
ex =rho*ex_unif
v1x=vx_unif*fx + ex*f1x
v2x=ex*f2x
v3x=ex*f3x
ex =ex*fx
@ -172,10 +171,9 @@ subroutine metac(rho,grho2,tau,ec,v1c,v2c,v3c)
real(DP) :: v1c_pbe, v2c_pbe, ec_pbe
real(DP) :: v1c_sum, v2c_sum, ec_sum
!
integer, parameter :: length=1 !^^^ PROVISIONAL
real(DP), dimension(length) :: rs, zeta
real(DP), dimension(length) :: ec_unif, vc_unif
real(DP), dimension(length,2) :: vc_unif_s
real(DP) :: rs, zeta
real(DP) :: ec_unif, vc_unif
real(DP) :: vc_unif_s(2)
!
real(DP) :: dd,cab,cabone
real(DP) :: rhoup,grhoup,dummy
@ -197,10 +195,9 @@ subroutine metac(rho,grho2,tau,ec,v1c,v2c,v3c)
grhoup=0.5_DP*SQRT(grho2)
if(rhoup.gt.small) then
!
rs(1)=(pi34/rhoup)**third
zeta(1)=1.0_DP
call pw_spin( length, rs, zeta, ec_unif, vc_unif_s )
dummy = vc_unif_s(1,2)
rs=(pi34/rhoup)**third
call pw_spin( rs, 1.0_DP, ec_unif, vc_unif_s )
dummy = vc_unif_s(2)
!
if(abs(grhoup).gt.small) then
!1.0_DP-small to avoid pow_e of 0 in pbec_spin
@ -211,8 +208,8 @@ subroutine metac(rho,grho2,tau,ec,v1c,v2c,v3c)
v1c_sum=0.0_DP
v2c_sum=0.0_DP
endif
ec_sum = ec_sum/rhoup + ec_unif(1)
v1c_sum = (v1c_sum + vc_unif_s(1,1)-ec_sum)/rho !rho, not rhoup
ec_sum = ec_sum/rhoup + ec_unif
v1c_sum = (v1c_sum + vc_unif_s(1)-ec_sum)/rho !rho, not rhoup
v2c_sum = v2c_sum/(2.0_DP*rho)
else
ec_sum=0.0_DP
@ -220,16 +217,16 @@ subroutine metac(rho,grho2,tau,ec,v1c,v2c,v3c)
v2c_sum=0.0_DP
endif
!
rs(1) = (pi34/rho)**third
call pw( length, rs, 1, ec_unif, vc_unif )
rs = (pi34/rho)**third
call pw( rs, 1, ec_unif, vc_unif )
!
! PBE correlation energy and potential
! ec_pbe=rho*H, not rho*(epsion_c_uinf + H)
! v1c_pbe=D (rho*H) /D rho
! v2c_pbe= for rho, 2 for
call pbec(rho,grho2,1,ec_pbe,v1c_pbe,v2c_pbe)
ec_pbe=ec_pbe/rho+ec_unif(1)
v1c_pbe=(v1c_pbe+vc_unif(1)-ec_pbe)/rho
ec_pbe=ec_pbe/rho+ec_unif
v1c_pbe=(v1c_pbe+vc_unif-ec_pbe)/rho
v2c_pbe=v2c_pbe/rho
!
if(ec_sum .lt. ec_pbe) then
@ -499,9 +496,8 @@ subroutine metac_spin(rho,zeta,grhoup,grhodw, &
real(DP) :: rhoup, rhodw,tauw,grhovec(3),grho2,grho,&
grhoup2,grhodw2
!
integer, parameter :: length=1 !^^^ PROVISIONAL
real(DP), dimension(length) :: rs, zeta_v, ec_u
real(DP), dimension(length,2) :: vc_u
real(DP) :: rs, zeta_v, ec_u
real(DP) :: vc_u(2)
!
!grhovec vector gradient of rho
!grho mod of gradient of rho
@ -545,9 +541,8 @@ subroutine metac_spin(rho,zeta,grhoup,grhodw, &
if(rho > small) then
v2_tmp=0.0_DP
!
rs(1) = (pi34/rho)**third
zeta_v(1) = zeta
call pw_spin( length, rs, zeta_v, ec_u, vc_u )
rs = (pi34/rho)**third
call pw_spin( rs, zeta, ec_u, vc_u )
!
if((abs(grho) > small) .and. (zeta <= 1.0_DP)) then
call pbec_spin(rho,zeta,grho2,1,&
@ -558,10 +553,10 @@ subroutine metac_spin(rho,zeta,grhoup,grhodw, &
v1dw_pbe=0.0_DP
v2up_pbe=0.0_DP
endif
ec_pbe = ec_pbe/rho+ec_u(1)
ec_pbe = ec_pbe/rho+ec_u
! v1xx_pbe = D_epsilon_c/ D_rho_xx :xx= up, dw
v1up_pbe = (v1up_pbe+vc_u(1,1)-ec_pbe)/rho
v1dw_pbe = (v1dw_pbe+vc_u(1,2)-ec_pbe)/rho
v1up_pbe = (v1up_pbe+vc_u(1)-ec_pbe)/rho
v1dw_pbe = (v1dw_pbe+vc_u(2)-ec_pbe)/rho
! v2xx_pbe = (D_Ec / D grho)/rho = (D_Ec/ D |grho| /|grho|)*grho/rho
v2up_pbe = v2_tmp/rho*grhovec
! v2dw === v2up for PBE
@ -578,8 +573,7 @@ subroutine metac_spin(rho,zeta,grhoup,grhodw, &
v2_tmp=0.0_DP
!
rs = (pi34/rhoup)**third
zeta_v(1) = 1.0_DP
call pw_spin( length, rs, zeta_v, ec_u, vc_u )
call pw_spin( rs, 1.0_DP, ec_u, vc_u )
!
if(sqrt(grhoup2) > small) then
call pbec_spin(rhoup,1.0_DP-small,grhoup2,1,&
@ -589,8 +583,8 @@ subroutine metac_spin(rho,zeta,grhoup,grhodw, &
v1up_0=0.0_DP
v2up_0=0.0_DP
endif
ecup_0 = ecup_0/rhoup + ec_u(1)
v1up_0 = (v1up_0 + vc_u(1,1)-ecup_0)/rhoup
ecup_0 = ecup_0/rhoup + ec_u
v1up_0 = (v1up_0 + vc_u(1)-ecup_0)/rhoup
v2up_0 = v2_tmp/rhoup*grhoup
else
ecup_0 = 0.0_DP
@ -616,9 +610,8 @@ subroutine metac_spin(rho,zeta,grhoup,grhodw, &
if(rhodw > small) then
v2_tmp=0.0_DP
!
rs(1) = (pi34/rhodw)**third
zeta_v(1) = -1.0_DP
call pw_spin( length, rs, zeta_v, ec_u, vc_u )
rs = (pi34/rhodw)**third
call pw_spin( rs, -1.0_DP, ec_u, vc_u )
!
if(sqrt(grhodw2) > small) then
call pbec_spin(rhodw,-1.0_DP+small,grhodw2,1,&
@ -628,8 +621,8 @@ subroutine metac_spin(rho,zeta,grhoup,grhodw, &
v1dw_0=0.0_DP
v2dw_0=0.0_DP
endif
ecdw_0 = ecdw_0/rhodw + ec_u(1)
v1dw_0 = (v1dw_0 + vc_u(1,2)-ecdw_0)/rhodw
ecdw_0 = ecdw_0/rhodw + ec_u
v1dw_0 = (v1dw_0 + vc_u(2)-ecdw_0)/rhodw
v2dw_0 = v2_tmp/rhodw*grhodw
else
ecdw_0 = 0.0_DP
@ -1110,12 +1103,11 @@ subroutine m06lc(rhoa, rhob, grho2a, grho2b, taua, taub, ec, v1c_up, v2c_up, v3c
implicit none
!-------------------------------------------------------------------------
real(dp), intent(in) :: rhoa, rhob, grho2a, grho2b, taua, taub
real(dp), intent(out) :: ec, v1c_up, v2c_up, v3c_up, v1c_dw, v2c_dw, v3c_dw
real(dp), intent(in) :: rhoa, rhob, grho2a, grho2b, taua, taub
real(dp), intent(out) :: ec, v1c_up, v2c_up, v3c_up, v1c_dw, v2c_dw, v3c_dw
!
integer, parameter :: length=1 !^^^ PROVISIONAL (xc-lib)
real(DP), dimension(length) :: rs, zeta
real(DP), dimension(length,2) :: vc_v
real(DP) :: rs, zeta
real(DP) :: vc_v(2)
!
!
real(dp), parameter :: zero = 0._dp, one = 1.0_dp, two=2.0_dp, three = 3.0_dp, &
@ -1136,7 +1128,7 @@ subroutine m06lc(rhoa, rhob, grho2a, grho2b, taua, taub, ec, v1c_up, v2c_up, v3c
!
! functions and variables
!
real(dp),dimension(length) :: ec_pw_a, ec_pw_b, ec_pw_ab
real(dp) :: ec_pw_a, ec_pw_b, ec_pw_ab
!
real(dp) :: vv, vc_pw_a, vc_pw_b, vc_pw_ab, vc_pw_up, vc_pw_dw, Ecaa, Ecbb, Ecab, &
& Ec_UEG_ab, Ec_UEG_aa, Ec_UEG_bb, decab_drhoa, decab_drhob, &
@ -1224,16 +1216,16 @@ subroutine m06lc(rhoa, rhob, grho2a, grho2b, taua, taub, ec, v1c_up, v2c_up, v3c
ec_pw_a = zero
vc_pw_a = zero
!
rs(1) = rsa
zeta(1) = one
call pw_spin( length, rs, zeta, ec_pw_a, vc_v )
vc_pw_a = vc_v(1,1)
vv = vc_v(1,2)
rs = rsa
zeta = one
call pw_spin( rs, zeta, ec_pw_a, vc_v )
vc_pw_a = vc_v(1)
vv = vc_v(2)
!
call gvt4 (xs2a, zsa, ds0, ds1, ds2, ds3, ds4, ds5, alpha_s, hga, dhga_dxs2a, dhga_dzsa)
call gfunc (cs, gama_s, xs2a, gsa, dgsa_dxs2a)
!
Ec_UEG_aa = rhoa*ec_pw_a(1)
Ec_UEG_aa = rhoa*ec_pw_a
num = (dgsa_dxs2a + dhga_dxs2a)*Dsa + (gsa + hga)*dDsa_dxs2a
!
!
@ -1276,16 +1268,16 @@ subroutine m06lc(rhoa, rhob, grho2a, grho2b, taua, taub, ec, v1c_up, v2c_up, v3c
dDsb_dxs2b = - one/(four * (zsb + CF))
dDsb_dzsb = xs2b/(four * (zsb + CF)**2)
!
rs(1) = rsb
zeta(1) = one
call pw_spin( length, rs, zeta, ec_pw_b, vc_v )
vc_pw_b = vc_v(1,1)
vv = vc_v(1,2)
zeta = one
rs = rsb
call pw_spin( rs, zeta, ec_pw_b, vc_v )
vc_pw_b = vc_v(1)
vv = vc_v(2)
!
call gvt4 (xs2b, zsb, ds0, ds1, ds2, ds3, ds4, ds5, alpha_s, hgb, dhgb_dxs2b, dhgb_dzsb)
call gfunc (cs, gama_s, xs2b, gsb, dgsb_dxs2b)
Ec_UEG_bb = rhob*ec_pw_b(1)
Ec_UEG_bb = rhob*ec_pw_b
num = (dgsb_dxs2b + dhgb_dxs2b)*Dsb + (gsb + hgb)*dDsb_dxs2b
!
!
@ -1318,20 +1310,20 @@ subroutine m06lc(rhoa, rhob, grho2a, grho2b, taua, taub, ec, v1c_up, v2c_up, v3c
xs2ab = xs2a + xs2b
zsab = zsa + zsb
rho = rhoa + rhob
zeta(1) = (rhoa - rhob)/rho
rs(1) = (pi34/rho)**f13
zeta = (rhoa - rhob)/rho
rs = (pi34/rho)**f13
call gvt4(xs2ab, zsab, dab0, dab1, dab2, dab3, dab4, dab5, alpha_ab, hgab, dhgab_dxs2ab, dhgab_dzsab)
!
call pw_spin( length, rs, zeta, ec_pw_ab, vc_v )
vc_pw_up = vc_v(1,1) ; vc_pw_dw=vc_v(1,2)
call pw_spin( rs, zeta, ec_pw_ab, vc_v )
vc_pw_up = vc_v(1) ; vc_pw_dw=vc_v(2)
!
call gfunc(cab, gama_ab, xs2ab, gsab, dgsab_dxs2ab)
!
decab_drhoa = vc_pw_up - vc_pw_a
decab_drhob = vc_pw_dw - vc_pw_b
Ec_UEG_ab = ec_pw_ab(1)*rho - ec_pw_a(1)*rhoa - ec_pw_b(1)*rhob
Ec_UEG_ab = ec_pw_ab*rho - ec_pw_a*rhoa - ec_pw_b*rhob
!
!
Ecab = Ec_UEG_ab * (gsab + hgab)

View File

@ -16,12 +16,16 @@ PRIVATE
SAVE
!
! LDA and LSDA exchange-correlation drivers
PUBLIC :: xc, xc_spin, select_functionals
PUBLIC :: xc, xc_lda, xc_lsda, select_lda_functionals
!
PUBLIC :: libxc_switches
PUBLIC :: iexch_l, icorr_l
PUBLIC :: exx_started_l, exx_fraction_l
PUBLIC :: is_there_finite_size_corr, finite_size_cell_volume_l
!
! use qe or libxc for the different terms (0: qe, 1: libxc)
INTEGER :: libxc_switches(2)
!
! indexes defining xc functionals
INTEGER :: iexch_l, icorr_l
!
@ -36,7 +40,7 @@ REAL(DP) :: exx_fraction_l, finite_size_cell_volume_l
!----------------------------------------------------------------------------
!----- Select functionals by the corresponding indexes ----------------------
!----------------------------------------------------------------------------
SUBROUTINE select_functionals( iexch, icorr, exx_fraction, finite_size_cell_volume )
SUBROUTINE select_lda_functionals( iexch, icorr, exx_fraction, finite_size_cell_volume )
!
IMPLICIT NONE
!
@ -48,409 +52,632 @@ SUBROUTINE select_functionals( iexch, icorr, exx_fraction, finite_size_cell_volu
icorr_l = icorr
!
! hybrid exchange vars
exx_started_l = .false.
exx_started_l = .FALSE.
exx_fraction_l = 0._DP
IF ( present(exx_fraction) ) THEN
exx_started_l = .true.
IF ( PRESENT(exx_fraction) ) THEN
exx_started_l = .TRUE.
exx_fraction_l = exx_fraction
ENDIF
!
! finite size correction vars
is_there_finite_size_corr = .false.
is_there_finite_size_corr = .FALSE.
finite_size_cell_volume_l = -1.0_DP
IF ( present(finite_size_cell_volume) ) THEN
is_there_finite_size_corr = .true.
IF ( PRESENT(finite_size_cell_volume) ) THEN
is_there_finite_size_corr = .TRUE.
finite_size_cell_volume_l = finite_size_cell_volume
ENDIF
!
!
RETURN
!
END SUBROUTINE
END SUBROUTINE select_lda_functionals
!
!
!----------------------------------------------------------------------------
!------- LDA-LSDA DRIVERS --------------------------------------------------
!----------------------------------------------------------------------------
!
!----------------------------------------------------------------------------
SUBROUTINE xc( length, rho, ex, ec, vx, vc )
!--------------------------------------------------------------------------
! lda exchange and correlation functionals - Hartree a.u.
!---------------------------------------------------------------------
SUBROUTINE xc( length, sr_d, sv_d, rho_in, ex_out, ec_out, vx_out, vc_out )
!---------------------------------------------------------------------
!! Wrapper routine. Calls xc-driver routines from internal libraries
!! of q-e or from the external libxc, depending on the input choice.
!
! exchange : Slater, relativistic Slater
! correlation: Ceperley-Alder (Perdew-Zunger parameters)
! Vosko-Wilk-Nusair
! Lee-Yang-Parr
! Perdew-Wang
! Wigner
! Hedin-Lundqvist
! Ortiz-Ballone (Perdew-Zunger formula)
! Ortiz-Ballone (Perdew-Wang formula)
! Gunnarsson-Lundqvist
!
! input : rho=rho(r)
! definitions: E_x = \int E_x(rho) dr, E_x(rho) = rho\epsilon_c(rho)
! same for correlation
! output: ex = \epsilon_x(rho) ( NOT E_x(rho) )
! vx = dE_x(rho)/drho ( NOT d\epsilon_x(rho)/drho )
! ec, vc as above for correlation
!! NOTE: look at 'PP/src/benchmark_libxc.f90' to see the differences
!! between q-e and libxc.
!
#if defined(__LIBXC)
USE xc_f90_types_m
USE xc_f90_lib_m
#endif
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: length
REAL(DP), INTENT(IN), DIMENSION(length) :: rho
REAL(DP), INTENT(OUT), DIMENSION(length) :: ec, vc, ex, vx
!! length of the I/O arrays
INTEGER, INTENT(IN) :: sr_d
!! spin dimension of rho
INTEGER, INTENT(IN) :: sv_d
!! spin dimension of v
REAL(DP), INTENT(IN) :: rho_in(length,sr_d)
!! Charge density
REAL(DP), INTENT(OUT) :: ex_out(length)
!! \(\epsilon_x(rho)\) ( NOT \(E_x(\text{rho})\) )
REAL(DP), INTENT(OUT) :: vx_out(length,sv_d)
!! \(dE_x(\text{rho})/d\text{rho} ( NOT d\epsilon_x(\text{rho})/d\text{rho} )
REAL(DP), INTENT(OUT) :: ec_out(length)
!! \(\epsilon_c(rho)\) ( NOT \(E_c(\text{rho})\) )
REAL(DP), INTENT(OUT) :: vc_out(length,sv_d)
!! \(dE_c(\text{rho})/d\text{rho} ( NOT d\epsilon_c(\text{rho})/d\text{rho} )
!
! local vars
! ... local variables
!
REAL(DP), ALLOCATABLE, DIMENSION(:) :: ec_, vc_
REAL(DP), PARAMETER :: small = 1.E-10_DP, third = 1.0_DP / 3.0_DP, &
pi34 = 0.6203504908994_DP ! pi34=(3/4pi)^(1/3)
REAL(DP) :: rs(length)
#if defined(__LIBXC)
TYPE(xc_f90_pointer_t) :: xc_func
TYPE(xc_f90_pointer_t) :: xc_info1, xc_info2
REAL(DP) :: amag
REAL(DP), ALLOCATABLE :: rho_lxc(:)
REAL(DP), ALLOCATABLE :: vx_lxc(:), vc_lxc(:)
#endif
!
REAL(DP), ALLOCATABLE :: arho(:), zeta(:)
!
INTEGER :: ir
REAL(DP), PARAMETER :: small = 1.E-10_DP
!
!
WHERE ( rho > small )
rs = pi34 / rho**third
ELSEWHERE
rs = 1.0_DP
END WHERE
#if defined(__LIBXC)
!
IF ( icorr_l >= 12 .AND. icorr_l <= 14 ) THEN
ALLOCATE( ec_(length) )
ALLOCATE( vc_(length) )
IF (SUM(libxc_switches) /= 0) THEN
!
ALLOCATE( rho_lxc(length*sv_d) )
ALLOCATE( vx_lxc(length*sv_d), vc_lxc(length*sv_d) )
!
! ... set libxc input
SELECT CASE( sr_d )
CASE( 1 )
!
rho_lxc(:) = rho_in(:,1)
!
CASE( 2 )
!
DO ir = 1, length
rho_lxc(2*ir-1) = (rho_in(ir,1) + rho_in(ir,2)) * 0.5_DP
rho_lxc(2*ir) = (rho_in(ir,1) - rho_in(ir,2)) * 0.5_DP
ENDDO
!
CASE( 4 )
!
DO ir = 1, length
amag = SQRT( SUM(rho_in(ir,2:4)**2) )
rho_lxc(2*ir-1) = (rho_in(ir,1) + amag) * 0.5_DP
rho_lxc(2*ir) = (rho_in(ir,1) - amag) * 0.5_DP
ENDDO
!
CASE DEFAULT
!
CALL errore( 'xc_LDA', 'Wrong number of spin dimensions', 1 )
!
END SELECT
!
ENDIF
!
!
! ... EXCHANGE
!
SELECT CASE( iexch_l )
CASE( 1 ) ! 'sla'
!
CALL slater( length, rs, ex, vx )
!
CASE( 2 ) ! 'sl1'
!
CALL slater1( length, rs, ex, vx )
!
CASE( 3 ) ! 'rxc'
!
CALL slater_rxc( length, rs, ex, vx )
!
CASE( 4, 5 ) ! 'oep','hf'
!
IF ( exx_started_l ) THEN
ex = 0.0_DP
vx = 0.0_DP
ELSE
CALL slater( length, rs, ex, vx )
ENDIF
!
CASE( 6, 7 ) ! 'pb0x' or 'DF-cx-0', or 'DF2-0',
! ! 'B3LYP'
CALL slater( length, rs, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE( 8 ) ! 'sla+kzk'
!
IF (.NOT. is_there_finite_size_corr) CALL errore ('XC',&
'finite size corrected exchange used w/o initialization',1)
CALL slaterKZK( length, rs, ex, vx, finite_size_cell_volume_l )
!
CASE( 9 ) ! 'X3LYP'
!
CALL slater( length, rs, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE DEFAULT
!
ex = 0.0_DP
vx = 0.0_DP
!
END SELECT
!
IF ( libxc_switches(1)==1 ) THEN
CALL xc_f90_func_init( xc_func, xc_info1, iexch_l, sv_d )
CALL xc_f90_lda_exc_vxc( xc_func, length, rho_lxc(1), ex_out(1), vx_lxc(1) )
CALL xc_f90_func_end( xc_func )
ENDIF
!
! ... CORRELATION
IF ( libxc_switches(2)==1 ) THEN
CALL xc_f90_func_init( xc_func, xc_info2, icorr_l, sv_d )
CALL xc_f90_lda_exc_vxc( xc_func, length, rho_lxc(1), ec_out(1), vc_lxc(1) )
CALL xc_f90_func_end( xc_func )
ENDIF
!
SELECT CASE( icorr_l )
!
IF ( (libxc_switches(1)==0) .OR. (libxc_switches(2)==0) ) THEN
!
SELECT CASE( sr_d )
CASE( 1 )
!
CALL xc_lda( length, ABS(rho_in(:,1)), ex_out, ec_out, vx_out(:,1), vc_out(:,1) )
!
CASE( 2 )
!
ALLOCATE( arho(length), zeta(length) )
arho = ABS(rho_in(:,1))
WHERE (arho > small) zeta(:) = rho_in(:,2) / arho(:)
CALL xc_lsda( length, arho, zeta, ex_out, ec_out, vx_out, vc_out )
DEALLOCATE( arho, zeta )
!
CASE( 4 )
!
ALLOCATE( arho(length), zeta(length) )
arho = ABS( rho_in(:,1) )
WHERE (arho > small) zeta(:) = SQRT( rho_in(:,2)**2 + rho_in(:,3)**2 + &
rho_in(:,4)**2 ) / arho(:) ! amag/arho
CALL xc_lsda( length, arho, zeta, ex_out, ec_out, vx_out, vc_out )
DEALLOCATE( arho, zeta )
!
CASE DEFAULT
!
CALL errore( 'xc_LDA', 'Wrong ns input', 2 )
!
END SELECT
!
ENDIF
!
! ... fill output arrays
!
IF (sv_d == 1) THEN
IF (libxc_switches(1)==1) vx_out(:,1) = vx_lxc(:)
IF (libxc_switches(2)==1) vc_out(:,1) = vc_lxc(:)
ELSE
IF (libxc_switches(1)==1) THEN
DO ir = 1, length
vx_out(ir,1) = vx_lxc(2*ir-1)
vx_out(ir,2) = vx_lxc(2*ir)
ENDDO
ENDIF
IF (libxc_switches(2)==1) THEN
DO ir = 1, length
vc_out(ir,1) = vc_lxc(2*ir-1)
vc_out(ir,2) = vc_lxc(2*ir)
ENDDO
ENDIF
ENDIF
!
IF (SUM(libxc_switches) /= 0) THEN
DEALLOCATE( rho_lxc )
DEALLOCATE( vx_lxc, vc_lxc )
ENDIF
!
#else
!
SELECT CASE( sr_d )
CASE( 1 )
!
CALL pz( length, rs, 1, ec, vc )
CALL xc_lda( length, ABS(rho_in(:,1)), ex_out, ec_out, vx_out(:,1), vc_out(:,1) )
!
CASE( 2 )
!
CALL vwn( length, rs, ec, vc )
ALLOCATE( arho(length), zeta(length) )
!
CASE( 3 )
arho = ABS(rho_in(:,1))
WHERE (arho > small) zeta(:) = rho_in(:,2) / arho(:)
!
CALL lyp( length, rs, ec, vc )
CALL xc_lsda( length, arho, zeta, ex_out, ec_out, vx_out, vc_out )
!
DEALLOCATE( arho, zeta )
!
CASE( 4 )
!
CALL pw( length, rs, 1, ec, vc )
ALLOCATE( arho(length), zeta(length) )
!
CASE( 5 )
arho = ABS( rho_in(:,1) )
WHERE (arho > small) zeta(:) = SQRT( rho_in(:,2)**2 + rho_in(:,3)**2 + &
rho_in(:,4)**2 ) / arho(:) ! amag/arho
!
CALL wignerc( length, rs, ec, vc )
CALL xc_lsda( length, arho, zeta, ex_out, ec_out, vx_out, vc_out )
!
CASE( 6 )
!
CALL hl( length, rs, ec, vc )
!
CASE( 7 )
!
CALL pz( length, rs, 2, ec, vc )
!
CASE( 8 )
!
CALL pw( length, rs, 2, ec, vc )
!
CASE( 9 )
!
CALL gl( length, rs, ec, vc )
!
CASE( 10 )
!
IF (.NOT. is_there_finite_size_corr) CALL errore ('XC',&
'finite size corrected exchange used w/o initialization',2)
CALL pzKZK ( length, rs, ec, vc, finite_size_cell_volume_l )
!
CASE( 11 )
!
CALL vwn1_rpa( length, rs, ec, vc )
!
CASE( 12 ) ! 'B3LYP'
!
CALL vwn( length, rs, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lyp( length, rs, ec_, vc_ )
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 13 ) ! 'B3LYP-V1R'
!
CALL vwn1_rpa ( length, rs, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lyp( length, rs, ec_, vc_ )
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 14 ) ! 'X3LYP'
!
CALL vwn1_rpa( length, rs, ec, vc )
ec = 0.129_DP * ec
vc = 0.129_DP * vc
!
CALL lyp( length, rs, ec_, vc_ )
ec = ec + 0.871_DP * ec_
vc = vc + 0.871_DP * vc_
DEALLOCATE( arho, zeta )
!
CASE DEFAULT
!
ec = 0.0_DP
vc = 0.0_DP
CALL errore( 'xc_LDA', 'Wrong ns input', 2 )
!
END SELECT
!
!
WHERE ( rho <= small )
ex = 0.0_DP
ec = 0.0_DP
vx = 0.0_DP
vc = 0.0_DP
END WHERE
!
IF ( icorr_l >= 12 .AND. icorr_l <= 14 ) THEN
DEALLOCATE( ec_ )
DEALLOCATE( vc_ )
ENDIF
#endif
!
!
RETURN
!
END SUBROUTINE xc
!
!----------------------------------------------------------------------------
!------- LDA-LSDA DRIVERS --------------------------------------------------
!----------------------------------------------------------------------------
!
!
SUBROUTINE xc_spin( length, rho, zeta, ex, ec, vx, vc )
!---------------------------------------------------------------------
! lsd exchange and correlation functionals - Hartree a.u.
!----------------------------------------------------------------------------
SUBROUTINE xc_lda( length, rho_in, ex_out, ec_out, vx_out, vc_out )
!--------------------------------------------------------------------------
!! LDA exchange and correlation functionals - Hartree a.u.
!
! exchange : Slater (alpha=2/3)
! correlation: Ceperley & Alder (Perdew-Zunger parameters)
! Perdew & Wang
!! * Exchange:
!! * Slater;
!! * relativistic Slater.
!! * Correlation:
!! * Ceperley-Alder (Perdew-Zunger parameters);
!! * Vosko-Wilk-Nusair;
!! * Lee-Yang-Parr;
!! * Perdew-Wang;
!! * Wigner;
!! * Hedin-Lundqvist;
!! * Ortiz-Ballone (Perdew-Zunger formula);
!! * Ortiz-Ballone (Perdew-Wang formula);
!! * Gunnarsson-Lundqvist.
!
! input : rho = rhoup(r)+rhodw(r)
! zeta=(rhoup(r)-rhodw(r))/rho
!! NOTE:
!! $$ E_x = \int E_x(\text{rho}) dr, E_x(\text{rho}) =
!! \text{rho}\epsilon_c(\text{rho})\ . $$
!! Same for correlation.
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: length
REAL(DP), INTENT(IN), DIMENSION(length) :: rho, zeta
REAL(DP), INTENT(OUT), DIMENSION(length) :: ex, ec !^^^
REAL(DP), INTENT(OUT), DIMENSION(length,2) :: vx, vc
!! length of the I/O arrays
REAL(DP), INTENT(IN), DIMENSION(length) :: rho_in
!! Charge density
REAL(DP), INTENT(OUT), DIMENSION(length) :: ex_out
!! \(\epsilon_x(rho)\) ( NOT \(E_x(\text{rho})\) )
REAL(DP), INTENT(OUT), DIMENSION(length) :: vx_out
!! \(dE_x(\text{rho})/d\text{rho}\) ( NOT \(d\epsilon_x(\text{rho})/d\text{rho}\) )
REAL(DP), INTENT(OUT), DIMENSION(length) :: ec_out
!! \(\epsilon_c(rho)\) ( NOT \(E_c(\text{rho})\) )
REAL(DP), INTENT(OUT), DIMENSION(length) :: vc_out
!! \(dE_c(\text{rho})/d\text{rho}\) ( NOT \(d\epsilon_c(\text{rho})/d\text{rho}\) )
!
! local vars
REAL(DP), DIMENSION(length) :: rs
REAL(DP), ALLOCATABLE, DIMENSION(:) :: ec_
REAL(DP), ALLOCATABLE, DIMENSION(:,:) :: vc_
! ... local variables
!
REAL(DP), PARAMETER :: small= 1.E-10_DP, third = 1.0_DP/3.0_DP, &
pi34= 0.6203504908994_DP ! pi34=(3/4pi)^(1/3)
!
WHERE ( rho > small )
rs = pi34 / rho**third
ELSEWHERE
rs = 1.0_DP
END WHERE
!
IF ( icorr_l >= 12 .AND. icorr_l <= 14 ) THEN
ALLOCATE( ec_(length) )
ALLOCATE( vc_(length,2) )
ENDIF
INTEGER :: ir
REAL(DP) :: rho, rs
REAL(DP) :: ex, ec, ec_
REAL(DP) :: vx, vc, vc_
REAL(DP), PARAMETER :: small = 1.E-10_DP, third = 1.0_DP/3.0_DP, &
pi34 = 0.6203504908994_DP, e2 = 2.0_DP
! pi34 = (3/4pi)^(1/3)
!
!
! ... EXCHANGE
!
SELECT CASE( iexch_l )
CASE( 1 ) ! 'sla'
!$omp parallel do private( rho, rs, ex, ec, ec_, vx, vc, vc_ )
DO ir = 1, length
!
CALL slater_spin( length, rho, zeta, ex, vx )
rho = ABS(rho_in(ir))
!
CASE( 2 ) ! 'sl1'
! ... RHO THRESHOLD
!
CALL slater1_spin( length, rho, zeta, ex, vx )
IF ( rho > small ) THEN
rs = pi34 / rho**third
ELSE
ex_out(ir) = 0.0_DP ; ec_out(ir) = 0.0_DP
vx_out(ir) = 0.0_DP ; vc_out(ir) = 0.0_DP
CYCLE
ENDIF
!
CASE( 3 ) ! 'rxc'
! ... EXCHANGE
!
CALL slater_rxc_spin( length, rho, zeta, ex, vx )
!
CASE( 4, 5 ) ! 'oep','hf'
!
IF ( exx_started_l ) THEN
SELECT CASE( iexch_l )
CASE( 1 ) ! 'sla'
!
CALL slater( rs, ex, vx )
!
CASE( 2 ) ! 'sl1'
!
CALL slater1( rs, ex, vx )
!
CASE( 3 ) ! 'rxc'
!
CALL slater_rxc( rs, ex, vx )
!
CASE( 4, 5 ) ! 'oep','hf'
!
IF ( exx_started_l ) THEN
ex = 0.0_DP
vx = 0.0_DP
ELSE
CALL slater( rs, ex, vx )
ENDIF
!
CASE( 6, 7 ) ! 'pb0x' or 'DF-cx-0', or 'DF2-0',
! ! 'B3LYP'
CALL slater( rs, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE( 8 ) ! 'sla+kzk'
!
IF (.NOT. is_there_finite_size_corr) CALL errore( 'XC',&
'finite size corrected exchange used w/o initialization', 2 )
CALL slaterKZK( rs, ex, vx, finite_size_cell_volume_l )
!
CASE( 9 ) ! 'X3LYP'
!
CALL slater( rs, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE DEFAULT
!
ex = 0.0_DP
vx = 0.0_DP
ELSE
CALL slater_spin( length, rho, zeta, ex, vx )
ENDIF
!
END SELECT
!
CASE( 6 ) ! 'pb0x'
!
CALL slater_spin( length, rho, zeta, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
! ... CORRELATION
!
CASE( 7 ) ! 'B3LYP'
SELECT CASE( icorr_l )
CASE( 1 )
!
CALL pz( rs, 1, ec, vc )
!
CASE( 2 )
!
CALL vwn( rs, ec, vc )
!
CASE( 3 )
!
CALL lyp( rs, ec, vc )
!
CASE( 4 )
!
CALL pw( rs, 1, ec, vc )
!
CASE( 5 )
!
CALL wignerc( rs, ec, vc )
!
CASE( 6 )
!
CALL hl( rs, ec, vc )
!
CASE( 7 )
!
CALL pz( rs, 2, ec, vc )
!
CASE( 8 )
!
CALL pw( rs, 2, ec, vc )
!
CASE( 9 )
!
CALL gl( rs, ec, vc )
!
CASE( 10 )
!
IF (.NOT. is_there_finite_size_corr) CALL errore( 'XC',&
'finite size corrected exchange used w/o initialization', 3 )
CALL pzKZK( rs, ec, vc, finite_size_cell_volume_l )
!
CASE( 11 )
!
CALL vwn1_rpa( rs, ec, vc )
!
CASE( 12 ) ! 'B3LYP'
!
CALL vwn( rs, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lyp( rs, ec_, vc_ )
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 13 ) ! 'B3LYP-V1R'
!
CALL vwn1_rpa ( rs, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lyp( rs, ec_, vc_ )
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 14 ) ! 'X3LYP'
!
CALL vwn1_rpa( rs, ec, vc )
ec = 0.129_DP * ec
vc = 0.129_DP * vc
!
CALL lyp( rs, ec_, vc_ )
ec = ec + 0.871_DP * ec_
vc = vc + 0.871_DP * vc_
!
CASE DEFAULT
!
ec = 0.0_DP
vc = 0.0_DP
!
END SELECT
!
CALL slater_spin( length, rho, zeta, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
ex_out(ir) = ex ; ec_out(ir) = ec
vx_out(ir) = vx ; vc_out(ir) = vc
!
CASE( 9 ) ! 'X3LYP'
!
CALL slater_spin( length, rho, zeta, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE DEFAULT
!
ex = 0.0_DP
vx = 0.0_DP
!
END SELECT
!
!
! ... CORRELATION
!
SELECT CASE( icorr_l )
CASE( 0 )
!
ec = 0.0_DP
vc = 0.0_DP
!
CASE( 1 )
!
CALL pz_spin( length, rs, zeta, ec, vc )
!
CASE( 2 )
!
CALL vwn_spin( length, rs, zeta, ec, vc )
!
CASE( 3 )
!
CALL lsd_lyp( length, rho, zeta, ec, vc ) ! from CP/FPMD (more_functionals)
!
CASE( 4 )
!
CALL pw_spin( length, rs, zeta, ec, vc )
!
CASE( 12 ) ! 'B3LYP'
!
CALL vwn_spin( length, rs, zeta, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lsd_lyp( length, rho, zeta, ec_, vc_ ) ! from CP/FPMD (more_functionals)
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 13 ) ! 'B3LYP-V1R'
!
CALL vwn1_rpa_spin( length, rs, zeta, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lsd_lyp( length, rho, zeta, ec_, vc_ ) ! from CP/FPMD (more_functionals)
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 14 ) ! 'X3LYP
!
CALL vwn1_rpa_spin( length, rs, zeta, ec, vc )
ec = 0.129_DP * ec
vc = 0.129_DP * vc
!
CALL lsd_lyp( length, rho, zeta, ec_, vc_ ) ! from CP/FPMD (more_functionals)
ec = ec + 0.871_DP * ec_
vc = vc + 0.871_DP * vc_
!
CASE DEFAULT
!
CALL errore( 'lsda_functional (xc_spin)', 'not implemented', icorr_l )
!
END SELECT
!
!
WHERE ( rho <= small )
ex = 0.0_DP
ec = 0.0_DP
vx(:,1) = 0.0_DP
vx(:,2) = 0.0_DP
vc(:,1) = 0.0_DP
vc(:,2) = 0.0_DP
END WHERE
ENDDO
!$omp end parallel do
!
!
RETURN
!
END SUBROUTINE xc_spin
END SUBROUTINE xc_lda
!
!
!-----------------------------------------------------------------------------
SUBROUTINE xc_lsda( length, rho_in, zeta_in, ex_out, ec_out, vx_out, vc_out )
!-----------------------------------------------------------------------------
!! LSD exchange and correlation functionals - Hartree a.u.
!
!! * Exchange:
!! * Slater (alpha=2/3).
!! * Correlation:
!! * Ceperley & Alder (Perdew-Zunger parameters);
!! * Perdew & Wang.
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: length
!! length of the I/O arrays
REAL(DP), INTENT(IN), DIMENSION(length) :: rho_in
!! Total charge density
REAL(DP), INTENT(IN), DIMENSION(length) :: zeta_in
!! zeta = mag / rho_tot
REAL(DP), INTENT(OUT), DIMENSION(length) :: ex_out
!! \(\epsilon_x(rho)\) ( NOT \(E_x(\text{rho})\) )
REAL(DP), INTENT(OUT), DIMENSION(length) :: ec_out
!! \(\epsilon_c(rho)\) ( NOT \(E_c(\text{rho})\) )
REAL(DP), INTENT(OUT), DIMENSION(length,2) :: vx_out
!! \(dE_x(\text{rho})/d\text{rho}\) ( NOT \(d\epsilon_x(\text{rho})/d\text{rho}\) )
REAL(DP), INTENT(OUT), DIMENSION(length,2) :: vc_out
!! \(dE_c(\text{rho})/d\text{rho}\) ( NOT \(d\epsilon_c(\text{rho})/d\text{rho}\) )
!
! ... local variables
!
INTEGER :: ir
REAL(DP) :: rho, rs, zeta
REAL(DP) :: ex, ec, ec_
REAL(DP) :: vx(2), vc(2), vc_(2)
!
REAL(DP), PARAMETER :: small= 1.E-10_DP, third = 1.0_DP/3.0_DP, &
pi34 = 0.6203504908994_DP
! pi34 = (3/4pi)^(1/3)
!
!
!$omp parallel do private( rho, rs, zeta, ex, ec, ec_, vx, vc, vc_ )
DO ir = 1, length
!
zeta = zeta_in(ir)
IF (ABS(zeta) > 1.D0) zeta = SIGN( 1.D0, zeta )
!
rho = ABS(rho_in(ir))
!
IF ( rho > small ) THEN
rs = pi34 / rho**third
ELSE
ex_out(ir) = 0.0_DP ; vx_out(ir,:) = 0.0_DP
ec_out(ir) = 0.0_DP ; vc_out(ir,:) = 0.0_DP
CYCLE
ENDIF
!
!
! ... EXCHANGE
!
SELECT CASE( iexch_l )
CASE( 1 ) ! 'sla'
!
CALL slater_spin( rho, zeta, ex, vx )
!
CASE( 2 ) ! 'sl1'
!
CALL slater1_spin( rho, zeta, ex, vx )
!
CASE( 3 ) ! 'rxc'
!
CALL slater_rxc_spin( rho, zeta, ex, vx )
!
CASE( 4, 5 ) ! 'oep','hf'
!
IF ( exx_started_l ) THEN
ex = 0.0_DP
vx = 0.0_DP
ELSE
CALL slater_spin( rho, zeta, ex, vx )
ENDIF
!
CASE( 6 ) ! 'pb0x'
!
CALL slater_spin( rho, zeta, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE( 7 ) ! 'B3LYP'
!
CALL slater_spin( rho, zeta, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE( 9 ) ! 'X3LYP'
!
CALL slater_spin( rho, zeta, ex, vx )
IF ( exx_started_l ) THEN
ex = (1.0_DP - exx_fraction_l) * ex
vx = (1.0_DP - exx_fraction_l) * vx
ENDIF
!
CASE DEFAULT
!
ex = 0.0_DP
vx = 0.0_DP
!
END SELECT
!
!
! ... CORRELATION
!
SELECT CASE( icorr_l )
CASE( 0 )
!
ec = 0.0_DP
vc = 0.0_DP
!
CASE( 1 )
!
CALL pz_spin( rs, zeta, ec, vc )
!
CASE( 2 )
!
CALL vwn_spin( rs, zeta, ec, vc )
!
CASE( 3 )
!
CALL lsd_lyp( rho, zeta, ec, vc ) ! from CP/FPMD (more_functionals)
!
CASE( 4 )
!
CALL pw_spin( rs, zeta, ec, vc )
!
CASE( 12 ) ! 'B3LYP'
!
CALL vwn_spin( rs, zeta, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lsd_lyp( rho, zeta, ec_, vc_ ) ! from CP/FPMD (more_functionals)
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 13 ) ! 'B3LYP-V1R'
!
CALL vwn1_rpa_spin( rs, zeta, ec, vc )
ec = 0.19_DP * ec
vc = 0.19_DP * vc
!
CALL lsd_lyp( rho, zeta, ec_, vc_ ) ! from CP/FPMD (more_functionals)
ec = ec + 0.81_DP * ec_
vc = vc + 0.81_DP * vc_
!
CASE( 14 ) ! 'X3LYP
!
CALL vwn1_rpa_spin( rs, zeta, ec, vc )
ec = 0.129_DP * ec
vc = 0.129_DP * vc
!
CALL lsd_lyp( rho, zeta, ec_, vc_ ) ! from CP/FPMD (more_functionals)
ec = ec + 0.871_DP * ec_
vc = vc + 0.871_DP * vc_
!
CASE DEFAULT
!
CALL errore( 'lsda_functional (xc_spin)', 'not implemented', icorr_l )
!
END SELECT
!
ex_out(ir) = ex ; vx_out(ir,:) = vx(:)
ec_out(ir) = ec ; vc_out(ir,:) = vc(:)
!
ENDDO
!$omp end parallel do
!
!
RETURN
!
END SUBROUTINE xc_lsda
!
!
END MODULE xc_lda_lsda

View File

@ -594,14 +594,12 @@ CONTAINS
integer, parameter :: m_cut = 12 ! How many terms to include in the sum
! of SOLER equation 5.
integer, parameter :: length = 1 !^^^ PROVISIONAL (xc-lib)
real(dp) :: rho ! Local variable for the density.
real(dp) :: r_s(length) ! WignerSeitz radius.
real(dp) :: r_s ! WignerSeitz radius.
real(dp) :: s ! Reduced gradient.
real(dp) :: q
real(dp) :: ec(length), dq0dr_v(length) !^^^ PROVISIONAL
real(dp) :: ec
real(dp) :: dq0_dq ! The derivative of the saturated
! q0 with respect to q.
@ -634,20 +632,19 @@ CONTAINS
! -----------------------------------------------------------------
! Calculate some intermediate values needed to find q.
r_s(1) = ( 3.0D0 / (4.0D0*pi*rho) )**(1.0D0/3.0D0)
r_s = ( 3.0D0 / (4.0D0*pi*rho) )**(1.0D0/3.0D0)
s = sqrt( grad_rho(1,i_grid)**2 + grad_rho(2,i_grid)**2 + grad_rho(3,i_grid)**2 ) &
/ (2.0D0 * kF(rho) * rho )
s = sqrt( grad_rho(1,i_grid)**2 + grad_rho(2,i_grid)**2 + grad_rho(3,i_grid)**2 ) / &
(2.0D0 * kF(rho) * rho )
! -----------------------------------------------------------------
! This is the q value defined in equations 11 and 12 of DION.
! Use pw() from flib/functionals.f90 to get qc = kf/eps_x * eps_c.
!
call pw(length, r_s, 1, ec, dq0dr_v)
dq0_drho(i_grid) = dq0dr_v(1)
call pw(r_s, 1, ec, dq0_drho(i_grid))
!
q = -4.0D0*pi/3.0D0 * ec(1) + kF(rho) * Fs(s)
q = -4.0D0*pi/3.0D0 * ec + kF(rho) * Fs(s)
! -----------------------------------------------------------------
@ -674,7 +671,7 @@ CONTAINS
! dP_dq0 term will be interpolated later.
dq0_drho(i_grid) = dq0_dq * rho * ( -4.0D0*pi/3.0D0 * &
(dq0_drho(i_grid) - ec(1))/rho + dqx_drho(rho, s) )
(dq0_drho(i_grid) - ec)/rho + dqx_drho(rho, s) )
dq0_dgradrho(i_grid) = dq0_dq * rho * kF(rho) * dFs_ds(s) * ds_dgradrho(rho)
end do
@ -737,14 +734,13 @@ CONTAINS
real(dp), intent(OUT) :: dq0_dgradrho_up(:), dq0_dgradrho_down(:) ! Output variables.
complex(dp), intent(inout) :: thetas(:,:) ! The thetas from SOLER.
integer, parameter :: length=1 !^^^ PROVISIONAL (xc-lib)
real(dp) :: rho, up, down ! Local copy of densities.
real(dp) :: zeta(length) ! Spin polarization.
real(dp) :: r_s(length) ! Wigner-Seitz radius.
real(dp) :: zeta ! Spin polarization.
real(dp) :: r_s ! Wigner-Seitz radius.
real(dp) :: q, qc, qx, qx_up, qx_down ! q for exchange and correlation.
real(dp) :: q0x_up, q0x_down ! Saturated q values.
real(dp) :: fac
real(dp) :: ec(length), vc_v(length,2) !^^^ PROVISIONAL
real(dp) :: ec, vc(2)
real(dp) :: dq0_dq, dq0x_up_dq, dq0x_down_dq ! Derivative of q0 w.r.t q.
real(dp) :: dqc_drho_up, dqc_drho_down ! Intermediate values.
real(dp) :: dqx_drho_up, dqx_drho_down ! Intermediate values.
@ -821,14 +817,14 @@ CONTAINS
! This is the q value defined in equations 11 and 12 of DION and
! equation 8 of THONHAUSER (also see text above that equation).
r_s(1) = ( 3.0D0 / (4.0D0*pi*rho) )**(1.0D0/3.0D0)
zeta(1) = (up - down) / rho
IF ( ABS(zeta(1)) > 1.0D0 ) zeta(1) = SIGN(1.0D0, zeta(1))
call pw_spin( length, r_s, zeta, ec, vc_v )
dqc_drho_up = vc_v(1,1) ; dqc_drho_down = vc_v(1,2)
r_s = ( 3.0D0 / (4.0D0*pi*rho) )**(1.0D0/3.0D0)
zeta = (up - down) / rho
IF ( ABS(zeta) > 1.0D0 ) zeta = SIGN(1.0D0, zeta)
call pw_spin( r_s, zeta, ec, vc )
dqc_drho_up = vc(1) ; dqc_drho_down = vc(2)
!
qx = ( up * q0x_up + down * q0x_down ) / rho
qc = -4.0D0*pi/3.0D0 * ec(1)
qc = -4.0D0*pi/3.0D0 * ec
q = qx + qc
@ -870,8 +866,8 @@ CONTAINS
if (calc_qx_down) dqx_drho_up = dqx_drho_up - q0x_down*down/rho
if (calc_qx_up) dqx_drho_down = dqx_drho_down - q0x_up *up /rho
dqc_drho_up = -4.0D0*pi/3.0D0 * (dqc_drho_up - ec(1))
dqc_drho_down = -4.0D0*pi/3.0D0 * (dqc_drho_down - ec(1))
dqc_drho_up = -4.0D0*pi/3.0D0 * (dqc_drho_up - ec)
dqc_drho_down = -4.0D0*pi/3.0D0 * (dqc_drho_down - ec)
dq0_drho_up (i_grid) = dq0_dq * (dqc_drho_up + dqx_drho_up )
dq0_drho_down(i_grid) = dq0_dq * (dqc_drho_down + dqx_drho_down)

View File

@ -18,7 +18,7 @@ SUBROUTINE cg_setup
USE uspp_param, ONLY: upf
USE wavefunctions, ONLY: evc
USE io_files, ONLY: prefix, iunpun, iunres, diropn
USE funct, ONLY: dft_is_gradient
USE funct, ONLY: dft_is_gradient, init_lda_xc
USE dfunct, ONLY: newd
USE fft_base, ONLY: dfftp
USE gvect, ONLY: g, ngm, eigts1, eigts2, eigts3
@ -85,6 +85,8 @@ SUBROUTINE cg_setup
!
! derivative of the xc potential - NOT IMPLEMENTED FOR LSDA
!
CALL init_lda_xc()
!
rhotot(:) = rho%of_r(:,1) + rho_core(:)
!
sign_r = 1.0_DP
@ -98,7 +100,7 @@ SUBROUTINE cg_setup
ENDIF
ENDDO
!
CALL dmxc( dfftp%nnr, rhotot, dmuxc )
CALL dmxc_lda( dfftp%nnr, rhotot, dmuxc )
!
dmuxc = dmuxc * sign_r
!

View File

@ -138,6 +138,7 @@ phcg.o : ../../Modules/constants.o
phcg.o : ../../Modules/control_flags.o
phcg.o : ../../Modules/environment.o
phcg.o : ../../Modules/fft_base.o
phcg.o : ../../Modules/funct.o
phcg.o : ../../Modules/io_files.o
phcg.o : ../../Modules/io_global.o
phcg.o : ../../Modules/ions_base.o

View File

@ -421,6 +421,7 @@ SUBROUTINE cg_neweps
USE ions_base, ONLY : nat, tau
USE fft_base, ONLY : dfftp
USE scf, ONLY : rho, rho_core
USE funct, ONLY : init_lda_xc
USE cgcom
!
IMPLICIT NONE
@ -433,6 +434,8 @@ SUBROUTINE cg_neweps
!
! new derivative of the xc potential - NOT IMPLEMENTED FOR LSDA
!
CALL init_lda_xc()
!
rhotot(:) = rho%of_r(:,1) + rho_core(:)
!
sign_r = 1.0_DP
@ -446,7 +449,7 @@ SUBROUTINE cg_neweps
ENDIF
ENDDO
!
CALL dmxc( dfftp%nnr, rhotot, dmuxc )
CALL dmxc_lda( dfftp%nnr, rhotot, dmuxc )
!
dmuxc = dmuxc * sign_r
!

View File

@ -8,11 +8,11 @@
!
PROGRAM benchmark_libxc
!
!**--------------------------------------------------------------------------------**
!** REMEMBER to comment the libxc blocks in 'Modules/correlation_lda_lsda.f90' and **
!** 'Modules/exchange_lda_lsda.f90' in order to run consistent tests (they should **
!** be commented already however). **
!**--------------------------------------------------------------------------------**
!------------------------------------------------------------------------------------!
! REMEMBER to comment eventual libxc blocks in the functional routines in 'Modules' !
! folder in order to run consistent tests (in the present version they should be !
! already absent, however). !
!------------------------------------------------------------------------------------!
!
#if defined(__LIBXC)
!
@ -23,94 +23,351 @@ PROGRAM benchmark_libxc
!
IMPLICIT NONE
!
INTEGER, PARAMETER :: DP = selected_real_kind(14,200)
!-------- Common vars ----------------------
INTEGER, PARAMETER :: DP = SELECTED_REAL_KIND(14,200)
INTEGER, PARAMETER :: nnr = 6
CHARACTER(LEN=120) :: e_q, f_q
INTEGER :: ii, ns, np, quit, i_sub
LOGICAL :: LDA, POLARIZED, ENERGY_ONLY, DF_OK
REAL(DP), PARAMETER :: null = 0.0_DP, pi34 = 0.6203504908994_DP
!
!----------QE vars --------------------------
INTEGER :: iexch_qe, icorr_qe
REAL(DP) :: rs(nnr)
REAL(DP), ALLOCATABLE :: rho_qe(:,:)
REAL(DP), ALLOCATABLE :: rho_tot(:), zeta(:)
REAL(DP), ALLOCATABLE :: ex_qe(:), ec_qe(:)
REAL(DP), ALLOCATABLE :: vx_qe(:,:), vc_qe(:,:)
REAL(DP), ALLOCATABLE :: dmuxc(:,:,:)
!
!--------- LIBXC vars -----------------------
TYPE(xc_f90_pointer_t) :: xc_func
TYPE(xc_f90_pointer_t) :: xc_info1, xc_info2
!
! The dimension of the arrays
INTEGER, PARAMETER :: nnr=10
!
REAL(DP), DIMENSION(nnr) :: ex_lda, vx_lda, ec_lda, vc_lda
!-----------------------------
REAL(DP), DIMENSION(nnr) :: rho, ex, vx, ec, vc
CHARACTER(LEN=120) :: name1, name2
INTEGER :: ii,nnr
INTEGER :: iexch_qe, icorr_qe, iexch_xc, icorr_xc
INTEGER :: iexch_lxc, icorr_lxc
INTEGER :: pol_unpol
REAL(DP), ALLOCATABLE :: rho_lxc(:)
REAL(DP), ALLOCATABLE :: ex_lxc(:), ec_lxc(:)
REAL(DP), ALLOCATABLE :: vx_lxc(:), vc_lxc(:)
REAL(DP), ALLOCATABLE :: dex_lxc(:), dcr_lxc(:), df_lxc(:)
!
!
!
! **************************************************************************
! *------------------------------------------------------------------------*
! * libxc funct. indexes: http://bigdft.org/Wiki/index.php?title=XC_codes *
! * qe " " : see comments in Modules/funct.f90 *
! *------------------------------------------------------------------------*
! * *
! * ... some examples for LDA case: *
! * *
! * *
! * | q-e | libxc | *
! * |___________|__________| *
! * slater (x) | 1 | 1 | *
! * pz (c) | 1 | 9 | *
! * | | | *
! * wigner (c) | 5 | 2 | *
! * vwn (c) | 2 | 7 | *
! * pw (c) | 4 | 12 | *
! * ... | ... | ... | *
! * *
! **************************************************************************
!
!
!
WRITE (*,'(/,1x,a)', ADVANCE='no') "Derivative of xc?(y/n) "
READ(*,*) f_q
DF_OK = .FALSE.
IF ( TRIM(f_q) == 'y' ) DF_OK = .TRUE.
IF ( TRIM(f_q) /= 'y' .AND. TRIM(f_q) /= 'n' ) THEN
PRINT *, CHAR(10)//"ERROR: it is yes (y) or no (n)"//CHAR(10)
RETURN
ENDIF
!
IF ( .NOT.DF_OK ) THEN
WRITE (*,'(/,1x,a)', ADVANCE='no') "Energy only (y/n)? "
READ(*,*) e_q
ENERGY_ONLY = .FALSE.
IF ( TRIM(e_q) == 'y' ) ENERGY_ONLY = .TRUE.
IF ( TRIM(e_q) /= 'y' .AND. TRIM(e_q) /= 'n' ) THEN
PRINT *, CHAR(10)//"ERROR: it is yes (y) or no (n)"//CHAR(10)
RETURN
ENDIF
ENDIF
!
WRITE (*,'(/,1x,a)', ADVANCE='no') "Polarization switch (1 unpolarized, &
& 2 polarized): "
READ(*,*) ns
IF ( ns/=1 .AND. ns/=2 ) THEN
PRINT *, CHAR(10)//"ERROR: you can only choose 1 or 2"//CHAR(10)
RETURN
ENDIF
WRITE (*,'(/,1x,a)') "-- Functional indexes "
WRITE (*,'(/,1x,a)', ADVANCE='no') "iexch_libxc icorr_libxc: "
READ(*,*) iexch_lxc, icorr_lxc
WRITE (*,'(/,1x,a)', ADVANCE='no') "iexch_qe icorr_qe: "
READ(*,*) iexch_qe, icorr_qe
IF (ns == 2 .AND. icorr_qe/=0 .AND. icorr_qe/=1 .AND. icorr_qe/=2 .AND. &
icorr_qe/=4 .AND. icorr_qe/=8 .AND. icorr_qe/=3 .AND. &
icorr_qe/=7 .AND. icorr_qe/=13) THEN
PRINT *, CHAR(10)//" ERROR: icorr_qe not available at these conditions"//CHAR(10)
RETURN
ENDIF
!
!
POLARIZED = .FALSE.
IF (ns == 2) THEN
POLARIZED = .TRUE.
ENDIF
!
pol_unpol = XC_UNPOLARIZED
np = 1
!
IF ( ns == 2 ) THEN
pol_unpol = XC_POLARIZED
np = 3
ENDIF
!
!
! *******************************************************************************
! * Polarized case: *
! * *
! * qe => rho_qe(:,1) = up | libxc => rho_lxc(2n+1) = up *
! * rho_qe(:,2) = down | (dim=2*nnr) rho_lxc(2n+2) = down *
! * | *
! * dmxc(:,1,1) = uu | (dim=3*nnr) df_lxc(3n+1) = uu *
! * dmxc(:,1,2) = ud | df_lxc(3n+2) = ud *
! * dmxc(:,2,1) = du | df_lxc(3n+2) = du *
! * dmxc(:,2,2) = dd | df_lxc(3n+3) = dd *
! * *
! *******************************************************************************
!
!
! ------ Allocations --------
!
! ... qe
!
ALLOCATE( rho_qe(nnr,ns) )
IF ( POLARIZED ) ALLOCATE( rho_tot(nnr), zeta(nnr) )
ALLOCATE( ex_qe(nnr), ec_qe(nnr) )
ALLOCATE( vx_qe(nnr,ns), vc_qe(nnr,ns) )
IF ( DF_OK ) THEN
IF ( .NOT.POLARIZED ) ALLOCATE( dmuxc(nnr,1,1) )
IF ( POLARIZED ) ALLOCATE( dmuxc(nnr,2,2) )
ENDIF
!
! ... libxc
!
ALLOCATE( rho_lxc(nnr*ns) )
ALLOCATE( ex_lxc(nnr), ec_lxc(nnr) )
ALLOCATE( vx_lxc(nnr*ns), vc_lxc(nnr*ns) )
IF ( DF_OK ) THEN
IF ( .NOT.POLARIZED ) ALLOCATE( dex_lxc(nnr), dcr_lxc(nnr), df_lxc(nnr) )
IF ( POLARIZED ) ALLOCATE( dex_lxc(nnr*3), dcr_lxc(nnr*3), df_lxc(nnr*3) )
ENDIF
!
!
!----- Initializations -----
!
! ... qe
!
rho_qe = 0.0_DP
IF ( POLARIZED ) THEN
rho_tot = 0.0_DP
zeta = 0.0_DP
ENDIF
!
! ... libcx
!
rho_lxc = 0.0_DP
!
!
! -------- Setting up an arbitrary input for both qe and libxc -----
!
! ... qe
!
DO ii = 1, nnr
rho(ii)=DBLE(ii)/DBLE(nnr)
!
rho_qe(ii,1) = DBLE(ii)/DBLE(nnr+2)
!
IF ( POLARIZED ) THEN
!
rho_qe(ii,2) = (1.0_DP - rho_qe(ii,1))*0.7_DP
rho_tot(ii) = rho_qe(ii,1) + rho_qe(ii,2)
zeta(ii) = (rho_qe(ii,1) - rho_qe(ii,2)) / rho_tot(ii)
!
ENDIF
!
ENDDO
!
ex_lda = 0._dp ; ec_lda = 0._dp
vx_lda = 0._dp ; vc_lda = 0._dp
ex = 0._dp ; ec = 0._dp
vx = 0._dp ; vc = 0._dp
! ... libxc
!
!**--------------------------------------------------------------------------------**
!** libxc funct. indexes: http://bigdft.org/Wiki/index.php?title=XC_codes **
!** qe " " : see comments in Modules/funct.f90 **
!**--------------------------------------------------------------------------------**
!** **
!** ... some examples: **
!** **
!** | q-e | libxc | **
!** |___________|______________| **
!** exchange: | 1 | 1 | **
!** pz | 1 | 9 | **
!** wigner | 5 | 2 | **
!** vwn | 2 | 7 | **
!** pw | 4 | 12 | **
!** **
!**--------------------------------------------------------------------------------**
DO ii = 1, nnr
!
IF ( .NOT. POLARIZED ) THEN
!
rho_lxc(ii) = rho_qe(ii,1)
!
ELSE
!
rho_lxc(2*ii-1) = rho_qe(ii,1)
rho_lxc(2*ii) = rho_qe(ii,2)
!
ENDIF
!
ENDDO
!
!
PRINT *, "Insert functional indexes"
PRINT *, " "
PRINT *, "iexch_xc, icorr_xc: "
READ(*,*) iexch_xc, icorr_xc
PRINT *, "iexch_qe, icorr_qe: "
READ(*,*) iexch_qe, icorr_qe
!-------- Calculation of energies and potential -------------------
!
!------ LIBXC ------
!
CALL xc_f90_func_init( xc_func, xc_info1, iexch_xc, XC_UNPOLARIZED )
CALL xc_f90_lda_exc_vxc( xc_func, nnr, rho(1), ex_lda(1), vx_lda(1) )
CALL xc_f90_func_end( xc_func )
!
CALL xc_f90_func_init( xc_func, xc_info2, icorr_xc, XC_UNPOLARIZED )
CALL xc_f90_lda_exc_vxc( xc_func, nnr, rho(1), ec_lda(1), vc_lda(1) )
CALL xc_f90_func_end( xc_func )
!
!----- QE ----------
!
CALL select_functionals( iexch_qe, icorr_qe )
CALL xc( nnr, rho, ex, ec, vx, vc )
!CALL xc_spin( nnr, rho, zeta, ex, ec, vx, vc )
!
CALL xc_f90_func_init( xc_func, xc_info1, iexch_lxc, pol_unpol ) ! ... EXCHANGE
CALL xc_f90_lda_exc_vxc( xc_func, nnr, rho_lxc(1), ex_lxc(1), vx_lxc(1) )
!
IF ( DF_OK ) CALL xc_f90_lda_fxc( xc_func, nnr, rho_lxc(1), dex_lxc(1) )
CALL xc_f90_func_end( xc_func )
!
CALL xc_f90_func_init( xc_func, xc_info2, icorr_lxc, pol_unpol ) ! ... CORRELATION
CALL xc_f90_lda_exc_vxc( xc_func, nnr, rho_lxc(1), ec_lxc(1), vc_lxc(1) )
!
IF ( DF_OK ) THEN
CALL xc_f90_lda_fxc( xc_func, nnr, rho_lxc(1), dcr_lxc(1) )
df_lxc = (dex_lxc + dcr_lxc) * 2.0_DP
ENDIF
CALL xc_f90_func_end( xc_func )
!
!----- QE ----------
!
CALL select_lda_functionals( iexch_qe, icorr_qe ) ! ... EXCHANGE and CORRELATION
!
IF ( DF_OK ) THEN
IF ( .NOT.POLARIZED ) THEN
CALL dmxc_lda( nnr, rho_qe(:,1), dmuxc(:,1,1) )
ELSE
CALL dmxc_lsda( nnr, rho_qe, dmuxc )
ENDIF
ENDIF
!
IF ( .NOT. POLARIZED ) THEN
CALL xc_lda( nnr, rho_qe(:,1), ex_qe, ec_qe, vx_qe(:,1), vc_qe(:,1) )
ELSE
CALL xc_lsda( nnr, rho_tot, zeta, ex_qe, ec_qe, vx_qe, vc_qe )
ENDIF
!
!------------------
!
CALL xc_f90_info_name(xc_info1,name1)
CALL xc_f90_info_name(xc_info2,name2)
PRINT *, " "
PRINT *, "libxc: ", trim(name1), " + ", trim(name2)
PRINT *, " "
DO ii = 1, nnr, nnr
PRINT *, "rho:",rho(ii)
PRINT *, "--- ex, vx ---"
PRINT *, "libxc:",ex_lda(ii),vx_lda(ii)
PRINT *, "libqe:",ex(ii),vx(ii)
PRINT *, "diffs:",ex_lda(ii)-ex(ii),vx_lda(ii)-vx(ii)
PRINT *, "--- ec, vc ---"
PRINT *, "libxc:",ec_lda(ii),vc_lda(ii)
PRINT *, "libqe:",ec(ii),vc(ii)
PRINT *, "diffs:",ec_lda(ii)-ec(ii),vc_lda(ii)-vc(ii)
PRINT *, "--- ---"
ENDDO
CALL xc_f90_info_name( xc_info1, name1 )
CALL xc_f90_info_name( xc_info2, name2 )
!
PRINT *, "=================================== "//CHAR(10)//" "
PRINT *, "libxc functionals:"//CHAR(10)//" "
PRINT *, "Exchange: ", TRIM(name1)
PRINT *, "Correlation: ", TRIM(name2)
PRINT *, " "
!
DO ii = 1, nnr, nnr-1
WRITE(*,*) ' '
WRITE(*,*) ' '
WRITE(*,909) ii, nnr
IF ( .NOT. POLARIZED ) THEN
WRITE (*, 401 ) rho_qe(ii,1)
ELSE
WRITE (*, 402 ) rho_qe(ii,1), rho_qe(ii,2)
ENDIF
PRINT *, " "
IF (.NOT. DF_OK) THEN
PRINT *, "=== Exchange and correlation energies: ==="
WRITE (*,102) ex_qe(ii), ec_qe(ii)
WRITE (*,202) ex_lxc(ii), ec_lxc(ii)
PRINT *, " --- "
WRITE (*,302) ex_qe(ii)-ex_lxc(ii), ec_qe(ii)-ec_lxc(ii)
!
IF (.NOT. ENERGY_ONLY) THEN
PRINT *, " "
PRINT *, "=== Exchange potential ==="
IF ( .NOT. POLARIZED ) THEN
WRITE (*,101) vx_qe(ii,1)
WRITE (*,201) vx_lxc(ii)
PRINT *, " --- "
WRITE (*,301) vx_qe(ii,1)-vx_lxc(ii)
ELSEIF ( POLARIZED ) THEN
WRITE (*,102) vx_qe(ii,1), vx_qe(ii,2)
WRITE (*,202) vx_lxc(2*ii-1), vx_lxc(2*ii)
PRINT *, " --- "
WRITE (*,302) vx_qe(ii,1)-vx_lxc(2*ii-1), vx_qe(ii,2)-vx_lxc(2*ii)
ENDIF
PRINT *, " "
PRINT *, "=== Correlation potential ==="
IF ( .NOT. POLARIZED ) THEN
WRITE (*,101) vc_qe(ii,1)
WRITE (*,201) vc_lxc(ii)
PRINT *, " --- "
WRITE (*,301) vc_qe(ii,1)-vc_lxc(ii)
ELSEIF ( POLARIZED ) THEN
WRITE (*,102) vc_qe(ii,1), vc_qe(ii,2)
WRITE (*,202) vc_lxc(2*ii-1), vc_lxc(2*ii)
PRINT *, " --- "
WRITE (*,302) vc_qe(ii,1)-vc_lxc(2*ii-1), vc_qe(ii,2)-vc_lxc(2*ii)
ENDIF
PRINT *, "--- ---"
ENDIF
ELSE
PRINT *, " "
PRINT *, "=== First derivative of xc functional: ==="
IF ( .NOT. POLARIZED ) THEN
WRITE (*,101) dmuxc(ii,1,1)
WRITE (*,201) df_lxc(ii)
PRINT *, " --- "
WRITE (*,301) dmuxc(ii,1,1)-df_lxc(ii)
ELSE
WRITE (*,104) dmuxc(ii,1,1), dmuxc(ii,2,1), dmuxc(ii,2,2), dmuxc(ii,1,2)
WRITE (*,203) df_lxc(3*ii-2), df_lxc(3*ii-1), df_lxc(3*ii)
PRINT *, " --- "
WRITE (*,303) dmuxc(ii,1,1)-df_lxc(3*ii-2), dmuxc(ii,2,1)-df_lxc(3*ii-1), &
dmuxc(ii,2,2)-df_lxc(3*ii)
ENDIF
ENDIF
ENDDO
!
101 FORMAT('qe: ',3x,F17.14)
102 FORMAT('qe: ',3x,F17.14,4x,F17.14)
103 FORMAT('qe: ',3x,F17.14,4x,F17.14,4x,F17.14)
104 FORMAT('qe: ',3x,F17.14,4x,F17.14,4x,F17.14,4x,F17.14)
!
201 FORMAT('libxc: ',F17.14)
202 FORMAT('libxc: ',F17.14,4x,F17.14)
203 FORMAT('libxc: ',F17.14,4x,F17.14,4x,F17.14)
!
301 FORMAT('diffs: ',F17.14)
302 FORMAT('diffs: ',F17.14,4x,F17.14)
303 FORMAT('diffs: ',F17.14,4x,F17.14,4x,F17.14)
!
401 FORMAT('rho: ',F17.14)
402 FORMAT('rho(up,down): ',F17.14,4x,F17.14)
!
909 FORMAT('grid-point: ',I4,' of',I4)
!
DEALLOCATE( rho_qe )
IF ( POLARIZED ) DEALLOCATE( rho_tot, zeta )
DEALLOCATE( ex_qe, ec_qe )
DEALLOCATE( vx_qe, vc_qe )
IF (DF_OK) DEALLOCATE( dmuxc )
!
DEALLOCATE( rho_lxc )
DEALLOCATE( ex_lxc, ec_lxc )
DEALLOCATE( vx_lxc, vc_lxc )
IF (DF_OK) DEALLOCATE( dex_lxc, dcr_lxc, df_lxc )
!
PRINT *, " "
!
RETURN
!
#else
!
PRINT *, "ERROR: library libxc not found. Check Makefile."
PRINT *, "ERROR: library libxc not included."
RETURN
!
#endif
!

View File

@ -51,7 +51,7 @@ PROGRAM do_ppacf
USE funct, ONLY : gcxc,gcx_spin,gcc_spin,dft_is_nonlocc,nlc
USE funct, ONLY : get_iexch, get_icorr, get_igcx, get_igcc
USE funct, ONLY : set_exx_fraction,set_auxiliary_flags,enforce_input_dft, init_lda_xc
USE xc_lda_lsda, ONLY : xc, xc_spin
USE xc_lda_lsda, ONLY : xc_lda, xc_lsda
USE wvfct, ONLY : npw, npwx
USE environment, ONLY : environment_start, environment_end
USE kernel_table, ONLY : Nqs, vdw_table_name, kernel_file_name
@ -337,7 +337,7 @@ PROGRAM do_ppacf
rs = pi34 /arhox**third
CALL slater(1, rs, ex, vx(:,1)) ! \epsilon_x,\lambda[n]=\epsilon_x[n]
ELSE
CALL xc( 1, arhox, ex, ec, vx(:,1), vc(:,1) )
CALL xc_lda( 1, arhox, ex, ec, vx(:,1), vc(:,1) )
ENDIF
etx=etx+e2*ex(1)*rhox
etxlda=etxlda+e2*ex(1)*rhox
@ -356,15 +356,15 @@ PROGRAM do_ppacf
IF(icorr==4) THEN
CALL pwcc(rs(1),cc,ec(1),vc(1,1),ec_l)
ELSE
CALL xc(1,arhox/ccp3,expp,ecpp,vx(:,1),vc(:,1))
CALL xc(1,arhox/ccm3,exm,ecm,vx(:,1),vc(:,1))
CALL xc_lda(1,arhox/ccp3,expp,ecpp,vx(:,1),vc(:,1))
CALL xc_lda(1,arhox/ccm3,exm,ecm,vx(:,1),vc(:,1))
!
ec_l=(ccp2*ecpp(1)-ccm2*ecm(1))/dcc*0.5_DP
ENDIF
etcldalambda=etcldalambda+e2*ec_l*rhox
IF(icc == ncc) THEN
IF(icorr.NE.4) THEN
CALL xc(1,arhox,ex,ec,vx(:,1),vc(:,1))
CALL xc_lda(1,arhox,ex,ec,vx(:,1),vc(:,1))
ENDIF
tclda%of_r(ir,1)=e2*(ec(1)-ec_l)*rhox
ttclda=ttclda+e2*(ec(1)-ec_l)*rhox
@ -377,7 +377,7 @@ PROGRAM do_ppacf
etcgclambda=etcgclambda+e2*ecgc_l*segno
ENDIF
ENDIF
CALL xc(1,arhox,ex,ec,vx(:,1),vc(:,1))
CALL xc_lda(1,arhox,ex,ec,vx(:,1),vc(:,1))
!
etclda=etclda+e2*ec(1)*rhox
etc=etc+e2*ec(1)*rhox
@ -418,7 +418,7 @@ PROGRAM do_ppacf
CALL slater_spin(1, arhox, zeta, ex, vx)
!
ELSE
CALL xc_spin( 1, arhox, zeta, ex, ec, vx, vc )
CALL xc_lsda( 1, arhox, zeta, ex, ec, vx, vc )
!
ENDIF
etx=etx+e2*ex(1)*rhox
@ -440,9 +440,9 @@ PROGRAM do_ppacf
IF(icorr==4) THEN
CALL pwcc_spin (rs(1),cc, zeta(1), ec(1), vc(1,1), vc(1,2), ec_l)
ELSE
CALL xc_spin( 1, arhox/ccp3, zeta, expp, ecpp, vx, vc )
CALL xc_lsda( 1, arhox/ccp3, zeta, expp, ecpp, vx, vc )
!
CALL xc_spin( 1, arhox/ccm3, zeta, exm, ecm, vx, vc )
CALL xc_lsda( 1, arhox/ccm3, zeta, exm, ecm, vx, vc )
!
ec_l=(ccp2*ecpp(1)-ccm2*ecm(1))/dcc*0.5_DP
ENDIF
@ -458,7 +458,7 @@ PROGRAM do_ppacf
etcgclambda=etcgclambda+e2*ecgc_l
ENDIF
ENDIF
CALL xc_spin( 1, arhox, zeta, ex, ec, vx, vc )
CALL xc_lsda( 1, arhox, zeta, ex, ec, vx, vc )
!
etclda=etclda+e2*ec(1)*rhox
etc=etc+e2*ec(1)*rhox

View File

@ -319,8 +319,6 @@ CONTAINS
real(dp) :: dqc_drho
integer :: i_grid, idx ! Indexing variables.
!
real(dp) :: rs_v(1), ec_v(1), dqcdr_v(1) !^^^ PROVISIONAL (xc-lib)
@ -359,10 +357,7 @@ CONTAINS
! This is the q value defined in equations 11 and 12 of DION.
! Use pw() from flib/functionals.f90 to get qc = kf/eps_x * eps_c.
rs_v(1)=cc*r_s
call pw(1, rs_v, 1, ec_v, dqcdr_v)
ec=ec_v(1)
dqc_drho=dqcdr_v(1)
call pw( cc*r_s, 1, ec, dqc_drho)
!
q = -4.0D0*pi/3.0D0 * ec + kF(rho) * Fs(s)/cc
if(lecnl_qx) then
@ -452,7 +447,7 @@ CONTAINS
integer :: i_grid, idx ! Indexing variables
logical :: calc_qx_up, calc_qx_down
!
real(dp) :: rs_v(1), zeta_v(1), ec_v(1), vc_v(1,2)
real(dp) :: vc_v(2) ! auxiliary array for pw_spin call
@ -525,10 +520,8 @@ CONTAINS
zeta = (up - down) / rho
IF (ABS(zeta) > 1.0D0 ) zeta = SIGN(1.0D0, zeta)
!
rs_v(1)=cc*r_s ; zeta_v(1)=zeta
call pw_spin( 1, rs_v, zeta_v, ec_v, vc_v )
ec=ec_v(1)
dqc_drho_up=vc_v(1,1) ; dqc_drho_down=vc_v(1,2)
call pw_spin( cc*r_s, zeta, ec, vc_v )
dqc_drho_up=vc_v(1) ; dqc_drho_down=vc_v(2)
!
qx = ( up * q0x_up + down * q0x_down ) / rho / cc
qc = -4.0D0*pi/3.0D0 * ec

View File

@ -408,8 +408,8 @@ SUBROUTINE PAW_xc_potential(i, rho_lm, rho_core, v_lm, energy)
USE uspp_param, ONLY : upf
USE lsda_mod, ONLY : nspin
USE atom, ONLY : g => rgrid
USE funct, ONLY : dft_is_gradient, init_lda_xc !^^^
USE xc_lda_lsda, ONLY : xc, xc_spin !^^^
USE funct, ONLY : dft_is_gradient, init_lda_xc
USE xc_lda_lsda, ONLY : xc
USE constants, ONLY : fpi ! REMOVE
TYPE(paw_info), INTENT(IN) :: i ! atom's minimal info
@ -435,7 +435,7 @@ SUBROUTINE PAW_xc_potential(i, rho_lm, rho_core, v_lm, energy)
INTEGER :: mytid, ntids
!
!^^^****************************************** !^^^
REAL(DP), ALLOCATABLE :: arho(:), zeta(:), amag(:)
REAL(DP), ALLOCATABLE :: arho(:,:), zeta(:), amag(:)
REAL(DP), ALLOCATABLE :: ex(:), ec(:)
REAL(DP), ALLOCATABLE :: vx(:,:), vc(:,:)
REAL(DP), PARAMETER :: eps = 1.e-30_dp
@ -473,7 +473,7 @@ SUBROUTINE PAW_xc_potential(i, rho_lm, rho_core, v_lm, energy)
!
ALLOCATE( rho_rad(i%m,nspin_mag) )
!
ALLOCATE( arho(i%m) ) !^^^
ALLOCATE( arho(i%m,2) ) !^^^
ALLOCATE( zeta(i%m) )
ALLOCATE( amag(i%m) )
ALLOCATE( ex(i%m) )
@ -505,18 +505,12 @@ SUBROUTINE PAW_xc_potential(i, rho_lm, rho_core, v_lm, energy)
IF ( nspin_mag ==4 ) THEN
IF (with_small_so.AND.i%ae==1) CALL add_small_mag(i,ix,rho_rad)
!
!
DO k=1,i%m
rho_loc(k,1:nspin) = rho_rad(k,1:nspin)*g(i%t)%rm2(k)
amag(k) = SQRT(rho_loc(k,2)**2+rho_loc(k,3)**2+rho_loc(k,4)**2)
arho(k) = ABS( rho_loc(k,1)+rho_core(k) )
IF ( arho(k) > eps12 ) THEN
zeta(k) = amag(k) / arho(k)
IF ( ABS( zeta(k) ) > 1.D0 ) zeta(k) = SIGN( 1.D0, zeta(k) )
ENDIF
rho_loc(k,1) = rho_loc(k,1) + rho_core(k)
ENDDO
!
CALL xc_spin( i%m, arho, zeta, ex, ec, vx, vc )
CALL xc( i%m, 4, 2, rho_loc, ex, ec, vx, vc )
!
DO k=1,i%m
IF (present(energy)) &
@ -550,33 +544,25 @@ SUBROUTINE PAW_xc_potential(i, rho_lm, rho_core, v_lm, energy)
!
IF (lsd==0) THEN
!
arho = ABS( rho_loc(:,1)+rho_core ) !^^^ def arhox, eps, e2,
arho(:,1) = rho_loc(:,1) + rho_core
!
CALL xc( i%m, arho, ex, ec, vx(:,1), vc(:,1) )
CALL xc( i%m, 1, 1, arho(:,1), ex, ec, vx(:,1), vc(:,1) )
!
v_rad(:,ix,1) = e2*( vx(:,1) + vc(:,1) )
if (present(energy)) e_rad = e2*( ex + ec )
if (present(energy)) e_rad = e2*( ex(:) + ec(:) )
!
ELSE
!
zeta=0.0_DP
DO k = 1, i%m
arho(k) = ABS( rho_loc(k,1)+rho_loc(k,2)+rho_core(k) )
IF ( arho(k) > eps ) THEN
zeta(k) = (rho_loc(k,1)-rho_loc(k,2)) / arho(k)
IF ( ABS(zeta(k)) > 1.D0 ) zeta(k) = SIGN( 1.D0, zeta(k) )
ENDIF
ENDDO
arho(:,1) = rho_loc(:,1) + rho_loc(:,2) + rho_core(:)
arho(:,2) = rho_loc(:,1) - rho_loc(:,2)
!
CALL xc_spin( i%m, arho, zeta, ex, ec, vx, vc )
CALL xc( i%m, 2, 2, arho, ex, ec, vx, vc )
!
v_rad(:,ix,:) = e2*( vx(:,:) + vc(:,:) ) !^^^**
v_rad(:,ix,:) = e2*( vx(:,:) + vc(:,:) )
if (present(energy)) e_rad(:) = e2*( ex(:) + ec(:) )
!
ENDIF
!
!CALL evxc_t_vec(rho_loc, rho_core, lsd, i%m, v_rad(:,ix,:), e_rad) !^^^
!
IF (present(energy)) THEN
IF ( nspin_mag < 2 ) THEN
e_rad = e_rad * ( rho_rad(:,1) + rho_core*g(i%t)%r2 )
@ -1605,18 +1591,19 @@ SUBROUTINE PAW_dpotential(dbecsum, becsum, int3, npe)
CALL stop_clock('PAW_dpot')
END SUBROUTINE PAW_dpotential
!
!
SUBROUTINE PAW_dxc_potential( i, drho_lm, rho_lm, rho_core, v_lm )
!
!! This routine computes the change of the exchange and correlation
!! potential in the spherical basis. It receives as input the charge
!! density and its variation.
!
USE spin_orb, ONLY : domag
USE noncollin_module, ONLY : nspin_mag
USE lsda_mod, ONLY : nspin
USE atom, ONLY : g => rgrid
USE funct, ONLY : dft_is_gradient
USE funct, ONLY : dft_is_gradient, init_lda_xc
!
TYPE(paw_info), INTENT(IN) :: i ! atom's minimal info
REAL(DP), INTENT(IN) :: rho_lm(i%m,i%l**2,nspin_mag) ! charge density as
@ -1644,6 +1631,7 @@ SUBROUTINE PAW_dxc_potential( i, drho_lm, rho_lm, rho_core, v_lm )
ALLOCATE(v_rad(i%m,rad(i%t)%nx,nspin_mag))
ALLOCATE(dmuxc(i%m,nspin_mag,nspin_mag))
!
CALL init_lda_xc()
!
DO ix = ix_s, ix_e
!
@ -1662,13 +1650,14 @@ SUBROUTINE PAW_dxc_potential( i, drho_lm, rho_lm, rho_core, v_lm )
CASE( 4 )
!
rho_rad(:,1) = rho_rad(:,1) + rho_core(:)
CALL dmxc_nc( i%m, rho_rad(:,1),rho_rad(:,2:4), dmuxc )
CALL dmxc( i%m, 4, rho_rad, dmuxc )
!
CASE( 2 )
!
rho_rad(:,1) = rho_rad(:,1) + 0.5_DP*rho_core(:)
rho_rad(:,2) = rho_rad(:,2) + 0.5_DP*rho_core(:)
CALL dmxc_spin( i%m, rho_rad, dmuxc )
!
CALL dmxc( i%m, 2, rho_rad, dmuxc )
!
CASE DEFAULT
!
@ -1685,7 +1674,7 @@ SUBROUTINE PAW_dxc_potential( i, drho_lm, rho_lm, rho_core, v_lm )
ENDIF
ENDDO
!
CALL dmxc( i%m, rho_rad(:,1), dmuxc(:,1,1) )
CALL dmxc( i%m, 1, rho_rad(:,1), dmuxc )
!
v_rad(:,ix,1) = dmuxc(:,1,1)*sign_r(:)
!
@ -1730,6 +1719,7 @@ SUBROUTINE PAW_dxc_potential( i, drho_lm, rho_lm, rho_core, v_lm )
!
END SUBROUTINE PAW_dxc_potential
!
!
! add gradient correction to dvxc. Both unpolarized and
! spin polarized cases are supported.
!

View File

@ -347,7 +347,7 @@ SUBROUTINE v_xc( rho, rho_core, rhog_core, etxc, vtxc, v )
USE cell_base, ONLY : omega
USE spin_orb, ONLY : domag
USE funct, ONLY : nlc, dft_is_nonlocc, init_lda_xc
USE xc_lda_lsda, ONLY : xc, xc_spin
USE xc_lda_lsda, ONLY : xc
USE scf, ONLY : scf_type
USE mp_bands, ONLY : intra_bgrp_comm
USE mp, ONLY : mp_sum
@ -371,7 +371,9 @@ SUBROUTINE v_xc( rho, rho_core, rhog_core, etxc, vtxc, v )
!
REAL(DP) :: rhoneg(2), vs
!
REAL(DP), ALLOCATABLE :: arhox(:), amag(:), zeta(:)
!REAL(DP), ALLOCATABLE :: arhox(:), amag(:), zeta(:)
REAL(DP) :: arho, amag
REAL(DP) :: rhoup2, rhodw2
REAL(DP), ALLOCATABLE :: ex(:), ec(:)
REAL(DP), ALLOCATABLE :: vx(:,:), vc(:,:)
! In order:
@ -392,123 +394,87 @@ SUBROUTINE v_xc( rho, rho_core, rhog_core, etxc, vtxc, v )
!
CALL start_clock( 'v_xc' )
!
ALLOCATE(ex(dfftp%nnr))
ALLOCATE(ec(dfftp%nnr))
ALLOCATE(vx(dfftp%nnr,nspin))
ALLOCATE(vc(dfftp%nnr,nspin))
ALLOCATE( ex(dfftp%nnr) )
ALLOCATE( ec(dfftp%nnr) )
ALLOCATE( vx(dfftp%nnr,nspin) )
ALLOCATE( vc(dfftp%nnr,nspin) )
!
CALL init_lda_xc()
!
!
etxc = 0.D0
vtxc = 0.D0
v(:,:) = 0.D0
rhoneg = 0.D0
!
!
rho%of_r(:,1) = rho%of_r(:,1) + rho_core(:)
!
IF ( nspin == 1 .OR. ( nspin == 4 .AND. .NOT. domag ) ) THEN
!
! ... spin-unpolarized case
!
rho%of_r(:,1) = rho%of_r(:,1) + rho_core(:)
CALL xc( dfftp%nnr, 1, 1, rho%of_r(:,1), ex, ec, vx(:,1), vc(:,1) )
!
CALL xc( dfftp%nnr, ABS(rho%of_r), ex, ec, vx(:,1), vc(:,1) )
!
v(:,1) = e2*( vx(:,1) + vc(:,1) )
etxc = SUM( e2*((ex(:) + ec(:))*rho%of_r(:,1)) )
rho%of_r(:,1)=rho%of_r(:,1)-rho_core(:)
vtxc = SUM( v(:,1)*rho%of_r(:,1) )
DO ir=1, dfftp%nnr
IF ( rho%of_r(ir,1) < 0.D0 ) rhoneg(1) = rhoneg(1) - rho%of_r(ir,1)
DO ir = 1, dfftp%nnr
v(ir,1) = e2*( vx(ir,1) + vc(ir,1) )
etxc = etxc + e2*( ex(ir) + ec(ir) )*rho%of_r(ir,1)
rho%of_r(ir,1) = rho%of_r(ir,1) - rho_core(ir)
vtxc = vtxc + v(ir,1)*rho%of_r(ir,1)
IF (rho%of_r(ir,1) < 0.D0) rhoneg(1) = rhoneg(1)-rho%of_r(ir,1)
ENDDO
!
!
ELSE IF ( nspin == 2 ) THEN
!
ELSEIF ( nspin == 2 ) THEN
! ... spin-polarized case
!
ALLOCATE(arhox(dfftp%nnr))
ALLOCATE(zeta(dfftp%nnr))
zeta=0.D0
CALL xc( dfftp%nnr, 2, 2, rho%of_r, ex, ec, vx, vc )
!
DO ir = 1, dfftp%nnr
IF ( rho%of_r(ir,1) < 0.D0 ) rhoneg(1) = rhoneg(1) - rho%of_r(ir,1)
rho%of_r(ir,1) = rho%of_r(ir,1) + rho_core(ir)
arhox(ir) = ABS(rho%of_r(ir,1))
IF ( arhox(ir) > vanishing_charge ) THEN
zeta(ir) = rho%of_r(ir,2) / arhox(ir)
IF ( ABS(zeta(ir)) > 1.D0 ) THEN
rhoneg(2) = rhoneg(2) + 1.D0 / omega
zeta(ir) = SIGN( 1.D0, zeta(ir) )
END IF
ENDIF
ENDDO
!
CALL xc_spin( dfftp%nnr, arhox, zeta, ex, ec, vx, vc )
!
DO ir = 1, dfftp%nnr
DO ir = 1, dfftp%nnr !OMP ?
v(ir,:) = e2*( vx(ir,:) + vc(ir,:) )
etxc = etxc + e2*( (ex(ir) + ec(ir))*rho%of_r(ir,1) )
rho%of_r(ir,1) = rho%of_r(ir,1) - rho_core(ir)
vtxc = vtxc + ( ( v(ir,1) + v(ir,2) )*rho%of_r(ir,1) + &
( v(ir,1) - v(ir,2) )*rho%of_r(ir,2) )
!
rhoup2 = rho%of_r(ir,1)+rho%of_r(ir,2)
rhodw2 = rho%of_r(ir,1)-rho%of_r(ir,2)
IF (rhoup2 < 0.d0) rhoneg(1) = rhoneg(1) + rhoup2
IF (rhodw2 < 0.d0) rhoneg(2) = rhoneg(2) + rhodw2
ENDDO
vtxc = 0.5d0 * vtxc
!
DEALLOCATE(arhox)
DEALLOCATE(zeta)
!
vtxc = 0.5d0 * vtxc
rhoneg = 0.5d0 * rhoneg
!
!
ELSE IF ( nspin == 4 ) THEN
!
! ... noncolinear case
!
ALLOCATE(arhox(dfftp%nnr))
ALLOCATE(amag(dfftp%nnr))
ALLOCATE(zeta(dfftp%nnr))
zeta=0.D0
CALL xc( dfftp%nnr, 4, 2, rho%of_r, ex, ec, vx, vc )
!
DO ir = 1, dfftp%nnr
amag(ir) = SQRT( rho%of_r(ir,2)**2 + rho%of_r(ir,3)**2 + rho%of_r(ir,4)**2 )
IF ( rho%of_r(ir,1) < 0.D0 ) rhoneg(1) = rhoneg(1) - rho%of_r(ir,1)
rho%of_r(ir,1) = rho%of_r(ir,1) + rho_core(ir)
arhox(ir) = ABS( rho%of_r(ir,1) )
IF ( arhox(ir) > vanishing_charge ) THEN
zeta(ir) = amag(ir) / arhox(ir)
IF ( ABS( zeta(ir) ) > 1.D0 ) THEN
rhoneg(2) = rhoneg(2) + 1.D0 / omega
zeta(ir) = SIGN( 1.D0, zeta(ir) )
END IF
DO ir = 1, dfftp%nnr !OMP ?
arho = ABS( rho%of_r(ir,1) )
IF ( arho < vanishing_charge ) CYCLE
vs = 0.5D0*( vx(ir,1) + vc(ir,1) - vx(ir,2) - vc(ir,2) )
v(ir,1) = e2*( 0.5D0*( vx(ir,1) + vc(ir,1) + vx(ir,2) + vc(ir,2) ) )
!
amag = SQRT( SUM( rho%of_r(ir,2:4)**2 ) )
IF ( amag > vanishing_mag ) THEN
v(ir,2:4) = e2 * vs * rho%of_r(ir,2:4) / amag
vtxc = vtxc + SUM( v(ir,2:4) * rho%of_r(ir,2:4) )
ENDIF
etxc = etxc + e2*( ex(ir) + ec(ir) ) * arho
!
rho%of_r(ir,1) = 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)
IF ( amag / arho > 1.D0 ) rhoneg(2) = rhoneg(2) + 1.D0/omega
vtxc = vtxc + v(ir,1) * rho%of_r(ir,1)
ENDDO
!
CALL xc_spin( dfftp%nnr, arhox, zeta, ex, ec, vx, vc )
!
DO ir = 1, dfftp%nnr
IF ( arhox(ir) > vanishing_charge ) THEN
vs = 0.5D0*( vx(ir,1) + vc(ir,1) - vx(ir,2) - vc(ir,2) )
v(ir,1) = e2*( 0.5D0*( vx(ir,1) + vc(ir,1) + vx(ir,2) + vc(ir,2) ) )
IF ( amag(ir) > vanishing_mag ) THEN
DO ipol = 2, 4
v(ir,ipol) = e2 * vs * rho%of_r(ir,ipol) / amag(ir)
vtxc = vtxc + v(ir,ipol) * rho%of_r(ir,ipol)
ENDDO
END IF
etxc = etxc + e2*( ex(ir) + ec(ir) ) * rho%of_r(ir,1)
rho%of_r(ir,1) = rho%of_r(ir,1) - rho_core(ir)
vtxc = vtxc + v(ir,1) * rho%of_r(ir,1)
ENDIF
ENDDO
!
DEALLOCATE(arhox)
DEALLOCATE(amag)
DEALLOCATE(zeta)
!
END IF
ENDIF
!
DEALLOCATE(ex)
DEALLOCATE(ec)
DEALLOCATE(vx)
DEALLOCATE(vc)
DEALLOCATE( ex, ec )
DEALLOCATE( vx, vc )
!
CALL mp_sum( rhoneg , intra_bgrp_comm )
!

View File

@ -420,7 +420,7 @@ subroutine dvxc_dn(mesh, rho, dvxc)
! compute the derivative of xc-potential w.r.t local density.
! some routine in PH and flibs will be called
!
use funct, only : dft_is_gradient
use funct, only : dft_is_gradient, init_lda_xc
!
implicit none
!
@ -439,7 +439,10 @@ subroutine dvxc_dn(mesh, rho, dvxc)
call errore ('dvxc_dn', 'gradient correction to dvxc not yet implemented', 1)
!
! LDA only
CALL dmxc( mesh, rho, dvxc )
!
CALL init_lda_xc()
!
CALL dmxc_lda( mesh, rho, dvxc )
!
return
!

View File

@ -15,15 +15,15 @@ subroutine vxc_t(lsd,rho,rhoc,exc,vxc)
!
use kinds, only : DP
use funct, only : init_lda_xc
use xc_lda_lsda, only: xc, xc_spin
use xc_lda_lsda, only: xc
implicit none
integer, intent(in) :: lsd ! 1 in the LSDA case, 0 otherwise
real(DP), intent(in) :: rho(2), rhoc ! the system density
real(DP), intent(out):: exc, vxc(2)
real(DP), intent(out):: exc(1), vxc(2) !^^^
!
integer, parameter :: length=1 !^^^ PROVISIONAL (xc-lib)
real(DP), dimension(length) :: arho, zeta, ex, ec
REAL(DP), dimension(length,2) :: vx, vc
integer, parameter :: length=1 !^^^ PROVISIONAL (xc-lib)
real(DP), dimension(length) :: ex, ec , arho
REAL(DP), dimension(length,2) :: rhoaux, vx, vc
!
real(DP), parameter :: e2=2.0_dp, eps=1.e-30_dp
!
@ -36,10 +36,10 @@ subroutine vxc_t(lsd,rho,rhoc,exc,vxc)
!
! LDA case
!
arho(1) = abs(rho(1) + rhoc)
if (arho(1) > eps) then
rhoaux(1,1) = abs(rho(1) + rhoc)
if (rhoaux(1,1) > eps) then
!
call xc( length, arho ,ex, ec, vx(:,1), vc(:,1) )
CALL xc( length, 1, 1, rhoaux, ex, ec, vx(:,1), vc(:,1) )
!
vxc(1) = e2 * ( vx(1,1) + vc(1,1) )
exc = e2 * ( ex(1) + ec(1) )
@ -49,24 +49,23 @@ subroutine vxc_t(lsd,rho,rhoc,exc,vxc)
! LSDA case
!
vxc(2)=0.0_dp
arho(1) = abs(rho(1)+rho(2)+rhoc)
if (arho(1) > eps) then
zeta(1) = (rho(1)-rho(2)) / arho(1)
! zeta has to stay between -1 and 1, but can get a little
! out the bound during the first iterations.
if (abs(zeta(1)) > 1.0_dp) zeta(1) = sign(1._dp, zeta(1))
!
CALL xc_spin( length, arho, zeta, ex, ec, vx, vc )
!
vxc(1) = e2 * ( vx(1,1) + vc(1,1) )
vxc(2) = e2 * ( vx(1,2) + vc(1,2) )
exc = e2 * ( ex(1) + ec(1) )
endif
!
rhoaux(1,1) = rho(1) + rho(2) + rhoc
rhoaux(1,2) = rho(1) - rho(2)
!
CALL xc( length, 2, 2, rhoaux, ex, ec, vx, vc )
!
vxc(1) = e2 * ( vx(1,1) + vc(1,1) )
vxc(2) = e2 * ( vx(1,2) + vc(1,2) )
exc = e2 * ( ex(1) + ec(1) )
!
endif
!
return
!
end subroutine vxc_t
!
!
!---------------------------------------------------------------
subroutine vxcgc ( ndm, mesh, nspin, r, r2, rho, rhoc, vgc, egc, &
tau, vtau, iflag)