mirror of https://gitlab.com/QEF/q-e.git
svdW-DF implemented
git-svn-id: http://qeforge.qe-forge.org/svn/q-e/trunk/espresso@11720 c92efa57-630b-4861-b058-cf58834340f0
This commit is contained in:
parent
08a572991e
commit
1c4852024f
|
@ -1,5 +1,6 @@
|
|||
New in svn version:
|
||||
|
||||
* svdW-DF - a proper spin version of vdW-DF (courtesy of Timo Thonhauser)
|
||||
* XSpectra: various improvements
|
||||
|
||||
Incompatible changes in 5.2.0 version:
|
||||
|
|
|
@ -188,9 +188,8 @@ mentioned in Sect.\ref{SubSec:Terms}, include:
|
|||
vdW corrections;
|
||||
\item Ikutaro Hamada (NIMS, Japan) for OPTB86B-vdW and REV-vdW-DF2
|
||||
functionals;
|
||||
\item Timo Thonhauser's group (Wake Forest University)
|
||||
for vdW-DF and variants, with support from
|
||||
Riccardo Sabatini and Stefano de Gironcoli (SISSA and DEMOCRITOS);
|
||||
\item Timo Thonhauser (WFU) for vdW-DF and variants, including the
|
||||
spin development svdW-DF;
|
||||
\item Daniel Forrer (Padua Univ.) and Michele Pavone
|
||||
(Naples Univ. Federico II) for dispersions interaction in the
|
||||
framework of DFT-D;
|
||||
|
|
|
@ -110,8 +110,11 @@ module funct
|
|||
! "hse" = "sla+pw+hse+pbc" = Heyd-Scuseria-Ernzerhof (HSE 06, see note below)
|
||||
! "b3lyp" = "b3lp+vwn+b3lp+b3lp"= B3LYP
|
||||
! "gaupbe"= "sla+pw+gaup+pbc" = Gau-PBE (also "gaup")
|
||||
! "vdw-df" ="sla+pw+rpb +vdw1" = vdW-DF
|
||||
! "vdw-df" ="sla+pw+rpb +vdw1" = vdW-DF1
|
||||
! "vdw-df2" ="sla+pw+rw86+vdw2" = vdW-DF2
|
||||
! "vdw-df-x" ="sla+pw+????+vdwx" = vdW-DF-x, reserved Thonhauser, not implemented
|
||||
! "vdw-df-y" ="sla+pw+????+vdwy" = vdW-DF-y, reserved Thonhauser, not implemented
|
||||
! "vdw-df-z" ="sla+pw+????+vdwz" = vdW-DF-z, reserved Thonhauser, not implemented
|
||||
! "vdw-df-c09" ="sla+pw+c09x+vdw1" = vdW-DF-C09
|
||||
! "vdw-df2-c09" ="sla+pw+c09x+vdw2" = vdW-DF2-C09
|
||||
! "vdw-df-cx" ="sla+pw+cx13+vdW1" = vdW-DF-cx
|
||||
|
@ -189,10 +192,13 @@ module funct
|
|||
! "tb09" TB09 Meta-GGA imeta=3
|
||||
!
|
||||
! Van der Waals functionals (nonlocal term only)
|
||||
! "nonlc" none inlc =0 (default)
|
||||
! "nonlc" none inlc =0 (default)
|
||||
! "vdw1" vdW-DF1 inlc =1
|
||||
! "vdw2" vdW-DF2 inlc =2
|
||||
! "vv10" rVV10 inlc =3
|
||||
! "vv10" rVV10 inlc =3
|
||||
! "vdwx" vdW-DF-x inlc =4, reserved Thonhauser, not implemented
|
||||
! "vdwy" vdW-DF-y inlc =5, reserved Thonhauser, not implemented
|
||||
! "vdwz" vdW-DF-z inlc =6, reserved Thonhauser, not implemented
|
||||
!
|
||||
! Note: as a rule, all keywords should be unique, and should be different
|
||||
! from the short name, but there are a few exceptions.
|
||||
|
@ -230,7 +236,7 @@ module funct
|
|||
! J.Phys.Chem 98, 11623 (1994)
|
||||
! vdW-DF M. Dion et al., PRL 92, 246401 (2004)
|
||||
! T. Thonhauser et al., PRB 76, 125112 (2007)
|
||||
! vdw-DF2 Lee et al., Phys. Rev. B 82, 081101 (2010)
|
||||
! vdW-DF2 Lee et al., Phys. Rev. B 82, 081101 (2010)
|
||||
! rev-vdW-DF2 I. Hamada, Phys. Rev. B 89, 121103(R) (2014)
|
||||
! vdW-DF-cx K. Berland and P. Hyldgaard, PRB 89, 035412 (2014)
|
||||
! vdW-DF-obk8 Klimes et al, J. Phys. Cond. Matter, 22, 022201 (2010)
|
||||
|
@ -286,7 +292,7 @@ module funct
|
|||
real(DP):: finite_size_cell_volume = notset
|
||||
logical :: discard_input_dft = .false.
|
||||
!
|
||||
integer, parameter:: nxc=8, ncc=10, ngcx=27, ngcc=12, nmeta=3, ncnl=3
|
||||
integer, parameter:: nxc=8, ncc=10, ngcx=27, ngcc=12, nmeta=3, ncnl=6
|
||||
character (len=4) :: exc, corr, gradx, gradc, meta, nonlocc
|
||||
dimension :: exc (0:nxc), corr (0:ncc), gradx (0:ngcx), gradc (0:ngcc), &
|
||||
meta(0:nmeta), nonlocc (0:ncnl)
|
||||
|
@ -305,7 +311,7 @@ module funct
|
|||
|
||||
data meta / 'NONE', 'TPSS', 'M06L', 'TB09' /
|
||||
|
||||
data nonlocc/'NONE', 'VDW1', 'VDW2', 'VV10' /
|
||||
data nonlocc/'NONE', 'VDW1', 'VDW2', 'VV10', 'VDWX', 'VDWY', 'VDWZ' /
|
||||
|
||||
CONTAINS
|
||||
!-----------------------------------------------------------------------
|
||||
|
@ -450,6 +456,15 @@ CONTAINS
|
|||
! Special case vdW-DF
|
||||
dft_defined = set_dft_values(1,4,4,0,1,0)
|
||||
|
||||
else if ('VDW-DF-X' .EQ. TRIM(dftout) ) then
|
||||
call errore('set_dft_from_name','functional not yet implemented',1)
|
||||
|
||||
else if ('VDW-DF-Y' .EQ. TRIM(dftout) ) then
|
||||
call errore('set_dft_from_name','functional not yet implemented',1)
|
||||
|
||||
else if ('VDW-DF-Z' .EQ. TRIM(dftout) ) then
|
||||
call errore('set_dft_from_name','functional not yet implemented',1)
|
||||
|
||||
else if ('VDW-DF-CX' .EQ. TRIM(dftout)) then
|
||||
! Special case vdW-DF-CX
|
||||
dft_defined = set_dft_values(1,4,27,0,1,0)
|
||||
|
@ -461,12 +476,14 @@ CONTAINS
|
|||
else if ('VDW-DF-OBK8' .EQ. TRIM(dftout)) then
|
||||
! Special case vdW-DF-obk8, or vdW-DF + optB88
|
||||
dft_defined = set_dft_values(1,4,23,0,1,0)
|
||||
|
||||
else if ('VDW-DF3' .EQ. TRIM(dftout) ) then
|
||||
call errore('set_dft_from_name','obsolete XC label, use VDW-DF-OBK8',1)
|
||||
|
||||
else if ('VDW-DF-OB86' .EQ. TRIM(dftout) ) then
|
||||
! Special case vdW-DF-ob86, or vdW-DF + optB86
|
||||
dft_defined = set_dft_values(1,4,24,0,1,0)
|
||||
|
||||
else if ('VDW-DF4'.EQ.TRIM(dftout) .OR. 'OPTB86B-VDW'.EQ.TRIM(dftout) ) then
|
||||
call errore('set_dft_from_name','obsolete XC label, use VDW-DF-OB86',1)
|
||||
|
||||
|
@ -966,7 +983,7 @@ CONTAINS
|
|||
shortname_ = 'TB09'
|
||||
end if
|
||||
|
||||
if ( inlc_==1) then
|
||||
if ( inlc_==1 ) then
|
||||
if (iexch_==1.and.icorr_==4.and.igcx_==4.and.igcc_==0) then
|
||||
shortname_ = 'VDW-DF'
|
||||
else if (iexch_==1.and.icorr_==4.and.igcx_==27.and.igcc_==0) then
|
||||
|
@ -978,7 +995,7 @@ CONTAINS
|
|||
else if (iexch_==1.and.icorr_==4.and.igcx_==23.and.igcc_==0) then
|
||||
shortname_ = 'VDW-DF-OBK8'
|
||||
end if
|
||||
else if ( inlc_==2) then
|
||||
else if ( inlc_==2 ) then
|
||||
if (iexch_==1.and.icorr_==4.and.igcx_==13.and.igcc_==0) then
|
||||
shortname_ = 'VDW-DF2'
|
||||
else if (iexch_==1.and.icorr_==4.and.igcx_==16.and.igcc_==0) then
|
||||
|
@ -1618,6 +1635,44 @@ subroutine gcx_spin (rhoup, rhodw, grhoup2, grhodw2, &
|
|||
v2xup = 2.0_DP * v2xup
|
||||
v2xdw = 2.0_DP * v2xdw
|
||||
|
||||
elseif (igcx == 13) then ! 'revised PW86 for vdw-df2'
|
||||
if (rhoup > small .and. sqrt (abs (grhoup2) ) > small) then
|
||||
call rPW86 (2.0_DP * rhoup, 4.0_DP * grhoup2, sxup, v1xup, v2xup)
|
||||
else
|
||||
sxup = 0.0_DP
|
||||
v1xup = 0.0_DP
|
||||
v2xup = 0.0_DP
|
||||
endif
|
||||
if (rhodw > small .and. sqrt (abs (grhodw2) ) > small) then
|
||||
call rPW86 (2.0_DP * rhodw, 4.0_DP * grhodw2, sxdw, v1xdw, v2xdw)
|
||||
else
|
||||
sxdw = 0.0_DP
|
||||
v1xdw = 0.0_DP
|
||||
v2xdw = 0.0_DP
|
||||
endif
|
||||
sx = 0.5_DP * (sxup + sxdw)
|
||||
v2xup = 2.0_DP * v2xup
|
||||
v2xdw = 2.0_DP * v2xdw
|
||||
|
||||
elseif (igcx == 16) then ! 'c09x for vdw-df-c09.'
|
||||
if (rhoup > small .and. sqrt (abs (grhoup2) ) > small) then
|
||||
call c09x (2.0_DP * rhoup, 4.0_DP * grhoup2, sxup, v1xup, v2xup)
|
||||
else
|
||||
sxup = 0.0_DP
|
||||
v1xup = 0.0_DP
|
||||
v2xup = 0.0_DP
|
||||
endif
|
||||
if (rhodw > small .and. sqrt (abs (grhodw2) ) > small) then
|
||||
call c09x (2.0_DP * rhodw, 4.0_DP * grhodw2, sxdw, v1xdw, v2xdw)
|
||||
else
|
||||
sxdw = 0.0_DP
|
||||
v1xdw = 0.0_DP
|
||||
v2xdw = 0.0_DP
|
||||
endif
|
||||
sx = 0.5_DP * (sxup + sxdw)
|
||||
v2xup = 2.0_DP * v2xup
|
||||
v2xdw = 2.0_DP * v2xdw
|
||||
|
||||
elseif (igcx == 21) then ! 'PW86'
|
||||
if (rhoup > small .and. sqrt (abs (grhoup2) ) > small) then
|
||||
call pw86 (2.0_DP * rhoup, 4.0_DP * grhoup2, sxup, v1xup, v2xup)
|
||||
|
@ -1869,6 +1924,48 @@ subroutine gcx_spin_vec(rhoup, rhodw, grhoup2, grhodw2, &
|
|||
v2xup = 2.0_DP * v2xup
|
||||
v2xdw = 2.0_DP * v2xdw
|
||||
|
||||
case(13) ! 'rPW86 for vdw-df2'
|
||||
do i=1,length
|
||||
if (rhoup(i) > small .and. sqrt(abs(grhoup2(i))) > small) then
|
||||
call rPW86 (2.0_DP * rhoup(i), 4.0_DP * grhoup2(i), sxup(i), v1xup(i), v2xup(i))
|
||||
else
|
||||
sxup(i) = 0.0_DP
|
||||
v1xup(i) = 0.0_DP
|
||||
v2xup(i) = 0.0_DP
|
||||
endif
|
||||
if (rhodw(i) > small .and. sqrt(abs(grhodw2(i))) > small) then
|
||||
call rPW86 (2.0_DP * rhodw(i), 4.0_DP * grhodw2(i), sxdw(i), v1xdw(i), v2xdw(i))
|
||||
else
|
||||
sxdw(i) = 0.0_DP
|
||||
v1xdw(i) = 0.0_DP
|
||||
v2xdw(i) = 0.0_DP
|
||||
endif
|
||||
end do
|
||||
sx = 0.5_DP * (sxup + sxdw)
|
||||
v2xup = 2.0_DP * v2xup
|
||||
v2xdw = 2.0_DP * v2xdw
|
||||
|
||||
case(16) ! 'c09x for vdw-df-c09'
|
||||
do i=1,length
|
||||
if (rhoup(i) > small .and. sqrt(abs(grhoup2(i))) > small) then
|
||||
call c09x (2.0_DP * rhoup(i), 4.0_DP * grhoup2(i), sxup(i), v1xup(i), v2xup(i))
|
||||
else
|
||||
sxup(i) = 0.0_DP
|
||||
v1xup(i) = 0.0_DP
|
||||
v2xup(i) = 0.0_DP
|
||||
endif
|
||||
if (rhodw(i) > small .and. sqrt(abs(grhodw2(i))) > small) then
|
||||
call c09x (2.0_DP * rhodw(i), 4.0_DP * grhodw2(i), sxdw(i), v1xdw(i), v2xdw(i))
|
||||
else
|
||||
sxdw(i) = 0.0_DP
|
||||
v1xdw(i) = 0.0_DP
|
||||
v2xdw(i) = 0.0_DP
|
||||
endif
|
||||
end do
|
||||
sx = 0.5_DP * (sxup + sxdw)
|
||||
v2xup = 2.0_DP * v2xup
|
||||
v2xdw = 2.0_DP * v2xdw
|
||||
|
||||
case(21) ! 'pw86'
|
||||
do i=1,length
|
||||
if (rhoup(i) > small .and. sqrt(abs(grhoup2(i))) > small) then
|
||||
|
@ -2087,7 +2184,7 @@ subroutine nlc (rho_valence, rho_core, nspin, enl, vnl, v)
|
|||
! v = Correction to the potential
|
||||
!
|
||||
|
||||
USE vdW_DF, ONLY: xc_vdW_DF, vdw_type
|
||||
USE vdW_DF, ONLY: xc_vdW_DF, xc_vdW_DF_spin, vdw_type
|
||||
USE rVV10, ONLY: xc_rVV10
|
||||
|
||||
implicit none
|
||||
|
@ -2097,14 +2194,20 @@ subroutine nlc (rho_valence, rho_core, nspin, enl, vnl, v)
|
|||
REAL(DP), INTENT(INOUT) :: v(:,:)
|
||||
REAL(DP), INTENT(INOUT) :: enl, vnl
|
||||
|
||||
if (inlc == 1 .or. inlc == 2) then
|
||||
|
||||
if ( inlc == 1 .or. inlc == 2 .or. inlc == 4 .or. inlc == 5 .or. inlc == 6 ) then
|
||||
|
||||
vdw_type = inlc
|
||||
call xc_vdW_DF(rho_valence, rho_core, nspin, enl, vnl, v)
|
||||
if( nspin == 1 ) then
|
||||
call xc_vdW_DF (rho_valence, rho_core, enl, vnl, v)
|
||||
else if( nspin == 2 ) then
|
||||
call xc_vdW_DF_spin (rho_valence, rho_core, enl, vnl, v)
|
||||
else
|
||||
call errore ('nlc','vdW-DF not available for noncollinear spin case',1)
|
||||
end if
|
||||
|
||||
elseif (inlc == 3) then
|
||||
|
||||
call xc_rVV10(rho_valence, rho_core, nspin, enl, vnl, v)
|
||||
call xc_rVV10 (rho_valence, rho_core, nspin, enl, vnl, v)
|
||||
|
||||
else
|
||||
enl = 0.0_DP
|
||||
|
|
|
@ -1,183 +1,198 @@
|
|||
!
|
||||
! Copyright (C) 2001-2009 Quantum ESPRESSO group
|
||||
! Copyright (C) 2009 Brian Kolb, Timo Thonhauser - Wake Forest University
|
||||
! This file is distributed under the terms of the
|
||||
! GNU General Public License. See the file `License'
|
||||
! in the root directory of the present distribution,
|
||||
! or http://www.gnu.org/copyleft/gpl.txt .
|
||||
!
|
||||
!----------------------------------------------------------------------------
|
||||
! ----------------------------------------------------------------------
|
||||
|
||||
|
||||
MODULE kernel_table
|
||||
|
||||
!! This module is used to read in the kernel table file
|
||||
!! "vdW_kernel_table" and store some of the important parameters. The
|
||||
!! top of the vdW_kernel_table file holds the number of q points, the
|
||||
!! number of radial points (r) used in the kernel generation, the maximum
|
||||
!! value of r used (r is the parameter in the kernel function d=q*r where
|
||||
!! q is defined in DION equation 11), and the values of the q points
|
||||
!! used. These parameters are stored as public parameters for use in
|
||||
!! various routines. This routine also reads the tabulated values of the
|
||||
!! Fourier transformed kernel function for each pair of q values (see
|
||||
!! SOLER equations 3 and 8). Since these kernel functions need to be
|
||||
!! interpolated using splines, the second derivatives of the Fourier
|
||||
!! transformed kernel functions (phi_alpha_beta) are also tabulated in
|
||||
!! the vdW_kernel_table and are read in here.
|
||||
|
||||
!! This is done in a module because there are quite a few subroutines in
|
||||
!! xc_vdW_DF.f90 that require knowledge of the number (identity) of q
|
||||
!! points, the maximum value of the radius, and, of course, the tabulated
|
||||
!! kernel function and its second derivatives (for spline interpolation).
|
||||
!! Putting this routine in a module meas that those routines can just use
|
||||
!! kernel_table rather than passing variables around all over the place.
|
||||
|
||||
USE kinds, ONLY : dp
|
||||
USE io_files, ONLY : pseudo_dir
|
||||
USE constants, ONLY : pi
|
||||
use wrappers, ONLY : md5_from_file
|
||||
implicit none
|
||||
|
||||
private
|
||||
save
|
||||
|
||||
!! Variables to be used by various routines in xc_vdW_DF.f90, declared
|
||||
!! public so they can be seen from outside
|
||||
! --------------------------------------------------------------------------
|
||||
|
||||
public :: Nqs, Nr_points, r_max, q_mesh, q_cut, q_min, dk
|
||||
public :: kernel, d2phi_dk2
|
||||
public :: initialize_kernel_table
|
||||
public :: vdw_table_name
|
||||
public :: vdw_kernel_md5_cksum
|
||||
integer :: Nqs, Nr_points !! The number of q points and radial points
|
||||
! !! used in generating the kernel phi(q1*r, q2*r)
|
||||
! !! (see DION 14-16 and SOLER 3)
|
||||
! This module is used to read in the kernel table file
|
||||
! "vdW_kernel_table" and store some of the important parameters. The top
|
||||
! of the vdW_kernel_table file holds the number of q points, the number
|
||||
! of radial points (r) used in the kernel generation, the maximum value
|
||||
! of r used (r is the parameter in the kernel function d=q*r where q is
|
||||
! defined in DION equation 11), and the values of the q points used.
|
||||
! These parameters are stored as public parameters for use in various
|
||||
! routines. This routine also reads the tabulated values of the Fourier
|
||||
! transformed kernel function for each pair of q values (see SOLER
|
||||
! equations 3 and 8). Since these kernel functions need to be
|
||||
! interpolated using splines, the second derivatives of the Fourier
|
||||
! transformed kernel functions (phi_alpha_beta) are also tabulated in
|
||||
! the vdW_kernel_table and are read in here.
|
||||
|
||||
real(dp) :: r_max, q_cut, q_min, dk !! The maximum value of r, the maximum and minimum
|
||||
! !! values of q and the k-space spacing of grid points.
|
||||
! !! Note that, during a vdW run, values of q0 found
|
||||
! !! larger than q_cut will be saturated (SOLER 5) to
|
||||
! !! q_cut
|
||||
! This is done in a module because there are quite a few subroutines in
|
||||
! xc_vdW_DF.f90 that require knowledge of the number (identity) of q
|
||||
! points, the maximum value of the radius, and, of course, the tabulated
|
||||
! kernel function and its second derivatives (for spline interpolation).
|
||||
! Putting this routine in a module meas that those routines can just use
|
||||
! kernel_table rather than passing variables around all over the place.
|
||||
|
||||
real(dp), allocatable :: q_mesh(:) !! The values of all the q points used
|
||||
USE kinds, ONLY : dp
|
||||
USE io_files, ONLY : pseudo_dir
|
||||
USE constants, ONLY : pi
|
||||
use wrappers, ONLY : md5_from_file
|
||||
implicit none
|
||||
|
||||
real(dp), allocatable :: kernel(:,:,:) !! A matrix holding the Fourier transformed kernel function
|
||||
! !! for each pair of q values. The ordering is
|
||||
! !! kernel(k_point, q1_value, q2_value)
|
||||
private
|
||||
save
|
||||
|
||||
|
||||
! ----------------------------------------------------------------------
|
||||
! Variables to be used by various routines in xc_vdW_DF.f90, declared
|
||||
! public so they can be seen from outside
|
||||
|
||||
public :: Nqs, Nr_points, r_max, q_mesh, q_cut, q_min, dk
|
||||
public :: kernel, d2phi_dk2
|
||||
public :: initialize_kernel_table
|
||||
public :: vdw_table_name
|
||||
public :: vdw_kernel_md5_cksum
|
||||
integer :: Nqs, Nr_points ! The number of q points and radial points
|
||||
! used in generating the kernel phi(q1*r, q2*r)
|
||||
! (see DION 14-16 and SOLER 3-5).
|
||||
|
||||
real(dp) :: r_max, q_cut, q_min, dk ! The maximum value of r, the maximum and minimum
|
||||
! values of q and the k-space spacing of grid points.
|
||||
! Note that, during a vdW run, values of q0 found
|
||||
! larger than q_cut will be saturated (SOLER 5) to
|
||||
! q_cut.
|
||||
|
||||
real(dp), allocatable :: q_mesh(:) ! The values of all the q points used.
|
||||
|
||||
real(dp), allocatable :: kernel(:,:,:) ! A matrix holding the Fourier transformed kernel
|
||||
! function for each pair of q values. The ordering
|
||||
! is kernel(k_point, q1_value, q2_value).
|
||||
|
||||
real(dp), allocatable :: d2phi_dk2(:,:,:) ! A matrix holding the second derivatives of the
|
||||
! above kernel matrix at each of the q points.
|
||||
! Stored as d2phi_dk2(k_point, q1_value, q2_value).
|
||||
|
||||
character(len=256) :: vdw_table_name = ' ' ! If present from input use this name.
|
||||
character(LEN=30) :: double_format = "(1p4e23.14)"
|
||||
character(len=32) :: vdw_kernel_md5_cksum = 'NOT SET'
|
||||
|
||||
integer, external :: find_free_unit
|
||||
|
||||
real(dp), allocatable :: d2phi_dk2(:,:,:) !! A matrix holding the second derivatives of the above
|
||||
! !! kernel matrix at each of the q points. Stored as
|
||||
! !! d2phi_dk2(k_point, q1_value, q2_value)
|
||||
!
|
||||
character(len=256) :: vdw_table_name = ' ' !! If present from input use this name
|
||||
CHARACTER(LEN=30) :: double_format = "(1p4e23.14)"
|
||||
CHARACTER(len=32) :: vdw_kernel_md5_cksum = 'NOT SET'
|
||||
!
|
||||
INTEGER, EXTERNAL :: find_free_unit
|
||||
! --------------------------------------------------------------------------
|
||||
|
||||
CONTAINS
|
||||
|
||||
|
||||
!! ###################################################################################
|
||||
!! | |
|
||||
!! | INITIALIZE_KERNEL_TABLE |
|
||||
!! |___________________________|
|
||||
|
||||
!! Subroutine that actually reads the kernel file and stores the parameters. This routine
|
||||
!! is called only once, at the start of a vdW run.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
! ####################################################################
|
||||
! | |
|
||||
! | INITIALIZE_KERNEL_TABLE |
|
||||
! |___________________________|
|
||||
!
|
||||
! Subroutine that actually reads the kernel file and stores the
|
||||
! parameters. This routine is called only once, at the start of a vdW
|
||||
! run.
|
||||
|
||||
subroutine initialize_kernel_table(inlc)
|
||||
|
||||
|
||||
integer, INTENT(IN) :: inlc
|
||||
|
||||
integer :: q1_i, q2_i !! Indexing variables
|
||||
integer :: q1_i, q2_i ! Indexing variables.
|
||||
|
||||
integer :: kernel_file ! The unit number for the kernel file.
|
||||
|
||||
logical :: file_exists ! A variable to say whether
|
||||
! needed file exists.
|
||||
|
||||
character(len=1000) :: kernel_file_name ! The path to the kernel file.
|
||||
! Although this name must be
|
||||
! "vdW_kernel_table", this variable
|
||||
! is used to hold the entire path
|
||||
! since we check 3 places for it.
|
||||
|
||||
integer :: kernel_file !! The unit number for the kernel file
|
||||
|
||||
logical :: file_exists !! A variable to say whether
|
||||
! !! needed file exists
|
||||
|
||||
character(len=1000) :: kernel_file_name !! The path to the kernel file.
|
||||
! !! Although this name must be
|
||||
! !! "vdW_kernel_table", this variable
|
||||
! !! is used to hold the entire path
|
||||
! !! since we check 3 places for it.
|
||||
|
||||
|
||||
!!write(*,*) "Reading kernel table ... "
|
||||
|
||||
!! Get the unit number for the kernel file
|
||||
kernel_file = find_free_unit()
|
||||
|
||||
|
||||
!!
|
||||
!!
|
||||
|
||||
if (TRIM(vdw_table_name)==' ') then
|
||||
|
||||
|
||||
if (inlc==3) then
|
||||
vdw_table_name='rVV10_kernel_table'
|
||||
else
|
||||
vdw_table_name='vdW_kernel_table'
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
if (allocated(kernel)) then
|
||||
|
||||
return
|
||||
if (allocated(kernel)) return
|
||||
|
||||
end if
|
||||
|
||||
|
||||
!! First we check the current directory for the vdW_kernel_table file
|
||||
!! If it is not found there it is looked for in the pseudopotential
|
||||
!! directory. If it's not there the default kernel file installed
|
||||
!! in the PW directory of the PWSCF source is tried. If none of those
|
||||
!! exist the code crashes.
|
||||
! ------------------------------------------------------------------
|
||||
! First we check the current directory for the vdW_kernel_table
|
||||
! file. If it is not found there, it is looked for in the
|
||||
! pseudopotential directory. If it's not therei, the default kernel
|
||||
! file installed in the PW directory of the PWSCF source is tried.
|
||||
! If none of those exist the code crashes.
|
||||
|
||||
kernel_file_name=vdw_table_name
|
||||
inquire(file=kernel_file_name, exist=file_exists)
|
||||
|
||||
!! If the file is found in the current directory we use that one
|
||||
!! ------------------------------------------------------------------------------------------
|
||||
|
||||
! ------------------------------------------------------------------
|
||||
! If the file is found in the current directory we use that one.
|
||||
|
||||
if (.not. file_exists) then
|
||||
|
||||
!! No "vdW_kernel_table" file in the current directory. Try the pseudopotential directory
|
||||
!! -----------------------------------------------------------------------------------------
|
||||
! ---------------------------------------------------------------
|
||||
! No "vdW_kernel_table" file in the current directory. Try the
|
||||
! pseudopotential directory.
|
||||
|
||||
kernel_file_name = trim(pseudo_dir)//'/'//vdw_table_name
|
||||
inquire(file=kernel_file_name, exist=file_exists)
|
||||
|
||||
if (.not. file_exists) call errore('read_kernel_table', &
|
||||
TRIM(vdw_table_name)//' file could be found',1)
|
||||
if (.not. file_exists) call errore('read_kernel_table', &
|
||||
TRIM(vdw_table_name)//' file not found',1)
|
||||
|
||||
end if
|
||||
|
||||
!! Generates the md5 file
|
||||
|
||||
! ------------------------------------------------------------------
|
||||
! Generates the md5 file.
|
||||
|
||||
CALL md5_from_file(kernel_file_name, vdw_kernel_md5_cksum)
|
||||
|
||||
!! Open the file to read
|
||||
open(unit=kernel_file, file=kernel_file_name, status='old', form='formatted', action='read')
|
||||
|
||||
!! Read in the number of q points used for this kernel file, the
|
||||
!! number of r points, and the maximum value of the r point
|
||||
! ------------------------------------------------------------------
|
||||
! Open the file to read.
|
||||
|
||||
open(unit=kernel_file, file=kernel_file_name, status='old', form='formatted', action='read')
|
||||
|
||||
|
||||
! ------------------------------------------------------------------
|
||||
! Read in the number of q points used for this kernel file, the
|
||||
! number of r points, and the maximum value of the r point.
|
||||
|
||||
read(kernel_file, '(2i5)') Nqs, Nr_points
|
||||
read(kernel_file, double_format) r_max
|
||||
|
||||
allocate( q_mesh(Nqs) )
|
||||
allocate( kernel(0:Nr_points,Nqs,Nqs), d2phi_dk2(0:Nr_points,Nqs,Nqs) )
|
||||
|
||||
!! Read in the values of the q points used to generate this kernel
|
||||
|
||||
|
||||
! ------------------------------------------------------------------
|
||||
! Read in the values of the q points used to generate this kernel.
|
||||
|
||||
read(kernel_file, double_format) q_mesh
|
||||
|
||||
|
||||
!! For each pair of q values, read in the function phi_q1_q2(k).
|
||||
!! That is, the fourier transformed kernel function assuming q1 and q2
|
||||
!! for all the values of r used.
|
||||
!! ----------------------------------------------------------------------------------------------
|
||||
|
||||
! ------------------------------------------------------------------
|
||||
! For each pair of q values, read in the function phi_q1_q2(k).
|
||||
! That is, the fourier transformed kernel function assuming q1 and
|
||||
! q2 for all the values of r used.
|
||||
|
||||
do q1_i = 1, Nqs
|
||||
do q2_i = 1, q1_i
|
||||
|
||||
|
@ -187,15 +202,12 @@ CONTAINS
|
|||
end do
|
||||
end do
|
||||
|
||||
!! ----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
!! Again, for each pair of q values (q1 and q2), read in the value
|
||||
!! of the second derivative of the above mentiond Fourier transformed
|
||||
!! kernel function phi_alpha_beta(k). These are used for spline
|
||||
!! interpolation of the Fourier transformed kernel.
|
||||
!! -----------------------------------------------------------------------------------------------
|
||||
! ------------------------------------------------------------------
|
||||
! Again, for each pair of q values (q1 and q2), read in the value of
|
||||
! the second derivative of the above mentiond Fourier transformed
|
||||
! kernel function phi_alpha_beta(k). These are used for spline
|
||||
! interpolation of the Fourier transformed kernel.
|
||||
|
||||
do q1_i = 1, Nqs
|
||||
do q2_i = 1, q1_i
|
||||
|
@ -206,23 +218,19 @@ CONTAINS
|
|||
end do
|
||||
end do
|
||||
|
||||
!! -----------------------------------------------------------------------------------------------
|
||||
|
||||
close(kernel_file)
|
||||
|
||||
!! Define a few more vaiables useful to some of the subroutines in xc_vdW_DF.f90
|
||||
!! ------------------------------------------------------------------------------------------------
|
||||
|
||||
! ------------------------------------------------------------------
|
||||
! Define a few more vaiables useful to some of the subroutines in
|
||||
! xc_vdW_DF.f90.
|
||||
|
||||
q_cut = q_mesh(Nqs)
|
||||
q_min = q_mesh(1)
|
||||
dk = 2.0D0*pi/r_max
|
||||
|
||||
!! ------------------------------------------------------------------------------------------------
|
||||
|
||||
end subroutine initialize_kernel_table
|
||||
|
||||
!! #################################################################################################
|
||||
|
||||
|
||||
|
||||
end MODULE kernel_table
|
||||
|
|
|
@ -1349,12 +1349,11 @@ CONTAINS
|
|||
! Vdw kernel table
|
||||
!
|
||||
IF ( present(inlc) ) THEN
|
||||
IF ( inlc == 1 .OR. inlc ==2 .OR. inlc == 3 ) THEN
|
||||
IF ( inlc > 0 ) THEN
|
||||
IF ( .NOT. PRESENT( vdw_table_name ) .OR. &
|
||||
.NOT. PRESENT( pseudo_dir ) .OR. &
|
||||
.NOT. PRESENT( dirname )) &
|
||||
CALL errore( 'write_xc', &
|
||||
' variable vdw_table_name not present', 1 )
|
||||
.NOT. PRESENT( pseudo_dir ) .OR. &
|
||||
.NOT. PRESENT( dirname )) &
|
||||
CALL errore( 'write_xc', ' variable vdw_table_name not present', 1 )
|
||||
|
||||
CALL iotk_write_dat( ounit, "NON_LOCAL_DF", inlc )
|
||||
CALL iotk_write_dat( ounit, "VDW_KERNEL_NAME", TRIM(vdw_table_name))
|
||||
|
@ -3453,8 +3452,7 @@ CONTAINS
|
|||
CALL iotk_scan_dat( iunit, "NON_LOCAL_DF", inlc_, FOUND = found )
|
||||
IF ( found ) THEN
|
||||
!
|
||||
IF ( inlc_ == 1 .OR. inlc_ == 2 .OR. inlc_ == 3 ) &
|
||||
CALL iotk_scan_dat( iunit, "VDW_KERNEL_NAME", vdw_table_name_ )
|
||||
IF ( inlc_ > 0 ) CALL iotk_scan_dat( iunit, "VDW_KERNEL_NAME", vdw_table_name_ )
|
||||
!
|
||||
ELSE
|
||||
!
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -139,8 +139,7 @@ and many others. We quote in particular:
|
|||
built upon previous work by Guido Fratesi (Univ.Milano Bicocca)
|
||||
and Riccardo Mazzarello (ETHZ-USI Lugano);
|
||||
\item Matteo Cococcioni (Univ. Minnesota) for DFT+U implementation;
|
||||
\item Timo Thonhauser's group (Wake Forest University) for vdW-DF and
|
||||
variants;
|
||||
\item Timo Thonhauser (WFU) for vdW-DF, svdW-DF, and variants;
|
||||
\end{itemize}
|
||||
and the more recent contributors:
|
||||
\begin{itemize}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,14 +30,12 @@ subroutine stres_nonloc_dft( rho, rho_core, nspin, sigma_nonloc_dft )
|
|||
sigma_nonloc_dft(:,:) = 0.d0
|
||||
inlc = get_inlc()
|
||||
|
||||
if (inlc==1 .or. inlc==2) then
|
||||
if (nspin>2) call errore('stres_vdW_DF', &
|
||||
'vdW+DF non implemented in spin polarized calculations',1)
|
||||
if ( inlc==1 .or. inlc==2 .or. inlc==4 .or. inlc==5 .or. inlc==6 ) then
|
||||
if ( nspin>1 ) call errore ('stres_vdW_DF', 'vdW stress not implemented for nspin > 1',1)
|
||||
CALL stress_vdW_DF(rho, rho_core, nspin, sigma_nonloc_dft)
|
||||
elseif (inlc == 3) then
|
||||
if (nspin>2) call errore('stress_rVV10', &
|
||||
'rVV10 non implemented with nspin>2',1)
|
||||
CALL stress_rVV10(rho, rho_core, nspin, sigma_nonloc_dft)
|
||||
elseif ( inlc == 3 ) then
|
||||
if ( nspin>2 ) call errore ('stress_rVV10', 'rVV10 stress not implemented for nspin > 2',1)
|
||||
CALL stress_rVV10(rho, rho_core, nspin, sigma_nonloc_dft)
|
||||
end if
|
||||
|
||||
return
|
||||
|
|
|
@ -471,10 +471,8 @@ SUBROUTINE print_vdw_info
|
|||
integer :: inlc
|
||||
|
||||
inlc = get_inlc()
|
||||
if (inlc==1 .or. inlc==2 .or. inlc==3) then
|
||||
|
||||
WRITE( stdout, '(/5x,"vdW kernel table read from file ",a)')&
|
||||
TRIM (vdw_table_name)
|
||||
if ( inlc > 0 ) then
|
||||
WRITE( stdout, '(/5x,"vdW kernel table read from file ",a)') TRIM (vdw_table_name)
|
||||
WRITE( stdout, '(5x,"MD5 check sum: ", a )') vdw_kernel_md5_cksum
|
||||
endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue