quantum-espresso/Modules/solvation_force.f90

209 lines
5.6 KiB
Fortran

!
! Copyright (C) 2015-2016 Satomichi Nishihara
!
! 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 solvation_force(rismt, force, vloc, ierr)
!---------------------------------------------------------------------------
!
! ... calculate force of 3D-RISM.
! ...
! ... F_sol = F_ele + F_ion + F_lj
! ...
! ... (1) contribution from electrons, which is included in Hellmann-Feynman force,
! ... is set to zero now.
! ... F_ele = 0
! ...
! ... (2) contribution from ions (local part)
! ... F_ion = -Omega \Sum_G -n_sol*(G) d V_loc(G)/d R_i
! ...
! ... (3) contribution from Lennard-Jones potential
! ... F_lj = -Omega \Sum_r n_sol*(r) d V_lj(r)/d R_i
! ...
! ... (Force of solute: T.Luchko et al., J. Chem. Theory Comput. 2010, 6, 607-624)
!
USE err_rism, ONLY : IERR_RISM_NULL, IERR_RISM_INCORRECT_DATA_TYPE
USE gvect, ONLY : ngl
USE ions_base, ONLY : nsp, nat
USE kinds, ONLY : DP
USE solute, ONLY : get_solU_LJ_force
USE rism, ONLY : rism_type, ITYPE_3DRISM, ITYPE_LAUERISM
!
IMPLICIT NONE
!
TYPE(rism_type), INTENT(IN) :: rismt
REAL(DP), INTENT(OUT) :: force(3, nat)
REAL(DP), INTENT(IN) :: vloc(ngl, nsp)
INTEGER, INTENT(OUT) :: ierr
!
REAL(DP), ALLOCATABLE :: forceion(:,:)
REAL(DP), ALLOCATABLE :: forcelj (:,:)
!
! ... check data type
IF (rismt%itype /= ITYPE_3DRISM .AND. rismt%itype /= ITYPE_LAUERISM) THEN
ierr = IERR_RISM_INCORRECT_DATA_TYPE
RETURN
END IF
!
! ... allocate memory
ALLOCATE(forceion(3, nat))
ALLOCATE(forcelj (3, nat))
!
! ... ions term (local part)
forceion = 0.0_DP
CALL solvation_force_ion(rismt, forceion, vloc, ierr)
!
IF (ierr /= IERR_RISM_NULL) THEN
GOTO 1
END IF
!
! ... Lennad-Jones term
forcelj = 0.0_DP
CALL get_solU_LJ_force(rismt, forcelj, ierr)
!
IF (ierr /= IERR_RISM_NULL) THEN
GOTO 1
END IF
!
! ... total solvation force
force = forceion + forcelj
!
! ... normally done
ierr = IERR_RISM_NULL
!
! ... deallocate memory
1 CONTINUE
DEALLOCATE(forceion)
DEALLOCATE(forcelj)
!
END SUBROUTINE solvation_force
!
!---------------------------------------------------------------------------
SUBROUTINE solvation_force_ion(rismt, force, vloc, ierr)
!---------------------------------------------------------------------------
!
USE cell_base, ONLY : alat, omega
USE constants, ONLY : tpi
USE control_flags, ONLY : gamma_only
USE err_rism, ONLY : IERR_RISM_NULL, IERR_RISM_INCORRECT_DATA_TYPE
USE gvect, ONLY : ngl, igtongl
USE ions_base, ONLY : nsp, nat, ityp, tau
USE kinds, ONLY : DP
USE mp, ONLY : mp_sum
USE rism, ONLY : rism_type, ITYPE_3DRISM, ITYPE_LAUERISM
!
IMPLICIT NONE
!
TYPE(rism_type), INTENT(IN) :: rismt
REAL(DP), INTENT(OUT) :: force(3, nat)
REAL(DP), INTENT(IN) :: vloc(ngl, nsp)
INTEGER, INTENT(OUT) :: ierr
!
INTEGER :: ipol
INTEGER :: ig
INTEGER :: na
REAL(DP) :: arg
REAL(DP) :: rhogr
REAL(DP) :: rhogi
REAL(DP) :: vrho
REAL(DP) :: fact
REAL(DP) :: forc1(3)
REAL(DP), ALLOCATABLE :: forcesm(:,:)
COMPLEX(DP), POINTER :: rhogt(:)
LOGICAL :: laue
!
! ... check data type
IF (rismt%itype /= ITYPE_3DRISM .AND. rismt%itype /= ITYPE_LAUERISM) THEN
ierr = IERR_RISM_INCORRECT_DATA_TYPE
RETURN
END IF
!
IF (rismt%ng < rismt%gvec%ngm) THEN
ierr = IERR_RISM_INCORRECT_DATA_TYPE
RETURN
END IF
!
! ... Laue-RISM or not
laue = .FALSE.
IF (rismt%itype == ITYPE_LAUERISM) THEN
laue = .TRUE.
END IF
!
! ... allocate memory
IF (laue .AND. (nat > 0)) THEN
ALLOCATE(forcesm(3, nat))
END IF
!
! ... factor of Gamma-trick
IF (gamma_only) THEN
fact = 2.0_DP
ELSE
fact = 1.0_DP
END IF
!
! ... set solvent density
IF (laue) THEN
rhogt => rismt%rhog_pbc
ELSE
rhogt => rismt%rhog
END IF
!
! ... calculate forces for each atom
DO na = 1, nat
DO ipol = 1, 3
forc1(ipol) = 0.0_DP
END DO
!
! ... contribution from G=0 is zero
!$omp parallel do default(shared) private(ig, ipol, arg, rhogr, rhogi, vrho) reduction(+:forc1)
DO ig = rismt%gvec%gstart, rismt%gvec%ngm
arg = (rismt%gvec%g(1, ig) * tau(1, na) &
& + rismt%gvec%g(2, ig) * tau(2, na) &
& + rismt%gvec%g(3, ig) * tau(3, na)) * tpi
rhogr = -DBLE( rhogt(ig))
rhogi = -AIMAG(rhogt(ig))
vrho = vloc(igtongl(ig), ityp(na)) * (SIN(arg) * rhogr + COS(arg) * rhogi)
!
DO ipol = 1, 3
forc1(ipol) = forc1(ipol) + rismt%gvec%g(ipol, ig) * vrho
END DO
END DO
!$omp end parallel do
!
DO ipol = 1, 3
force(ipol, na) = fact * forc1(ipol) * omega * tpi / alat
END DO
END DO
!
CALL mp_sum(force, rismt%mp_site%intra_sitg_comm)
!
! ... clear solvent density
NULLIFY(rhogt)
!
! ... add long-range from ESM(BC1)
IF (laue .AND. (nat > 0)) THEN
forcesm = 0.0_DP
CALL solvation_esm_force(rismt, 1.0_DP / alat, forcesm, ierr)
!
IF (ierr /= IERR_RISM_NULL) THEN
GOTO 1
END IF
!
force = force + forcesm
END IF
!
! ... normally done
ierr = IERR_RISM_NULL
!
! ... deallocate memory
1 CONTINUE
IF (laue .AND. (nat > 0)) THEN
DEALLOCATE(forcesm)
END IF
!
END SUBROUTINE solvation_force_ion