mirror of https://gitlab.com/QEF/q-e.git
152 lines
3.8 KiB
Fortran
152 lines
3.8 KiB
Fortran
!
|
|
! Copyright (C) 2001-2005 PWSCF 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 .
|
|
!
|
|
#include "f_defs.h"
|
|
!
|
|
#define ZERO ( 0.D0, 0.D0 )
|
|
#define ONE ( 1.D0, 0.D0 )
|
|
!
|
|
!----------------------------------------------------------------------------
|
|
SUBROUTINE cinitcgg( ndmx, ndim, nstart, nbnd, psi, evc, e, ik )
|
|
!----------------------------------------------------------------------------
|
|
!
|
|
! ... Hamiltonian diagonalization in the subspace spanned
|
|
! ... by nstart states psi (atomic or random wavefunctions).
|
|
! ... Produces on output nbnd eigenvectors (nbnd <= nstart) in evc.
|
|
! ... Minimal memory use - evc and psi may overlap
|
|
! ... Calls h_1psi to calculate H|psi>, S|psi
|
|
!
|
|
USE kinds, ONLY : DP
|
|
USE noncollin_module, ONLY : noncolin, npol
|
|
USE bp, ONLY : lelfield
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER :: ndim, ndmx, nstart, nbnd, ik
|
|
! dimension of the matrix to be diagonalized
|
|
! leading dimension of matrix psi, as declared in the calling pgm unit
|
|
! input number of states
|
|
! output number of states
|
|
! k-point considered
|
|
COMPLEX(KIND=DP) :: psi(ndmx,npol,nstart), evc(ndmx,npol,nbnd)
|
|
! input and output eigenvectors (may overlap)
|
|
REAL(KIND=DP) :: e(nbnd)
|
|
! eigenvalues
|
|
!
|
|
! ... local variables
|
|
!
|
|
INTEGER :: m, i, j, ipol
|
|
INTEGER :: kdim, kdmx, kdim2, kdmx2
|
|
REAL (KIND=DP) :: rtmp(2)
|
|
COMPLEX (KIND=DP) :: ctmp(2)
|
|
COMPLEX (KIND=DP), ALLOCATABLE :: aux(:,:,:), hc(:,:,:), sc(:,:)
|
|
REAL (KIND=DP), ALLOCATABLE :: en(:)
|
|
!
|
|
!
|
|
CALL start_clock( 'wfcrot1' )
|
|
!
|
|
IF ( npol == 1 ) THEN
|
|
!
|
|
kdim = ndim
|
|
kdmx = ndmx
|
|
!
|
|
ELSE
|
|
!
|
|
kdim = ndmx * npol
|
|
kdmx = ndmx * npol
|
|
!
|
|
END IF
|
|
!
|
|
kdim2 = 2 * kdim
|
|
kdmx2 = 2 * kdmx
|
|
!
|
|
ALLOCATE( aux( ndmx, npol, 2 ) )
|
|
ALLOCATE( hc( nstart, nstart, 2 ) )
|
|
ALLOCATE( sc( nstart, nstart ) )
|
|
ALLOCATE( en( nstart ) )
|
|
!
|
|
aux = ZERO
|
|
hc = ZERO
|
|
sc = ZERO
|
|
en = 0.D0
|
|
!
|
|
! ... Set up the Hamiltonian and Overlap matrix
|
|
!
|
|
DO m = 1, nstart
|
|
!
|
|
IF ( noncolin ) THEN
|
|
!
|
|
CALL h_1psi_nc( ndmx, ndim, npol, psi(1,1,m), aux(1,1,1), aux(1,1,2) )
|
|
IF(lelfield) call h_epsi_her(ndmx,ndim,1, ik, psi(1,1,m), aux(1,1,1))
|
|
|
|
!
|
|
ELSE
|
|
!
|
|
CALL h_1psi( ndmx, ndim, psi(1,1,m), aux(1,1,1), aux(1,1,2) )
|
|
IF(lelfield) call h_epsi_her(ndmx,ndim,1, ik, psi(1,1,m), aux(1,1,1))
|
|
!
|
|
END IF
|
|
!
|
|
CALL DGEMV( 'T', kdim2, 2, 1.D0, aux(1,1,1), &
|
|
kdmx2, psi(1,1,m), 1, 0.D0, rtmp, 1 )
|
|
!
|
|
hc(m,m,1) = DCMPLX( rtmp(1), 0.D0 )
|
|
sc(m,m) = DCMPLX( rtmp(2), 0.D0 )
|
|
!
|
|
DO j = m + 1, nstart
|
|
!
|
|
CALL ZGEMV( 'C', kdim, 2, ONE, aux(1,1,1), &
|
|
kdmx, psi(1,1,j), 1, ZERO, ctmp, 1 )
|
|
!
|
|
hc(m,j,1) = ctmp(1)
|
|
sc(m,j) = ctmp(2)
|
|
!
|
|
hc(j,m,1) = CONJG( ctmp(1) )
|
|
sc(j,m) = CONJG( ctmp(2) )
|
|
!
|
|
END DO
|
|
!
|
|
END DO
|
|
!
|
|
CALL reduce( 2 * nstart * nstart, hc(1,1,1) )
|
|
CALL reduce( 2 * nstart * nstart, sc(1,1) )
|
|
!
|
|
! ... diagonalize
|
|
!
|
|
CALL cdiaghg( nstart, nbnd, hc, sc, nstart, en, hc(1,1,2) )
|
|
!
|
|
e(1:nbnd) = en(1:nbnd)
|
|
!
|
|
! ... update the basis set
|
|
!
|
|
DO ipol = 1, npol
|
|
!
|
|
DO i = 1, ndim
|
|
!
|
|
DO m = 1, nbnd
|
|
!
|
|
hc(m,1,1) = SUM( hc(:,m,2) * psi(i,ipol,:) )
|
|
!
|
|
END DO
|
|
!
|
|
evc(i,ipol,1:nbnd) = hc(1:nbnd,1,1)
|
|
!
|
|
END DO
|
|
!
|
|
END DO
|
|
!
|
|
DEALLOCATE( en )
|
|
DEALLOCATE( sc )
|
|
DEALLOCATE( hc )
|
|
DEALLOCATE( aux )
|
|
!
|
|
CALL stop_clock( 'wfcrot1' )
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE cinitcgg
|