70#if defined (__parallel)
73#if defined (__HAS_IEEE_EXCEPTIONS)
74 USE ieee_exceptions,
ONLY: ieee_get_halting_mode, &
75 ieee_set_halting_mode, &
78#include "../base/base_uses.f90"
83 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_fm_diag'
109 REAL(kind=
dp),
SAVE :: eps_check_diag = -1.0_dp
116#if defined(__CUSOLVERMP)
161 SUBROUTINE diag_init(diag_lib, fallback_applied, elpa_kernel, elpa_c_kernel, elpa_neigvec_min_input, &
162 elpa_qr, elpa_print, elpa_one_stage, dlaf_neigvec_min_input, eps_check_diag_input, &
163 direct_generalized_diagonalization_input, diag_lib_explicit_input)
164 CHARACTER(LEN=*),
INTENT(IN) :: diag_lib
165 LOGICAL,
INTENT(OUT) :: fallback_applied
166 INTEGER,
INTENT(IN) :: elpa_kernel
167 INTEGER,
INTENT(IN),
OPTIONAL :: elpa_c_kernel
168 INTEGER,
INTENT(IN) :: elpa_neigvec_min_input
170 INTEGER,
INTENT(IN) :: dlaf_neigvec_min_input
171 REAL(kind=
dp),
INTENT(IN) :: eps_check_diag_input
172 LOGICAL,
INTENT(IN),
OPTIONAL :: direct_generalized_diagonalization_input, &
173 diag_lib_explicit_input
175 LOGICAL,
SAVE :: initialized = .false.
177 fallback_applied = .false.
179 IF (diag_lib ==
"ScaLAPACK")
THEN
181 ELSE IF (diag_lib ==
"ELPA")
THEN
188 fallback_applied = .true.
190 ELSE IF (diag_lib ==
"cuSOLVER")
THEN
192 ELSE IF (diag_lib ==
"DLAF")
THEN
196 cpabort(
"ERROR in diag_init: CP2K was not compiled with DLA-Future support")
199 cpabort(
"ERROR in diag_init: Initialization of unknown diagonalization library requested")
205 IF (
PRESENT(diag_lib_explicit_input))
diag_lib_explicit = diag_lib_explicit_input
221 mark_used(dlaf_neigvec_min_input)
225 eps_check_diag = eps_check_diag_input
226 IF (
PRESENT(direct_generalized_diagonalization_input))
THEN
263 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
264 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
265 INTEGER,
INTENT(OUT),
OPTIONAL :: info
267 CHARACTER(LEN=*),
PARAMETER :: routinen =
'choose_eigv_solver'
272 IF (
PRESENT(info)) info = 0
275 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
280 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
288 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
297 CALL cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
304 cpabort(
"ERROR in "//routinen//
": Invalid diagonalization type requested")
307 CALL check_diag(matrix, eigenvectors, nvec=
SIZE(eigenvalues))
316 LOGICAL :: check_requested
318#if defined(__CHECK_DIAG)
319 check_requested = .true.
321 check_requested = eps_check_diag >= 0.0_dp
331 REAL(kind=
dp) :: eps_warning
334 IF (eps_check_diag >= 0.0_dp)
THEN
335 eps_warning = eps_check_diag
346 SUBROUTINE check_diag(matrix, eigenvectors, nvec)
348 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
349 INTEGER,
INTENT(IN) :: nvec
351 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_diag'
353 CHARACTER(LEN=default_string_length) :: diag_type_name
354 REAL(kind=
dp) :: eps, eps_abort, eps_warning, gold, test
355 INTEGER :: handle, i, j, ncol, nrow, output_unit
356 LOGICAL :: check_eigenvectors
357#if defined(__parallel)
359 INTEGER :: il, jl, ipcol, iprow, &
360 mypcol, myprow, npcol, nprow
361 INTEGER,
DIMENSION(9) :: desca
364 CALL timeset(routinen, handle)
369 eps_abort = 10.0_dp*eps_warning
375 IF (check_eigenvectors)
THEN
376#if defined(__parallel)
377 nrow = eigenvectors%matrix_struct%nrow_global
378 ncol = min(eigenvectors%matrix_struct%ncol_global, nvec)
379 CALL cp_fm_gemm(
"T",
"N", ncol, ncol, nrow, 1.0_dp, eigenvectors, eigenvectors, 0.0_dp, matrix)
380 context => matrix%matrix_struct%context
381 myprow = context%mepos(1)
382 mypcol = context%mepos(2)
383 nprow = context%num_pe(1)
384 npcol = context%num_pe(2)
385 desca(:) = matrix%matrix_struct%descriptor(:)
386 outer:
DO j = 1, ncol
388 CALL infog2l(i, j, desca, nprow, npcol, myprow, mypcol, il, jl, iprow, ipcol)
389 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
390 gold = merge(0.0_dp, 1.0_dp, i /= j)
391 test = matrix%local_data(il, jl)
392 eps = abs(test - gold)
393 IF (eps > eps_warning)
EXIT outer
398 nrow =
SIZE(eigenvectors%local_data, 1)
399 ncol = min(
SIZE(eigenvectors%local_data, 2), nvec)
400 CALL dgemm(
"T",
"N", ncol, ncol, nrow, 1.0_dp, &
401 eigenvectors%local_data(1, 1), nrow, &
402 eigenvectors%local_data(1, 1), nrow, &
403 0.0_dp, matrix%local_data(1, 1), nrow)
404 outer:
DO j = 1, ncol
406 gold = merge(0.0_dp, 1.0_dp, i /= j)
407 test = matrix%local_data(i, j)
408 eps = abs(test - gold)
409 IF (eps > eps_warning)
EXIT outer
413 IF (eps > eps_warning)
THEN
415 diag_type_name =
"SYEVD"
417 diag_type_name =
"ELPA"
419 diag_type_name =
"CUSOLVER"
421 diag_type_name =
"DLAF"
423 cpabort(
"Unknown diag_type")
425 WRITE (unit=output_unit, fmt=
"(/,T2,A,/,T2,A,I0,A,I0,A,F0.15,/,T2,A,F0.0,A,ES10.3)") &
426 "The eigenvectors returned by "//trim(diag_type_name)//
" are not orthonormal", &
427 "Matrix element (", i,
", ", j,
") = ", test, &
428 "The deviation from the expected value ", gold,
" is", eps
429 IF (eps > eps_abort)
THEN
430 cpabort(
"ERROR in "//routinen//
": Check of matrix diagonalization failed")
432 cpwarn(
"Check of matrix diagonalization failed in routine "//routinen)
437 CALL timestop(handle)
439 END SUBROUTINE check_diag
448 SUBROUTINE check_generalized_diag(overlap, eigenvectors, scratch, nvec)
451 TYPE(
cp_fm_type),
INTENT(INOUT) :: overlap, scratch
452 INTEGER,
INTENT(IN) :: nvec
454 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_generalized_diag'
456 CHARACTER(LEN=default_string_length) :: diag_type_name
457 REAL(kind=
dp) :: eps, eps_abort, eps_warning, gold, test
458 INTEGER :: handle, i, j, ncol, nrow, output_unit
459#if defined(__parallel)
461 INTEGER :: il, jl, ipcol, iprow, &
462 mypcol, myprow, npcol, nprow
463 INTEGER,
DIMENSION(9) :: desca
466 CALL timeset(routinen, handle)
469 CALL timestop(handle)
475 eps_abort = 10.0_dp*eps_warning
477 nrow = eigenvectors%matrix_struct%nrow_global
478 ncol = min(eigenvectors%matrix_struct%ncol_global, nvec)
480 CALL parallel_gemm(
"N",
"N", nrow, ncol, nrow, 1.0_dp, overlap, eigenvectors, 0.0_dp, scratch)
481 CALL parallel_gemm(
"T",
"N", ncol, ncol, nrow, 1.0_dp, eigenvectors, scratch, 0.0_dp, overlap)
487#if defined(__parallel)
488 context => overlap%matrix_struct%context
489 myprow = context%mepos(1)
490 mypcol = context%mepos(2)
491 nprow = context%num_pe(1)
492 npcol = context%num_pe(2)
493 desca(:) = overlap%matrix_struct%descriptor(:)
494 outer:
DO j = 1, ncol
496 CALL infog2l(i, j, desca, nprow, npcol, myprow, mypcol, il, jl, iprow, ipcol)
497 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
498 gold = merge(0.0_dp, 1.0_dp, i /= j)
499 test = overlap%local_data(il, jl)
500 eps = abs(test - gold)
501 IF (eps > eps_warning)
EXIT outer
506 outer:
DO j = 1, ncol
508 gold = merge(0.0_dp, 1.0_dp, i /= j)
509 test = overlap%local_data(i, j)
510 eps = abs(test - gold)
511 IF (eps > eps_warning)
EXIT outer
516 IF (eps > eps_warning)
THEN
518 diag_type_name =
"SYGVX"
520 diag_type_name =
"ELPA"
522 diag_type_name =
"CUSOLVER"
524 diag_type_name =
"DLAF"
526 cpabort(
"Unknown diag_type")
528 WRITE (unit=output_unit, fmt=
"(/,T2,A,/,T2,A,I0,A,I0,A,F0.15,/,T2,A,F0.0,A,ES10.3)") &
529 "The generalized eigenvectors returned by "//trim(diag_type_name)//
" are not S-orthonormal", &
530 "Matrix element (", i,
", ", j,
") = ", test, &
531 "The deviation from the expected value ", gold,
" is", eps
532 IF (eps > eps_abort)
THEN
533 cpabort(
"ERROR in "//routinen//
": Check of generalized matrix diagonalization failed")
535 cpwarn(
"Check of generalized matrix diagonalization failed in routine "//routinen)
539 CALL timestop(handle)
541 END SUBROUTINE check_generalized_diag
549 SUBROUTINE cp_fm_error(mesg, info, warn)
550 CHARACTER(LEN=*),
INTENT(IN) :: mesg
551 INTEGER,
INTENT(IN),
OPTIONAL :: info
552 LOGICAL,
INTENT(IN),
OPTIONAL :: warn
554 CHARACTER(LEN=2*default_string_length) :: message
557 IF (
PRESENT(info))
THEN
558 WRITE (message,
"(A,A,I0,A)") mesg,
" (INFO = ", info,
")"
560 WRITE (message,
"(A)") mesg
563 IF (
PRESENT(warn))
THEN
570 cpwarn(trim(message))
572 cpabort(trim(message))
574 END SUBROUTINE cp_fm_error
591 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
592 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
593 INTEGER,
INTENT(OUT),
OPTIONAL :: info
595 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_syevd'
597 INTEGER :: handle, myinfo, n, nmo
598 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eig
599#if defined(__parallel)
600 TYPE(
cp_fm_type) :: eigenvectors_new, matrix_new
602 INTEGER :: liwork, lwork
603 INTEGER,
DIMENSION(:),
POINTER :: iwork
604 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m
605 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
606 INTEGER,
TARGET :: v(1)
607 REAL(kind=
dp),
TARGET :: w(1)
610 CALL timeset(routinen, handle)
614 n = matrix%matrix_struct%nrow_global
617#if defined(__parallel)
625 IF (
ASSOCIATED(matrix_new%matrix_struct))
THEN
626 IF (
PRESENT(info))
THEN
627 CALL cp_fm_syevd_base(matrix_new, eigenvectors_new, eig, myinfo)
629 CALL cp_fm_syevd_base(matrix_new, eigenvectors_new, eig)
638 m => matrix%local_data
642 CALL dsyevd(
'V',
'U', n, m(1, 1),
SIZE(m, 1), eig(1), work(1), lwork, iwork(1), liwork, myinfo)
644 IF (myinfo /= 0)
THEN
645 CALL cp_fm_error(
"ERROR in DSYEVD: Work space query failed", myinfo,
PRESENT(info))
649 lwork = nint(work(1))
650 ALLOCATE (work(lwork))
653 ALLOCATE (iwork(liwork))
655 CALL dsyevd(
'V',
'U', n, m(1, 1),
SIZE(m, 1), eig(1), work(1), lwork, iwork(1), liwork, myinfo)
657 IF (myinfo /= 0)
THEN
658 CALL cp_fm_error(
"ERROR in DSYEVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
667 IF (
PRESENT(info)) info = myinfo
669 nmo =
SIZE(eigenvalues, 1)
671 eigenvalues(1:n) = eig(1:n)
673 eigenvalues(1:nmo) = eig(1:nmo)
678 CALL check_diag(matrix, eigenvectors, n)
680 CALL timestop(handle)
691 SUBROUTINE cp_fm_syevd_base(matrix, eigenvectors, eigenvalues, info)
693 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, eigenvectors
694 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
695 INTEGER,
INTENT(OUT),
OPTIONAL :: info
697 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_syevd_base'
699 INTEGER :: handle, myinfo
700#if defined(__parallel)
702 INTEGER :: liwork, lwork, n
703 INTEGER,
DIMENSION(9) :: descm, descv
704 INTEGER,
DIMENSION(:),
POINTER :: iwork
705 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
706 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m, v
707 REAL(kind=
dp),
TARGET :: w(1)
708#if defined (__HAS_IEEE_EXCEPTIONS)
709 LOGICAL,
DIMENSION(5) :: halt
713 CALL timeset(routinen, handle)
717#if defined(__parallel)
719 n = matrix%matrix_struct%nrow_global
720 m => matrix%local_data
721 context => matrix%matrix_struct%context
722 descm(:) = matrix%matrix_struct%descriptor(:)
724 v => eigenvectors%local_data
725 descv(:) = eigenvectors%matrix_struct%descriptor(:)
727 liwork = 7*n + 8*context%num_pe(2) + 2
728 ALLOCATE (iwork(liwork))
734 CALL pdsyevd(
'V',
'U', n, m(1, 1), 1, 1, descm, eigenvalues(1), v(1, 1), 1, 1, descv, &
735 work(1), lwork, iwork(1), liwork, myinfo)
737 IF (matrix%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
738 CALL cp_fm_error(
"ERROR in PDSYEVD: Work space query failed", myinfo,
PRESENT(info))
741 lwork = nint(work(1))
742#if !defined(__SCALAPACK_NO_WA)
744 CALL pdormtr(
'L',
'U',
'N', n, n, m(1, 1), 1, 1, descm, m(1, 1), &
745 v(1, 1), 1, 1, descv, work(1), -1, myinfo)
747 IF (matrix%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
748 CALL cp_fm_error(
"ERROR in PDORMTR: Work space query failed", myinfo,
PRESENT(info))
751 IF (lwork < (work(1) + 2*n))
THEN
752 lwork = nint(work(1)) + 2*n
755 ALLOCATE (work(lwork))
758 IF (liwork < iwork(1))
THEN
761 ALLOCATE (iwork(liwork))
766#if defined (__HAS_IEEE_EXCEPTIONS)
767 CALL ieee_get_halting_mode(ieee_all, halt)
768 CALL ieee_set_halting_mode(ieee_all, .false.)
771 CALL pdsyevd(
'V',
'U', n, m(1, 1), 1, 1, descm, eigenvalues(1), v(1, 1), 1, 1, descv, &
772 work(1), lwork, iwork(1), liwork, myinfo)
774#if defined (__HAS_IEEE_EXCEPTIONS)
775 CALL ieee_set_halting_mode(ieee_all, halt)
777 IF (matrix%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
778 CALL cp_fm_error(
"ERROR in PDSYEVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
781 IF (
PRESENT(info)) info = myinfo
787 mark_used(eigenvectors)
788 mark_used(eigenvalues)
790 IF (
PRESENT(info)) info = myinfo
791 CALL cp_fm_error(
"ERROR in "//trim(routinen)// &
792 ": Matrix diagonalization using PDSYEVD requested without ScaLAPACK support")
795 CALL timestop(handle)
797 END SUBROUTINE cp_fm_syevd_base
813 SUBROUTINE cp_fm_syevx(matrix, eigenvectors, eigenvalues, neig, work_syevx)
818 TYPE(
cp_fm_type),
OPTIONAL,
INTENT(IN) :: eigenvectors
819 REAL(kind=
dp),
OPTIONAL,
INTENT(IN) :: work_syevx
820 INTEGER,
INTENT(IN),
OPTIONAL :: neig
821 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
823 CHARACTER(LEN=*),
PARAMETER :: routinen =
"cp_fm_syevx"
825#if defined(__parallel)
826 REAL(kind=
dp),
PARAMETER :: orfac = -1.0_dp
828 REAL(kind=
dp),
PARAMETER :: vl = 0.0_dp, &
833 CHARACTER(LEN=1) :: job_type
834 REAL(kind=
dp) :: abstol, work_syevx_local
835 INTEGER :: handle, info, liwork, lwork, &
836 m, n, nb, npcol, nprow, &
837 output_unit, neig_local
838 LOGICAL :: ionode, needs_evecs
839 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ifail, iwork
840 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: w, work
841 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, z
843 REAL(kind=
dp),
EXTERNAL :: dlamch
845#if defined(__parallel)
846 INTEGER :: nn, np0, npe, nq0, nz
847 INTEGER,
DIMENSION(9) :: desca, descz
848 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iclustr
849 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: gap
850 INTEGER,
EXTERNAL :: iceil, numroc
853 INTEGER,
EXTERNAL :: ilaenv
855#if defined (__HAS_IEEE_EXCEPTIONS)
856 LOGICAL,
DIMENSION(5) :: halt
860 n = matrix%matrix_struct%nrow_global
862 IF (
PRESENT(neig)) neig_local = neig
863 IF (neig_local == 0)
RETURN
865 CALL timeset(routinen, handle)
867 needs_evecs =
PRESENT(eigenvectors)
870 ionode = logger%para_env%is_source()
871 n = matrix%matrix_struct%nrow_global
874 work_syevx_local = 1.0_dp
875 IF (
PRESENT(work_syevx)) work_syevx_local = work_syevx
878 IF (needs_evecs)
THEN
885 abstol = 2.0_dp*dlamch(
"S")
887 context => matrix%matrix_struct%context
888 nprow = context%num_pe(1)
889 npcol = context%num_pe(2)
892 eigenvalues(:) = 0.0_dp
893#if defined(__parallel)
895 IF (matrix%matrix_struct%nrow_block /= matrix%matrix_struct%ncol_block)
THEN
896 cpabort(
"ERROR in "//routinen//
": Invalid blocksize (no square blocks) found")
899 a => matrix%local_data
900 desca(:) = matrix%matrix_struct%descriptor(:)
902 IF (needs_evecs)
THEN
903 z => eigenvectors%local_data
904 descz(:) = eigenvectors%matrix_struct%descriptor(:)
907 z => matrix%local_data
914 nb = matrix%matrix_struct%nrow_block
916 np0 = numroc(nn, nb, 0, 0, nprow)
917 nq0 = max(numroc(nn, nb, 0, 0, npcol), nb)
919 IF (needs_evecs)
THEN
920 lwork = 5*n + max(5*nn, np0*nq0) + iceil(neig_local, npe)*nn + 2*nb*nb + &
921 int(work_syevx_local*real((neig_local - 1)*n,
dp))
923 lwork = 5*n + max(5*nn, nb*(np0 + 1))
925 liwork = 6*max(n, npe + 1, 4)
929 ALLOCATE (iclustr(2*npe))
933 ALLOCATE (iwork(liwork))
934 ALLOCATE (work(lwork))
938#if defined (__HAS_IEEE_EXCEPTIONS)
939 CALL ieee_get_halting_mode(ieee_all, halt)
940 CALL ieee_set_halting_mode(ieee_all, .false.)
942 CALL pdsyevx(job_type,
"I",
"U", n, a(1, 1), 1, 1, desca, vl, vu, 1, neig_local, abstol, m, nz, w(1), orfac, &
943 z(1, 1), 1, 1, descz, work(1), lwork, iwork(1), liwork, ifail(1), iclustr(1), gap, info)
944#if defined (__HAS_IEEE_EXCEPTIONS)
945 CALL ieee_set_halting_mode(ieee_all, halt)
952 WRITE (unit=output_unit, fmt=
"(/,(T3,A,T12,1X,I10))") &
955 "liwork = ", liwork, &
958 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,I10)))") &
960 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,I10)))") &
961 "iclustr = ", iclustr
962 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,E10.3)))") &
966 cpabort(
"ERROR in PDSYEVX (ScaLAPACK)")
975 a => matrix%local_data
976 IF (needs_evecs)
THEN
977 z => eigenvectors%local_data
980 z => matrix%local_data
985 nb = max(ilaenv(1,
"DSYTRD",
"U", n, -1, -1, -1), &
986 ilaenv(1,
"DORMTR",
"U", n, -1, -1, -1))
988 lwork = max((nb + 3)*n, 8*n) + n
993 ALLOCATE (iwork(liwork))
994 ALLOCATE (work(lwork))
1001#if defined (__HAS_IEEE_EXCEPTIONS)
1002 CALL ieee_get_halting_mode(ieee_all, halt)
1003 CALL ieee_set_halting_mode(ieee_all, .false.)
1005 CALL dsyevx(job_type,
"I",
"U", n, a(1, 1), nla, vl, vu, 1, neig_local, &
1006 abstol, m, w, z(1, 1), nlz, work(1), lwork, iwork(1), ifail(1), info)
1007#if defined (__HAS_IEEE_EXCEPTIONS)
1008 CALL ieee_set_halting_mode(ieee_all, halt)
1014 WRITE (unit=output_unit, fmt=
"(/,(T3,A,T12,1X,I10))") &
1017 WRITE (unit=output_unit, fmt=
"(/,T3,A,(T12,6(1X,I10)))") &
1020 cpabort(
"Error in DSYEVX (ScaLAPACK)")
1028 eigenvalues(1:neig_local) = w(1:neig_local)
1031 IF (needs_evecs)
CALL check_diag(matrix, eigenvectors, neig_local)
1033 CALL timestop(handle)
1046 SUBROUTINE cp_fm_svd(matrix_a, matrix_eigvl, matrix_eigvr_t, eigval, info)
1049 TYPE(
cp_fm_type),
INTENT(INOUT) :: matrix_eigvl, matrix_eigvr_t
1050 REAL(kind=
dp),
DIMENSION(:),
POINTER, &
1051 INTENT(INOUT) :: eigval
1052 INTEGER,
INTENT(OUT),
OPTIONAL :: info
1054 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_svd'
1056 INTEGER :: handle, n, m, myinfo, lwork
1057 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1059 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
1060 REAL(kind=
dp),
TARGET :: w(1)
1061#if defined(__parallel)
1062 INTEGER,
DIMENSION(9) :: desca, descu, descvt
1065 CALL timeset(routinen, handle)
1068 matrix_struct=matrix_a%matrix_struct, &
1071 a => matrix_lu%local_data
1072 m = matrix_lu%matrix_struct%nrow_global
1073 n = matrix_lu%matrix_struct%ncol_global
1081#if defined(__parallel)
1083 desca(:) = matrix_lu%matrix_struct%descriptor(:)
1084 descu(:) = matrix_eigvl%matrix_struct%descriptor(:)
1085 descvt(:) = matrix_eigvr_t%matrix_struct%descriptor(:)
1088 CALL pdgesvd(
'V',
'V', m, m, matrix_lu%local_data, 1, 1, desca, eigval, matrix_eigvl%local_data, &
1089 1, 1, descu, matrix_eigvr_t%local_data, 1, 1, descvt, work, lwork, myinfo)
1091 IF (matrix_lu%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
1092 CALL cp_fm_error(
"ERROR in PDGESVD: Work space query failed", myinfo,
PRESENT(info))
1095 lwork = nint(work(1))
1096 ALLOCATE (work(lwork))
1098 CALL pdgesvd(
'V',
'V', m, m, matrix_lu%local_data, 1, 1, desca, eigval, matrix_eigvl%local_data, &
1099 1, 1, descu, matrix_eigvr_t%local_data, 1, 1, descvt, work, lwork, myinfo)
1101 IF (matrix_lu%matrix_struct%para_env%is_source() .AND. (myinfo /= 0))
THEN
1102 CALL cp_fm_error(
"ERROR in PDGESVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
1106 CALL dgesvd(
'S',
'S', m, m, matrix_lu%local_data, m, eigval, matrix_eigvl%local_data, &
1107 m, matrix_eigvr_t%local_data, m, work, lwork, myinfo)
1109 IF (myinfo /= 0)
THEN
1110 CALL cp_fm_error(
"ERROR in DGESVD: Work space query failed", myinfo,
PRESENT(info))
1113 lwork = nint(work(1))
1114 ALLOCATE (work(lwork))
1116 CALL dgesvd(
'S',
'S', m, m, matrix_lu%local_data, m, eigval, matrix_eigvl%local_data, &
1117 m, matrix_eigvr_t%local_data, m, work, lwork, myinfo)
1119 IF (myinfo /= 0)
THEN
1120 CALL cp_fm_error(
"ERROR in DGESVD: Matrix diagonalization failed", myinfo,
PRESENT(info))
1128 IF (
PRESENT(info)) info = myinfo
1130 CALL timestop(handle)
1143 SUBROUTINE cp_fm_power(matrix, work, exponent, threshold, n_dependent, verbose, eigvals)
1153 REAL(kind=
dp),
INTENT(IN) :: exponent, threshold
1154 INTEGER,
INTENT(OUT) :: n_dependent
1155 LOGICAL,
INTENT(IN),
OPTIONAL :: verbose
1156 REAL(kind=
dp),
DIMENSION(2),
INTENT(OUT), &
1159 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_power'
1161 INTEGER :: handle, icol_global, &
1163 ncol_global, nrow_global
1164 LOGICAL :: my_verbose
1165 REAL(kind=
dp) :: condition_number, f, p
1166 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: eigenvalues
1167 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: eigenvectors
1170#if defined(__parallel)
1171 INTEGER :: icol_local, ipcol, iprow, irow_global, irow_local
1174 CALL timeset(routinen, handle)
1176 my_verbose = .false.
1177 IF (
PRESENT(verbose)) my_verbose = verbose
1179 context => matrix%matrix_struct%context
1180 myprow = context%mepos(1)
1181 mypcol = context%mepos(2)
1185 nrow_global = matrix%matrix_struct%nrow_global
1186 ncol_global = matrix%matrix_struct%ncol_global
1188 ALLOCATE (eigenvalues(ncol_global))
1189 eigenvalues(:) = 0.0_dp
1195 IF (
PRESENT(eigvals))
THEN
1196 eigvals(1) = eigenvalues(1)
1197 eigvals(2) = eigenvalues(ncol_global)
1200#if defined(__parallel)
1201 eigenvectors => work%local_data
1205 DO icol_global = 1, ncol_global
1207 IF (eigenvalues(icol_global) < threshold)
THEN
1209 n_dependent = n_dependent + 1
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) = 0.0_dp
1226 f = eigenvalues(icol_global)**p
1228 ipcol = work%matrix_struct%g2p_col(icol_global)
1230 IF (mypcol == ipcol)
THEN
1231 icol_local = work%matrix_struct%g2l_col(icol_global)
1232 DO irow_global = 1, nrow_global
1233 iprow = work%matrix_struct%g2p_row(irow_global)
1234 IF (myprow == iprow)
THEN
1235 irow_local = work%matrix_struct%g2l_row(irow_global)
1236 eigenvectors(irow_local, icol_local) = &
1237 f*eigenvectors(irow_local, icol_local)
1248 eigenvectors => work%local_data
1252 DO icol_global = 1, ncol_global
1254 IF (eigenvalues(icol_global) < threshold)
THEN
1256 n_dependent = n_dependent + 1
1257 eigenvectors(1:nrow_global, icol_global) = 0.0_dp
1261 f = eigenvalues(icol_global)**p
1262 eigenvectors(1:nrow_global, icol_global) = &
1263 f*eigenvectors(1:nrow_global, icol_global)
1270 CALL cp_fm_syrk(
"U",
"N", ncol_global, 1.0_dp, work, 1, 1, 0.0_dp, matrix)
1274 IF (matrix%matrix_struct%para_env%is_source() .AND. my_verbose)
THEN
1275 condition_number = abs(eigenvalues(ncol_global)/eigenvalues(1))
1277 "CP_FM_POWER: smallest eigenvalue:", eigenvalues(1), &
1278 "CP_FM_POWER: largest eigenvalue: ", eigenvalues(ncol_global), &
1279 "CP_FM_POWER: condition number: ", condition_number
1280 IF (eigenvalues(1) <= 0.0_dp)
THEN
1282 "WARNING: matrix has a negative eigenvalue, tighten EPS_DEFAULT"
1284 IF (condition_number > 1.0e12_dp)
THEN
1286 "WARNING: high condition number => possibly ill-conditioned matrix"
1290 DEALLOCATE (eigenvalues)
1292 CALL timestop(handle)
1315 TYPE(
cp_fm_type),
INTENT(IN) :: eigenvectors, matrix
1316 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: eigval
1317 INTEGER,
INTENT(IN) :: start_sec_block
1318 REAL(kind=
dp),
INTENT(IN) :: thresh
1320 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_block_jacobi'
1323 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, ev
1325 REAL(kind=
dp) :: tan_theta, tau, c, s
1327 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: c_ip
1329#if defined(__parallel)
1332 INTEGER :: nprow, npcol, block_dim_row, block_dim_col, info, &
1333 ev_row_block_size, iam, mynumrows, mype, npe, q_loc
1334 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: a_loc, ev_loc
1335 INTEGER,
DIMENSION(9) :: desca, descz, &
1340 INTEGER,
EXTERNAL :: numroc
1345 CALL timeset(routinen, handle)
1347#if defined(__parallel)
1348 context => matrix%matrix_struct%context
1349 allgrp = matrix%matrix_struct%para_env
1351 nprow = context%num_pe(1)
1352 npcol = context%num_pe(2)
1354 n = matrix%matrix_struct%nrow_global
1356 a => matrix%local_data
1357 desca(:) = matrix%matrix_struct%descriptor(:)
1358 ev => eigenvectors%local_data
1359 descz(:) = eigenvectors%matrix_struct%descriptor(:)
1365 block_dim_row = start_sec_block - 1
1366 block_dim_col = n - block_dim_row
1367 ALLOCATE (a_loc(block_dim_row, block_dim_col))
1369 mype = matrix%matrix_struct%para_env%mepos
1370 npe = matrix%matrix_struct%para_env%num_pe
1372 CALL ictxt_loc%gridinit(matrix%matrix_struct%para_env,
'R', nprow*npcol, 1)
1374 CALL descinit(desc_a_block, block_dim_row, block_dim_col, block_dim_row, &
1375 block_dim_col, 0, 0, ictxt_loc%get_handle(), block_dim_row, info)
1377 CALL pdgemr2d(block_dim_row, block_dim_col, a, 1, start_sec_block, desca, &
1378 a_loc, 1, 1, desc_a_block, context%get_handle())
1380 CALL allgrp%bcast(a_loc, 0)
1387 ev_row_block_size = n/(nprow*npcol)
1388 mynumrows = numroc(n, ev_row_block_size, iam, 0, nprow*npcol)
1390 ALLOCATE (ev_loc(mynumrows, n), c_ip(mynumrows))
1392 CALL descinit(desc_ev_loc, n, n, ev_row_block_size, n, 0, 0, ictxt_loc%get_handle(), &
1395 CALL pdgemr2d(n, n, ev, 1, 1, descz, ev_loc, 1, 1, desc_ev_loc, context%get_handle())
1401 DO q = start_sec_block, n
1403 DO p = 1, (start_sec_block - 1)
1405 IF (abs(a_loc(p, q_loc)) > thresh)
THEN
1407 tau = (eigval(q) - eigval(p))/(2.0_dp*a_loc(p, q_loc))
1409 tan_theta = sign(1.0_dp, tau)/(abs(tau) + sqrt(1.0_dp + tau*tau))
1412 c = 1.0_dp/sqrt(1.0_dp + tan_theta*tan_theta)
1420 CALL dcopy(mynumrows, ev_loc(1, p), 1, c_ip(1), 1)
1421 CALL dscal(mynumrows, c, ev_loc(1, p), 1)
1422 CALL daxpy(mynumrows, -s, ev_loc(1, q), 1, ev_loc(1, p), 1)
1423 CALL dscal(mynumrows, c, ev_loc(1, q), 1)
1424 CALL daxpy(mynumrows, s, c_ip(1), 1, ev_loc(1, q), 1)
1432 CALL pdgemr2d(n, n, ev_loc, 1, 1, desc_ev_loc, ev, 1, 1, descz, context%get_handle())
1435 DEALLOCATE (a_loc, ev_loc, c_ip)
1437 CALL ictxt_loc%gridexit()
1441 n = matrix%matrix_struct%nrow_global
1445 a => matrix%local_data
1446 ev => eigenvectors%local_data
1453 DO q = start_sec_block, n
1454 DO p = 1, (start_sec_block - 1)
1456 IF (abs(a(p, q)) > thresh)
THEN
1458 tau = (eigval(q) - eigval(p))/(2.0_dp*a(p, q))
1460 tan_theta = sign(1.0_dp, tau)/(abs(tau) + sqrt(1.0_dp + tau*tau))
1463 c = 1.0_dp/sqrt(1.0_dp + tan_theta*tan_theta)
1471 CALL dcopy(n, ev(1, p), 1, c_ip(1), 1)
1472 CALL dscal(n, c, ev(1, p), 1)
1473 CALL daxpy(n, -s, ev(1, q), 1, ev(1, p), 1)
1474 CALL dscal(n, c, ev(1, q), 1)
1475 CALL daxpy(n, s, c_ip(1), 1, ev(1, q), 1)
1488 CALL timestop(handle)
1502 SUBROUTINE cp_fm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
1504 TYPE(
cp_fm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
1505 REAL(kind=
dp),
DIMENSION(:) :: eigenvalues
1508 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geeig'
1510 INTEGER :: handle, nao, nmo
1511 LOGICAL :: check_eigenvectors
1512 TYPE(
cp_fm_type) :: overlap_check, scratch_check
1514 CALL timeset(routinen, handle)
1517 nmo =
SIZE(eigenvalues)
1525 IF (check_eigenvectors)
THEN
1526 CALL cp_fm_create(overlap_check, bmatrix%matrix_struct)
1527 CALL cp_fm_create(scratch_check, bmatrix%matrix_struct)
1531 IF (check_eigenvectors)
THEN
1532 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
1537#if defined(__parallel)
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)
1546 CALL cp_fm_geeig_scalapack(amatrix, bmatrix, work, eigenvalues)
1547 IF (check_eigenvectors)
THEN
1548 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
1558 IF (check_eigenvectors)
THEN
1559 CALL cp_fm_create(overlap_check, bmatrix%matrix_struct)
1560 CALL cp_fm_create(scratch_check, bmatrix%matrix_struct)
1564 IF (check_eigenvectors)
THEN
1565 CALL check_generalized_diag(overlap_check, work, scratch_check, nmo)
1581 eigenvalues=eigenvalues)
1587 CALL timestop(handle)
1598 SUBROUTINE cp_fm_geeig_scalapack(amatrix, bmatrix, eigenvectors, eigenvalues)
1600 TYPE(
cp_fm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
1601 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1603 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geeig_scalapack'
1605#if defined(__parallel)
1606 REAL(kind=
dp),
PARAMETER :: orfac = -1.0_dp, &
1610 INTEGER :: handle, info, liwork, lwork, m, n, nb, &
1611 neig, npcol, nprow, nz
1612 INTEGER,
DIMENSION(9) :: desca, descb, descz
1613 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iclustr, ifail, iwork
1614 REAL(kind=
dp) :: abstol
1615 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: gap, w, work
1616 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, z
1618 INTEGER :: mq0, nn, np0, npe
1619 INTEGER,
EXTERNAL :: iceil, numroc
1620 REAL(kind=
dp),
EXTERNAL :: dlamch
1621#if defined (__HAS_IEEE_EXCEPTIONS)
1622 LOGICAL,
DIMENSION(5) :: halt
1628 CALL timeset(routinen, handle)
1630#if defined(__parallel)
1631 n = amatrix%matrix_struct%nrow_global
1632 neig = min(
SIZE(eigenvalues), n)
1635 CALL timestop(handle)
1639 IF (amatrix%matrix_struct%nrow_block /= amatrix%matrix_struct%ncol_block)
THEN
1640 cpabort(
"ERROR in "//routinen//
": Invalid blocksize (no square blocks) found")
1643 a => amatrix%local_data
1644 b => bmatrix%local_data
1645 z => eigenvectors%local_data
1646 desca(:) = amatrix%matrix_struct%descriptor(:)
1647 descb(:) = bmatrix%matrix_struct%descriptor(:)
1648 descz(:) = eigenvectors%matrix_struct%descriptor(:)
1650 nprow = amatrix%matrix_struct%context%num_pe(1)
1651 npcol = amatrix%matrix_struct%context%num_pe(2)
1653 nb = amatrix%matrix_struct%nrow_block
1655 np0 = numroc(nn, nb, 0, 0, nprow)
1656 mq0 = max(numroc(nn, nb, 0, 0, npcol), nb)
1658 lwork = 5*n + max(5*nn, np0*mq0 + 2*nb*nb) + iceil(neig, npe)*nn + &
1660 liwork = 6*max(n, npe + 1, 4)
1664 ALLOCATE (iclustr(2*npe))
1668 ALLOCATE (iwork(liwork))
1670 ALLOCATE (work(lwork))
1672 abstol = 2.0_dp*dlamch(
"S")
1674#if defined (__HAS_IEEE_EXCEPTIONS)
1675 CALL ieee_get_halting_mode(ieee_all, halt)
1676 CALL ieee_set_halting_mode(ieee_all, .false.)
1678 CALL pdsygvx(1,
"V",
"I",
"U", n, a(1, 1), 1, 1, desca, b(1, 1), 1, 1, descb, &
1679 vl, vu, 1, neig, abstol, m, nz, w(1), orfac, z(1, 1), 1, 1, descz, &
1680 work(1), lwork, iwork(1), liwork, ifail(1), iclustr(1), gap(1), info)
1681#if defined (__HAS_IEEE_EXCEPTIONS)
1682 CALL ieee_set_halting_mode(ieee_all, halt)
1685 IF (info /= 0 .OR. m < neig .OR. nz < neig)
THEN
1686 cpabort(
"ERROR in PDSYGVX (ScaLAPACK), info="//trim(
cp_to_string(info)))
1689 eigenvalues(:) = 0.0_dp
1690 eigenvalues(1:neig) = w(1:neig)
1692 DEALLOCATE (gap, iclustr, ifail, iwork, w, work)
1696 mark_used(eigenvectors)
1697 mark_used(eigenvalues)
1698 cpabort(
"ERROR in "//routinen//
": PDSYGVX requested without ScaLAPACK support")
1701 CALL timestop(handle)
1703 END SUBROUTINE cp_fm_geeig_scalapack
1719 TYPE(
cp_fm_type),
INTENT(IN) :: amatrix, bmatrix, eigenvectors
1720 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1722 REAL(kind=
dp),
INTENT(IN) :: epseig
1723 INTEGER,
INTENT(OUT),
OPTIONAL :: nmo_retained
1725 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geeig_canon'
1727 INTEGER :: handle, i, icol, irow, nao, nc, ncol, &
1729 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
1731 CALL timeset(routinen, handle)
1735 nmo =
SIZE(eigenvalues)
1736 ALLOCATE (evals(nao))
1741 evals(:) = -evals(:)
1744 IF (evals(i) < epseig)
THEN
1755 CALL cp_fm_to_fm(work, eigenvectors, ncol, nc + 1, nc + 1)
1758 DO icol = nc + 1, nao
1764 evals(nc + 1:nao) = 1.0_dp
1767 evals(:) = 1.0_dp/sqrt(evals(:))
1770 CALL cp_fm_gemm(
"T",
"N", nao, nao, nao, 1.0_dp, work, amatrix, 0.0_dp, bmatrix)
1771 CALL cp_fm_gemm(
"N",
"N", nao, nao, nao, 1.0_dp, bmatrix, work, 0.0_dp, amatrix)
1774 DO icol = nc + 1, nao
1779 CALL choose_eigv_solver(matrix=amatrix, eigenvectors=bmatrix, eigenvalues=eigenvalues)
1782 CALL cp_fm_gemm(
"N",
"N", nao, nx, nc, 1.0_dp, work, bmatrix, 0.0_dp, eigenvectors)
1786 IF (
PRESENT(nmo_retained)) nmo_retained = nc
1790 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 ...
Wrapper for ELPA (complex matrices, i.e. cp_cfm_type).
subroutine, public set_elpa_c_kernel(requested_kernel)
Sets the active ELPA kernel for complex matrices.
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 and cp_cfm_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
real(kind=dp), parameter, public set_removed_eigval_to
subroutine, public cp_fm_svd(matrix_a, matrix_eigvl, matrix_eigvr_t, eigval, info)
decomposes a quadratic matrix into its singular value decomposition
subroutine, public cp_fm_geeig_canon(amatrix, bmatrix, eigenvectors, eigenvalues, work, epseig, nmo_retained)
General Eigenvalue Problem AX = BXE Use canonical diagonalization : U*s**(-1/2).
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
integer, save, public elpa_neigvec_min
subroutine, public diag_init(diag_lib, fallback_applied, elpa_kernel, elpa_c_kernel, elpa_neigvec_min_input, elpa_qr, elpa_print, elpa_one_stage, dlaf_neigvec_min_input, eps_check_diag_input, direct_generalized_diagonalization_input, diag_lib_explicit_input)
Setup the diagonalization library to be used.
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, save, public dlaf_neigvec_min
integer, parameter, public fm_diag_type_elpa
integer, parameter, public cusolver_n_min
logical function, public diag_check_requested()
Return whether diagonalization checks should be performed.
subroutine, public cp_fm_syevx(matrix, eigenvectors, eigenvalues, neig, work_syevx)
compute eigenvalues and optionally eigenvectors of a real symmetric matrix using scalapack....
logical, save, public diag_lib_explicit
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_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_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
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...