2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
! Copyright (C) 2001-2204 PWSCF group
|
2003-01-20 05:58:50 +08:00
|
|
|
! 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 .
|
|
|
|
!
|
2004-06-26 01:25:37 +08:00
|
|
|
#include "f_defs.h"
|
2004-03-08 01:18:22 +08:00
|
|
|
!
|
|
|
|
!----------------------------------------------------------------------------
|
|
|
|
SUBROUTINE cdiaghg( n, m, h, s, ldh, e, v )
|
|
|
|
!----------------------------------------------------------------------------
|
|
|
|
!
|
|
|
|
! ... calculates eigenvalues and eigenvectors of the generalized problem
|
|
|
|
! ... Hv=eSv, with H hermitean matrix, S overlap matrix .
|
|
|
|
! ... On output both matrix are unchanged
|
|
|
|
!
|
2004-03-15 18:07:07 +08:00
|
|
|
! ... LAPACK version - uses both ZHEGV and ZHEGVX
|
2004-03-08 01:18:22 +08:00
|
|
|
!
|
|
|
|
USE kinds, ONLY : DP
|
2004-03-29 16:42:37 +08:00
|
|
|
USE mp_global, ONLY : npool, me_pool, root_pool, intra_pool_comm
|
2004-03-08 01:18:22 +08:00
|
|
|
USE mp, ONLY : mp_bcast
|
|
|
|
!
|
|
|
|
IMPLICIT NONE
|
|
|
|
!
|
|
|
|
! ... on INPUT
|
|
|
|
!
|
|
|
|
INTEGER :: n, m, ldh
|
|
|
|
! dimension of the matrix to be diagonalized
|
|
|
|
! number of eigenstates to be calculate
|
|
|
|
! leading dimension of h, as declared in the calling pgm unit
|
|
|
|
COMPLEX(KIND=DP) :: h(ldh,n), s(ldh,n)
|
|
|
|
! matrix to be diagonalized
|
|
|
|
! overlap matrix
|
|
|
|
!
|
|
|
|
! ... on OUTPUT
|
|
|
|
!
|
|
|
|
REAL(KIND=DP) :: e(n)
|
|
|
|
! eigenvalues
|
|
|
|
COMPLEX(KIND=DP) :: v(ldh,m)
|
|
|
|
! eigenvectors (column-wise)
|
|
|
|
!
|
|
|
|
! ... LOCAL variables
|
|
|
|
!
|
2004-03-15 18:07:07 +08:00
|
|
|
INTEGER :: lwork, nb, mm, info
|
2004-03-08 01:18:22 +08:00
|
|
|
! mm = number of calculated eigenvectors
|
2004-03-15 18:07:07 +08:00
|
|
|
INTEGER, EXTERNAL :: ILAENV
|
|
|
|
! ILAENV returns optimal block size "nb"
|
2004-03-08 01:18:22 +08:00
|
|
|
INTEGER, ALLOCATABLE :: iwork(:), ifail(:)
|
|
|
|
REAL(KIND=DP), ALLOCATABLE :: rwork(:)
|
|
|
|
COMPLEX(KIND=DP), ALLOCATABLE :: sdum(:,:), hdum(:,:), work(:)
|
|
|
|
LOGICAL :: all_eigenvalues
|
|
|
|
!
|
2004-03-15 23:25:20 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
CALL start_clock( 'cdiaghg' )
|
|
|
|
!
|
2004-03-15 23:25:20 +08:00
|
|
|
#if defined (__PARA) && defined (__T3E)
|
2004-03-08 01:18:22 +08:00
|
|
|
!
|
|
|
|
! ... NB: 150 has been determined empirically on the T3E as the point
|
|
|
|
! ... where it is convenient to use a parallel routines.
|
|
|
|
!
|
|
|
|
IF ( npool == 1 .AND. n > 150 ) THEN
|
|
|
|
!
|
|
|
|
CALL scala_cdiaghg( n, h, ldh, s, ldh, e, v, ldh )
|
|
|
|
!
|
|
|
|
CALL stop_clock( 'cdiaghg' )
|
|
|
|
!
|
|
|
|
RETURN
|
|
|
|
!
|
|
|
|
END IF
|
|
|
|
!
|
2003-01-20 05:58:50 +08:00
|
|
|
#endif
|
2004-03-08 01:18:22 +08:00
|
|
|
!
|
|
|
|
all_eigenvalues = ( m == n )
|
|
|
|
!
|
|
|
|
! ... check for optimal block size
|
|
|
|
!
|
|
|
|
nb = ILAENV( 1, 'ZHETRD', 'U', n, -1, -1, -1 )
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
IF ( nb < 1 ) nb = MAX( 1, n )
|
|
|
|
!
|
|
|
|
IF ( nb == 1 .OR. nb >= n ) THEN
|
|
|
|
!
|
2003-02-08 00:04:36 +08:00
|
|
|
lwork = 2 * n - 1
|
2004-03-08 01:18:22 +08:00
|
|
|
!
|
|
|
|
ELSE
|
|
|
|
!
|
|
|
|
lwork = ( nb + 1 ) * n
|
|
|
|
!
|
|
|
|
END IF
|
|
|
|
!
|
|
|
|
! ... allocate workspace
|
|
|
|
!
|
|
|
|
ALLOCATE( work( lwork ) )
|
|
|
|
ALLOCATE( sdum( ldh, n ) )
|
|
|
|
!
|
|
|
|
IF ( all_eigenvalues ) THEN
|
|
|
|
!
|
|
|
|
ALLOCATE( rwork( 3 * n - 2 ) )
|
|
|
|
!
|
|
|
|
ELSE
|
|
|
|
!
|
|
|
|
ALLOCATE( rwork( 7 * n ) )
|
|
|
|
ALLOCATE( hdum( ldh, n ) )
|
|
|
|
ALLOCATE( iwork( 5 * n ) )
|
|
|
|
ALLOCATE( ifail( n ) )
|
|
|
|
!
|
|
|
|
END IF
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
|
|
|
! input s and (see below) h are copied so that they are not destroyed
|
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
sdum = s
|
|
|
|
!
|
|
|
|
! ... only the first processor diagonalize the matrix
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-24 17:36:50 +08:00
|
|
|
IF ( me_pool == root_pool ) THEN
|
2004-03-08 01:18:22 +08:00
|
|
|
!
|
|
|
|
IF ( all_eigenvalues ) THEN
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
! ... calculate all eigenvalues
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
v(:,1:n) = h(:,:)
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
CALL ZHEGV( 1, 'V', 'U', n, v, ldh, sdum, ldh, e, work, &
|
|
|
|
lwork, rwork, info )
|
|
|
|
!
|
|
|
|
ELSE
|
|
|
|
!
|
|
|
|
! ... calculate only m lowest eigenvalues
|
|
|
|
!
|
|
|
|
hdum = h
|
|
|
|
!
|
|
|
|
CALL ZHEGVX( 1, 'V', 'I', 'U', n, hdum, ldh, sdum, ldh, &
|
|
|
|
0.0D0, 0.0D0, 1, m, 0.D0, mm, e(1), v, ldh, &
|
|
|
|
work, lwork, rwork, iwork, ifail, info )
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
END IF
|
|
|
|
!
|
|
|
|
CALL errore( 'cdiaghg', 'info =/= 0', ABS( info ) )
|
|
|
|
!
|
|
|
|
END IF
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
! ... broadcast the eigenvectors and the eigenvalues
|
|
|
|
!
|
2004-03-25 00:30:44 +08:00
|
|
|
CALL mp_bcast( e, root_pool, intra_pool_comm )
|
|
|
|
CALL mp_bcast( v, root_pool, intra_pool_comm )
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
! ... deallocate workspace
|
|
|
|
!
|
|
|
|
IF ( .NOT. all_eigenvalues ) THEN
|
|
|
|
!
|
|
|
|
DEALLOCATE( ifail )
|
|
|
|
DEALLOCATE( iwork )
|
|
|
|
DEALLOCATE( hdum )
|
|
|
|
!
|
|
|
|
END IF
|
|
|
|
!
|
|
|
|
DEALLOCATE( sdum )
|
|
|
|
DEALLOCATE( rwork )
|
|
|
|
DEALLOCATE( work )
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
CALL stop_clock( 'cdiaghg' )
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
RETURN
|
2003-01-20 05:58:50 +08:00
|
|
|
!
|
2004-03-08 01:18:22 +08:00
|
|
|
END SUBROUTINE cdiaghg
|