quantum-espresso/LR_Modules/setup_dgc.f90

177 lines
5.5 KiB
Fortran
Raw Normal View History

!
! Copyright (C) 2001-2018 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
SUBROUTINE setup_dgc
!-----------------------------------------------------------------------
!! Allocate and set up all variable needed in the gradient correction case.
!
!! GGA+LSDA is allowed. ADC (September 1999);
!! GGA+LSDA+NLCC is allowed. ADC (November 1999);
!! GGA+noncollinear+NLCC is allowed. ADC (June 2007).
!
USE constants, ONLY : e2
USE fft_base, ONLY : dfftp
USE fft_interfaces, ONLY : fwfft
2017-12-24 22:24:26 +08:00
USE gvect, ONLY : ngm, g
USE spin_orb, ONLY : domag
2019-01-21 19:02:37 +08:00
USE scf, ONLY : rho, rho_core, rhog_core, rhoz_or_updw
USE noncollin_module, ONLY : noncolin, ux, nspin_gga, nspin_mag
2019-01-21 19:02:37 +08:00
USE wavefunctions, ONLY : psic
USE kinds, ONLY : DP
2020-10-19 02:16:45 +08:00
USE xc_lib, ONLY : xclib_dft_is, xc_gcx
USE uspp, ONLY : nlcc_any
USE gc_lr, ONLY : grho, gmag, dvxc_rr, dvxc_sr, &
dvxc_ss, dvxc_s, vsgga, segni
!
IMPLICIT NONE
!
INTEGER :: k, is, ipol, jpol, ir
!
2019-08-22 21:49:25 +08:00
REAL(DP), ALLOCATABLE :: grh(:,:,:)
REAL(DP) :: fac, sgn(2)
!
REAL(DP), ALLOCATABLE :: v1x(:,:), v2x(:,:), v1c(:,:), v2c(:,:)
2019-08-22 21:49:25 +08:00
REAL(DP), ALLOCATABLE :: v2c_ud(:)
REAL(DP), ALLOCATABLE :: sc(:), sx(:)
!
REAL(DP), ALLOCATABLE :: rhoout(:,:)
COMPLEX(DP), ALLOCATABLE :: rhogout(:,:)
!
REAL(DP), PARAMETER :: epsr=1.0d-6, epsg=1.0d-10
!
2020-10-08 21:48:10 +08:00
IF ( .NOT. xclib_dft_is('gradient') ) RETURN
!
CALL start_clock( 'setup_dgc' )
!
IF (noncolin .AND. domag) THEN
ALLOCATE( segni(dfftp%nnr) )
ALLOCATE( vsgga(dfftp%nnr) )
ALLOCATE( gmag(3,dfftp%nnr,nspin_mag) )
gmag = 0.0_dp
ENDIF
!
IF (.NOT.ALLOCATED(dvxc_rr)) ALLOCATE( dvxc_rr(dfftp%nnr,nspin_gga,nspin_gga) )
IF (.NOT.ALLOCATED(dvxc_sr)) ALLOCATE( dvxc_sr(dfftp%nnr,nspin_gga,nspin_gga) )
IF (.NOT.ALLOCATED(dvxc_ss)) ALLOCATE( dvxc_ss(dfftp%nnr,nspin_gga,nspin_gga) )
IF (.NOT.ALLOCATED(dvxc_s) ) ALLOCATE( dvxc_s(dfftp%nnr,nspin_gga,nspin_gga) )
IF (.NOT.ALLOCATED(grho) ) ALLOCATE( grho(3,dfftp%nnr,nspin_gga) )
IF (.NOT.ALLOCATED(rhoout) ) ALLOCATE( rhoout(dfftp%nnr,nspin_gga) )
!
ALLOCATE( v1x(dfftp%nnr,nspin_gga), v2x(dfftp%nnr,nspin_gga) )
ALLOCATE( v1c(dfftp%nnr,nspin_gga), v2c(dfftp%nnr,nspin_gga) )
2019-08-22 21:49:25 +08:00
IF (nspin_gga == 2) ALLOCATE( v2c_ud(dfftp%nnr) )
ALLOCATE( sx(dfftp%nnr), sc(dfftp%nnr) )
2019-08-22 21:49:25 +08:00
ALLOCATE( grh(dfftp%nnr,3,nspin_gga) )
!
dvxc_rr(:,:,:) = 0.d0
dvxc_sr(:,:,:) = 0.d0
dvxc_ss(:,:,:) = 0.d0
2019-08-22 21:49:25 +08:00
dvxc_s(:,:,:) = 0.d0
grho(:,:,:) = 0.d0
!
sgn(1)=1.d0 ; sgn(2)=-1.d0
fac = 1.d0/DBLE(nspin_gga)
!
IF (noncolin .AND. domag) THEN
!
ALLOCATE( rhogout(ngm,nspin_mag) )
!
CALL compute_rho( rho%of_r, rhoout, segni, dfftp%nnr )
!
DO is = 1, nspin_gga
IF (nlcc_any) rhoout(:,is) = fac*rho_core(:) + rhoout(:,is)
psic(:) = rhoout(:,is)
CALL fwfft( 'Rho', psic, dfftp )
2017-12-24 22:24:26 +08:00
rhogout(:,is) = psic(dfftp%nl(:))
CALL fft_gradient_g2r( dfftp, rhogout(1,is), g, grho(1,1,is) )
ENDDO
2019-01-21 19:02:37 +08:00
!
DEALLOCATE( rhogout )
2019-01-21 19:02:37 +08:00
!
ELSE
! ... for convenience, if LSDA, rhoout is kept in (up,down) format
DO is = 1, nspin_gga
2019-01-21 19:02:37 +08:00
rhoout(:,is) = ( rho%of_r(:,1) + sgn(is)*rho%of_r(:,nspin_gga) )*0.5d0
ENDDO
2019-01-21 19:02:37 +08:00
!
! ... if LSDA rho%of_g is temporarily converted in (up,down) format
CALL rhoz_or_updw( rho, 'only_g', '->updw' )
2019-01-21 19:02:37 +08:00
!
IF (nlcc_any) THEN
DO is = 1, nspin_gga
rhoout(:,is) = fac * rho_core(:) + rhoout(:,is)
rho%of_g(:,is) = fac * rhog_core(:) + rho%of_g(:,is)
ENDDO
ENDIF
!
DO is = 1, nspin_gga
CALL fft_gradient_g2r( dfftp, rho%of_g(1,is), g, grho(1,1,is) )
ENDDO
!
ENDIF
!
2019-08-22 21:49:25 +08:00
! ... swap grho indices to match xc_gcx input (waiting for a better fix)
DO k = 1, dfftp%nnr
grh(k,1:3,1) = grho(1:3,k,1)
IF (nspin_gga==2) grh(k,1:3,2) = grho(1:3,k,2)
ENDDO
!
!
IF (nspin_gga == 1) THEN
!
2019-08-22 21:49:25 +08:00
CALL dgcxc( dfftp%nnr, 1, rhoout, grh, dvxc_rr, dvxc_sr, dvxc_ss )
!
2019-12-05 17:34:34 +08:00
WHERE( rhoout(:,1)<0.d0 ) rhoout(:,1)=0.d0
!
2019-08-22 21:49:25 +08:00
CALL xc_gcx( dfftp%nnr, nspin_gga, rhoout, grho, sx, sc, v1x, v2x, v1c, v2c )
!
2019-08-22 21:49:25 +08:00
dvxc_s(:,1,1) = e2 * (v2x(:,1) + v2c(:,1))
!
ELSE
!
2019-08-22 21:49:25 +08:00
CALL dgcxc( dfftp%nnr, nspin_gga, rhoout, grh, dvxc_rr, dvxc_sr, dvxc_ss )
!
2019-08-22 21:49:25 +08:00
CALL xc_gcx( dfftp%nnr, nspin_gga, rhoout, grho, sx, sc, v1x, v2x, v1c, v2c, v2c_ud )
!
DO k = 1, dfftp%nnr
2019-08-22 21:49:25 +08:00
IF ( rhoout(k,1)+rhoout(k,2) > epsr) THEN
dvxc_s(k,1,1) = e2 * (v2x(k,1) + v2c(k,1))
dvxc_s(k,1,2) = e2 * v2c(k,1)
dvxc_s(k,2,1) = e2 * v2c(k,1)
dvxc_s(k,2,2) = e2 * (v2x(k,2) + v2c(k,1))
ENDIF
ENDDO
!
ENDIF
!
!
IF (noncolin .AND. domag) THEN
CALL compute_vsgga( rhoout, grho, vsgga )
ELSE
IF (nlcc_any) THEN
DO is = 1, nspin_gga
rho%of_g(:,is) = rho%of_g(:,is) - fac*rhog_core(:)
ENDDO
ENDIF
!
CALL rhoz_or_updw( rho, 'only_g', '->rhoz' )
!
ENDIF
!
DEALLOCATE( v1x, v2x, v1c, v2c )
2019-08-22 21:49:25 +08:00
IF (nspin_gga == 2) DEALLOCATE( v2c_ud )
DEALLOCATE( sx, sc )
DEALLOCATE( grh )
DEALLOCATE( rhoout )
!
CALL stop_clock( 'setup_dgc' )
!
RETURN
!
END SUBROUTINE setup_dgc