31#if defined (__HAS_IEEE_EXCEPTIONS)
32 USE ieee_exceptions,
ONLY: ieee_get_halting_mode, &
33 ieee_set_halting_mode, &
36#include "../base/base_uses.f90"
41 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
42 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_fm_basic_linalg'
77 REAL(KIND=
dp),
EXTERNAL :: dlange, pdlange, pdlatra
80 MODULE PROCEDURE cp_fm_trace_a0b0t0
81 MODULE PROCEDURE cp_fm_trace_a1b0t1_a
82 MODULE PROCEDURE cp_fm_trace_a1b0t1_p
83 MODULE PROCEDURE cp_fm_trace_a1b1t1_aa
84 MODULE PROCEDURE cp_fm_trace_a1b1t1_ap
85 MODULE PROCEDURE cp_fm_trace_a1b1t1_pa
86 MODULE PROCEDURE cp_fm_trace_a1b1t1_pp
90 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_aa
91 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_ap
92 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pa
93 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pp
104 REAL(kind=
dp),
INTENT(OUT) :: det_a
105 REAL(kind=
dp) :: determinant
107 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
108 INTEGER :: n, i, info, p
109 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
110 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
112#if defined(__parallel)
113 INTEGER :: myprow, nprow, npcol, nrow_local, nrow_block, irow_local
114 INTEGER,
DIMENSION(9) :: desca
118 matrix_struct=matrix_a%matrix_struct, &
122 a => matrix_lu%local_data
123 n = matrix_lu%matrix_struct%nrow_global
129#if defined(__parallel)
131 desca(:) = matrix_lu%matrix_struct%descriptor(:)
132 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
134 determinant = product(
diag)
135 myprow = matrix_lu%matrix_struct%context%mepos(1)
136 nprow = matrix_lu%matrix_struct%context%num_pe(1)
137 npcol = matrix_lu%matrix_struct%context%num_pe(2)
138 nrow_local = matrix_lu%matrix_struct%nrow_locals(myprow)
139 nrow_block = matrix_lu%matrix_struct%nrow_block
140 DO irow_local = 1, nrow_local
141 i = matrix_lu%matrix_struct%row_indices(irow_local)
142 IF (ipivot(irow_local) /= i) p = p + 1
144 CALL matrix_lu%matrix_struct%para_env%sum(p)
148 CALL dgetrf(n, n, a, n, ipivot, info)
150 determinant = product(
diag)
152 IF (ipivot(i) /= i) p = p + 1
158 det_a = determinant*(-2*mod(p, 2) + 1.0_dp)
172 REAL(kind=
dp),
INTENT(IN) :: alpha
174 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: beta
175 TYPE(
cp_fm_type),
INTENT(IN),
OPTIONAL :: matrix_b
177 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_scale_and_add'
179 INTEGER :: handle, size_a, size_b
180 REAL(kind=
dp) :: my_beta
181 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
183 CALL timeset(routinen, handle)
186 IF (
PRESENT(matrix_b)) my_beta = 1.0_dp
187 IF (
PRESENT(beta)) my_beta = beta
190 IF (
PRESENT(beta))
THEN
191 cpassert(
PRESENT(matrix_b))
192 IF (
ASSOCIATED(matrix_a%local_data, matrix_b%local_data))
THEN
193 cpwarn(
"Bad use of routine. Call cp_fm_scale instead")
195 CALL timestop(handle)
200 a => matrix_a%local_data
202 size_a =
SIZE(a, 1)*
SIZE(a, 2)
204 IF (alpha /= 1.0_dp)
THEN
205 CALL dscal(size_a, alpha, a, 1)
207 IF (my_beta /= 0.0_dp)
THEN
208 IF (matrix_a%matrix_struct%context /= matrix_b%matrix_struct%context) &
209 cpabort(
"Matrices must be in the same blacs context")
212 matrix_b%matrix_struct))
THEN
214 b => matrix_b%local_data
215 size_b =
SIZE(b, 1)*
SIZE(b, 2)
216 IF (size_a /= size_b) &
217 cpabort(
"Matrices must have same local sizes")
219 CALL daxpy(size_a, my_beta, b, 1, a, 1)
222 CALL cp_abort(__location__, &
223 "cp_fm_scale_and_add is not yet implemented for cases "// &
224 "where two input matrix structures are not equivalent")
229 CALL timestop(handle)
250 REAL(kind=
dp),
INTENT(IN) :: alpha, beta
251 CHARACTER,
INTENT(IN) :: trans
252 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
254 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geadd'
256 INTEGER :: nrow_global, ncol_global, handle
257 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa, bb
258#if defined(__parallel)
259 INTEGER,
DIMENSION(9) :: desca, descb
264 CALL timeset(routinen, handle)
266 nrow_global = matrix_a%matrix_struct%nrow_global
267 ncol_global = matrix_a%matrix_struct%ncol_global
268 cpassert(nrow_global == matrix_b%matrix_struct%nrow_global)
269 cpassert(ncol_global == matrix_b%matrix_struct%ncol_global)
271 aa => matrix_a%local_data
272 bb => matrix_b%local_data
274#if defined(__parallel)
275 desca = matrix_a%matrix_struct%descriptor
276 descb = matrix_b%matrix_struct%descriptor
277 CALL pdgeadd(trans, &
289 CALL mkl_domatadd(
'C', trans,
'N', nrow_global, ncol_global, &
290 alpha, aa, nrow_global, beta, bb, nrow_global, bb, nrow_global)
296 DO jj = 1, ncol_global
297 DO ii = 1, nrow_global
298 bb(ii, jj) = beta*bb(ii, jj) + alpha*aa(jj, ii)
302 DO jj = 1, ncol_global
303 DO ii = 1, nrow_global
304 bb(ii, jj) = beta*bb(ii, jj) + alpha*aa(ii, jj)
310 CALL timestop(handle)
326 TYPE(
cp_fm_type),
INTENT(IN) :: msource, mtarget
327 INTEGER,
INTENT(IN) :: ncol
328 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: alpha
329 INTEGER,
INTENT(IN),
OPTIONAL :: source_start, target_start
331 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_add_columns'
333 INTEGER :: handle, n, ss, ts, i
334 REAL(kind=
dp) :: fscale
335 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
336#if defined(__parallel)
337 INTEGER,
DIMENSION(9) :: desca, descb
340 CALL timeset(routinen, handle)
345 IF (
PRESENT(source_start)) ss = source_start
346 IF (
PRESENT(target_start)) ts = target_start
349 IF (
PRESENT(alpha)) fscale = alpha
351 n = msource%matrix_struct%nrow_global
353 a => msource%local_data
354 b => mtarget%local_data
356#if defined(__parallel)
358 desca(:) = msource%matrix_struct%descriptor(:)
359 descb(:) = mtarget%matrix_struct%descriptor(:)
360 CALL pdgeadd(
"N", n, ncol, fscale, a, 1, ss, desca, 1.0_dp, b, 1, ts, descb)
363 b(1:n, ts + i) = b(1:n, ts + i) + fscale*a(1:n, ss + i)
367 CALL timestop(handle)
388 SUBROUTINE cp_fm_lu_decompose(matrix_a, almost_determinant, correct_sign)
390 REAL(kind=
dp),
INTENT(OUT) :: almost_determinant
391 LOGICAL,
INTENT(IN),
OPTIONAL :: correct_sign
393 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_lu_decompose'
395 INTEGER :: handle, i, info, n
396 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
397 REAL(kind=
dp) :: determinant
398 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
399#if defined(__parallel)
400 INTEGER,
DIMENSION(9) :: desca
401 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
406 CALL timeset(routinen, handle)
408 a => matrix_a%local_data
409 n = matrix_a%matrix_struct%nrow_global
410 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
412#if defined(__parallel)
413 mark_used(correct_sign)
414 desca(:) = matrix_a%matrix_struct%descriptor(:)
415 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
422 determinant = determinant*
diag(i)
427 CALL dgetrf(n, n, a, lda, ipivot, info)
429 IF (correct_sign)
THEN
431 IF (ipivot(i) /= i)
THEN
432 determinant = -determinant*a(i, i)
434 determinant = determinant*a(i, i)
439 determinant = determinant*a(i, i)
446 almost_determinant = determinant
447 CALL timestop(handle)
448 END SUBROUTINE cp_fm_lu_decompose
473 SUBROUTINE cp_fm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, &
474 matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, &
475 c_first_col, c_first_row)
477 CHARACTER(LEN=1),
INTENT(IN) :: transa, transb
478 INTEGER,
INTENT(IN) :: m, n, k
479 REAL(kind=
dp),
INTENT(IN) :: alpha
480 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
481 REAL(kind=
dp),
INTENT(IN) :: beta
483 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, &
484 b_first_col, b_first_row, &
485 c_first_col, c_first_row
487 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_gemm'
489 INTEGER :: handle, i_a, i_b, i_c, j_a, &
491 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
492#if defined(__parallel)
493 INTEGER,
DIMENSION(9) :: desca, descb, descc
495 INTEGER :: lda, ldb, ldc
498 CALL timeset(routinen, handle)
503 a => matrix_a%local_data
504 b => matrix_b%local_data
505 c => matrix_c%local_data
508 IF (
PRESENT(a_first_row)) i_a = a_first_row
511 IF (
PRESENT(a_first_col)) j_a = a_first_col
514 IF (
PRESENT(b_first_row)) i_b = b_first_row
517 IF (
PRESENT(b_first_col)) j_b = b_first_col
520 IF (
PRESENT(c_first_row)) i_c = c_first_row
523 IF (
PRESENT(c_first_col)) j_c = c_first_col
525#if defined(__parallel)
527 desca(:) = matrix_a%matrix_struct%descriptor(:)
528 descb(:) = matrix_b%matrix_struct%descriptor(:)
529 descc(:) = matrix_c%matrix_struct%descriptor(:)
531 CALL pdgemm(transa, transb, m, n, k, alpha, a, i_a, j_a, desca, b, i_b, j_b, &
532 descb, beta, c, i_c, j_c, descc)
540 CALL dgemm(transa, transb, m, n, k, alpha, a(i_a, j_a), lda, b(i_b, j_b), ldb, beta, c(i_c, j_c), ldc)
543 CALL timestop(handle)
568 SUBROUTINE cp_fm_symm(side, uplo, m, n, alpha, matrix_a, matrix_b, beta, matrix_c)
570 CHARACTER(LEN=1),
INTENT(IN) :: side, uplo
571 INTEGER,
INTENT(IN) :: m, n
572 REAL(kind=
dp),
INTENT(IN) :: alpha
573 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
574 REAL(kind=
dp),
INTENT(IN) :: beta
577 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_symm'
580 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
581#if defined(__parallel)
582 INTEGER,
DIMENSION(9) :: desca, descb, descc
584 INTEGER :: lda, ldb, ldc
587 CALL timeset(routinen, handle)
589 a => matrix_a%local_data
590 b => matrix_b%local_data
591 c => matrix_c%local_data
593#if defined(__parallel)
595 desca(:) = matrix_a%matrix_struct%descriptor(:)
596 descb(:) = matrix_b%matrix_struct%descriptor(:)
597 descc(:) = matrix_c%matrix_struct%descriptor(:)
599 CALL pdsymm(side, uplo, m, n, alpha, a(1, 1), 1, 1, desca, b(1, 1), 1, 1, descb, beta, c(1, 1), 1, 1, descc)
603 lda = matrix_a%matrix_struct%local_leading_dimension
604 ldb = matrix_b%matrix_struct%local_leading_dimension
605 ldc = matrix_c%matrix_struct%local_leading_dimension
607 CALL dsymm(side, uplo, m, n, alpha, a(1, 1), lda, b(1, 1), ldb, beta, c(1, 1), ldc)
610 CALL timestop(handle)
623 REAL(kind=
dp) :: norm
625 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_frobenius_norm'
627 INTEGER :: handle, size_a
628 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
629 REAL(kind=
dp),
EXTERNAL :: ddot
630#if defined(__parallel)
634 CALL timeset(routinen, handle)
637 a => matrix_a%local_data
638 size_a =
SIZE(a, 1)*
SIZE(a, 2)
639 norm = ddot(size_a, a(1, 1), 1, a(1, 1), 1)
640#if defined(__parallel)
641 group = matrix_a%matrix_struct%para_env
646 CALL timestop(handle)
665 SUBROUTINE cp_fm_syrk(uplo, trans, k, alpha, matrix_a, ia, ja, beta, matrix_c)
666 CHARACTER(LEN=1),
INTENT(IN) :: uplo, trans
667 INTEGER,
INTENT(IN) :: k
668 REAL(kind=
dp),
INTENT(IN) :: alpha
670 INTEGER,
INTENT(IN) :: ia, ja
671 REAL(kind=
dp),
INTENT(IN) :: beta
674 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_syrk'
677 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
678#if defined(__parallel)
679 INTEGER,
DIMENSION(9) :: desca, descc
683#if defined (__HAS_IEEE_EXCEPTIONS)
684 LOGICAL,
DIMENSION(5) :: halt
687 CALL timeset(routinen, handle)
689 n = matrix_c%matrix_struct%nrow_global
691 a => matrix_a%local_data
692 c => matrix_c%local_data
694#if defined (__HAS_IEEE_EXCEPTIONS)
695 CALL ieee_get_halting_mode(ieee_all, halt)
696 CALL ieee_set_halting_mode(ieee_all, .false.)
698#if defined(__parallel)
699 desca(:) = matrix_a%matrix_struct%descriptor(:)
700 descc(:) = matrix_c%matrix_struct%descriptor(:)
702 CALL pdsyrk(uplo, trans, n, k, alpha, a(1, 1), ia, ja, desca, beta, c(1, 1), 1, 1, descc)
707 CALL dsyrk(uplo, trans, n, k, alpha, a(ia, ja), lda, beta, c(1, 1), ldc)
709#if defined (__HAS_IEEE_EXCEPTIONS)
710 CALL ieee_set_halting_mode(ieee_all, halt)
712 CALL timestop(handle)
726 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
728 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_schur_product'
730 INTEGER :: handle, icol_local, irow_local, mypcol, &
731 myprow, ncol_local, &
733 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
736 CALL timeset(routinen, handle)
738 context => matrix_a%matrix_struct%context
739 myprow = context%mepos(1)
740 mypcol = context%mepos(2)
742 a => matrix_a%local_data
743 b => matrix_b%local_data
744 c => matrix_c%local_data
746 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
747 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
749 DO icol_local = 1, ncol_local
750 DO irow_local = 1, nrow_local
751 c(irow_local, icol_local) = a(irow_local, icol_local)*b(irow_local, icol_local)
755 CALL timestop(handle)
772 SUBROUTINE cp_fm_trace_a0b0t0(matrix_a, matrix_b, trace)
774 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
775 REAL(KIND=
dp),
INTENT(OUT) :: trace
777 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a0b0t0'
779 INTEGER :: handle, mypcol, myprow, ncol_local, &
781 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: a, b
785 CALL timeset(routinen, handle)
787 context => matrix_a%matrix_struct%context
788 myprow = context%mepos(1)
789 mypcol = context%mepos(2)
791 group = matrix_a%matrix_struct%para_env
793 a => matrix_a%local_data
794 b => matrix_b%local_data
796 nrow_local = min(matrix_a%matrix_struct%nrow_locals(myprow), matrix_b%matrix_struct%nrow_locals(myprow))
797 ncol_local = min(matrix_a%matrix_struct%ncol_locals(mypcol), matrix_b%matrix_struct%ncol_locals(mypcol))
801 b(1:nrow_local, 1:ncol_local))
803 CALL group%sum(trace)
805 CALL timestop(handle)
807 END SUBROUTINE cp_fm_trace_a0b0t0
828 SUBROUTINE cp_fm_trace_a1b0t1_a (matrix_a, matrix_b, trace)
829 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
831 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
833 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b0t1_a'
835 INTEGER :: handle, imatrix, n_matrices, &
836 ncols_local, nrows_local
837 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
840 CALL timeset(routinen, handle)
842 n_matrices =
SIZE(trace)
843 cpassert(
SIZE(matrix_a) == n_matrices)
845 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
847 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
854 DO imatrix = 1, n_matrices
857 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
862 group = matrix_b%matrix_struct%para_env
863 CALL group%sum(trace)
865 CALL timestop(handle)
866 END SUBROUTINE cp_fm_trace_a1b0t1_a
867 SUBROUTINE cp_fm_trace_a1b0t1_p (matrix_a, matrix_b, trace)
868 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
870 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
872 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b0t1_p'
874 INTEGER :: handle, imatrix, n_matrices, &
875 ncols_local, nrows_local
876 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
879 CALL timeset(routinen, handle)
881 n_matrices =
SIZE(trace)
882 cpassert(
SIZE(matrix_a) == n_matrices)
884 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
886 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
893 DO imatrix = 1, n_matrices
896 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
901 group = matrix_b%matrix_struct%para_env
902 CALL group%sum(trace)
904 CALL timestop(handle)
905 END SUBROUTINE cp_fm_trace_a1b0t1_p
925 SUBROUTINE cp_fm_trace_a1b1t1_aa (matrix_a, matrix_b, trace, accurate)
926 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
927 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
928 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
929 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
931 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_aa'
933 INTEGER :: handle, imatrix, n_matrices, &
934 ncols_local, nrows_local
935 LOGICAL :: use_accurate_sum
936 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
939 CALL timeset(routinen, handle)
941 n_matrices =
SIZE(trace)
942 cpassert(
SIZE(matrix_a) == n_matrices)
943 cpassert(
SIZE(matrix_b) == n_matrices)
945 use_accurate_sum = .true.
946 IF (
PRESENT(accurate)) use_accurate_sum = accurate
952 DO imatrix = 1, n_matrices
953 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
956 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
957 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
958 IF (use_accurate_sum)
THEN
961 trace(imatrix) = sum(ldata_a*ldata_b)
966 group = matrix_a(1) %matrix_struct%para_env
967 CALL group%sum(trace)
969 CALL timestop(handle)
970 END SUBROUTINE cp_fm_trace_a1b1t1_aa
971 SUBROUTINE cp_fm_trace_a1b1t1_ap (matrix_a, matrix_b, trace, accurate)
972 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
973 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
974 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
975 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
977 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_ap'
979 INTEGER :: handle, imatrix, n_matrices, &
980 ncols_local, nrows_local
981 LOGICAL :: use_accurate_sum
982 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
985 CALL timeset(routinen, handle)
987 n_matrices =
SIZE(trace)
988 cpassert(
SIZE(matrix_a) == n_matrices)
989 cpassert(
SIZE(matrix_b) == n_matrices)
991 use_accurate_sum = .true.
992 IF (
PRESENT(accurate)) use_accurate_sum = accurate
998 DO imatrix = 1, n_matrices
999 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
1002 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1003 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1004 IF (use_accurate_sum)
THEN
1007 trace(imatrix) = sum(ldata_a*ldata_b)
1012 group = matrix_a(1) %matrix_struct%para_env
1013 CALL group%sum(trace)
1015 CALL timestop(handle)
1016 END SUBROUTINE cp_fm_trace_a1b1t1_ap
1017 SUBROUTINE cp_fm_trace_a1b1t1_pa (matrix_a, matrix_b, trace, accurate)
1018 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
1019 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
1020 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
1021 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1023 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_pa'
1025 INTEGER :: handle, imatrix, n_matrices, &
1026 ncols_local, nrows_local
1027 LOGICAL :: use_accurate_sum
1028 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1031 CALL timeset(routinen, handle)
1033 n_matrices =
SIZE(trace)
1034 cpassert(
SIZE(matrix_a) == n_matrices)
1035 cpassert(
SIZE(matrix_b) == n_matrices)
1037 use_accurate_sum = .true.
1038 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1044 DO imatrix = 1, n_matrices
1045 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1048 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1049 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1050 IF (use_accurate_sum)
THEN
1053 trace(imatrix) = sum(ldata_a*ldata_b)
1058 group = matrix_a(1) %matrix%matrix_struct%para_env
1059 CALL group%sum(trace)
1061 CALL timestop(handle)
1062 END SUBROUTINE cp_fm_trace_a1b1t1_pa
1063 SUBROUTINE cp_fm_trace_a1b1t1_pp (matrix_a, matrix_b, trace, accurate)
1064 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
1065 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
1066 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
1067 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1069 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_pp'
1071 INTEGER :: handle, imatrix, n_matrices, &
1072 ncols_local, nrows_local
1073 LOGICAL :: use_accurate_sum
1074 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1077 CALL timeset(routinen, handle)
1079 n_matrices =
SIZE(trace)
1080 cpassert(
SIZE(matrix_a) == n_matrices)
1081 cpassert(
SIZE(matrix_b) == n_matrices)
1083 use_accurate_sum = .true.
1084 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1090 DO imatrix = 1, n_matrices
1091 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1094 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1095 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1096 IF (use_accurate_sum)
THEN
1099 trace(imatrix) = sum(ldata_a*ldata_b)
1104 group = matrix_a(1) %matrix%matrix_struct%para_env
1105 CALL group%sum(trace)
1107 CALL timestop(handle)
1108 END SUBROUTINE cp_fm_trace_a1b1t1_pp
1117 SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa (matrix_a, matrix_b, trace, accurate)
1118 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1119 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1120 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1121 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1123 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_aa'
1125 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1127 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1128 LOGICAL :: use_accurate_sum
1130 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1133 CALL timeset(routinen, handle)
1135 nz =
SIZE(matrix_a, 1)
1136 cpassert(
SIZE(matrix_b, 1) == nz)
1138 na =
SIZE(matrix_a, 2)
1139 nb =
SIZE(matrix_b, 2)
1140 cpassert(
SIZE(trace, 1) == na)
1141 cpassert(
SIZE(trace, 2) == nb)
1143 use_accurate_sum = .true.
1144 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1149 na8 = int(na, kind=
int_8)
1155 DO itrace = 1, ntraces
1156 ib8 = (itrace - 1)/na8
1157 ia = int(itrace - ib8*na8)
1162 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1165 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1166 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1167 IF (use_accurate_sum)
THEN
1170 t = t + sum(ldata_a*ldata_b)
1177 group = matrix_a(1, 1) %matrix_struct%para_env
1178 CALL group%sum(trace)
1180 CALL timestop(handle)
1181 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa
1182 SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap (matrix_a, matrix_b, trace, accurate)
1183 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1184 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1185 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1186 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1188 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_ap'
1190 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1192 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1193 LOGICAL :: use_accurate_sum
1195 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1198 CALL timeset(routinen, handle)
1200 nz =
SIZE(matrix_a, 1)
1201 cpassert(
SIZE(matrix_b, 1) == nz)
1203 na =
SIZE(matrix_a, 2)
1204 nb =
SIZE(matrix_b, 2)
1205 cpassert(
SIZE(trace, 1) == na)
1206 cpassert(
SIZE(trace, 2) == nb)
1208 use_accurate_sum = .true.
1209 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1214 na8 = int(na, kind=
int_8)
1220 DO itrace = 1, ntraces
1221 ib8 = (itrace - 1)/na8
1222 ia = int(itrace - ib8*na8)
1227 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1230 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1231 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1232 IF (use_accurate_sum)
THEN
1235 t = t + sum(ldata_a*ldata_b)
1242 group = matrix_a(1, 1) %matrix_struct%para_env
1243 CALL group%sum(trace)
1245 CALL timestop(handle)
1246 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap
1247 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa (matrix_a, matrix_b, trace, accurate)
1248 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1249 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1250 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1251 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1253 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_pa'
1255 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1257 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1258 LOGICAL :: use_accurate_sum
1260 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1263 CALL timeset(routinen, handle)
1265 nz =
SIZE(matrix_a, 1)
1266 cpassert(
SIZE(matrix_b, 1) == nz)
1268 na =
SIZE(matrix_a, 2)
1269 nb =
SIZE(matrix_b, 2)
1270 cpassert(
SIZE(trace, 1) == na)
1271 cpassert(
SIZE(trace, 2) == nb)
1273 use_accurate_sum = .true.
1274 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1279 na8 = int(na, kind=
int_8)
1285 DO itrace = 1, ntraces
1286 ib8 = (itrace - 1)/na8
1287 ia = int(itrace - ib8*na8)
1292 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1295 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1296 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1297 IF (use_accurate_sum)
THEN
1300 t = t + sum(ldata_a*ldata_b)
1307 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1308 CALL group%sum(trace)
1310 CALL timestop(handle)
1311 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa
1312 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp (matrix_a, matrix_b, trace, accurate)
1313 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1314 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1315 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1316 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1318 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_pp'
1320 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1322 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1323 LOGICAL :: use_accurate_sum
1325 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1328 CALL timeset(routinen, handle)
1330 nz =
SIZE(matrix_a, 1)
1331 cpassert(
SIZE(matrix_b, 1) == nz)
1333 na =
SIZE(matrix_a, 2)
1334 nb =
SIZE(matrix_b, 2)
1335 cpassert(
SIZE(trace, 1) == na)
1336 cpassert(
SIZE(trace, 2) == nb)
1338 use_accurate_sum = .true.
1339 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1344 na8 = int(na, kind=
int_8)
1350 DO itrace = 1, ntraces
1351 ib8 = (itrace - 1)/na8
1352 ia = int(itrace - ib8*na8)
1357 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1360 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1361 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1362 IF (use_accurate_sum)
THEN
1365 t = t + sum(ldata_a*ldata_b)
1372 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1373 CALL group%sum(trace)
1375 CALL timestop(handle)
1376 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp
1412 transpose_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, &
1414 TYPE(
cp_fm_type),
INTENT(IN) :: triangular_matrix, matrix_b
1415 CHARACTER,
INTENT(IN),
OPTIONAL :: side
1416 LOGICAL,
INTENT(IN),
OPTIONAL :: transpose_tr, invert_tr
1417 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo_tr
1418 LOGICAL,
INTENT(IN),
OPTIONAL :: unit_diag_tr
1419 INTEGER,
INTENT(IN),
OPTIONAL :: n_rows, n_cols
1420 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: alpha
1422 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_triangular_multiply'
1424 CHARACTER :: side_char, transa, unit_diag, uplo
1425 INTEGER :: handle, mdim, m, n
1429 CALL timeset(routinen, handle)
1437 IF (
PRESENT(side)) side_char = side
1438 mdim = merge(1, 2,
'L' == side_char)
1439 IF (
PRESENT(invert_tr)) invert = invert_tr
1440 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1441 IF (
PRESENT(unit_diag_tr))
THEN
1442 IF (unit_diag_tr)
THEN
1448 IF (
PRESENT(transpose_tr))
THEN
1449 IF (transpose_tr)
THEN
1455 IF (
PRESENT(alpha)) al = alpha
1456 IF (
PRESENT(n_rows)) m = n_rows
1457 IF (
PRESENT(n_cols)) n = n_cols
1461#if defined(__parallel)
1462 CALL pdtrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1463 triangular_matrix%local_data(1, 1), 1, 1, &
1464 triangular_matrix%matrix_struct%descriptor, &
1465 matrix_b%local_data(1, 1), 1, 1, &
1466 matrix_b%matrix_struct%descriptor(1))
1468 CALL dtrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1469 triangular_matrix%local_data(1, 1), &
1470 SIZE(triangular_matrix%local_data, mdim), &
1471 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1476#if defined(__parallel)
1477 CALL pdtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1478 triangular_matrix%local_data(1, 1), 1, 1, &
1479 triangular_matrix%matrix_struct%descriptor, &
1480 matrix_b%local_data(1, 1), 1, 1, &
1481 matrix_b%matrix_struct%descriptor(1))
1483 CALL dtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1484 triangular_matrix%local_data(1, 1), &
1485 SIZE(triangular_matrix%local_data, mdim), &
1486 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1491 CALL timestop(handle)
1503 REAL(kind=
dp),
INTENT(IN) :: alpha
1506 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_scale'
1508 INTEGER :: handle, size_a
1509 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1511 CALL timeset(routinen, handle)
1515 a => matrix_a%local_data
1516 size_a =
SIZE(a, 1)*
SIZE(a, 2)
1518 CALL dscal(size_a, alpha, a, 1)
1520 CALL timestop(handle)
1533 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, matrixt
1535 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_transpose'
1537 INTEGER :: handle, ncol_global, &
1538 nrow_global, ncol_globalt, nrow_globalt
1539 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
1540#if defined(__parallel)
1541 INTEGER,
DIMENSION(9) :: desca, descc
1542#elif !defined(__MKL)
1546 nrow_global = matrix%matrix_struct%nrow_global
1547 ncol_global = matrix%matrix_struct%ncol_global
1548 nrow_globalt = matrixt%matrix_struct%nrow_global
1549 ncol_globalt = matrixt%matrix_struct%ncol_global
1550 cpassert(nrow_global == ncol_globalt)
1551 cpassert(nrow_globalt == ncol_global)
1553 CALL timeset(routinen, handle)
1555 a => matrix%local_data
1556 c => matrixt%local_data
1558#if defined(__parallel)
1559 desca(:) = matrix%matrix_struct%descriptor(:)
1560 descc(:) = matrixt%matrix_struct%descriptor(:)
1561 CALL pdtran(ncol_global, nrow_global, 1.0_dp, a(1, 1), 1, 1, desca, 0.0_dp, c(1, 1), 1, 1, descc)
1563 CALL mkl_domatcopy(
'C',
'T', nrow_global, ncol_global, 1.0_dp, a(1, 1), nrow_global, c(1, 1), ncol_global)
1565 DO j = 1, ncol_global
1566 DO i = 1, nrow_global
1571 CALL timestop(handle)
1587 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
1589 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_uplo_to_full'
1592 INTEGER :: handle, icol_global, irow_global, &
1593 mypcol, myprow, ncol_global, &
1595 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1598#if defined(__parallel)
1599 INTEGER :: icol_local, irow_local, &
1600 ncol_block, ncol_local, &
1601 nrow_block, nrow_local
1602 INTEGER,
DIMENSION(9) :: desca, descc
1603 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: c
1607 IF (
PRESENT(uplo)) myuplo = uplo
1609 nrow_global = matrix%matrix_struct%nrow_global
1610 ncol_global = matrix%matrix_struct%ncol_global
1611 cpassert(nrow_global == ncol_global)
1612 nrow_global = work%matrix_struct%nrow_global
1613 ncol_global = work%matrix_struct%ncol_global
1614 cpassert(nrow_global == ncol_global)
1616 CALL timeset(routinen, handle)
1618 context => matrix%matrix_struct%context
1619 myprow = context%mepos(1)
1620 mypcol = context%mepos(2)
1622#if defined(__parallel)
1624 nrow_block = matrix%matrix_struct%nrow_block
1625 ncol_block = matrix%matrix_struct%ncol_block
1627 nrow_local = matrix%matrix_struct%nrow_locals(myprow)
1628 ncol_local = matrix%matrix_struct%ncol_locals(mypcol)
1630 a => work%local_data
1631 desca(:) = work%matrix_struct%descriptor(:)
1632 c => matrix%local_data
1633 descc(:) = matrix%matrix_struct%descriptor(:)
1635 DO icol_local = 1, ncol_local
1636 icol_global = matrix%matrix_struct%col_indices(icol_local)
1637 DO irow_local = 1, nrow_local
1638 irow_global = matrix%matrix_struct%row_indices(irow_local)
1639 IF (merge(irow_global > icol_global, irow_global < icol_global, (myuplo ==
"U") .OR. (myuplo ==
"u")))
THEN
1640 c(irow_local, icol_local) = 0.0_dp
1641 ELSE IF (irow_global == icol_global)
THEN
1642 c(irow_local, icol_local) = 0.5_dp*c(irow_local, icol_local)
1647 DO icol_local = 1, ncol_local
1648 DO irow_local = 1, nrow_local
1649 a(irow_local, icol_local) = c(irow_local, icol_local)
1653 CALL pdtran(nrow_global, ncol_global, 1.0_dp, a(1, 1), 1, 1, desca, 1.0_dp, c(1, 1), 1, 1, descc)
1657 a => matrix%local_data
1659 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
1660 DO irow_global = 1, nrow_global
1661 DO icol_global = irow_global + 1, ncol_global
1662 a(icol_global, irow_global) = a(irow_global, icol_global)
1666 DO icol_global = 1, ncol_global
1667 DO irow_global = icol_global + 1, nrow_global
1668 a(irow_global, icol_global) = a(icol_global, irow_global)
1674 CALL timestop(handle)
1692 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: scaling
1694 INTEGER :: k, mypcol, myprow, n, ncol_global, &
1696 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1697#if defined(__parallel)
1698 INTEGER :: icol_global, icol_local, &
1699 ipcol, iprow, irow_local
1704 myprow = matrixa%matrix_struct%context%mepos(1)
1705 mypcol = matrixa%matrix_struct%context%mepos(2)
1706 nprow = matrixa%matrix_struct%context%num_pe(1)
1707 npcol = matrixa%matrix_struct%context%num_pe(2)
1709 ncol_global = matrixa%matrix_struct%ncol_global
1711 a => matrixa%local_data
1713 k = min(
SIZE(scaling), ncol_global)
1715#if defined(__parallel)
1717 DO icol_global = 1, k
1718 CALL infog2l(1, icol_global, matrixa%matrix_struct%descriptor, &
1719 nprow, npcol, myprow, mypcol, &
1720 irow_local, icol_local, iprow, ipcol)
1721 IF ((ipcol == mypcol))
THEN
1722 CALL dscal(n, scaling(icol_global), a(:, icol_local), 1)
1727 CALL dscal(n, scaling(i), a(:, i), 1)
1741 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: scaling
1743 INTEGER :: n, m, nrow_global, nrow_local, ncol_local
1744 INTEGER,
DIMENSION(:),
POINTER :: row_indices
1745 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1746#if defined(__parallel)
1747 INTEGER :: irow_global, icol, irow
1752 CALL cp_fm_get_info(matrixa, row_indices=row_indices, nrow_global=nrow_global, &
1753 nrow_local=nrow_local, ncol_local=ncol_local)
1754 cpassert(
SIZE(scaling) == nrow_global)
1756 a => matrixa%local_data
1760#if defined(__parallel)
1761 DO icol = 1, ncol_local
1762 DO irow = 1, nrow_local
1763 irow_global = row_indices(irow)
1764 a(irow, icol) = scaling(irow_global)*a(irow, icol)
1769 a(1:n, j) = scaling(1:n)*a(1:n, j)
1792 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_inverse
1793 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: det_a
1794 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: eps_svd
1795 REAL(kind=
dp),
DIMENSION(:),
POINTER, &
1796 INTENT(INOUT),
OPTIONAL :: eigval
1799 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
1800 REAL(kind=
dp) :: determinant, my_eps_svd
1801 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1804#if defined(__parallel)
1805 TYPE(
cp_fm_type) :: u, vt, sigma, inv_sigma_ut
1807 INTEGER :: i, info, liwork, lwork, exponent_of_minus_one
1808 INTEGER,
DIMENSION(9) :: desca
1810 REAL(kind=
dp) :: alpha, beta
1811 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
1812 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
1815 REAL(kind=
dp) :: eps1
1819 IF (
PRESENT(eps_svd)) my_eps_svd = eps_svd
1822 matrix_struct=matrix_a%matrix_struct, &
1826 a => matrix_lu%local_data
1827 n = matrix_lu%matrix_struct%nrow_global
1828 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
1830#if defined(__parallel)
1831 IF (my_eps_svd == 0.0_dp)
THEN
1835 desca(:) = matrix_lu%matrix_struct%descriptor(:)
1836 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
1838 IF (
PRESENT(det_a) .OR.
PRESENT(eigval))
THEN
1844 exponent_of_minus_one = 0
1845 determinant = 1.0_dp
1847 determinant = determinant*
diag(i)
1848 IF (ipivot(i) /= i)
THEN
1849 exponent_of_minus_one = exponent_of_minus_one + 1
1852 IF (
PRESENT(eigval))
THEN
1853 cpassert(.NOT.
ASSOCIATED(eigval))
1854 ALLOCATE (eigval(n))
1859 group = matrix_lu%matrix_struct%para_env
1860 CALL group%sum(exponent_of_minus_one)
1862 determinant = determinant*(-1.0_dp)**exponent_of_minus_one
1869 CALL pdgetrs(
'N', n, n, matrix_lu%local_data, 1, 1, desca, ipivot, matrix_inverse%local_data, 1, 1, desca, info)
1873 matrix_struct=matrix_a%matrix_struct, &
1874 name=
"LEFT_SINGULAR_MATRIX")
1877 matrix_struct=matrix_a%matrix_struct, &
1878 name=
"RIGHT_SINGULAR_MATRIX")
1882 desca(:) = matrix_lu%matrix_struct%descriptor(:)
1886 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca,
diag, u%local_data, &
1887 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
1888 lwork = int(work(1))
1890 ALLOCATE (work(lwork))
1892 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca,
diag, u%local_data, &
1893 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
1896 IF (info /= 0 .AND. info /= n + 1) &
1897 cpabort(
"Singular value decomposition of matrix failed.")
1900 matrix_struct=matrix_a%matrix_struct, &
1901 name=
"SINGULAR_VALUE_MATRIX")
1903 determinant = 1.0_dp
1905 IF (
PRESENT(eigval))
THEN
1906 cpassert(.NOT.
ASSOCIATED(eigval))
1907 ALLOCATE (eigval(n))
1911 IF (
diag(i) < my_eps_svd)
THEN
1915 determinant = determinant*
diag(i)
1922 CALL cp_warn(__location__, &
1923 "Linear dependencies were detected in the SVD inversion of matrix "//trim(adjustl(matrix_a%name))// &
1924 ". At least one singular value has been quenched.")
1927 matrix_struct=matrix_a%matrix_struct, &
1928 name=
"SINGULAR_VALUE_MATRIX")
1930 CALL pdgemm(
'N',
'T', n, n, n, 1.0_dp, sigma%local_data, 1, 1, desca, &
1931 u%local_data, 1, 1, desca, 0.0_dp, inv_sigma_ut%local_data, 1, 1, desca)
1934 CALL pdgemm(
'T',
'N', n, n, n, 1.0_dp, vt%local_data, 1, 1, desca, &
1935 inv_sigma_ut%local_data, 1, 1, desca, 0.0_dp, matrix_inverse%local_data, 1, 1, desca)
1944 IF (my_eps_svd == 0.0_dp)
THEN
1946 CALL invert_matrix(matrix_a%local_data, matrix_inverse%local_data, &
1948 CALL cp_fm_lu_decompose(matrix_lu, determinant, correct_sign=sign)
1949 IF (
PRESENT(eigval)) &
1950 CALL cp_abort(__location__, &
1951 "NYI. Eigenvalues not available for return without SCALAPACK.")
1954 determinant, eigval)
1959 IF (
PRESENT(det_a)) det_a = determinant
1971 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo_tr
1973 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_triangular_invert'
1975 CHARACTER :: unit_diag, uplo
1976 INTEGER :: handle, info, ncol_global
1977 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1978#if defined(__parallel)
1979 INTEGER,
DIMENSION(9) :: desca
1982 CALL timeset(routinen, handle)
1986 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1988 ncol_global = matrix_a%matrix_struct%ncol_global
1990 a => matrix_a%local_data
1992#if defined(__parallel)
1993 desca(:) = matrix_a%matrix_struct%descriptor(:)
1995 CALL pdtrtri(uplo, unit_diag, ncol_global, a(1, 1), 1, 1, desca, info)
1998 CALL dtrtri(uplo, unit_diag, ncol_global, a(1, 1), ncol_global, info)
2001 CALL timestop(handle)
2017 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_r
2018 INTEGER,
INTENT(IN),
OPTIONAL :: nrow_fact, ncol_fact, &
2019 first_row, first_col
2020 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
2022 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_qr_factorization'
2025 INTEGER :: handle, i, icol, info, irow, &
2026 j, lda, lwork, ncol, &
2028 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: tau, work
2029 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: r_mat
2030 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2031#if defined(__parallel)
2032 INTEGER,
DIMENSION(9) :: desca
2035 CALL timeset(routinen, handle)
2038 IF (
PRESENT(uplo)) myuplo = uplo
2040 ncol = matrix_a%matrix_struct%ncol_global
2041 nrow = matrix_a%matrix_struct%nrow_global
2044 a => matrix_a%local_data
2046 IF (
PRESENT(nrow_fact)) nrow = nrow_fact
2047 IF (
PRESENT(ncol_fact)) ncol = ncol_fact
2049 IF (
PRESENT(first_row)) irow = first_row
2051 IF (
PRESENT(first_col)) icol = first_col
2053 cpassert(nrow >= ncol)
2055 ALLOCATE (tau(ndim))
2057#if defined(__parallel)
2059 desca(:) = matrix_a%matrix_struct%descriptor(:)
2062 ALLOCATE (work(2*ndim))
2063 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2064 lwork = int(work(1))
2066 ALLOCATE (work(lwork))
2067 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2071 ALLOCATE (work(2*ndim))
2072 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2073 lwork = int(work(1))
2075 ALLOCATE (work(lwork))
2076 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2080 ALLOCATE (r_mat(ncol, ncol))
2082 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
2085 r_mat(j, i) = 0.0_dp
2091 r_mat(i, j) = 0.0_dp
2097 DEALLOCATE (tau, work, r_mat)
2099 CALL timestop(handle)
2110 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, general_a
2112 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_solve'
2114 INTEGER :: handle, info, n, nrhs
2115 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
2116 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, a_general
2117#if defined(__parallel)
2118 INTEGER,
DIMENSION(9) :: desca, descb
2123 CALL timeset(routinen, handle)
2125 a => matrix_a%local_data
2126 a_general => general_a%local_data
2127 n = matrix_a%matrix_struct%nrow_global
2128 nrhs = general_a%matrix_struct%ncol_global
2129 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
2131#if defined(__parallel)
2132 desca(:) = matrix_a%matrix_struct%descriptor(:)
2133 descb(:) = general_a%matrix_struct%descriptor(:)
2134 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
2135 CALL pdgetrs(
"N", n, nrhs, a, 1, 1, desca, ipivot, a_general, &
2140 ldb =
SIZE(a_general, 1)
2141 CALL dgetrf(n, n, a, lda, ipivot, info)
2142 CALL dgetrs(
"N", n, nrhs, a, lda, ipivot, a_general, ldb, info)
2148 CALL timestop(handle)
2179 SUBROUTINE cp_complex_fm_gemm(transa, transb, m, n, k, alpha, A_re, A_im, B_re, B_im, beta, &
2180 C_re, C_im, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, &
2182 CHARACTER(LEN=1),
INTENT(IN) :: transa, transb
2183 INTEGER,
INTENT(IN) :: m, n, k
2184 REAL(kind=
dp),
INTENT(IN) :: alpha
2185 TYPE(
cp_fm_type),
INTENT(IN) :: a_re, a_im, b_re, b_im
2186 REAL(kind=
dp),
INTENT(IN) :: beta
2188 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, b_first_col, &
2189 b_first_row, c_first_col, c_first_row
2191 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_complex_fm_gemm'
2193 CHARACTER(LEN=1) :: transa_real, transb_real
2195 REAL(kind=
dp) :: sign_a, sign_b
2197 CALL timeset(routinen, handle)
2199 transa_real = transa
2200 transb_real = transb
2203 IF (transa ==
"C")
THEN
2207 IF (transb ==
"C")
THEN
2212 CALL cp_fm_gemm(transa_real, transb_real, m, n, k, alpha, a_re, b_re, beta, c_re, &
2213 a_first_col=a_first_col, &
2214 a_first_row=a_first_row, &
2215 b_first_col=b_first_col, &
2216 b_first_row=b_first_row, &
2217 c_first_col=c_first_col, &
2218 c_first_row=c_first_row)
2219 CALL cp_fm_gemm(transa_real, transb_real, m, n, k, -sign_a*sign_b*alpha, &
2220 a_im, b_im, 1.0_dp, c_re, &
2221 a_first_col=a_first_col, &
2222 a_first_row=a_first_row, &
2223 b_first_col=b_first_col, &
2224 b_first_row=b_first_row, &
2225 c_first_col=c_first_col, &
2226 c_first_row=c_first_row)
2227 CALL cp_fm_gemm(transa_real, transb_real, m, n, k, sign_b*alpha, a_re, b_im, beta, c_im, &
2228 a_first_col=a_first_col, &
2229 a_first_row=a_first_row, &
2230 b_first_col=b_first_col, &
2231 b_first_row=b_first_row, &
2232 c_first_col=c_first_col, &
2233 c_first_row=c_first_row)
2234 CALL cp_fm_gemm(transa_real, transb_real, m, n, k, sign_a*alpha, a_im, b_re, 1.0_dp, c_im, &
2235 a_first_col=a_first_col, &
2236 a_first_row=a_first_row, &
2237 b_first_col=b_first_col, &
2238 b_first_row=b_first_row, &
2239 c_first_col=c_first_col, &
2240 c_first_row=c_first_row)
2242 CALL timestop(handle)
2253 SUBROUTINE cp_fm_lu_invert(matrix, info_out)
2255 INTEGER,
INTENT(OUT),
OPTIONAL :: info_out
2257 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_lu_invert'
2259 INTEGER :: nrows_global, handle, info, lwork
2260 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ipivot
2261 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: mat
2262 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2263#if defined(__parallel)
2265 INTEGER,
DIMENSION(9) :: desca
2266 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
2271 CALL timeset(routinen, handle)
2273 mat => matrix%local_data
2274 nrows_global = matrix%matrix_struct%nrow_global
2275 cpassert(nrows_global == matrix%matrix_struct%ncol_global)
2276 ALLOCATE (ipivot(nrows_global))
2278#if defined(__parallel)
2279 desca = matrix%matrix_struct%descriptor
2280 CALL pdgetrf(nrows_global, nrows_global, &
2281 mat, 1, 1, desca, ipivot, info)
2284 CALL dgetrf(nrows_global, nrows_global, &
2285 mat, lda, ipivot, info)
2288 CALL cp_abort(__location__,
"LU decomposition has failed")
2291#if defined(__parallel)
2293 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2294 ipivot, work, -1, iwork, -1, info)
2295 lwork = int(work(1))
2297 ALLOCATE (work(lwork))
2298 liwork = int(iwork(1))
2300 ALLOCATE (iwork(liwork))
2301 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2302 ipivot, work, lwork, iwork, liwork, info)
2305 CALL dgetri(nrows_global, mat, lda, &
2306 ipivot, work, -1, info)
2307 lwork = int(work(1))
2309 ALLOCATE (work(lwork))
2310 CALL dgetri(nrows_global, mat, lda, &
2311 ipivot, work, lwork, info)
2316 IF (
PRESENT(info_out))
THEN
2320 CALL cp_abort(__location__,
"LU inversion has failed")
2323 CALL timestop(handle)
2325 END SUBROUTINE cp_fm_lu_invert
2339 CHARACTER,
INTENT(IN) :: mode
2340 REAL(kind=
dp) :: res
2342 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_norm'
2344 INTEGER :: nrows, ncols, handle, lwork, nrows_local, ncols_local
2345 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2346 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2347#if defined(__parallel)
2348 INTEGER,
DIMENSION(9) :: desca
2353 CALL timeset(routinen, handle)
2356 nrow_global=nrows, &
2357 ncol_global=ncols, &
2358 nrow_local=nrows_local, &
2359 ncol_local=ncols_local)
2360 aa => matrix%local_data
2362#if defined(__parallel)
2363 desca = matrix%matrix_struct%descriptor
2367 CASE (
'1',
'O',
'o')
2371 CASE (
'F',
'f',
'E',
'e')
2374 cpabort(
"mode input is not valid")
2376 ALLOCATE (work(lwork))
2377 res = pdlange(mode, nrows, ncols, aa, 1, 1, desca, work)
2383 CASE (
'1',
'O',
'o')
2387 CASE (
'F',
'f',
'E',
'e')
2390 cpabort(
"mode input is not valid")
2392 ALLOCATE (work(lwork))
2394 res = dlange(mode, nrows, ncols, aa, lda, work)
2398 CALL timestop(handle)
2408 FUNCTION cp_fm_latra(matrix)
RESULT(res)
2410 REAL(kind=
dp) :: res
2412 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_latra'
2414 INTEGER :: nrows, ncols, handle
2415 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2416#if defined(__parallel)
2417 INTEGER,
DIMENSION(9) :: desca
2422 CALL timeset(routinen, handle)
2424 nrows = matrix%matrix_struct%nrow_global
2425 ncols = matrix%matrix_struct%ncol_global
2426 cpassert(nrows == ncols)
2427 aa => matrix%local_data
2429#if defined(__parallel)
2430 desca = matrix%matrix_struct%descriptor
2431 res = pdlatra(nrows, aa, 1, 1, desca)
2435 res = res + aa(ii, ii)
2439 CALL timestop(handle)
2441 END FUNCTION cp_fm_latra
2457 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2458 INTEGER,
INTENT(IN) :: nrow, ncol, first_row, first_col
2460 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdgeqpf'
2463 INTEGER :: info, lwork
2464 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
2465 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2466 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2467#if defined(__parallel)
2468 INTEGER,
DIMENSION(9) :: descc
2473 CALL timeset(routinen, handle)
2475 a => matrix%local_data
2477 ALLOCATE (work(2*nrow))
2478 ALLOCATE (ipiv(ncol))
2481#if defined(__parallel)
2482 descc(:) = matrix%matrix_struct%descriptor(:)
2484 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2485 lwork = int(work(1))
2487 ALLOCATE (work(lwork))
2492 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2494 cpassert(first_row == 1 .AND. first_col == 1)
2496 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2497 lwork = int(work(1))
2499 ALLOCATE (work(lwork))
2502 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2509 CALL timestop(handle)
2529 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2530 INTEGER,
INTENT(IN) :: nrow, first_row, first_col
2532 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdorgqr'
2535 INTEGER :: info, lwork
2536 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2537 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2538#if defined(__parallel)
2539 INTEGER,
DIMENSION(9) :: descc
2544 CALL timeset(routinen, handle)
2546 a => matrix%local_data
2548 ALLOCATE (work(2*nrow))
2551#if defined(__parallel)
2552 descc(:) = matrix%matrix_struct%descriptor(:)
2554 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2556 lwork = int(work(1))
2558 ALLOCATE (work(lwork))
2561 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2563 cpassert(first_row == 1 .AND. first_col == 1)
2565 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2566 lwork = int(work(1))
2568 ALLOCATE (work(lwork))
2569 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2574 CALL timestop(handle)
2589 INTEGER,
INTENT(IN) :: irow, jrow
2590 REAL(
dp),
INTENT(IN) :: cs, sn
2592 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_rows'
2593 INTEGER :: handle, ncol
2595#if defined(__parallel)
2596 INTEGER :: info, lwork
2597 INTEGER,
DIMENSION(9) :: desc
2598 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2600 CALL timeset(routinen, handle)
2602#if defined(__parallel)
2603 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
2605 ALLOCATE (work(lwork))
2606 desc(:) = matrix%matrix_struct%descriptor(:)
2608 matrix%local_data(1, 1), irow, 1, desc, ncol, &
2609 matrix%local_data(1, 1), jrow, 1, desc, ncol, &
2610 cs, sn, work, lwork, info)
2615 CALL drot(ncol, matrix%local_data(irow, 1), ncol, matrix%local_data(jrow, 1), ncol, cs, sn)
2616#if defined(__parallel)
2619 CALL timestop(handle)
2633 INTEGER,
INTENT(IN) :: icol, jcol
2634 REAL(
dp),
INTENT(IN) :: cs, sn
2636 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_cols'
2637 INTEGER :: handle, nrow
2639#if defined(__parallel)
2640 INTEGER :: info, lwork
2641 INTEGER,
DIMENSION(9) :: desc
2642 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2644 CALL timeset(routinen, handle)
2646#if defined(__parallel)
2647 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
2649 ALLOCATE (work(lwork))
2650 desc(:) = matrix%matrix_struct%descriptor(:)
2652 matrix%local_data(1, 1), 1, icol, desc, 1, &
2653 matrix%local_data(1, 1), 1, jcol, desc, 1, &
2654 cs, sn, work, lwork, info)
2659 CALL drot(nrow, matrix%local_data(1, icol), 1, matrix%local_data(1, jcol), 1, cs, sn)
2660#if defined(__parallel)
2663 CALL timestop(handle)
2681 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: b
2682 INTEGER,
INTENT(IN),
OPTIONAL :: nrows, ncols, start_row, start_col
2683 LOGICAL,
INTENT(IN),
OPTIONAL :: do_norm, do_print
2685 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_Gram_Schmidt_orthonorm'
2687 INTEGER :: end_col_global, end_col_local, end_row_global, end_row_local, handle, i, j, &
2688 j_col, ncol_global, ncol_local, nrow_global, nrow_local, start_col_global, &
2689 start_col_local, start_row_global, start_row_local, this_col, unit_nr
2690 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2691 LOGICAL :: my_do_norm, my_do_print
2692 REAL(kind=
dp) :: norm
2693 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2695 CALL timeset(routinen, handle)
2698 IF (
PRESENT(do_norm)) my_do_norm = do_norm
2700 my_do_print = .false.
2701 IF (
PRESENT(do_print) .AND. (my_do_norm)) my_do_print = do_print
2704 IF (my_do_print)
THEN
2706 IF (unit_nr < 1) my_do_print = .false.
2709 IF (
SIZE(b) /= 0)
THEN
2710 IF (
PRESENT(nrows))
THEN
2713 nrow_global =
SIZE(b, 1)
2716 IF (
PRESENT(ncols))
THEN
2719 ncol_global =
SIZE(b, 2)
2722 IF (
PRESENT(start_row))
THEN
2723 start_row_global = start_row
2725 start_row_global = 1
2728 IF (
PRESENT(start_col))
THEN
2729 start_col_global = start_col
2731 start_col_global = 1
2734 end_row_global = start_row_global + nrow_global - 1
2735 end_col_global = start_col_global + ncol_global - 1
2738 nrow_global=nrow_global, ncol_global=ncol_global, &
2739 nrow_local=nrow_local, ncol_local=ncol_local, &
2740 row_indices=row_indices, col_indices=col_indices)
2741 IF (end_row_global > nrow_global)
THEN
2742 end_row_global = nrow_global
2744 IF (end_col_global > ncol_global)
THEN
2745 end_col_global = ncol_global
2752 DO start_row_local = 1, nrow_local
2753 IF (row_indices(start_row_local) >= start_row_global)
EXIT
2756 DO end_row_local = start_row_local, nrow_local
2757 IF (row_indices(end_row_local) > end_row_global)
EXIT
2759 end_row_local = end_row_local - 1
2761 DO start_col_local = 1, ncol_local
2762 IF (col_indices(start_col_local) >= start_col_global)
EXIT
2765 DO end_col_local = start_col_local, ncol_local
2766 IF (col_indices(end_col_local) > end_col_global)
EXIT
2768 end_col_local = end_col_local - 1
2770 a => matrix_a%local_data
2772 this_col = col_indices(start_col_local) - start_col_global + 1
2774 b(:, this_col) = a(:, start_col_local)
2776 IF (my_do_norm)
THEN
2778 b(:, this_col) = b(:, this_col)/norm
2779 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
2782 DO i = start_col_local + 1, end_col_local
2783 this_col = col_indices(i) - start_col_global + 1
2784 b(:, this_col) = a(:, i)
2785 DO j = start_col_local, i - 1
2786 j_col = col_indices(j) - start_col_global + 1
2787 b(:, this_col) = b(:, this_col) - &
2792 IF (my_do_norm)
THEN
2794 b(:, this_col) = b(:, this_col)/norm
2795 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
2799 CALL matrix_a%matrix_struct%para_env%sum(b)
2802 CALL timestop(handle)
2814 INTEGER,
INTENT(IN) :: n
2815 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
2819 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2820#if defined(__parallel)
2821 INTEGER,
DIMENSION(9) :: desca
2825 IF (
PRESENT(uplo)) myuplo = uplo
2827 a => fm_matrix%local_data
2828#if defined(__parallel)
2829 desca(:) = fm_matrix%matrix_struct%descriptor(:)
2830 CALL pdpotrf(myuplo, n, a(1, 1), 1, 1, desca, info)
2832 CALL dpotrf(myuplo, n, a(1, 1),
SIZE(a, 1), info)
2835 cpabort(
"Cholesky decomposition failed. Matrix ill-conditioned?")
2847 INTEGER,
INTENT(IN) :: n
2848 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
2851 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2853#if defined(__parallel)
2854 INTEGER,
DIMENSION(9) :: desca
2858 IF (
PRESENT(uplo)) myuplo = uplo
2860 a => fm_matrix%local_data
2861#if defined(__parallel)
2862 desca(:) = fm_matrix%matrix_struct%descriptor(:)
2863 CALL pdpotri(myuplo, n, a(1, 1), 1, 1, desca, info)
2865 CALL dpotri(myuplo, n, a(1, 1),
SIZE(a, 1), info)
2880 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: xv
2881 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: yv
2882 REAL(kind=
dp),
OPTIONAL,
INTENT(IN) :: alpha, beta
2884 INTEGER :: na, nc, nx, ny
2885 REAL(kind=
dp) :: aval, bval
2886#if defined(__parallel)
2887 INTEGER :: nrl, ncl, ic, ir
2888 INTEGER,
DIMENSION(:),
POINTER :: rind, cind
2889 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: xvl, yvl, yvm
2893 IF (
PRESENT(alpha)) aval = alpha
2895 IF (
PRESENT(beta)) bval = beta
2900 IF ((nx /= ny) .OR. (nc /= nx))
THEN
2901 cpabort(
"cp_fm_matvec: incompatible dimensions")
2903#if defined(__parallel)
2905 row_indices=rind, col_indices=cind)
2906 ALLOCATE (xvl(ncl), yvl(nrl), yvm(ny))
2908 xvl(ic) = xv(cind(ic))
2911 IF (nrl > 0 .AND. ncl > 0)
THEN
2912 yvl(1:nrl) = matmul(amat%local_data(1:nrl, 1:ncl), xvl)
2916 yvm(rind(ir)) = yvl(ir)
2918 CALL amat%matrix_struct%para_env%sum(yvm)
2919 IF (bval == 0.0_dp)
THEN
2922 yv = bval*yv + aval*yvm
2925 IF (bval == 0.0_dp)
THEN
2926 yv = aval*matmul(amat%local_data, xv)
2928 yv = bval*yv + aval*matmul(amat%local_data, xv)
2942 REAL(kind=
dp),
INTENT(IN) :: alpha
2943 INTEGER,
INTENT(IN),
OPTIONAL :: n_active
2945 INTEGER :: i_global, n_diag, ncol_global, nrow_global
2946#if defined(__parallel)
2947 INTEGER :: icol_local, ipcol, iprow, irow, irow_local, &
2948 mypcol, myprow, npcol, nprow, nrow_local
2949 INTEGER,
DIMENSION(9) :: desca
2950 INTEGER,
DIMENSION(:),
POINTER :: row_indices
2954 CALL cp_fm_get_info(matrix, nrow_global=nrow_global, ncol_global=ncol_global)
2956 n_diag = min(nrow_global, ncol_global)
2957 IF (
PRESENT(n_active)) n_diag = n_active
2958 cpassert(n_diag >= 0 .AND. n_diag <= min(nrow_global, ncol_global))
2960#if defined(__parallel)
2961 CALL cp_fm_get_info(matrix, nrow_local=nrow_local, row_indices=row_indices)
2962 context => matrix%matrix_struct%context
2963 myprow = context%mepos(1)
2964 mypcol = context%mepos(2)
2965 nprow = context%num_pe(1)
2966 npcol = context%num_pe(2)
2967 desca(:) = matrix%matrix_struct%descriptor(:)
2969 DO irow = 1, nrow_local
2970 i_global = row_indices(irow)
2971 IF (i_global > n_diag)
EXIT
2972 CALL infog2l(i_global, i_global, desca, nprow, npcol, myprow, mypcol, &
2973 irow_local, icol_local, iprow, ipcol)
2974 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
2975 matrix%local_data(irow_local, icol_local) = matrix%local_data(irow_local, icol_local) + alpha
2979 DO i_global = 1, n_diag
2980 matrix%local_data(i_global, i_global) = matrix%local_data(i_global, i_global) + alpha
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
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_rot_rows(matrix, irow, jrow, cs, sn)
Applies a planar rotation defined by cs and sn to the i'th and j'th rows.
subroutine, public cp_fm_row_scale(matrixa, scaling)
scales row i of matrix a with scaling(i)
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_add_on_diag(matrix, alpha, n_active)
Adds a scalar to the diagonal of a distributed real full matrix.
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
subroutine, public cp_fm_add_columns(msource, mtarget, ncol, alpha, source_start, target_start)
Add (and scale) a subset of columns of a fm to a fm b = alpha*a + b.
subroutine, public cp_fm_rot_cols(matrix, icol, jcol, cs, sn)
Applies a planar rotation defined by cs and sn to the i'th and j'th columnns.
subroutine, public cp_fm_solve(matrix_a, general_a)
computes the the solution to A*b=A_general using lu decomposition
subroutine, public cp_fm_pdgeqpf(matrix, tau, nrow, ncol, first_row, first_col)
compute a QR factorization with column pivoting of a M-by-N distributed matrix sub( A ) = A(IA:IA+M-1...
real(kind=dp) function, public cp_fm_frobenius_norm(matrix_a)
computes the Frobenius norm of matrix_a
subroutine, public cp_fm_det(matrix_a, det_a)
Computes the determinant (with a correct sign even in parallel environment!) of a real square matrix.
subroutine, public cp_fm_transpose(matrix, matrixt)
transposes a matrix matrixt = matrix ^ T
subroutine, public cp_fm_qr_factorization(matrix_a, matrix_r, nrow_fact, ncol_fact, first_row, first_col, uplo)
performs a QR factorization of the input rectangular matrix A or of a submatrix of A the computed tri...
subroutine, public cp_fm_gram_schmidt_orthonorm(matrix_a, b, nrows, ncols, start_row, start_col, do_norm, do_print)
Orthonormalizes selected rows and columns of a full matrix, matrix_a.
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_potrf(fm_matrix, n, uplo)
Cholesky decomposition.
subroutine, public cp_fm_potri(fm_matrix, n, uplo)
Invert trianguar matrix.
subroutine, public cp_fm_geadd(alpha, trans, matrix_a, beta, matrix_b)
interface to BLACS geadd: matrix_b = beta*matrix_b + alpha*opt(matrix_a) where opt(matrix_a) can be e...
subroutine, public cp_fm_schur_product(matrix_a, matrix_b, matrix_c)
computes the schur product of two matrices c_ij = a_ij * b_ij
real(kind=dp) function, public cp_fm_norm(matrix, mode)
norm of matrix using (p)dlange
subroutine, public cp_fm_scale_and_add(alpha, matrix_a, beta, matrix_b)
calc A <- alpha*A + beta*B optimized for alpha == 1.0 (just add beta*B) and beta == 0....
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_invert(matrix_a, matrix_inverse, det_a, eps_svd, eigval)
Inverts a cp_fm_type matrix, optionally returning the determinant of the input matrix.
subroutine, public cp_complex_fm_gemm(transa, transb, m, n, k, alpha, a_re, a_im, b_re, b_im, beta, c_re, c_im, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, c_first_row)
Convenience function. Computes the matrix multiplications needed for the multiplication of complex ma...
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_symm(side, uplo, m, n, alpha, matrix_a, matrix_b, beta, matrix_c)
computes matrix_c = beta * matrix_c + alpha * matrix_a * matrix_b computes matrix_c = beta * matrix_c...
subroutine, public cp_fm_matvec(amat, xv, yv, alpha, beta)
Calculates yv = alpha*amat*xv + beta*yv where amat: fm matrix xv : vector replicated yv : vector repl...
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...
subroutine, public cp_fm_pdorgqr(matrix, tau, nrow, first_row, first_col)
generates an M-by-N real distributed matrix Q denoting A(IA:IA+M-1,JA:JA+N-1) with orthonormal column...
represent the structure of a full matrix
logical function, public cp_fm_struct_equivalent(fmstruct1, fmstruct2)
returns true if the two matrix structures are equivalent, false otherwise.
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_get_diag(matrix, diag, n_active)
returns the diagonal elements of a fm
subroutine, public cp_fm_set_submatrix(fm, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
sets a submatrix of a full matrix fm(start_row:start_row+n_rows,start_col:start_col+n_cols) = alpha*o...
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_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
gets a submatrix of a full matrix op(target_m)(1:n_rows,1:n_cols) =fm(start_row:start_row+n_rows,...
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
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_memory(mem)
Returns the total amount of memory [bytes] in use, if known, zero otherwise.
Collection of simple mathematical functions and subroutines.
subroutine, public get_pseudo_inverse_svd(a, a_pinverse, rskip, determinant, sval)
returns the pseudoinverse of a real, square matrix using singular value decomposition
subroutine, public diag(n, a, d, v)
Diagonalize matrix a. The eigenvalues are returned in vector d and the eigenvectors are returned in m...
Interface to the message passing library MPI.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
just to build arrays of pointers to matrices