69#if defined (__parallel)
72#if defined (__HAS_IEEE_EXCEPTIONS)
73 USE ieee_exceptions,
ONLY: ieee_get_halting_mode, &
74 ieee_set_halting_mode, &
77#include "../base/base_uses.f90"
82 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_fm_diag'
91 INTEGER,
SAVE :: elpa_neigvec_min = 0
98 INTEGER,
SAVE,
PUBLIC :: dlaf_neigvec_min = 0
103 REAL(kind=
dp),
SAVE :: eps_check_diag = -1.0_dp
110#if defined(__CUSOLVERMP)
153 SUBROUTINE diag_init(diag_lib, fallback_applied, elpa_kernel, elpa_neigvec_min_input, elpa_qr, &
154 elpa_print, elpa_one_stage, dlaf_neigvec_min_input, eps_check_diag_input, &
155 direct_generalized_diagonalization_input)
156 CHARACTER(LEN=*),
INTENT(IN) :: diag_lib
157 LOGICAL,
INTENT(OUT) :: fallback_applied
158 INTEGER,
INTENT(IN) :: elpa_kernel, elpa_neigvec_min_input
160 INTEGER,
INTENT(IN) :: dlaf_neigvec_min_input
161 REAL(kind=
dp),
INTENT(IN) :: eps_check_diag_input
162 LOGICAL,
INTENT(IN),
OPTIONAL :: direct_generalized_diagonalization_input
164 LOGICAL,
SAVE :: initialized = .false.
166 fallback_applied = .false.
168 IF (diag_lib ==
"ScaLAPACK")
THEN
170 ELSE IF (diag_lib ==
"ELPA")
THEN
177 fallback_applied = .true.
179 ELSE IF (diag_lib ==
"cuSOLVER")
THEN
181 ELSE IF (diag_lib ==
"DLAF")
THEN
185 cpabort(
"ERROR in diag_init: CP2K was not compiled with DLA-Future support")
188 cpabort(
"ERROR in diag_init: Initialization of unknown diagonalization library requested")
202 dlaf_neigvec_min = dlaf_neigvec_min_input
204 mark_used(dlaf_neigvec_min_input)
207 elpa_neigvec_min = elpa_neigvec_min_input
208 eps_check_diag = eps_check_diag_input
209 IF (
PRESENT(direct_generalized_diagonalization_input))
THEN
246 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
247 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
248 INTEGER,
INTENT(OUT),
OPTIONAL :: info
250 CHARACTER(LEN=*),
PARAMETER :: routinen =
'choose_eigv_solver'
255 IF (
PRESENT(info)) info = 0
258 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
261 IF (matrix%matrix_struct%nrow_global < elpa_neigvec_min)
THEN
263 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
271 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
278 IF (matrix%matrix_struct%nrow_global < dlaf_neigvec_min)
THEN
280 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
287 cpabort(
"ERROR in "//routinen//
": Invalid diagonalization type requested")
290 CALL check_diag(matrix, eigenvectors, nvec=
SIZE(eigenvalues))
299 LOGICAL :: check_requested
301#if defined(__CHECK_DIAG)
302 check_requested = .true.
304 check_requested = eps_check_diag >= 0.0_dp
314 REAL(kind=
dp) :: eps_warning
317 IF (eps_check_diag >= 0.0_dp)
THEN
318 eps_warning = eps_check_diag
329 SUBROUTINE check_diag(matrix, eigenvectors, nvec)
331 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
332 INTEGER,
INTENT(IN) :: nvec
334 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_diag'
336 CHARACTER(LEN=default_string_length) :: diag_type_name
337 REAL(kind=
dp) :: eps, eps_abort, eps_warning, gold, test
338 INTEGER :: handle, i, j, ncol, nrow, output_unit
339 LOGICAL :: check_eigenvectors
340#if defined(__parallel)
342 INTEGER :: il, jl, ipcol, iprow, &
343 mypcol, myprow, npcol, nprow
344 INTEGER,
DIMENSION(9) :: desca
347 CALL timeset(routinen, handle)
352 eps_abort = 10.0_dp*eps_warning
358 IF (check_eigenvectors)
THEN
359#if defined(__parallel)
360 nrow = eigenvectors%matrix_struct%nrow_global
361 ncol = min(eigenvectors%matrix_struct%ncol_global, nvec)
362 CALL cp_fm_gemm(
"T",
"N", ncol, ncol, nrow, 1.0_dp, eigenvectors, eigenvectors, 0.0_dp, matrix)
363 context => matrix%matrix_struct%context
364 myprow = context%mepos(1)
365 mypcol = context%mepos(2)
366 nprow = context%num_pe(1)
367 npcol = context%num_pe(2)
368 desca(:) = matrix%matrix_struct%descriptor(:)
369 outer:
DO j = 1, ncol
371 CALL infog2l(i, j, desca, nprow, npcol, myprow, mypcol, il, jl, iprow, ipcol)
372 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
373 gold = merge(0.0_dp, 1.0_dp, i /= j)
374 test = matrix%local_data(il, jl)
375 eps = abs(test - gold)
376 IF (eps > eps_warning)
EXIT outer
381 nrow =
SIZE(eigenvectors%local_data, 1)
382 ncol = min(
SIZE(eigenvectors%local_data, 2), nvec)
383 CALL dgemm(
"T",
"N", ncol, ncol, nrow, 1.0_dp, &
384 eigenvectors%local_data(1, 1), nrow, &
385 eigenvectors%local_data(1, 1), nrow, &
386 0.0_dp, matrix%local_data(1, 1), nrow)
387 outer:
DO j = 1, ncol
389 gold = merge(0.0_dp, 1.0_dp, i /= j)
390 test = matrix%local_data(i, j)
391 eps = abs(test - gold)
392 IF (eps > eps_warning)
EXIT outer
396 IF (eps > eps_warning)
THEN
398 diag_type_name =
"SYEVD"
400 diag_type_name =
"ELPA"
402 diag_type_name =
"CUSOLVER"
404 diag_type_name =
"DLAF"
406 cpabort(
"Unknown diag_type")
408 WRITE (unit=output_unit, fmt=
"(/,T2,A,/,T2,A,I0,A,I0,A,F0.15,/,T2,A,F0.0,A,ES10.3)") &
409 "The eigenvectors returned by "//trim(diag_type_name)//
" are not orthonormal", &
410 "Matrix element (", i,
", ", j,
") = ", test, &
411 "The deviation from the expected value ", gold,
" is", eps
412 IF (eps > eps_abort)
THEN
413 cpabort(
"ERROR in "//routinen//
": Check of matrix diagonalization failed")
415 cpwarn(
"Check of matrix diagonalization failed in routine "//routinen)
420 CALL timestop(handle)
422 END SUBROUTINE check_diag
431 SUBROUTINE check_generalized_diag(overlap, eigenvectors, scratch, nvec)
434 TYPE(
cp_fm_type),
INTENT(INOUT) :: overlap, scratch
435 INTEGER,
INTENT(IN) :: nvec
437 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_generalized_diag'
439 CHARACTER(LEN=default_string_length) :: diag_type_name
440 REAL(kind=
dp) :: eps, eps_abort, eps_warning, gold, test
441 INTEGER :: handle, i, j, ncol, nrow, output_unit
442#if defined(__parallel)
444 INTEGER :: il, jl, ipcol, iprow, &
445 mypcol, myprow, npcol, nprow
446 INTEGER,
DIMENSION(9) :: desca
449 CALL timeset(routinen, handle)
452 CALL timestop(handle)
458 eps_abort = 10.0_dp*eps_warning
460 nrow = eigenvectors%matrix_struct%nrow_global
461 ncol = min(eigenvectors%matrix_struct%ncol_global, nvec)
463 CALL parallel_gemm(
"N",
"N", nrow, ncol, nrow, 1.0_dp, overlap, eigenvectors, 0.0_dp, scratch)
464 CALL parallel_gemm(
"T",
"N", ncol, ncol, nrow, 1.0_dp, eigenvectors, scratch, 0.0_dp, overlap)
470#if defined(__parallel)
471 context => overlap%matrix_struct%context
472 myprow = context%mepos(1)
473 mypcol = context%mepos(2)
474 nprow = context%num_pe(1)
475 npcol = context%num_pe(2)
476 desca(:) = overlap%matrix_struct%descriptor(:)
477 outer:
DO j = 1, ncol
479 CALL infog2l(i, j, desca, nprow, npcol, myprow, mypcol, il, jl, iprow, ipcol)
480 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
481 gold = merge(0.0_dp, 1.0_dp, i /= j)
482 test = overlap%local_data(il, jl)
483 eps = abs(test - gold)
484 IF (eps > eps_warning)
EXIT outer
489 outer:
DO j = 1, ncol
491 gold = merge(0.0_dp, 1.0_dp, i /= j)
492 test = overlap%local_data(i, j)
493 eps = abs(test - gold)
494 IF (eps > eps_warning)
EXIT outer
499 IF (eps > eps_warning)
THEN
501 diag_type_name =
"SYGVX"
503 diag_type_name =
"ELPA"
505 diag_type_name =
"CUSOLVER"
507 diag_type_name =
"DLAF"
509 cpabort(
"Unknown diag_type")
511 WRITE (unit=output_unit, fmt=
"(/,T2,A,/,T2,A,I0,A,I0,A,F0.15,/,T2,A,F0.0,A,ES10.3)") &
512 "The generalized eigenvectors returned by "//trim(diag_type_name)//
" are not S-orthonormal", &
513 "Matrix element (", i,
", ", j,
") = ", test, &
514 "The deviation from the expected value ", gold,
" is", eps
515 IF (eps > eps_abort)
THEN
516 cpabort(
"ERROR in "//routinen//
": Check of generalized matrix diagonalization failed")
518 cpwarn(
"Check of generalized matrix diagonalization failed in routine "//routinen)
522 CALL timestop(handle)
524 END SUBROUTINE check_generalized_diag
532 SUBROUTINE cp_fm_error(mesg, info, warn)
533 CHARACTER(LEN=*),
INTENT(IN) :: mesg
534 INTEGER,
INTENT(IN),
OPTIONAL :: info
535 LOGICAL,
INTENT(IN),
OPTIONAL :: warn
537 CHARACTER(LEN=2*default_string_length) :: message
540 IF (
PRESENT(info))
THEN
541 WRITE (message,
"(A,A,I0,A)") mesg,
" (INFO = ", info,
")"
543 WRITE (message,
"(A)") mesg
546 IF (
PRESENT(warn))
THEN
553 cpwarn(trim(message))
555 cpabort(trim(message))
557 END SUBROUTINE cp_fm_error
574 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
575 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
576 INTEGER,
INTENT(OUT),
OPTIONAL :: info
578 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_syevd'
580 INTEGER :: handle, myinfo, n, nmo
581 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eig
582#if defined(__parallel)
583 TYPE(
cp_fm_type) :: eigenvectors_new, matrix_new
585 INTEGER :: liwork, lwork
586 INTEGER,
DIMENSION(:),
POINTER :: iwork
587 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m
588 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
589 INTEGER,
TARGET :: v(1)
590 REAL(kind=
dp),
TARGET :: w(1)
593 CALL timeset(routinen, handle)
597 n = matrix%matrix_struct%nrow_global
600#if defined(__parallel)
608 IF (
ASSOCIATED(matrix_new%matrix_struct))
THEN
609 IF (
PRESENT(info))
THEN
610 CALL cp_fm_syevd_base(matrix_new, eigenvectors_new, eig, myinfo)
612 CALL cp_fm_syevd_base(matrix_new, eigenvectors_new, eig)
621 m => matrix%local_data
625 CALL dsyevd(
'V',
'U', n, m(1, 1),
SIZE(m, 1), eig(1), work(1), lwork, iwork(1), liwork, myinfo)
627 IF (myinfo /= 0)
THEN
628 CALL cp_fm_error(
"ERROR in DSYEVD: Work space query failed", myinfo,
PRESENT(info))
632 lwork = nint(work(1))
633 ALLOCATE (work(lwork))
636 ALLOCATE (iwork(liwork))
638 CALL dsyevd(
'V',
'U', n, m(1, 1),
SIZE(m, 1), eig(1), work(1), lwork, iwork(1), liwork, myinfo)
640 IF (myinfo /= 0)
THEN
641 CALL cp_fm_error(
"ERROR in DSYEVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
650 IF (
PRESENT(info)) info = myinfo
652 nmo =
SIZE(eigenvalues, 1)
654 eigenvalues(1:n) = eig(1:n)
656 eigenvalues(1:nmo) = eig(1:nmo)
661 CALL check_diag(matrix, eigenvectors, n)
663 CALL timestop(handle)
674 SUBROUTINE cp_fm_syevd_base(matrix, eigenvectors, eigenvalues, info)
676 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
677 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
678 INTEGER,
INTENT(OUT),
OPTIONAL :: info
680 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_syevd_base'
682 INTEGER :: handle, myinfo
683#if defined(__parallel)
685 INTEGER :: liwork, lwork, n
686 INTEGER,
DIMENSION(9) :: descm, descv
687 INTEGER,
DIMENSION(:),
POINTER :: iwork
688 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
689 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m, v
690 REAL(kind=
dp),
TARGET :: w(1)
691#if defined (__HAS_IEEE_EXCEPTIONS)
692 LOGICAL,
DIMENSION(5) :: halt
696 CALL timeset(routinen, handle)
700#if defined(__parallel)
702 n = matrix%matrix_struct%nrow_global
703 m => matrix%local_data
704 context => matrix%matrix_struct%context
705 descm(:) = matrix%matrix_struct%descriptor(:)
707 v => eigenvectors%local_data
708 descv(:) = eigenvectors%matrix_struct%descriptor(:)
710 liwork = 7*n + 8*context%num_pe(2) + 2
711 ALLOCATE (iwork(liwork))
717 CALL pdsyevd(
'V',
'U', n, m(1, 1), 1, 1, descm, eigenvalues(1), v(1, 1), 1, 1, descv, &
718 work(1), lwork, iwork(1), liwork, myinfo)
720 IF (matrix%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
721 CALL cp_fm_error(
"ERROR in PDSYEVD: Work space query failed", myinfo,
PRESENT(info))
724 lwork = nint(work(1))
725#if !defined(__SCALAPACK_NO_WA)
727 CALL pdormtr(
'L',
'U',
'N', n, n, m(1, 1), 1, 1, descm, m(1, 1), &
728 v(1, 1), 1, 1, descv, work(1), -1, myinfo)
730 IF (matrix%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
731 CALL cp_fm_error(
"ERROR in PDORMTR: Work space query failed", myinfo,
PRESENT(info))
734 IF (lwork < (work(1) + 2*n))
THEN
735 lwork = nint(work(1)) + 2*n
738 ALLOCATE (work(lwork))
741 IF (liwork < iwork(1))
THEN
744 ALLOCATE (iwork(liwork))
749#if defined (__HAS_IEEE_EXCEPTIONS)
750 CALL ieee_get_halting_mode(ieee_all, halt)
751 CALL ieee_set_halting_mode(ieee_all, .false.)
754 CALL pdsyevd(
'V',
'U', n, m(1, 1), 1, 1, descm, eigenvalues(1), v(1, 1), 1, 1, descv, &
755 work(1), lwork, iwork(1), liwork, myinfo)
757#if defined (__HAS_IEEE_EXCEPTIONS)
758 CALL ieee_set_halting_mode(ieee_all, halt)
760 IF (matrix%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
761 CALL cp_fm_error(
"ERROR in PDSYEVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
764 IF (
PRESENT(info)) info = myinfo
770 mark_used(eigenvectors)
771 mark_used(eigenvalues)
773 IF (
PRESENT(info)) info = myinfo
774 CALL cp_fm_error(
"ERROR in "//trim(routinen)// &
775 ": Matrix diagonalization using PDSYEVD requested without ScaLAPACK support")
778 CALL timestop(handle)
780 END SUBROUTINE cp_fm_syevd_base
796 SUBROUTINE cp_fm_syevx(matrix, eigenvectors, eigenvalues, neig, work_syevx)
801 TYPE(
cp_fm_type),
OPTIONAL,
INTENT(IN) :: eigenvectors
802 REAL(kind=
dp),
OPTIONAL,
INTENT(IN) :: work_syevx
803 INTEGER,
INTENT(IN),
OPTIONAL :: neig
804 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
806 CHARACTER(LEN=*),
PARAMETER :: routinen =
"cp_fm_syevx"
808#if defined(__parallel)
809 REAL(kind=
dp),
PARAMETER :: orfac = -1.0_dp
811 REAL(kind=
dp),
PARAMETER :: vl = 0.0_dp, &
816 CHARACTER(LEN=1) :: job_type
817 REAL(kind=
dp) :: abstol, work_syevx_local
818 INTEGER :: handle, info, liwork, lwork, &
819 m, n, nb, npcol, nprow, &
820 output_unit, neig_local
821 LOGICAL :: ionode, needs_evecs
822 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ifail, iwork
823 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: w, work
824 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, z
826 REAL(kind=
dp),
EXTERNAL :: dlamch
828#if defined(__parallel)
829 INTEGER :: nn, np0, npe, nq0, nz
830 INTEGER,
DIMENSION(9) :: desca, descz
831 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iclustr
832 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: gap
833 INTEGER,
EXTERNAL :: iceil, numroc
836 INTEGER,
EXTERNAL :: ilaenv
838#if defined (__HAS_IEEE_EXCEPTIONS)
839 LOGICAL,
DIMENSION(5) :: halt
843 n = matrix%matrix_struct%nrow_global
845 IF (
PRESENT(neig)) neig_local = neig
846 IF (neig_local == 0)
RETURN
848 CALL timeset(routinen, handle)
850 needs_evecs =
PRESENT(eigenvectors)
853 ionode = logger%para_env%is_source()
854 n = matrix%matrix_struct%nrow_global
857 work_syevx_local = 1.0_dp
858 IF (
PRESENT(work_syevx)) work_syevx_local = work_syevx
861 IF (needs_evecs)
THEN
868 abstol = 2.0_dp*dlamch(
"S")
870 context => matrix%matrix_struct%context
871 nprow = context%num_pe(1)
872 npcol = context%num_pe(2)
875 eigenvalues(:) = 0.0_dp
876#if defined(__parallel)
878 IF (matrix%matrix_struct%nrow_block /= matrix%matrix_struct%ncol_block)
THEN
879 cpabort(
"ERROR in "//routinen//
": Invalid blocksize (no square blocks) found")
882 a => matrix%local_data
883 desca(:) = matrix%matrix_struct%descriptor(:)
885 IF (needs_evecs)
THEN
886 z => eigenvectors%local_data
887 descz(:) = eigenvectors%matrix_struct%descriptor(:)
890 z => matrix%local_data
897 nb = matrix%matrix_struct%nrow_block
899 np0 = numroc(nn, nb, 0, 0, nprow)
900 nq0 = max(numroc(nn, nb, 0, 0, npcol), nb)
902 IF (needs_evecs)
THEN
903 lwork = 5*n + max(5*nn, np0*nq0) + iceil(neig_local, npe)*nn + 2*nb*nb + &
904 int(work_syevx_local*real((neig_local - 1)*n,
dp))
906 lwork = 5*n + max(5*nn, nb*(np0 + 1))
908 liwork = 6*max(n, npe + 1, 4)
912 ALLOCATE (iclustr(2*npe))
916 ALLOCATE (iwork(liwork))
917 ALLOCATE (work(lwork))
921#if defined (__HAS_IEEE_EXCEPTIONS)
922 CALL ieee_get_halting_mode(ieee_all, halt)
923 CALL ieee_set_halting_mode(ieee_all, .false.)
925 CALL pdsyevx(job_type,
"I",
"U", n, a(1, 1), 1, 1, desca, vl, vu, 1, neig_local, abstol, m, nz, w(1), orfac, &
926 z(1, 1), 1, 1, descz, work(1), lwork, iwork(1), liwork, ifail(1), iclustr(1), gap, info)
927#if defined (__HAS_IEEE_EXCEPTIONS)
928 CALL ieee_set_halting_mode(ieee_all, halt)
935 WRITE (unit=output_unit, fmt=
"(/,(T3,A,T12,1X,I10))") &
938 "liwork = ", liwork, &
941 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,I10)))") &
943 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,I10)))") &
944 "iclustr = ", iclustr
945 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,E10.3)))") &
949 cpabort(
"ERROR in PDSYEVX (ScaLAPACK)")
958 a => matrix%local_data
959 IF (needs_evecs)
THEN
960 z => eigenvectors%local_data
963 z => matrix%local_data
968 nb = max(ilaenv(1,
"DSYTRD",
"U", n, -1, -1, -1), &
969 ilaenv(1,
"DORMTR",
"U", n, -1, -1, -1))
971 lwork = max((nb + 3)*n, 8*n) + n
976 ALLOCATE (iwork(liwork))
977 ALLOCATE (work(lwork))
984#if defined (__HAS_IEEE_EXCEPTIONS)
985 CALL ieee_get_halting_mode(ieee_all, halt)
986 CALL ieee_set_halting_mode(ieee_all, .false.)
988 CALL dsyevx(job_type,
"I",
"U", n, a(1, 1), nla, vl, vu, 1, neig_local, &
989 abstol, m, w, z(1, 1), nlz, work(1), lwork, iwork(1), ifail(1), info)
990#if defined (__HAS_IEEE_EXCEPTIONS)
991 CALL ieee_set_halting_mode(ieee_all, halt)
997 WRITE (unit=output_unit, fmt=
"(/,(T3,A,T12,1X,I10))") &
1000 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,I10)))") &
1003 cpabort(
"Error in DSYEVX (ScaLAPACK)")
1011 eigenvalues(1:neig_local) = w(1:neig_local)
1014 IF (needs_evecs)
CALL check_diag(matrix, eigenvectors, neig_local)
1016 CALL timestop(handle)
1029 SUBROUTINE cp_fm_svd(matrix_a, matrix_eigvl, matrix_eigvr_t, eigval, info)
1032 TYPE(
cp_fm_type),
INTENT(INOUT) :: matrix_eigvl, matrix_eigvr_t
1033 REAL(kind=
dp),
DIMENSION(:),
POINTER, &
1034 INTENT(INOUT) :: eigval
1035 INTEGER,
INTENT(OUT),
OPTIONAL :: info
1037 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_svd'
1039 INTEGER :: handle, n, m, myinfo, lwork
1040 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1042 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
1043 REAL(kind=
dp),
TARGET :: w(1)
1044#if defined(__parallel)
1045 INTEGER,
DIMENSION(9) :: desca, descu, descvt
1048 CALL timeset(routinen, handle)
1051 matrix_struct=matrix_a%matrix_struct, &
1054 a => matrix_lu%local_data
1055 m = matrix_lu%matrix_struct%nrow_global
1056 n = matrix_lu%matrix_struct%ncol_global
1064#if defined(__parallel)
1066 desca(:) = matrix_lu%matrix_struct%descriptor(:)
1067 descu(:) = matrix_eigvl%matrix_struct%descriptor(:)
1068 descvt(:) = matrix_eigvr_t%matrix_struct%descriptor(:)
1071 CALL pdgesvd(
'V',
'V', m, m, matrix_lu%local_data, 1, 1, desca, eigval, matrix_eigvl%local_data, &
1072 1, 1, descu, matrix_eigvr_t%local_data, 1, 1, descvt, work, lwork, myinfo)
1074 IF (matrix_lu%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
1075 CALL cp_fm_error(
"ERROR in PDGESVD: Work space query failed", myinfo,
PRESENT(info))
1078 lwork = nint(work(1))
1079 ALLOCATE (work(lwork))
1081 CALL pdgesvd(
'V',
'V', m, m, matrix_lu%local_data, 1, 1, desca, eigval, matrix_eigvl%local_data, &
1082 1, 1, descu, matrix_eigvr_t%local_data, 1, 1, descvt, work, lwork, myinfo)
1084 IF (matrix_lu%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
1085 CALL cp_fm_error(
"ERROR in PDGESVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
1089 CALL dgesvd(
'S',
'S', m, m, matrix_lu%local_data, m, eigval, matrix_eigvl%local_data, &
1090 m, matrix_eigvr_t%local_data, m, work, lwork, myinfo)
1092 IF (myinfo /= 0)
THEN
1093 CALL cp_fm_error(
"ERROR in DGESVD: Work space query failed", myinfo,
PRESENT(info))
1096 lwork = nint(work(1))
1097 ALLOCATE (work(lwork))
1099 CALL dgesvd(
'S',
'S', m, m, matrix_lu%local_data, m, eigval, matrix_eigvl%local_data, &
1100 m, matrix_eigvr_t%local_data, m, work, lwork, myinfo)
1102 IF (myinfo /= 0)
THEN
1103 CALL cp_fm_error(
"ERROR in DGESVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
1111 IF (
PRESENT(info)) info = myinfo
1113 CALL timestop(handle)
1126 SUBROUTINE cp_fm_power(matrix, work, exponent, threshold, n_dependent, verbose, eigvals)
1136 REAL(kind=
dp),
INTENT(IN) :: exponent, threshold
1137 INTEGER,
INTENT(OUT) :: n_dependent
1138 LOGICAL,
INTENT(IN),
OPTIONAL :: verbose
1139 REAL(kind=
dp),
DIMENSION(2),
INTENT(OUT), &
1142 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_power'
1144 INTEGER :: handle, icol_global, &
1146 ncol_global, nrow_global
1147 LOGICAL :: my_verbose
1148 REAL(kind=
dp) :: condition_number, f, p
1149 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: eigenvalues
1150 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: eigenvectors
1153#if defined(__parallel)
1154 INTEGER :: icol_local, ipcol, iprow, irow_global, irow_local
1157 CALL timeset(routinen, handle)
1159 my_verbose = .false.
1160 IF (
PRESENT(verbose)) my_verbose = verbose
1162 context => matrix%matrix_struct%context
1163 myprow = context%mepos(1)
1164 mypcol = context%mepos(2)
1168 nrow_global = matrix%matrix_struct%nrow_global
1169 ncol_global = matrix%matrix_struct%ncol_global
1171 ALLOCATE (eigenvalues(ncol_global))
1172 eigenvalues(:) = 0.0_dp
1178 IF (
PRESENT(eigvals))
THEN
1179 eigvals(1) = eigenvalues(1)
1180 eigvals(2) = eigenvalues(ncol_global)
1183#if defined(__parallel)
1184 eigenvectors => work%local_data
1188 DO icol_global = 1, ncol_global
1190 IF (eigenvalues(icol_global) < threshold)
THEN
1192 n_dependent = n_dependent + 1
1194 ipcol = work%matrix_struct%g2p_col(icol_global)
1196 IF (mypcol == ipcol)
THEN
1197 icol_local = work%matrix_struct%g2l_col(icol_global)
1198 DO irow_global = 1, nrow_global
1199 iprow = work%matrix_struct%g2p_row(irow_global)
1200 IF (myprow == iprow)
THEN
1201 irow_local = work%matrix_struct%g2l_row(irow_global)
1202 eigenvectors(irow_local, icol_local) = 0.0_dp
1209 f = eigenvalues(icol_global)**p
1211 ipcol = work%matrix_struct%g2p_col(icol_global)
1213 IF (mypcol == ipcol)
THEN
1214 icol_local = work%matrix_struct%g2l_col(icol_global)
1215 DO irow_global = 1, nrow_global
1216 iprow = work%matrix_struct%g2p_row(irow_global)
1217 IF (myprow == iprow)
THEN
1218 irow_local = work%matrix_struct%g2l_row(irow_global)
1219 eigenvectors(irow_local, icol_local) = &
1220 f*eigenvectors(irow_local, icol_local)
1231 eigenvectors => work%local_data
1235 DO icol_global = 1, ncol_global
1237 IF (eigenvalues(icol_global) < threshold)
THEN
1239 n_dependent = n_dependent + 1
1240 eigenvectors(1:nrow_global, icol_global) = 0.0_dp
1244 f = eigenvalues(icol_global)**p
1245 eigenvectors(1:nrow_global, icol_global) = &
1246 f*eigenvectors(1:nrow_global, icol_global)
1253 CALL cp_fm_syrk(
"U",
"N", ncol_global, 1.0_dp, work, 1, 1, 0.0_dp, matrix)
1257 IF (matrix%matrix_struct%para_env%is_source() .AND. my_verbose)
THEN
1258 condition_number = abs(eigenvalues(ncol_global)/eigenvalues(1))
1260 "CP_FM_POWER: smallest eigenvalue:", eigenvalues(1), &
1261 "CP_FM_POWER: largest eigenvalue: ", eigenvalues(ncol_global), &
1262 "CP_FM_POWER: condition number: ", condition_number
1263 IF (eigenvalues(1) <= 0.0_dp)
THEN
1265 "WARNING: matrix has a negative eigenvalue, tighten EPS_DEFAULT"
1267 IF (condition_number > 1.0e12_dp)
THEN
1269 "WARNING: high condition number => possibly ill-conditioned matrix"
1273 DEALLOCATE (eigenvalues)
1275 CALL timestop(handle)
1298 TYPE(
cp_fm_type),
INTENT(IN) :: eigenvectors, matrix
1299 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: eigval
1300 INTEGER,
INTENT(IN) :: start_sec_block
1301 REAL(kind=
dp),
INTENT(IN) :: thresh
1303 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_block_jacobi'
1306 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, ev
1308 REAL(kind=
dp) :: tan_theta, tau, c, s
1310 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: c_ip
1312#if defined(__parallel)
1315 INTEGER :: nprow, npcol, block_dim_row, block_dim_col, info, &
1316 ev_row_block_size, iam, mynumrows, mype, npe, q_loc
1317 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: a_loc, ev_loc
1318 INTEGER,
DIMENSION(9) :: desca, descz, &
1323 INTEGER,
EXTERNAL :: numroc
1328 CALL timeset(routinen, handle)
1330#if defined(__parallel)
1331 context => matrix%matrix_struct%context
1332 allgrp = matrix%matrix_struct%para_env
1334 nprow = context%num_pe(1)
1335 npcol = context%num_pe(2)
1337 n = matrix%matrix_struct%nrow_global
1339 a => matrix%local_data
1340 desca(:) = matrix%matrix_struct%descriptor(:)
1341 ev => eigenvectors%local_data
1342 descz(:) = eigenvectors%matrix_struct%descriptor(:)
1348 block_dim_row = start_sec_block - 1
1349 block_dim_col = n - block_dim_row
1350 ALLOCATE (a_loc(block_dim_row, block_dim_col))
1352 mype = matrix%matrix_struct%para_env%mepos
1353 npe = matrix%matrix_struct%para_env%num_pe
1355 CALL ictxt_loc%gridinit(matrix%matrix_struct%para_env,
'Row-major', nprow*npcol, 1)
1357 CALL descinit(desc_a_block, block_dim_row, block_dim_col, block_dim_row, &
1358 block_dim_col, 0, 0, ictxt_loc%get_handle(), block_dim_row, info)
1360 CALL pdgemr2d(block_dim_row, block_dim_col, a, 1, start_sec_block, desca, &
1361 a_loc, 1, 1, desc_a_block, context%get_handle())
1363 CALL allgrp%bcast(a_loc, 0)
1370 ev_row_block_size = n/(nprow*npcol)
1371 mynumrows = numroc(n, ev_row_block_size, iam, 0, nprow*npcol)
1373 ALLOCATE (ev_loc(mynumrows, n), c_ip(mynumrows))
1375 CALL descinit(desc_ev_loc, n, n, ev_row_block_size, n, 0, 0, ictxt_loc%get_handle(), &
1378 CALL pdgemr2d(n, n, ev, 1, 1, descz, ev_loc, 1, 1, desc_ev_loc, context%get_handle())
1384 DO q = start_sec_block, n
1386 DO p = 1, (start_sec_block - 1)
1388 IF (abs(a_loc(p, q_loc)) > thresh)
THEN
1390 tau = (eigval(q) - eigval(p))/(2.0_dp*a_loc(p, q_loc))
1392 tan_theta = sign(1.0_dp, tau)/(abs(tau) + sqrt(1.0_dp + tau*tau))
1395 c = 1.0_dp/sqrt(1.0_dp + tan_theta*tan_theta)
1403 CALL dcopy(mynumrows, ev_loc(1, p), 1, c_ip(1), 1)
1404 CALL dscal(mynumrows, c, ev_loc(1, p), 1)
1405 CALL daxpy(mynumrows, -s, ev_loc(1, q), 1, ev_loc(1, p), 1)
1406 CALL dscal(mynumrows, c, ev_loc(1, q), 1)
1407 CALL daxpy(mynumrows, s, c_ip(1), 1, ev_loc(1, q), 1)
1415 CALL pdgemr2d(n, n, ev_loc, 1, 1, desc_ev_loc, ev, 1, 1, descz, context%get_handle())
1418 DEALLOCATE (a_loc, ev_loc, c_ip)
1420 CALL ictxt_loc%gridexit()
1424 n = matrix%matrix_struct%nrow_global
1428 a => matrix%local_data
1429 ev => eigenvectors%local_data
1436 DO q = start_sec_block, n
1437 DO p = 1, (start_sec_block - 1)
1439 IF (abs(a(p, q)) > thresh)
THEN
1441 tau = (eigval(q) - eigval(p))/(2.0_dp*a(p, q))
1443 tan_theta = sign(1.0_dp, tau)/(abs(tau) + sqrt(1.0_dp + tau*tau))
1446 c = 1.0_dp/sqrt(1.0_dp + tan_theta*tan_theta)
1454 CALL dcopy(n, ev(1, p), 1, c_ip(1), 1)
1455 CALL dscal(n, c, ev(1, p), 1)
1456 CALL daxpy(n, -s, ev(1, q), 1, ev(1, p), 1)
1457 CALL dscal(n, c, ev(1, q), 1)
1458 CALL daxpy(n, s, c_ip(1), 1, ev(1, q), 1)
1471 CALL timestop(handle)
1485 SUBROUTINE cp_fm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
1487 TYPE(
cp_fm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
1488 REAL(kind=
dp),
DIMENSION(:) :: eigenvalues
1491 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geeig'
1493 INTEGER :: handle, nao, nmo
1494 LOGICAL :: check_eigenvectors
1495 TYPE(
cp_fm_type) :: overlap_check, scratch_check
1497 CALL timeset(routinen, handle)
1500 nmo =
SIZE(eigenvalues)
1508 IF (check_eigenvectors)
THEN
1509 CALL cp_fm_create(overlap_check, bmatrix%matrix_struct)
1510 CALL cp_fm_create(scratch_check, bmatrix%matrix_struct)
1514 IF (check_eigenvectors)
THEN
1515 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
1520#if defined(__parallel)
1524 IF (check_eigenvectors)
THEN
1525 CALL cp_fm_create(overlap_check, bmatrix%matrix_struct)
1526 CALL cp_fm_create(scratch_check, bmatrix%matrix_struct)
1529 CALL cp_fm_geeig_scalapack(amatrix, bmatrix, work, eigenvalues)
1530 IF (check_eigenvectors)
THEN
1531 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
1539 nao >= dlaf_neigvec_min)
THEN
1541 IF (check_eigenvectors)
THEN
1542 CALL cp_fm_create(overlap_check, bmatrix%matrix_struct)
1543 CALL cp_fm_create(scratch_check, bmatrix%matrix_struct)
1547 IF (check_eigenvectors)
THEN
1548 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
1564 eigenvalues=eigenvalues)
1570 CALL timestop(handle)
1581 SUBROUTINE cp_fm_geeig_scalapack(amatrix, bmatrix, eigenvectors, eigenvalues)
1583 TYPE(
cp_fm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
1584 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1586 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geeig_scalapack'
1588#if defined(__parallel)
1589 REAL(kind=
dp),
PARAMETER :: orfac = -1.0_dp, &
1593 INTEGER :: handle, info, liwork, lwork, m, n, nb, &
1594 neig, npcol, nprow, nz
1595 INTEGER,
DIMENSION(9) :: desca, descb, descz
1596 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iclustr, ifail, iwork
1597 REAL(kind=
dp) :: abstol
1598 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: gap, w, work
1599 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, z
1601 INTEGER :: mq0, nn, np0, npe
1602 INTEGER,
EXTERNAL :: iceil, numroc
1603 REAL(kind=
dp),
EXTERNAL :: dlamch
1604#if defined (__HAS_IEEE_EXCEPTIONS)
1605 LOGICAL,
DIMENSION(5) :: halt
1611 CALL timeset(routinen, handle)
1613#if defined(__parallel)
1614 n = amatrix%matrix_struct%nrow_global
1615 neig = min(
SIZE(eigenvalues), n)
1618 CALL timestop(handle)
1622 IF (amatrix%matrix_struct%nrow_block /= amatrix%matrix_struct%ncol_block)
THEN
1623 cpabort(
"ERROR in "//routinen//
": Invalid blocksize (no square blocks) found")
1626 a => amatrix%local_data
1627 b => bmatrix%local_data
1628 z => eigenvectors%local_data
1629 desca(:) = amatrix%matrix_struct%descriptor(:)
1630 descb(:) = bmatrix%matrix_struct%descriptor(:)
1631 descz(:) = eigenvectors%matrix_struct%descriptor(:)
1633 nprow = amatrix%matrix_struct%context%num_pe(1)
1634 npcol = amatrix%matrix_struct%context%num_pe(2)
1636 nb = amatrix%matrix_struct%nrow_block
1638 np0 = numroc(nn, nb, 0, 0, nprow)
1639 mq0 = max(numroc(nn, nb, 0, 0, npcol), nb)
1641 lwork = 5*n + max(5*nn, np0*mq0 + 2*nb*nb) + iceil(neig, npe)*nn + &
1643 liwork = 6*max(n, npe + 1, 4)
1647 ALLOCATE (iclustr(2*npe))
1651 ALLOCATE (iwork(liwork))
1653 ALLOCATE (work(lwork))
1655 abstol = 2.0_dp*dlamch(
"S")
1657#if defined (__HAS_IEEE_EXCEPTIONS)
1658 CALL ieee_get_halting_mode(ieee_all, halt)
1659 CALL ieee_set_halting_mode(ieee_all, .false.)
1661 CALL pdsygvx(1,
"V",
"I",
"U", n, a(1, 1), 1, 1, desca, b(1, 1), 1, 1, descb, &
1662 vl, vu, 1, neig, abstol, m, nz, w(1), orfac, z(1, 1), 1, 1, descz, &
1663 work(1), lwork, iwork(1), liwork, ifail(1), iclustr(1), gap(1), info)
1664#if defined (__HAS_IEEE_EXCEPTIONS)
1665 CALL ieee_set_halting_mode(ieee_all, halt)
1668 IF (info /= 0 .OR. m < neig .OR. nz < neig)
THEN
1669 cpabort(
"ERROR in PDSYGVX (ScaLAPACK), info="//trim(
cp_to_string(info)))
1672 eigenvalues(:) = 0.0_dp
1673 eigenvalues(1:neig) = w(1:neig)
1675 DEALLOCATE (gap, iclustr, ifail, iwork, w, work)
1679 mark_used(eigenvectors)
1680 mark_used(eigenvalues)
1681 cpabort(
"ERROR in "//routinen//
": PDSYGVX requested without ScaLAPACK support")
1684 CALL timestop(handle)
1686 END SUBROUTINE cp_fm_geeig_scalapack
1700 TYPE(
cp_fm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
1701 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1703 REAL(kind=
dp),
INTENT(IN) :: epseig
1705 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geeig_canon'
1707 INTEGER :: handle, i, icol, irow, nao, nc, ncol, &
1709 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
1711 CALL timeset(routinen, handle)
1715 nmo =
SIZE(eigenvalues)
1716 ALLOCATE (evals(nao))
1721 evals(:) = -evals(:)
1724 IF (evals(i) < epseig)
THEN
1735 CALL cp_fm_to_fm(work, eigenvectors, ncol, nc + 1, nc + 1)
1738 DO icol = nc + 1, nao
1744 evals(nc + 1:nao) = 1.0_dp
1747 evals(:) = 1.0_dp/sqrt(evals(:))
1750 CALL cp_fm_gemm(
"T",
"N", nao, nao, nao, 1.0_dp, work, amatrix, 0.0_dp, bmatrix)
1751 CALL cp_fm_gemm(
"N",
"N", nao, nao, nao, 1.0_dp, bmatrix, work, 0.0_dp, amatrix)
1754 DO icol = nc + 1, nao
1759 CALL choose_eigv_solver(matrix=amatrix, eigenvectors=bmatrix, eigenvalues=eigenvalues)
1762 CALL cp_fm_gemm(
"N",
"N", nao, nx, nc, 1.0_dp, work, bmatrix, 0.0_dp, eigenvectors)
1766 CALL timestop(handle)
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
methods related to the blacs parallel environment
wrappers for the actual blacs calls. all functionality needed in the code should actually be provide ...
subroutine, public cp_dlaf_finalize()
Finalize DLA-Future and pika runtime.
subroutine, public cp_dlaf_initialize()
Initialize DLA-Future and pika runtime.
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_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)
computes matrix_c = beta * matrix_c + alpha * ( matrix_a ** transa ) * ( matrix_b ** transb )
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
subroutine, public cp_fm_syrk(uplo, trans, k, alpha, matrix_a, ia, ja, beta, matrix_c)
performs a rank-k update of a symmetric matrix_c matrix_c = beta * matrix_c + alpha * matrix_a * tran...
subroutine, public cp_fm_uplo_to_full(matrix, work, uplo)
given a triangular matrix according to uplo, computes the corresponding full matrix
subroutine, public cp_fm_scale(alpha, matrix_a)
scales a matrix matrix_a = alpha * matrix_b
subroutine, public cp_fm_triangular_invert(matrix_a, uplo_tr)
inverts a triangular matrix
subroutine, public cp_fm_triangular_multiply(triangular_matrix, matrix_b, side, transpose_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...
various cholesky decomposition related routines
subroutine, public cp_fm_cholesky_decompose(matrix, n, info_out)
used to replace a symmetric positive def. matrix M with its cholesky decomposition U: M = U^T * U,...
subroutine, public cp_fm_general_cusolver(amatrix, bmatrix, eigenvectors, eigenvalues)
Driver routine to solve generalized eigenvalue problem A*x = lambda*B*x with cuSOLVERMp.
subroutine, public cp_fm_diag_cusolver(matrix, eigenvectors, eigenvalues)
Driver routine to diagonalize a FM matrix with the cuSOLVERMp library.
Auxiliary tools to redistribute cp_fm_type matrices before and after diagonalization....
subroutine, public cp_fm_redistribute_end(matrix, eigenvectors, eig, matrix_new, eigenvectors_new)
Redistributes eigenvectors and eigenvalues back to the original communicator group.
subroutine, public cp_fm_redistribute_start(matrix, eigenvectors, matrix_new, eigenvectors_new, caller_is_elpa, redist_info)
Determines the optimal number of CPUs for matrix diagonalization and redistributes the input matrices...
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
subroutine, public cp_fm_block_jacobi(matrix, eigenvectors, eigval, thresh, start_sec_block)
...
real(kind=dp), parameter, public eps_check_diag_default
subroutine, public cp_fm_power(matrix, work, exponent, threshold, n_dependent, verbose, eigvals)
...
integer, parameter, public fm_diag_type_cusolver
subroutine, public cp_fm_svd(matrix_a, matrix_eigvl, matrix_eigvr_t, eigval, info)
decomposes a quadratic matrix into its singular value decomposition
integer, parameter, public fm_diag_type_dlaf
integer, parameter, public fm_diag_type_scalapack
subroutine, public cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
Computes all eigenvalues and vectors of a real symmetric matrix significantly faster than syevx,...
subroutine, public diag_finalize()
Finalize the diagonalization library.
logical, save, public direct_generalized_diagonalization
integer, parameter, public fm_diag_type_default
subroutine, public cp_fm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
General Eigenvalue Problem AX = BXE. Use cuSOLVERMp directly when requested and large enough; otherwi...
subroutine, public choose_eigv_solver(matrix, eigenvectors, eigenvalues, info)
Choose the Eigensolver depending on which library is available ELPA seems to be unstable for small sy...
real(kind=dp) function, public diag_check_warning_threshold()
Return the warning threshold for diagonalization checks.
integer, save, public diag_type
integer, parameter, public fm_diag_type_elpa
integer, parameter, public cusolver_n_min
subroutine, public diag_init(diag_lib, fallback_applied, elpa_kernel, elpa_neigvec_min_input, elpa_qr, elpa_print, elpa_one_stage, dlaf_neigvec_min_input, eps_check_diag_input, direct_generalized_diagonalization_input)
Setup the diagonalization library to be used.
logical function, public diag_check_requested()
Return whether diagonalization checks should be performed.
subroutine, public cp_fm_geeig_canon(amatrix, bmatrix, eigenvectors, eigenvalues, work, epseig)
General Eigenvalue Problem AX = BXE Use canonical diagonalization : U*s**(-1/2)
subroutine, public cp_fm_syevx(matrix, eigenvectors, eigenvalues, neig, work_syevx)
compute eigenvalues and optionally eigenvectors of a real symmetric matrix using scalapack....
subroutine, public cp_fm_diag_dlaf(matrix, eigenvectors, eigenvalues)
...
subroutine, public cp_fm_diag_gen_dlaf(a_matrix, b_matrix, eigenvectors, eigenvalues)
...
subroutine, public set_elpa_kernel(requested_kernel)
Sets the active ELPA kernel.
logical, save, public elpa_qr
subroutine, public cp_fm_diag_elpa(matrix, eigenvectors, eigenvalues)
Driver routine to diagonalize a FM matrix with the ELPA library.
logical, save, public elpa_print
subroutine, public finalize_elpa_library()
Finalize the ELPA library.
logical, save, public elpa_one_stage
subroutine, public initialize_elpa_library(one_stage, qr, should_print)
Initialize the ELPA library.
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
logical function, public cp_fm_struct_equivalent(fmstruct1, fmstruct2)
returns true if the two matrix structures are equivalent, false otherwise.
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp, nrow, ncol, set_zero)
creates a new full matrix with the given structure
subroutine, public cp_fm_to_fm_submat(msource, mtarget, nrow, ncol, s_firstrow, s_firstcol, t_firstrow, t_firstcol)
copy just a part ot the matrix
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_set_element(matrix, irow_global, icol_global, alpha)
sets an element of a matrix
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
integer function, public cp_logger_get_unit_nr(logger, local)
returns the unit nr for the requested kind of log.
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
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
subroutine, public m_memory(mem)
Returns the total amount of memory [bytes] in use, if known, zero otherwise.
Interface to the message passing library MPI.
basic linear algebra operations for full matrixes
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...