mirror of https://gitlab.com/QEF/q-e.git
267 lines
7.8 KiB
Fortran
267 lines
7.8 KiB
Fortran
!
|
|
! Copyright (C) 2003-2010 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 .
|
|
!
|
|
! ... written by J. Tobik
|
|
!
|
|
! Changes 30/06/2003 (ADC) :
|
|
! Calculation of corrections to energy and forces due
|
|
! to the field.
|
|
! Added possibility to subtract the dipole field
|
|
! for slab or molecule calculation.
|
|
! (See Bengtsson PRB 59, 12 301 (1999) and
|
|
! Meyer and Vanderbilt, PRB 63, 205426 (2001).)
|
|
!
|
|
! 25/06/2009 (Riccardo Sabatini)
|
|
! reformulation using a unique saw(x) function (included in
|
|
! cell_base) in all e-field related routines and inclusion of
|
|
! a macroscopic electronic dipole contribution in the mixing
|
|
! scheme.
|
|
!
|
|
|
|
!
|
|
!--------------------------------------------------------------------------
|
|
SUBROUTINE add_efield(vpoten,etotefield,rho,iflag)
|
|
!--------------------------------------------------------------------------
|
|
!
|
|
! This routine adds an electric field to the local potential. The
|
|
! field is made artificially periodic by introducing a saw-tooth
|
|
! potential. The field is parallel to a reciprocal lattice vector bg,
|
|
! according to the index edir.
|
|
!
|
|
! if dipfield is false the electric field correction is added to the
|
|
! potential given as input (the bare local potential) only
|
|
! at the first call to this routine. In the following calls
|
|
! the routine exit.
|
|
!
|
|
! if dipfield is true the dipole moment per unit surface is calculated
|
|
! and used to cancel the electric field due to periodic boundary
|
|
! conditions. This potential is added to the Hartree and xc potential
|
|
! in v_of_rho. NB: in this case the electric field contribution to the
|
|
! band energy is subtracted by deband.
|
|
!
|
|
!
|
|
USE kinds, ONLY : DP
|
|
USE constants, ONLY : fpi, eps8, e2
|
|
USE ions_base, ONLY : nat, ityp, zv
|
|
USE cell_base, ONLY : alat, at, omega, bg, saw
|
|
USE extfield, ONLY : tefield, dipfield, edir, eamp, emaxpos, &
|
|
eopreg, forcefield
|
|
USE force_mod, ONLY : lforce
|
|
USE gvect, ONLY : nr1, nr2, nr3, nrx1, nrx2, nrx3, nrxx
|
|
USE io_global, ONLY : stdout,ionode
|
|
USE control_flags, ONLY : mixing_beta
|
|
USE lsda_mod, ONLY : nspin
|
|
USE mp_global, ONLY : intra_image_comm, me_pool, intra_pool_comm
|
|
USE fft_base, ONLY : dfftp
|
|
USE mp, ONLY : mp_bcast, mp_sum
|
|
USE control_flags, ONLY : iverbosity
|
|
|
|
IMPLICIT NONE
|
|
!
|
|
! I/O variables
|
|
!
|
|
REAL(DP),INTENT(INOUT) :: vpoten(nrxx) ! the ef is added to this potential
|
|
REAL(DP),INTENT(INOUT) :: etotefield ! the contribution to etot due to ef
|
|
REAL(DP),INTENT(IN) :: rho(nrxx,nspin) ! the density whose dipole is computed
|
|
LOGICAL,INTENT(IN) :: iflag ! set to true to force recalculation of field
|
|
!
|
|
! local variables
|
|
!
|
|
INTEGER :: index, index0, i, j, k
|
|
INTEGER :: ir, na, ipol
|
|
REAL(DP) :: length, vamp, value, sawarg, e_dipole, ion_dipole
|
|
REAL(DP) :: tot_dipole, bmod, debye
|
|
|
|
LOGICAL :: first=.TRUE.
|
|
SAVE first
|
|
|
|
!---------------------
|
|
! Execution control
|
|
!---------------------
|
|
|
|
IF (.NOT.tefield) RETURN
|
|
! efield only needs to be added on the first iteration, if dipfield
|
|
! is not used. note that for relax calculations it has to be added
|
|
! again on subsequent relax steps.
|
|
IF ((.NOT.dipfield).AND.(.NOT.first) .AND..NOT. iflag) RETURN
|
|
first=.FALSE.
|
|
|
|
IF ((edir.lt.1).or.(edir.gt.3)) THEN
|
|
CALL errore('add_efield',' wrong edir',1)
|
|
ENDIF
|
|
|
|
!---------------------
|
|
! Variable initialization
|
|
!---------------------
|
|
|
|
bmod=SQRT(bg(1,edir)**2+bg(2,edir)**2+bg(3,edir)**2)
|
|
debye = 2.54176D0
|
|
|
|
tot_dipole=0._dp
|
|
e_dipole =0._dp
|
|
ion_dipole=0._dp
|
|
|
|
!---------------------
|
|
! Calculate dipole
|
|
!---------------------
|
|
|
|
if (dipfield) then
|
|
!
|
|
! dipole correction is active
|
|
!
|
|
CALL compute_el_dip(emaxpos, eopreg, edir, rho, e_dipole)
|
|
CALL compute_ion_dip(emaxpos, eopreg, edir, ion_dipole)
|
|
|
|
tot_dipole = -e_dipole + ion_dipole
|
|
|
|
#ifdef __PARA
|
|
CALL mp_bcast(tot_dipole, 0, intra_image_comm)
|
|
#endif
|
|
!
|
|
! E_{TOT} = -e^{2} \left( eamp - dip \right) dip \frac{\Omega}{4\pi}
|
|
!
|
|
etotefield=-e2*(eamp-tot_dipole/2.d0)*tot_dipole*omega/fpi
|
|
|
|
!---------------------
|
|
! Define forcefield
|
|
!
|
|
! F_{s} = e^{2} \left( eamp - dip \right) z_{v}\cross\frac{\vec{b_{3}}}{bmod}
|
|
!---------------------
|
|
|
|
IF (lforce) THEN
|
|
DO na=1,nat
|
|
DO ipol=1,3
|
|
forcefield(ipol,na)= e2 *(eamp - tot_dipole) &
|
|
*zv(ityp(na))*bg(ipol,edir)/bmod
|
|
ENDDO
|
|
ENDDO
|
|
ENDIF
|
|
|
|
else
|
|
!
|
|
! dipole correction is not active
|
|
!
|
|
|
|
CALL compute_ion_dip(emaxpos, eopreg, edir, ion_dipole)
|
|
|
|
!
|
|
! E_{TOT} = -e^{2} eamp * iondip \frac{\Omega}{4\pi}
|
|
!
|
|
etotefield=-e2*eamp*ion_dipole*omega/fpi
|
|
|
|
!---------------------
|
|
! Define forcefield
|
|
!
|
|
! F_{s} = e^{2} eamp z_{v}\cross\frac{\vec{b_{3}}}{bmod}
|
|
!---------------------
|
|
|
|
IF (lforce) THEN
|
|
DO na=1,nat
|
|
DO ipol=1,3
|
|
forcefield(ipol,na)= e2 *eamp &
|
|
*zv(ityp(na))*bg(ipol,edir)/bmod
|
|
ENDDO
|
|
ENDDO
|
|
ENDIF
|
|
|
|
end if
|
|
|
|
!
|
|
! Calcualte potential and print values
|
|
!
|
|
|
|
length=(1._dp-eopreg)*(alat*SQRT(at(1,edir)**2+at(2,edir)**2+at(3,edir)**2))
|
|
|
|
vamp=e2*(eamp-tot_dipole)*length
|
|
|
|
IF (ionode) THEN
|
|
!
|
|
! Output data
|
|
!
|
|
WRITE( stdout,*)
|
|
WRITE( stdout,'(5x,"Adding external electric field":)')
|
|
|
|
IF (dipfield) then
|
|
WRITE( stdout,'(/5x,"Computed dipole along edir(",i1,") : ")' ) edir
|
|
|
|
!
|
|
! If verbose prints also the different components
|
|
!
|
|
IF (iverbosity>0) THEN
|
|
WRITE( stdout, '(8X,"Elec. dipole ",1F15.4," Ry au, ", 1F15.4," Debye")' ) &
|
|
e_dipole, (e_dipole*debye)
|
|
WRITE( stdout, '(8X,"Ion. dipole ",1F15.4," Ry au,", 1F15.4," Debye")' ) &
|
|
ion_dipole, (ion_dipole*debye)
|
|
ENDIF
|
|
|
|
WRITE( stdout, '(8X,"Dipole ",1F15.4," Ry au, ", 1F15.4," Debye")' ) &
|
|
(tot_dipole* (omega/fpi)), &
|
|
((tot_dipole* (omega/fpi))*debye)
|
|
|
|
WRITE( stdout, '(8x,"Dipole field ", f11.4," Ry au")') tot_dipole
|
|
WRITE( stdout,*)
|
|
|
|
ENDIF
|
|
|
|
IF (abs(eamp)>0._dp) WRITE( stdout, &
|
|
'(8x,"E field amplitude [Ha a.u.]: ", es11.4)') eamp
|
|
|
|
WRITE( stdout,'(8x,"Potential amp. ", f11.4," Ry")') vamp
|
|
WRITE( stdout,'(8x,"Total length ", f11.4," bohr")') length
|
|
WRITE( stdout,*)
|
|
ENDIF
|
|
|
|
|
|
!
|
|
!------------------------------
|
|
! Add potential
|
|
!
|
|
! V\left(ijk\right) = e^{2} \left( eamp - dip \right) z_{v}
|
|
! Saw\left( \frac{k}{nr3} \right) \frac{alat}{bmod}
|
|
!
|
|
!---------------------
|
|
|
|
! Index for parallel summation
|
|
!
|
|
index0 = 0
|
|
#if defined (__PARA)
|
|
!
|
|
DO i = 1, me_pool
|
|
index0 = index0 + nrx1*nrx2*dfftp%npp(i)
|
|
END DO
|
|
!
|
|
#endif
|
|
!
|
|
! Loop in the charge array
|
|
!
|
|
|
|
DO ir = 1, nrxx
|
|
!
|
|
! ... three dimensional indexes
|
|
!
|
|
index = index0 + ir - 1
|
|
k = index / (nrx1*nrx2)
|
|
index = index - (nrx1*nrx2)*k
|
|
j = index / nrx1
|
|
index = index - nrx1*j
|
|
i = index
|
|
|
|
if (edir.eq.1) sawarg = (i*1._dp)/(nr1*1._dp)
|
|
if (edir.eq.2) sawarg = (j*1._dp)/(nr2*1._dp)
|
|
if (edir.eq.3) sawarg = (k*1._dp)/(nr3*1._dp)
|
|
|
|
value = e2*(eamp - tot_dipole)*saw(emaxpos,eopreg,sawarg) * (alat/bmod)
|
|
|
|
vpoten(ir) = vpoten(ir) + value
|
|
|
|
END DO
|
|
|
|
|
|
RETURN
|
|
|
|
END SUBROUTINE add_efield
|