48#if defined (__HAS_IEEE_EXCEPTIONS)
49 USE ieee_exceptions,
ONLY: ieee_get_halting_mode, &
50 ieee_set_halting_mode, &
53#include "../base/base_uses.f90"
58 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_cfm_diag'
75 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix, eigenvectors
76 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
78 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_heevd'
82 CALL timeset(routinen, handle)
95 CALL cp_cfm_heevd_base(matrix, eigenvectors, eigenvalues)
100 CALL timestop(handle)
113 SUBROUTINE cp_cfm_heevd_base(matrix, eigenvectors, eigenvalues)
115 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix, eigenvectors
116 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
118 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_heevd_base'
120 COMPLEX(KIND=dp),
DIMENSION(:),
POINTER :: work
121 COMPLEX(KIND=dp),
DIMENSION(:, :), &
123 INTEGER :: handle, info, liwork, &
125 INTEGER,
DIMENSION(:),
POINTER :: iwork
126 REAL(kind=
dp),
DIMENSION(:),
POINTER :: rwork
127#if defined(__parallel)
128 INTEGER,
DIMENSION(9) :: descm, descv
129 COMPLEX(KIND=dp),
DIMENSION(:, :), &
132#if defined (__HAS_IEEE_EXCEPTIONS)
133 LOGICAL,
DIMENSION(5) :: halt
136 CALL timeset(routinen, handle)
138 n = matrix%matrix_struct%nrow_global
139 m => matrix%local_data
140 ALLOCATE (iwork(1), rwork(1), work(1))
146#if defined(__parallel)
147 v => eigenvectors%local_data
148 descm(:) = matrix%matrix_struct%descriptor(:)
149 descv(:) = eigenvectors%matrix_struct%descriptor(:)
150 CALL pzheevd(
'V',
'U', n, m(1, 1), 1, 1, descm, eigenvalues(1), v(1, 1), 1, 1, descv, &
151 work(1), lwork, rwork(1), lrwork, iwork(1), liwork, info)
154 lwork = ceiling(real(work(1), kind=
dp)) + 1000
156 lrwork = ceiling(rwork(1)) + 1000000
159 CALL zheevd(
'V',
'U', n, m(1, 1),
SIZE(m, 1), eigenvalues(1), &
160 work(1), lwork, rwork(1), lrwork, iwork(1), liwork, info)
161 lwork = ceiling(real(work(1), kind=
dp))
162 lrwork = ceiling(rwork(1))
166 DEALLOCATE (iwork, rwork, work)
167 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
171#if defined (__HAS_IEEE_EXCEPTIONS)
172 CALL ieee_get_halting_mode(ieee_all, halt)
173 CALL ieee_set_halting_mode(ieee_all, .false.)
175#if defined(__parallel)
176 CALL pzheevd(
'V',
'U', n, m(1, 1), 1, 1, descm, eigenvalues(1), v(1, 1), 1, 1, descv, &
177 work(1), lwork, rwork(1), lrwork, iwork(1), liwork, info)
179 CALL zheevd(
'V',
'U', n, m(1, 1),
SIZE(m, 1), eigenvalues(1), &
180 work(1), lwork, rwork(1), lrwork, iwork(1), liwork, info)
181 eigenvectors%local_data = matrix%local_data
183#if defined (__HAS_IEEE_EXCEPTIONS)
184 CALL ieee_set_halting_mode(ieee_all, halt)
187 DEALLOCATE (iwork, rwork, work)
188 IF (info /= 0) cpabort(
"Diagonalisation of a complex matrix failed")
190 CALL timestop(handle)
192 END SUBROUTINE cp_cfm_heevd_base
201 SUBROUTINE check_generalized_diag(overlap, eigenvectors, scratch, nvec)
204 TYPE(
cp_cfm_type),
INTENT(INOUT) :: overlap, scratch
205 INTEGER,
INTENT(IN) :: nvec
207 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_generalized_diag'
209 CHARACTER(LEN=default_string_length) :: diag_type_name
210 COMPLEX(KIND=dp) :: gold, test
211 INTEGER :: handle, i, j, ncol, nrow, output_unit
212 REAL(kind=
dp) :: eps, eps_abort, eps_warning
213#if defined(__parallel)
215 INTEGER :: il, jl, ipcol, iprow, &
216 mypcol, myprow, npcol, nprow
217 INTEGER,
DIMENSION(9) :: desca
220 CALL timeset(routinen, handle)
223 CALL timestop(handle)
229 eps_abort = 10.0_dp*eps_warning
231 nrow = eigenvectors%matrix_struct%nrow_global
232 ncol = min(eigenvectors%matrix_struct%ncol_global, nvec)
241#if defined(__parallel)
242 context => overlap%matrix_struct%context
243 myprow = context%mepos(1)
244 mypcol = context%mepos(2)
245 nprow = context%num_pe(1)
246 npcol = context%num_pe(2)
247 desca(:) = overlap%matrix_struct%descriptor(:)
248 outer:
DO j = 1, ncol
250 CALL infog2l(i, j, desca, nprow, npcol, myprow, mypcol, il, jl, iprow, ipcol)
251 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
253 test = overlap%local_data(il, jl)
254 eps = abs(test - gold)
255 IF (eps > eps_warning)
EXIT outer
260 outer:
DO j = 1, ncol
263 test = overlap%local_data(i, j)
264 eps = abs(test - gold)
265 IF (eps > eps_warning)
EXIT outer
270 IF (eps > eps_warning)
THEN
272 diag_type_name =
"HEGVX"
274 diag_type_name =
"CUSOLVER"
277 diag_type_name =
"DLAF"
280 diag_type_name =
"generalized eigensolver"
282 WRITE (unit=output_unit, fmt=
"(/,T2,A,/,T2,A,I0,A,I0,A,ES10.3,/,T2,A,F0.0,A,ES10.3)") &
283 "The generalized eigenvectors returned by "//trim(diag_type_name)//
" are not S-orthonormal", &
284 "Absolute deviation of matrix element (", i,
", ", j,
") is ", eps, &
285 "The deviation from the expected value ", real(gold, kind=
dp),
" is", eps
286 IF (eps > eps_abort)
THEN
287 cpabort(
"ERROR in "//routinen//
": Check of generalized matrix diagonalization failed")
289 cpwarn(
"Check of generalized matrix diagonalization failed in routine "//routinen)
293 CALL timestop(handle)
295 END SUBROUTINE check_generalized_diag
308 SUBROUTINE cp_cfm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
310 TYPE(
cp_cfm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
311 REAL(kind=
dp),
DIMENSION(:) :: eigenvalues
314 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_geeig'
316 INTEGER :: handle, nao, nmo
317 LOGICAL :: check_eigenvectors
318 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
321 CALL timeset(routinen, handle)
324 ALLOCATE (evals(nao))
325 nmo =
SIZE(eigenvalues)
332 IF (check_eigenvectors)
THEN
338 IF (check_eigenvectors)
THEN
339 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
345 nao >= dlaf_neigvec_min)
THEN
355 IF (check_eigenvectors)
THEN
361 IF (check_eigenvectors)
THEN
362 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
367#if defined(__parallel)
371 IF (check_eigenvectors)
THEN
376 CALL cp_cfm_geeig_scalapack(amatrix, bmatrix, work, evals)
377 IF (check_eigenvectors)
THEN
378 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
392 CALL cp_cfm_heevd(matrix=amatrix, eigenvectors=work, eigenvalues=evals)
398 eigenvalues(1:nmo) = evals(1:nmo)
402 CALL timestop(handle)
413 SUBROUTINE cp_cfm_geeig_scalapack(amatrix, bmatrix, eigenvectors, eigenvalues)
415 TYPE(
cp_cfm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
416 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
418 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_geeig_scalapack'
420#if defined(__parallel)
421 REAL(kind=
dp),
PARAMETER :: orfac = -1.0_dp, &
425 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
426 COMPLEX(KIND=dp),
DIMENSION(:, :),
POINTER :: a, b, z
427 INTEGER :: handle, info, liwork, lwork, lrwork, &
428 m, n, nb, neig, npcol, nprow, nz
429 INTEGER,
DIMENSION(9) :: desca, descb, descz
430 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iclustr, ifail, iwork
431 REAL(kind=
dp) :: abstol
432 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: gap, rwork, w
434 INTEGER :: mq0, nn, np0, npe
435 INTEGER,
EXTERNAL :: iceil, numroc
436 REAL(kind=
dp),
EXTERNAL :: dlamch
437#if defined (__HAS_IEEE_EXCEPTIONS)
438 LOGICAL,
DIMENSION(5) :: halt
444 CALL timeset(routinen, handle)
446#if defined(__parallel)
447 n = amatrix%matrix_struct%nrow_global
448 neig = min(
SIZE(eigenvalues), n)
451 CALL timestop(handle)
455 IF (amatrix%matrix_struct%nrow_block /= amatrix%matrix_struct%ncol_block)
THEN
456 cpabort(
"ERROR in "//routinen//
": Invalid blocksize (no square blocks) found")
459 a => amatrix%local_data
460 b => bmatrix%local_data
461 z => eigenvectors%local_data
462 desca(:) = amatrix%matrix_struct%descriptor(:)
463 descb(:) = bmatrix%matrix_struct%descriptor(:)
464 descz(:) = eigenvectors%matrix_struct%descriptor(:)
466 nprow = amatrix%matrix_struct%context%num_pe(1)
467 npcol = amatrix%matrix_struct%context%num_pe(2)
469 nb = amatrix%matrix_struct%nrow_block
471 np0 = numroc(nn, nb, 0, 0, nprow)
472 mq0 = max(numroc(nn, nb, 0, 0, npcol), nb)
474 lwork = n + (np0 + mq0 + nb)*nb
475 lrwork = 4*n + max(5*nn, np0*mq0) + iceil(neig, npe)*nn + max(0, neig - 1)*n
476 liwork = 6*max(n, npe + 1, 4)
480 ALLOCATE (iclustr(2*npe))
484 ALLOCATE (iwork(liwork))
485 ALLOCATE (rwork(lrwork))
487 ALLOCATE (work(lwork))
489 abstol = 2.0_dp*dlamch(
"S")
491#if defined (__HAS_IEEE_EXCEPTIONS)
492 CALL ieee_get_halting_mode(ieee_all, halt)
493 CALL ieee_set_halting_mode(ieee_all, .false.)
495 CALL pzhegvx(1,
"V",
"I",
"U", n, a(1, 1), 1, 1, desca, b(1, 1), 1, 1, descb, &
496 vl, vu, 1, neig, abstol, m, nz, w(1), orfac, z(1, 1), 1, 1, descz, &
497 work(1), lwork, rwork(1), lrwork, iwork(1), liwork, ifail(1), &
498 iclustr(1), gap(1), info)
499#if defined (__HAS_IEEE_EXCEPTIONS)
500 CALL ieee_set_halting_mode(ieee_all, halt)
503 IF (info /= 0 .OR. m < neig .OR. nz < neig)
THEN
504 cpabort(
"ERROR in PZHEGVX (ScaLAPACK), info="//trim(
cp_to_string(info)))
507 eigenvalues(:) = 0.0_dp
508 eigenvalues(1:neig) = w(1:neig)
510 DEALLOCATE (gap, iclustr, ifail, iwork, rwork, w, work)
514 mark_used(eigenvectors)
515 mark_used(eigenvalues)
516 cpabort(
"ERROR in "//routinen//
": PZHEGVX requested without ScaLAPACK support")
519 CALL timestop(handle)
521 END SUBROUTINE cp_cfm_geeig_scalapack
535 TYPE(
cp_cfm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
536 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
538 REAL(kind=
dp),
INTENT(IN) :: epseig
540 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_geeig_canon'
542 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: cevals
543 INTEGER :: handle, i, icol, irow, nao, nc, ncol, &
545 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
547 CALL timeset(routinen, handle)
551 nmo =
SIZE(eigenvalues)
552 ALLOCATE (evals(nao), cevals(nao))
560 IF (evals(i) < epseig)
THEN
574 DO icol = nc + 1, nao
580 evals(nc + 1:nao) = 1.0_dp
583 cevals(:) = cmplx(1.0_dp/sqrt(evals(:)), 0.0_dp, kind=
dp)
590 DO icol = nc + 1, nao
596 eigenvalues(1:nmo) = evals(1:nmo)
603 CALL timestop(handle)
methods related to the blacs parallel environment
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, c_first_row)
Performs one of the matrix-matrix operations: matrix_c = alpha * op1( matrix_a ) * op2( matrix_b ) + ...
subroutine, public cp_cfm_triangular_multiply(triangular_matrix, matrix_b, side, transa_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, alpha)
Multiplies in place by a triangular matrix: matrix_b = alpha op(triangular_matrix) matrix_b or (if si...
subroutine, public cp_cfm_column_scale(matrix_a, scaling)
Scales columns of the full matrix by corresponding factors.
subroutine, public cp_cfm_triangular_invert(matrix_a, uplo, info_out)
Inverts a triangular matrix.
various cholesky decomposition related routines
subroutine, public cp_cfm_cholesky_decompose(matrix, n, info_out)
Used to replace a symmetric positive definite matrix M with its Cholesky decomposition U: M = U^T * U...
used for collecting diagonalization schemes available for cp_cfm_type
subroutine, public cp_cfm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
General Eigenvalue Problem AX = BXE Single option version: Cholesky decomposition of B.
subroutine, public cp_cfm_heevd(matrix, eigenvectors, eigenvalues)
Perform a diagonalisation of a complex matrix.
subroutine, public cp_cfm_geeig_canon(amatrix, bmatrix, eigenvectors, eigenvalues, work, epseig)
General Eigenvalue Problem AX = BXE Use canonical orthogonalization.
subroutine, public cp_cfm_diag_dlaf(matrix, eigenvectors, eigenvalues)
DLA-Future eigensolver for complex Hermitian matrices.
subroutine, public cp_cfm_diag_gen_dlaf(amatrix, bmatrix, eigenvectors, eigenvalues)
DLA-Future generalized eigensolver for complex Hermitian matrices.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_cfm_set_element(matrix, irow_global, icol_global, alpha)
Set the matrix element (irow_global,icol_global) of the full matrix to alpha.
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
subroutine, public cp_dlaf_create_grid(blacs_context)
Create DLA-Future grid from BLACS context.
subroutine, public cp_dlaf_initialize()
Initialize DLA-Future and pika runtime.
subroutine, public cp_cfm_general_cusolver(amatrix, bmatrix, eigenvectors, eigenvalues)
Driver routine to solve generalized complex eigenvalue problem A*x = lambda*B*x with cuSOLVERMp.
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
integer, parameter, public fm_diag_type_cusolver
integer, parameter, public fm_diag_type_dlaf
integer, parameter, public fm_diag_type_scalapack
logical, save, public direct_generalized_diagonalization
real(kind=dp) function, public diag_check_warning_threshold()
Return the warning threshold for diagonalization checks.
integer, save, public diag_type
integer, parameter, public cusolver_n_min
logical function, public diag_check_requested()
Return whether diagonalization checks should be performed.
various routines to log and control the output. The idea is that decisions about where to log should ...
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Machine interface based on Fortran 2003 and POSIX.
integer, parameter, public default_output_unit
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public z_zero
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.