quantum-espresso/LR_Modules/setup_dgc.f90

220 lines
6.6 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
!-----------------------------------------------------------------------
2022-07-22 22:14:43 +08:00
!! This subroutine computes \(\text{dvxc}\), the derivative of the XC
!! potential for the gradient correction (GGA).
!
!! 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
2022-07-14 00:30:33 +08:00
USE fft_rho, ONLY : rho_r2g
2017-12-24 22:24:26 +08:00
USE gvect, ONLY : ngm, g
2019-01-21 19:02:37 +08:00
USE scf, ONLY : rho, rho_core, rhog_core, rhoz_or_updw
2021-10-22 13:56:50 +08:00
USE noncollin_module, ONLY : noncolin, domag, ux, nspin_gga, nspin_mag
USE kinds, ONLY : DP
2021-12-20 20:04:48 +08:00
USE xc_lib, ONLY : xclib_dft_is, xc_gcx, dgcxc
USE uspp, ONLY : nlcc_any
USE gc_lr, ONLY : grho, gmag, dvxc_rr, dvxc_sr, &
dvxc_ss, dvxc_s, vsgga, segni
!
IMPLICIT NONE
!
2022-12-13 22:32:38 +08:00
INTEGER :: k, is, ipol, jpol, ir, dfftp_nnr
!
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
!
2022-04-29 22:19:21 +08:00
!
2020-10-08 21:48:10 +08:00
IF ( .NOT. xclib_dft_is('gradient') ) RETURN
!
CALL start_clock( 'setup_dgc' )
!
2022-12-13 22:32:38 +08:00
dfftp_nnr = dfftp%nnr !to avoid unnecessary copies in acc loop
!
2022-04-29 22:19:21 +08:00
!$acc data copyin( rho )
!$acc data copyin( rho_core, rhog_core, rho%of_r, rho%of_g )
!
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) )
!
2022-04-29 22:19:21 +08:00
!$acc data create( rhoout, grh, sx, sc, v1x, v2x, v1c, v2c, v2c_ud )
2022-07-22 22:14:43 +08:00
!$acc data copyout( dvxc_rr, dvxc_sr, dvxc_ss, dvxc_s, grho )
2022-04-29 22:19:21 +08:00
!
fac = 1.d0/DBLE(nspin_gga)
!
!$acc kernels
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
2022-04-29 22:19:21 +08:00
!$acc end kernels
!
IF (noncolin .AND. domag) THEN
!
2022-07-22 22:14:43 +08:00
ALLOCATE( rhogout(ngm,nspin_mag) )
!$acc data create(rhogout)
!
CALL compute_rho( rho%of_r, rhoout, segni, dfftp%nnr )
!
DO is = 1, nspin_gga
2022-04-29 22:19:21 +08:00
!
IF (nlcc_any) THEN
!$acc kernels
rhoout(:,is) = rhoout(:,is) + fac*rho_core(:)
!$acc end kernels
ENDIF
!
2022-07-20 21:21:49 +08:00
CALL rho_r2g( dfftp, rhoout(:,is), rhogout(:,is:is) )
CALL fft_gradient_g2r( dfftp, rhogout(1,is), g, grho(1,1,is) )
2022-04-29 22:19:21 +08:00
!
ENDDO
2019-01-21 19:02:37 +08:00
!
2022-04-29 22:19:21 +08:00
!$acc end data
2022-07-22 22:14:43 +08:00
DEALLOCATE( rhogout )
2019-01-21 19:02:37 +08:00
!
ELSE
! ... for convenience, if LSDA, rhoout is kept in (up,down) format
2022-04-29 22:19:21 +08:00
!
sgn(1)=1.d0 ; sgn(2)=-1.d0
!
2022-04-29 22:22:58 +08:00
!$acc parallel loop collapse(2) copyin(sgn) present(rho)
DO is = 1, nspin_gga
2022-12-13 22:32:38 +08:00
DO ir = 1, dfftp_nnr
2022-04-29 22:19:21 +08:00
rhoout(ir,is) = ( rho%of_r(ir,1) + sgn(is)*rho%of_r(ir,nspin_gga) )*0.5d0
ENDDO
ENDDO
2019-01-21 19:02:37 +08:00
!
! ... if LSDA rho%of_g is temporarily converted in (up,down) format
2022-04-29 22:19:21 +08:00
!
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
2022-04-29 22:22:58 +08:00
!$acc kernels present(rho)
2022-04-29 22:19:21 +08:00
rhoout(:,is) = fac * rho_core(:) + rhoout(:,is)
rho%of_g(:,is) = fac * rhog_core(:) + rho%of_g(:,is)
2022-04-29 22:19:21 +08:00
!$acc end kernels
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)
2022-04-29 22:19:21 +08:00
!$acc parallel loop
2022-12-13 22:32:38 +08:00
DO k = 1, dfftp_nnr
2019-08-22 21:49:25 +08:00
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
!
2022-12-13 22:32:38 +08:00
CALL dgcxc( dfftp_nnr, 1, rhoout, grh, dvxc_rr, dvxc_sr, dvxc_ss, &
2022-04-29 22:19:21 +08:00
gpu_args_=.TRUE. )
!
2022-04-29 22:19:21 +08:00
!$acc parallel loop
2022-12-13 22:32:38 +08:00
DO ir = 1, dfftp_nnr
2022-04-29 22:19:21 +08:00
IF( rhoout(ir,1)<0.d0 ) rhoout(ir,1)=0.d0
ENDDO
2019-12-05 17:34:34 +08:00
!
2022-12-13 22:32:38 +08:00
CALL xc_gcx( dfftp_nnr, nspin_gga, rhoout, grho, sx, sc, v1x, v2x, v1c, v2c, &
2022-04-29 22:19:21 +08:00
gpu_args_=.TRUE. )
!
2022-04-29 22:19:21 +08:00
!$acc kernels
2019-08-22 21:49:25 +08:00
dvxc_s(:,1,1) = e2 * (v2x(:,1) + v2c(:,1))
2022-04-29 22:19:21 +08:00
!$acc end kernels
!
ELSE
!
2022-12-13 22:32:38 +08:00
CALL dgcxc( dfftp_nnr, nspin_gga, rhoout, grh, dvxc_rr, dvxc_sr, dvxc_ss, &
2022-04-29 22:19:21 +08:00
gpu_args_=.TRUE. )
!
2022-12-13 22:32:38 +08:00
CALL xc_gcx( dfftp_nnr, nspin_gga, rhoout, grho, sx, sc, v1x, v2x, v1c, v2c, &
2022-04-29 22:19:21 +08:00
v2c_ud, gpu_args_=.TRUE. )
!
2022-04-29 22:19:21 +08:00
!$acc parallel loop
2022-12-13 22:32:38 +08:00
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
2022-04-29 22:31:27 +08:00
!$acc kernels present(rho)
rho%of_g(:,is) = rho%of_g(:,is) - fac*rhog_core(:)
2022-04-29 22:29:01 +08:00
!$acc end kernels
ENDDO
ENDIF
!
CALL rhoz_or_updw( rho, 'only_g', '->rhoz' )
!
ENDIF
!
2022-04-29 22:29:01 +08:00
!$acc end data
!$acc end data
!
!$acc end data
!$acc end data
!
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