mirror of https://gitlab.com/QEF/q-e.git
442 lines
16 KiB
Fortran
442 lines
16 KiB
Fortran
!
|
|
! Copyright (C) 2001-2018 Quantum ESPRESSO
|
|
! This file is distributed under the terms
|
|
! GNU General Public License. See the file
|
|
! in the root directory of the present dis
|
|
! or http://www.gnu.org/copyleft/gpl.txt .
|
|
!
|
|
!
|
|
!-----------------------------------------------------------------------
|
|
SUBROUTINE dynmat_hub_scf (irr, nu_i0, nper)
|
|
!---------------------------------------------------------------------
|
|
!! DFPT+U: This routine adds to the dynamical matrix the scf+orth Hubbard terms.
|
|
!! It adds the scf derivative of the Hubbard energy (terms 1 and 2). Moreover,
|
|
!! it adds 3 terms due to the orthogonality constraints in the USPP formalism (terms 3,4,5).
|
|
!! Note, the orthogonality terms 4 and 5 DO NOT follow simply from the 2nd derivative of
|
|
!! the Hubbard energy \(\text{E_U}\); they stem from the coupling of the \(-\epsilon\ dS\ d\lambda\) in
|
|
!! the USPP forces with the part of \(d\psi\ d\mu\) projected onto the occupied manifold
|
|
!! (the variable dpsi stems from the scf linear system and lives in the unoccupied manifold).
|
|
!! See comments in the source code for other details on the implemented terms.
|
|
!
|
|
! Terms implemented:
|
|
! dyn_hub_scf (ipert, imode)
|
|
! 1) = +\sum_{I,m1,m2,is} Hubbard_U(I) [0.5\delta_m1m2-ns(m1, m2, is, I)]*
|
|
! \sum_{ibnd, k} wg(ibnd,k)[ <dpsi(ipert,ibnd,k+q, is)|dqsphi(imode,I,k+q,m1)><S\phi(I,k,m2)| psi(ibnd,k,is> +
|
|
! <dpsi(ipert,ibnd,k+q, is)|S\phi(I,k+q,m1)><dmqsphi(imode,I,k,m2)| psi(ibnd,k,is> + m1<=>m2]
|
|
! 2) = -\sum_{I,m1,m2,is} Hubbard_U(I) * CONJG(dnsscf(m1,m2,is,I,ipert)) * dnsbare(m2,m1,is,I,imode)
|
|
!
|
|
! Orthogonality terms present only in USPP:
|
|
! 3) = -\sum_{I,m1,m2,is} Hubbard_U(I) [0.5\delta_m1m2-ns(m1, m2, is, I)]*
|
|
! \sum_{ibnd, k} wg(ibnd,k)[ <dpsi_orth(ipert,ibnd,k+q, is)|dqsphi(imode,I,k+q,m2)><S\phi(I,k,m1)| psi(ibnd,k,is> +
|
|
! <dpsi_orth(ipert,ibnd,k+q, is)|S\phi(I,k+q,m2)><dmqsphi(imode,I,k,m1)| psi(ibnd,k,is>]
|
|
! 4) = -\sum_{I,m1,m2,is} Hubbard_U(I) [0.5\delta_m1m2-ns(m1, m2, is, I)]*
|
|
! \sum_{ibnd, k} wg(ibnd,k)[ <dpsi_orth(imode,ibnd,k+q, is)|dqsphi(ipert,I,k+q,m1)><S\phi(I,k,m2)| psi(ibnd,k,is> +
|
|
! <dpsi_orth(imode,ibnd,k+q, is)|S\phi(I,k+q,m1)><dmqsphi(ipert,I,k,m2)| psi(ibnd,k,is>]
|
|
! 5) = -\sum_{I,m1,m2,is} Hubbard_U(I) * [CONJG(dnsscf(m1,m2,is,I,ipert) + CONJG(dnsbare(m2,m1,is,I,ipert))]
|
|
! * dnsorth(m1,m2,is,I,imode)
|
|
!
|
|
! Note: dnsscf includes the orthogonality part (dnsorth)
|
|
!
|
|
!! Written by A. Floris.
|
|
!! Modified by I. Timrov (01.10.2018).
|
|
!
|
|
USE kinds, ONLY : DP
|
|
USE ions_base, ONLY : nat, ityp, ntyp => nsp
|
|
USE ldaU, ONLY : Hubbard_l, is_hubbard, Hubbard_J0
|
|
USE ldaU_lr, ONLY : dnsscf, effU
|
|
USE ldaU_ph, ONLY : dnsbare, dnsbare_all_modes, dnsorth_cart
|
|
USE lsda_mod, ONLY : lsda, current_spin, isk, nspin
|
|
USE modes, ONLY : u, nmodes
|
|
USE dynmat, ONLY : dyn, dyn_rec, dyn_hub_scf
|
|
USE qpoint, ONLY : nksq, ikks, ikqs
|
|
USE eqv, ONLY : dpsi
|
|
USE wvfct, ONLY : npwx, nbnd
|
|
USE control_lr, ONLY : lgamma
|
|
USE control_ph, ONLY : rec_code_read
|
|
USE units_lr, ONLY : iuwfc, lrwfc, iudwf, lrdwf
|
|
USE wavefunctions, ONLY : evc
|
|
USE klist, ONLY : wk, lgauss, ltetra, ngk, igk_k
|
|
USE uspp, ONLY : okvan
|
|
USE control_flags, ONLY : iverbosity
|
|
USE io_global, ONLY : stdout
|
|
USE mp_bands, ONLY : intra_bgrp_comm
|
|
USE mp_pools, ONLY : inter_pool_comm
|
|
USE mp, ONLY : mp_sum
|
|
USE buffers, ONLY : get_buffer
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: irr
|
|
!! the irreducible representation
|
|
INTEGER, INTENT(IN) :: nu_i0
|
|
!! the initial position of the mode
|
|
INTEGER, INTENT(IN) :: nper
|
|
!! number of perturbations in the current irreducible representation
|
|
!
|
|
! ... local variables
|
|
!
|
|
INTEGER :: icar, jcar, na, nap, nah, ihubst1, ihubst2, nt, counter, n, l, is, &
|
|
na_icar, nap_jcar, m1, m2, imode, jmode, ik, ikk, ikq, ipert, nrec1, &
|
|
ibnd, ig, isi, op_spin, npw, npwq
|
|
COMPLEX(DP), ALLOCATABLE :: dyn1 (:,:), dyn_orth(:,:), term(:,:), term_aux(:,:), &
|
|
dpsi_orth_cart(:,:,:,:), dyn_orth_cart(:,:), &
|
|
dvqhbar(:,:,:,:), dvqhbar_orth(:,:,:,:), &
|
|
dvqhbar_orth_lm(:,:,:,:), aux1(:,:,:), dyn1_test(:,:)
|
|
REAL(DP), ALLOCATABLE :: wgg(:,:,:)
|
|
COMPLEX(DP) :: dvi, prj, prj_orth
|
|
COMPLEX(DP), EXTERNAL :: ZDOTC
|
|
LOGICAL :: lmetq0 ! .true. if q=0 for a metal
|
|
!
|
|
CALL start_clock( 'dynmat_hub_scf' )
|
|
!
|
|
ALLOCATE (dyn1(nper,nmodes))
|
|
ALLOCATE (dyn_orth(nper,nmodes))
|
|
ALLOCATE (term(nat,3))
|
|
ALLOCATE (term_aux(nper,nmodes))
|
|
ALLOCATE (dpsi_orth_cart(npwx,nbnd,3,nat))
|
|
ALLOCATE (dyn_orth_cart(3*nat,3*nat))
|
|
ALLOCATE (dvqhbar(npwx,nbnd,3,nat))
|
|
ALLOCATE (aux1(npwx,nbnd,nmodes))
|
|
ALLOCATE (dyn1_test(nmodes,nmodes))
|
|
ALLOCATE (wgg(nbnd,nbnd,nksq))
|
|
ALLOCATE (dvqhbar_orth(npwx,nbnd,3,nat))
|
|
ALLOCATE (dvqhbar_orth_lm(npwx,nbnd,3,nat))
|
|
!
|
|
dyn1 = (0.d0, 0.d0)
|
|
dyn_orth_cart = (0.d0, 0.d0)
|
|
dyn1_test = (0.d0, 0.d0)
|
|
!
|
|
lmetq0 = (lgauss .OR. ltetra) .AND. lgamma
|
|
!
|
|
! USPP: compute the weights as in square bracket
|
|
! of Eq. (27) of A. Dal Corso PRB 64, 235118 (2001).
|
|
! Or see Eq. (B19) in the same reference.
|
|
!
|
|
IF (okvan) CALL compute_weight (wgg)
|
|
!
|
|
! If recover=.true. recompute dnsscf for the current irr
|
|
! (e.g. when convt=.true. in solve_linter but the code is
|
|
! interrupted before the call of this routine)
|
|
!
|
|
IF (rec_code_read==10) THEN
|
|
!WRITE(stdout,*) 'rec_code_read', rec_code_read
|
|
CALL dnsq_scf (nper, lmetq0, nu_i0, irr, .true.)
|
|
ENDIF
|
|
!
|
|
! We need a sum over all k points
|
|
!
|
|
DO ik = 1, nksq
|
|
!
|
|
ikk = ikks(ik)
|
|
ikq = ikqs(ik)
|
|
npw = ngk(ikk)
|
|
npwq= ngk(ikq)
|
|
!
|
|
IF (lsda) THEN
|
|
current_spin = isk(ikk)
|
|
IF (current_spin .eq. 1) THEN
|
|
op_spin = 2
|
|
ELSE
|
|
op_spin = 1
|
|
END IF
|
|
ELSE
|
|
op_spin = 1
|
|
ENDIF
|
|
!
|
|
! Read unperturbed KS wavefuctions psi(k)
|
|
!
|
|
IF (nksq.GT.1) CALL get_buffer (evc, lrwfc, iuwfc, ikk)
|
|
!
|
|
! Calculate d^{na,icar}V_tilde(q) |psi(ibnd,k)> =
|
|
! = |ket> Bloch vector at k+q for all cartesian coordinates (na,icar)
|
|
!
|
|
CALL dvqhub_barepsi_us2 (ik, dvqhbar, dvqhbar_orth, dvqhbar_orth_lm)
|
|
!
|
|
! Compute terms 3 and 4.
|
|
! Compute the orthogonality term in cartesian coordinates.
|
|
! Hubbard-potential analogue to the two terms in
|
|
! Eq. (42) of A. Dal Corso PRB 64, 235118 (2001).
|
|
!
|
|
IF (okvan) THEN
|
|
!
|
|
! Calculate dpsi_orth_cart which is the valence component
|
|
! of the response KS wavefunction (non-zero only in the USPP case).
|
|
!
|
|
CALL dpsi_orth (ik, wgg, dpsi_orth_cart)
|
|
!
|
|
DO na = 1, nat
|
|
DO icar = 1, 3
|
|
na_icar = 3*(na-1)+icar
|
|
DO nap = 1, nat
|
|
DO jcar = 1, 3
|
|
nap_jcar = 3*(nap-1)+jcar
|
|
DO ibnd = 1, nbnd
|
|
!
|
|
! from E_Hub alone
|
|
prj_orth = ZDOTC (npwq, dpsi_orth_cart(:,ibnd,jcar,nap), 1, &
|
|
dvqhbar_orth(:,ibnd,icar,na), 1) + &
|
|
! extra term
|
|
ZDOTC (npwq, dvqhbar_orth_lm(:,ibnd,jcar,nap), 1, &
|
|
dpsi_orth_cart(:,ibnd,icar,na), 1)
|
|
!
|
|
CALL mp_sum(prj_orth, intra_bgrp_comm)
|
|
!
|
|
dyn_orth_cart (nap_jcar,na_icar) = dyn_orth_cart (nap_jcar,na_icar) &
|
|
- wk(ikk) * prj_orth
|
|
!
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
!
|
|
ENDIF
|
|
!
|
|
! Compute term 1.
|
|
! Transform dvqhbar from the Cartesian to the pattern basis u.
|
|
! aux1 is dvqhbar in the pattern basis.
|
|
!
|
|
aux1 = (0.d0, 0.d0)
|
|
!
|
|
DO imode = 1, nmodes
|
|
DO na = 1, nat
|
|
DO icar = 1, 3
|
|
na_icar = 3*(na-1)+icar
|
|
DO ibnd = 1, nbnd
|
|
DO ig = 1, npwq
|
|
aux1(ig,ibnd,imode) = aux1(ig,ibnd,imode) + &
|
|
dvqhbar(ig,ibnd,icar,na) * u(na_icar,imode)
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
!
|
|
DO ipert = 1, nper
|
|
!
|
|
nrec1 = (ipert-1)*nksq+ik
|
|
!
|
|
! Read the response KS wave functions dpsi from file
|
|
!
|
|
CALL get_buffer (dpsi, lrdwf, iudwf, nrec1)
|
|
!
|
|
DO imode = 1, nmodes
|
|
!
|
|
! Calculate prj = <d^(ipert)dpsi_k+q | d^{imode}V_tilde(q) | psi(ibnd,k)>
|
|
!
|
|
DO ibnd = 1, nbnd
|
|
!
|
|
prj = ZDOTC (npwq, dpsi(:,ibnd), 1, aux1(:,ibnd,imode), 1)
|
|
|
|
CALL mp_sum (prj, intra_bgrp_comm)
|
|
!
|
|
! dyn1 is a sum over all the k and ibnd
|
|
!
|
|
dyn1(ipert,imode) = dyn1(ipert,imode) + wk(ikk)*prj
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDDO ! ik
|
|
!
|
|
CALL mp_sum (dyn1, inter_pool_comm)
|
|
CALL mp_sum (dyn_orth_cart, inter_pool_comm)
|
|
!
|
|
! Compute terms 2 and 5 (and the equivalent for Hubbard_J0)
|
|
!
|
|
DO ipert = 1, nper
|
|
!
|
|
term = (0.d0, 0.d0)
|
|
!
|
|
DO na = 1, nat
|
|
!
|
|
DO icar = 1, 3
|
|
!
|
|
DO nah = 1, nat
|
|
!
|
|
nt = ityp(nah)
|
|
!
|
|
! For effU = Hubbard_U - Hubbard_J0
|
|
!
|
|
IF (is_hubbard(nt)) THEN
|
|
!
|
|
dvi = (0.d0, 0.d0)
|
|
!
|
|
DO is = 1, nspin
|
|
!
|
|
DO m1 = 1, 2*Hubbard_l(nt)+1
|
|
!
|
|
DO m2 = 1, 2*Hubbard_l(nt)+1
|
|
!
|
|
! Term 2
|
|
!
|
|
dvi = dvi + CONJG(dnsscf(m1,m2,is,nah,ipert)) * &
|
|
dnsbare(m2,m1,is,nah,icar,na)
|
|
!
|
|
! Term 5
|
|
!
|
|
IF (okvan) dvi = dvi + CONJG( dnsscf(m1,m2,is,nah,ipert) + &
|
|
dnsbare_all_modes(m1,m2,is,nah,nu_i0+ipert) ) &
|
|
* dnsorth_cart(m1,m2,is,nah,icar,na)
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
!
|
|
! term is implicitly defined for each ipert
|
|
!
|
|
term(na,icar) = term(na,icar) - dvi*effU(nt)
|
|
!
|
|
ENDIF
|
|
!
|
|
! For Hubbard_J0
|
|
!
|
|
IF (Hubbard_J0(nt).NE.0.d0) THEN
|
|
!
|
|
dvi = (0.d0, 0.d0)
|
|
!
|
|
DO is = 1, nspin
|
|
!
|
|
IF ((is==1).AND.(nspin==2)) THEN
|
|
isi = 2
|
|
ELSE
|
|
isi = 1
|
|
ENDIF
|
|
!
|
|
DO m1 = 1, 2*Hubbard_l(nt)+1
|
|
!
|
|
DO m2 = 1, 2*Hubbard_l(nt)+1
|
|
!
|
|
! Term 2
|
|
!
|
|
dvi = dvi - CONJG(dnsscf(m1,m2,isi,nah,ipert)) * & ! sign change
|
|
dnsbare(m2,m1,is,nah,icar,na)
|
|
!
|
|
! Term 5
|
|
!
|
|
IF (okvan) dvi = dvi - CONJG( dnsscf(m1,m2,isi,nah,ipert) + & ! sign change
|
|
dnsbare_all_modes(m1,m2,isi,nah,nu_i0+ipert) ) &
|
|
* dnsorth_cart(m1,m2,is,nah,icar,na)
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
!
|
|
! term is implicitely defined for each ipert
|
|
!
|
|
term(na,icar) = term(na,icar) - dvi*Hubbard_J0(nt)
|
|
!
|
|
ENDIF
|
|
!
|
|
ENDDO ! nah
|
|
!
|
|
ENDDO ! icar
|
|
!
|
|
ENDDO ! na
|
|
!
|
|
! transform term from the Cartesian to the pattern basis u.
|
|
! The result is stored in term_aux.
|
|
!
|
|
DO imode = 1, nmodes
|
|
term_aux(ipert,imode) = (0.d0, 0.d0)
|
|
DO na = 1, nat
|
|
DO icar = 1, 3
|
|
na_icar = 3*(na-1)+icar
|
|
term_aux(ipert,imode) = term_aux(ipert,imode) + &
|
|
term(na,icar) * u(na_icar,imode)
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
!
|
|
ENDDO ! ipert
|
|
!
|
|
! Factor of 2 taking into account that
|
|
! if nspin=1 the spin sum above does not occur
|
|
!
|
|
IF (nspin==1) term_aux = 2.d0 * term_aux
|
|
!
|
|
! Add the contribution to the dyn_hub_scf matrix
|
|
!
|
|
dyn1 = dyn1 + term_aux
|
|
!
|
|
dyn_orth = (0.d0, 0.d0)
|
|
!
|
|
! Adding the orthogonality terms 3 and 4,
|
|
! which were computed above (and summed up over k), to dyn1.
|
|
!
|
|
IF (okvan) THEN
|
|
DO ipert = 1, nper
|
|
DO imode = 1, nmodes
|
|
DO na_icar = 1, 3*nat
|
|
DO nap_jcar = 1, 3*nat
|
|
dyn_orth(ipert,imode) = dyn_orth(ipert,imode) &
|
|
+ u(na_icar,imode) &
|
|
* dyn_orth_cart(nap_jcar,na_icar) &
|
|
* CONJG(u(nap_jcar,nu_i0+ipert))
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
dyn1 = dyn1 + dyn_orth
|
|
ENDIF
|
|
!
|
|
DO imode = 1, nmodes
|
|
DO ipert = 1, nper
|
|
!
|
|
jmode = nu_i0 + ipert
|
|
!
|
|
dyn_hub_scf(jmode,imode) = dyn1(ipert,imode)
|
|
!
|
|
dyn_rec(jmode,imode) = dyn_rec(jmode,imode) + dyn1(ipert,imode)
|
|
!
|
|
dyn1_test(jmode,imode) = dyn1 (ipert, imode)
|
|
!
|
|
ENDDO
|
|
ENDDO
|
|
!
|
|
! Write the symmetrized dyn_hub_scf (upgraded for the new ipert) and total
|
|
! dynamical matrix dyn in cartesian coordinates.
|
|
! dyn1 is instead the contribution of the particular irrep only.
|
|
!
|
|
IF (iverbosity==1) THEN
|
|
CALL tra_write_matrix_no_sym('dyn1 NOT SYMMETRIZED',dyn1_test,nat)
|
|
CALL tra_write_matrix('dyn1 SYMMETRIZED',dyn1_test,u,nat)
|
|
CALL tra_write_matrix('dyn',dyn,u,nat)
|
|
ENDIF
|
|
!
|
|
! Add Hubbard terms in the dynamical matrix to the total
|
|
! dynamical matrix.
|
|
!
|
|
DO imode = 1, nmodes
|
|
DO ipert = 1, nper
|
|
jmode = nu_i0 + ipert
|
|
dyn(jmode,imode) = dyn(jmode,imode) + dyn1(ipert,imode)
|
|
ENDDO
|
|
ENDDO
|
|
!
|
|
DEALLOCATE (dyn1)
|
|
DEALLOCATE (dyn_orth)
|
|
DEALLOCATE (term)
|
|
DEALLOCATE (term_aux)
|
|
DEALLOCATE (dpsi_orth_cart)
|
|
DEALLOCATE (dyn_orth_cart)
|
|
DEALLOCATE (dvqhbar)
|
|
DEALLOCATE (aux1)
|
|
DEALLOCATE (dyn1_test)
|
|
DEALLOCATE (wgg)
|
|
DEALLOCATE (dvqhbar_orth)
|
|
DEALLOCATE (dvqhbar_orth_lm)
|
|
!
|
|
CALL stop_clock ( 'dynmat_hub_scf' )
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE dynmat_hub_scf
|