mirror of https://gitlab.com/QEF/q-e.git
111 lines
3.3 KiB
Fortran
111 lines
3.3 KiB
Fortran
!
|
|
! Copyright (C) 2001-2007 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 pcgreen (avg_iter, thresh, ik, et_ )
|
|
!-----------------------------------------------------------------------
|
|
!! Solve the linear system which defines the change of the wavefunctions
|
|
!! due to the electric field for a given k_point in a non self-consistent
|
|
!! way. The self-consistent variation of the potential has been computed
|
|
!! previously and is in the common variable \(\text{dvscfs}\).
|
|
!
|
|
use kinds, only : DP
|
|
USE wvfct, ONLY : nbnd, npwx
|
|
USE klist, ONLY : ngk
|
|
USE wavefunctions, ONLY: evc
|
|
USE mp_bands, ONLY: intra_bgrp_comm
|
|
USE mp, ONLY: mp_sum
|
|
USE eqv, ONLY: dpsi, dvpsi
|
|
USE control_lr,ONLY : nbnd_occ
|
|
implicit none
|
|
!
|
|
integer :: ik
|
|
!! input: k-point under consideration
|
|
real(DP) :: avg_iter
|
|
!! in/out: number of diagonalization iterations
|
|
real(DP) :: thresh
|
|
!! input: convergence threshold
|
|
real(DP) :: et_ (nbnd)
|
|
!! input: eigenvalues of the hamiltonian
|
|
!
|
|
! ... local variables
|
|
!
|
|
logical :: conv_root
|
|
! .true. if linter is converged
|
|
|
|
integer :: npw, ibnd, ig, lter
|
|
! counters on bands
|
|
! counter on G-points
|
|
! # of diagonalization iterations
|
|
|
|
real(DP) :: anorm
|
|
! the norm of the error
|
|
|
|
real(DP) , allocatable :: h_diag(:,:)
|
|
! the diagonal part of the Hamiltonian
|
|
|
|
complex(DP) , allocatable :: ps(:,:), auxg (:)
|
|
! auxiliary work space
|
|
|
|
external ch_psi_all, cg_psi
|
|
|
|
npw = ngk(ik)
|
|
allocate (h_diag ( npwx, nbnd ))
|
|
allocate (auxg ( npwx ))
|
|
allocate (ps ( nbnd, nbnd ))
|
|
!
|
|
! Orthogonalize dvpsi to valence states: ps = <evc|dvpsi>
|
|
!
|
|
CALL zgemm( 'C', 'N', nbnd_occ (ik), nbnd_occ (ik), npw, &
|
|
(1.d0,0.d0), evc(1,1), npwx, dvpsi(1,1), npwx, (0.d0,0.d0), &
|
|
ps(1,1), nbnd )
|
|
call mp_sum( ps( :, 1:nbnd_occ(ik) ), intra_bgrp_comm )
|
|
!
|
|
! |dvspi> = - (|dvpsi> - S|evc><evc|dvpsi>)
|
|
! note the change of sign!
|
|
!
|
|
#if 0
|
|
! uncomment for ultrasoft PPs
|
|
! note that spsi is used as work space to store S|evc>
|
|
! CALL calbec ( npw, vkb, evc, becp, nbnd_occ(ik) )
|
|
! CALL s_psi (npwx, npw, nbnd_occ(ik), evc, spsi)
|
|
! CALL zgemm( 'N', 'N', npw, nbnd_occ(ik), nbnd_occ(ik), &
|
|
! (1.d0,0.d0), spsi(1,1), npwx, ps(1,1), nbnd, (-1.d0,0.d0), &
|
|
! dvpsi(1,1), npwx )
|
|
#endif
|
|
!
|
|
! comment for ultrasoft PPs
|
|
CALL zgemm( 'N', 'N', npw, nbnd_occ(ik), nbnd_occ(ik), &
|
|
(1.d0,0.d0), evc(1,1), npwx, ps(1,1), nbnd, (-1.d0,0.d0), &
|
|
dvpsi(1,1), npwx )
|
|
!
|
|
! iterative solution of the linear system (H-e)*dpsi=dvpsi
|
|
! dvpsi=-P_c+ (dvbare+dvscf)*psi , dvscf fixed.
|
|
!
|
|
! compute preconditioning matrix h_diag used by cgsolve_all
|
|
!
|
|
CALL h_prec (ik, evc, h_diag)
|
|
!
|
|
conv_root = .true.
|
|
|
|
call cgsolve_all( ch_psi_all, cg_psi, et_, dvpsi, dpsi, h_diag, &
|
|
npwx, npw, thresh, ik, lter, conv_root, anorm, &
|
|
nbnd_occ(ik), 1 )
|
|
|
|
avg_iter = avg_iter + DBLE (lter)
|
|
if (.not.conv_root) write(6, &
|
|
"(5x,'kpoint',i4,' ibnd',i4, ' pcgreen: root not converged',es10.3)") &
|
|
ik,ibnd,anorm
|
|
|
|
deallocate (ps)
|
|
deallocate (auxg)
|
|
deallocate (h_diag)
|
|
|
|
return
|
|
end subroutine pcgreen
|