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'
76 REAL(KIND=
dp),
EXTERNAL :: dlange, pdlange, pdlatra
79 MODULE PROCEDURE cp_fm_trace_a0b0t0
80 MODULE PROCEDURE cp_fm_trace_a1b0t1_a
81 MODULE PROCEDURE cp_fm_trace_a1b0t1_p
82 MODULE PROCEDURE cp_fm_trace_a1b1t1_aa
83 MODULE PROCEDURE cp_fm_trace_a1b1t1_ap
84 MODULE PROCEDURE cp_fm_trace_a1b1t1_pa
85 MODULE PROCEDURE cp_fm_trace_a1b1t1_pp
89 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_aa
90 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_ap
91 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pa
92 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pp
103 REAL(kind=
dp),
INTENT(OUT) :: det_a
104 REAL(kind=
dp) :: determinant
106 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
107 INTEGER :: n, i, info, p
108 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
109 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
111#if defined(__parallel)
112 INTEGER :: myprow, nprow, npcol, nrow_local, nrow_block, irow_local
113 INTEGER,
DIMENSION(9) :: desca
117 matrix_struct=matrix_a%matrix_struct, &
121 a => matrix_lu%local_data
122 n = matrix_lu%matrix_struct%nrow_global
128#if defined(__parallel)
130 desca(:) = matrix_lu%matrix_struct%descriptor(:)
131 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
133 determinant = product(
diag)
134 myprow = matrix_lu%matrix_struct%context%mepos(1)
135 nprow = matrix_lu%matrix_struct%context%num_pe(1)
136 npcol = matrix_lu%matrix_struct%context%num_pe(2)
137 nrow_local = matrix_lu%matrix_struct%nrow_locals(myprow)
138 nrow_block = matrix_lu%matrix_struct%nrow_block
139 DO irow_local = 1, nrow_local
140 i = matrix_lu%matrix_struct%row_indices(irow_local)
141 IF (ipivot(irow_local) /= i) p = p + 1
143 CALL matrix_lu%matrix_struct%para_env%sum(p)
147 CALL dgetrf(n, n, a, n, ipivot, info)
149 determinant = product(
diag)
151 IF (ipivot(i) /= i) p = p + 1
157 det_a = determinant*(-2*mod(p, 2) + 1.0_dp)
171 REAL(kind=
dp),
INTENT(IN) :: alpha
173 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: beta
174 TYPE(
cp_fm_type),
INTENT(IN),
OPTIONAL :: matrix_b
176 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_scale_and_add'
178 INTEGER :: handle, size_a, size_b
179 REAL(kind=
dp) :: my_beta
180 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
182 CALL timeset(routinen, handle)
185 IF (
PRESENT(matrix_b)) my_beta = 1.0_dp
186 IF (
PRESENT(beta)) my_beta = beta
189 IF (
PRESENT(beta))
THEN
190 cpassert(
PRESENT(matrix_b))
191 IF (
ASSOCIATED(matrix_a%local_data, matrix_b%local_data))
THEN
192 cpwarn(
"Bad use of routine. Call cp_fm_scale instead")
194 CALL timestop(handle)
199 a => matrix_a%local_data
201 size_a =
SIZE(a, 1)*
SIZE(a, 2)
203 IF (alpha /= 1.0_dp)
THEN
204 CALL dscal(size_a, alpha, a, 1)
206 IF (my_beta /= 0.0_dp)
THEN
207 IF (matrix_a%matrix_struct%context /= matrix_b%matrix_struct%context) &
208 cpabort(
"Matrices must be in the same blacs context")
211 matrix_b%matrix_struct))
THEN
213 b => matrix_b%local_data
214 size_b =
SIZE(b, 1)*
SIZE(b, 2)
215 IF (size_a /= size_b) &
216 cpabort(
"Matrices must have same local sizes")
218 CALL daxpy(size_a, my_beta, b, 1, a, 1)
221 CALL cp_abort(__location__, &
222 "cp_fm_scale_and_add is not yet implemented for cases "// &
223 "where two input matrix structures are not equivalent")
228 CALL timestop(handle)
249 REAL(kind=
dp),
INTENT(IN) :: alpha, beta
250 CHARACTER,
INTENT(IN) :: trans
251 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
253 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geadd'
255 INTEGER :: nrow_global, ncol_global, handle
256 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa, bb
257#if defined(__parallel)
258 INTEGER,
DIMENSION(9) :: desca, descb
263 CALL timeset(routinen, handle)
265 nrow_global = matrix_a%matrix_struct%nrow_global
266 ncol_global = matrix_a%matrix_struct%ncol_global
267 cpassert(nrow_global == matrix_b%matrix_struct%nrow_global)
268 cpassert(ncol_global == matrix_b%matrix_struct%ncol_global)
270 aa => matrix_a%local_data
271 bb => matrix_b%local_data
273#if defined(__parallel)
274 desca = matrix_a%matrix_struct%descriptor
275 descb = matrix_b%matrix_struct%descriptor
276 CALL pdgeadd(trans, &
288 CALL mkl_domatadd(
'C', trans,
'N', nrow_global, ncol_global, &
289 alpha, aa, nrow_global, beta, bb, nrow_global, bb, nrow_global)
295 DO jj = 1, ncol_global
296 DO ii = 1, nrow_global
297 bb(ii, jj) = beta*bb(ii, jj) + alpha*aa(jj, ii)
301 DO jj = 1, ncol_global
302 DO ii = 1, nrow_global
303 bb(ii, jj) = beta*bb(ii, jj) + alpha*aa(ii, jj)
309 CALL timestop(handle)
325 TYPE(
cp_fm_type),
INTENT(IN) :: msource, mtarget
326 INTEGER,
INTENT(IN) :: ncol
327 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: alpha
328 INTEGER,
INTENT(IN),
OPTIONAL :: source_start, target_start
330 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_add_columns'
332 INTEGER :: handle, n, ss, ts, i
333 REAL(kind=
dp) :: fscale
334 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
335#if defined(__parallel)
336 INTEGER,
DIMENSION(9) :: desca, descb
339 CALL timeset(routinen, handle)
344 IF (
PRESENT(source_start)) ss = source_start
345 IF (
PRESENT(target_start)) ts = target_start
348 IF (
PRESENT(alpha)) fscale = alpha
350 n = msource%matrix_struct%nrow_global
352 a => msource%local_data
353 b => mtarget%local_data
355#if defined(__parallel)
357 desca(:) = msource%matrix_struct%descriptor(:)
358 descb(:) = mtarget%matrix_struct%descriptor(:)
359 CALL pdgeadd(
"N", n, ncol, fscale, a, 1, ss, desca, 1.0_dp, b, 1, ts, descb)
362 b(1:n, ts + i) = b(1:n, ts + i) + fscale*a(1:n, ss + i)
366 CALL timestop(handle)
387 SUBROUTINE cp_fm_lu_decompose(matrix_a, almost_determinant, correct_sign)
389 REAL(kind=
dp),
INTENT(OUT) :: almost_determinant
390 LOGICAL,
INTENT(IN),
OPTIONAL :: correct_sign
392 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_lu_decompose'
394 INTEGER :: handle, i, info, n
395 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
396 REAL(kind=
dp) :: determinant
397 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
398#if defined(__parallel)
399 INTEGER,
DIMENSION(9) :: desca
400 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
405 CALL timeset(routinen, handle)
407 a => matrix_a%local_data
408 n = matrix_a%matrix_struct%nrow_global
409 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
411#if defined(__parallel)
412 mark_used(correct_sign)
413 desca(:) = matrix_a%matrix_struct%descriptor(:)
414 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
421 determinant = determinant*
diag(i)
426 CALL dgetrf(n, n, a, lda, ipivot, info)
428 IF (correct_sign)
THEN
430 IF (ipivot(i) /= i)
THEN
431 determinant = -determinant*a(i, i)
433 determinant = determinant*a(i, i)
438 determinant = determinant*a(i, i)
445 almost_determinant = determinant
446 CALL timestop(handle)
447 END SUBROUTINE cp_fm_lu_decompose
472 SUBROUTINE cp_fm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, &
473 matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, &
474 c_first_col, c_first_row)
476 CHARACTER(LEN=1),
INTENT(IN) :: transa, transb
477 INTEGER,
INTENT(IN) :: m, n, k
478 REAL(kind=
dp),
INTENT(IN) :: alpha
479 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
480 REAL(kind=
dp),
INTENT(IN) :: beta
482 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, &
483 b_first_col, b_first_row, &
484 c_first_col, c_first_row
486 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_gemm'
488 INTEGER :: handle, i_a, i_b, i_c, j_a, &
490 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
491#if defined(__parallel)
492 INTEGER,
DIMENSION(9) :: desca, descb, descc
494 INTEGER :: lda, ldb, ldc
497 CALL timeset(routinen, handle)
502 a => matrix_a%local_data
503 b => matrix_b%local_data
504 c => matrix_c%local_data
507 IF (
PRESENT(a_first_row)) i_a = a_first_row
510 IF (
PRESENT(a_first_col)) j_a = a_first_col
513 IF (
PRESENT(b_first_row)) i_b = b_first_row
516 IF (
PRESENT(b_first_col)) j_b = b_first_col
519 IF (
PRESENT(c_first_row)) i_c = c_first_row
522 IF (
PRESENT(c_first_col)) j_c = c_first_col
524#if defined(__parallel)
526 desca(:) = matrix_a%matrix_struct%descriptor(:)
527 descb(:) = matrix_b%matrix_struct%descriptor(:)
528 descc(:) = matrix_c%matrix_struct%descriptor(:)
530 CALL pdgemm(transa, transb, m, n, k, alpha, a, i_a, j_a, desca, b, i_b, j_b, &
531 descb, beta, c, i_c, j_c, descc)
539 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)
542 CALL timestop(handle)
567 SUBROUTINE cp_fm_symm(side, uplo, m, n, alpha, matrix_a, matrix_b, beta, matrix_c)
569 CHARACTER(LEN=1),
INTENT(IN) :: side, uplo
570 INTEGER,
INTENT(IN) :: m, n
571 REAL(kind=
dp),
INTENT(IN) :: alpha
572 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
573 REAL(kind=
dp),
INTENT(IN) :: beta
576 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_symm'
579 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
580#if defined(__parallel)
581 INTEGER,
DIMENSION(9) :: desca, descb, descc
583 INTEGER :: lda, ldb, ldc
586 CALL timeset(routinen, handle)
588 a => matrix_a%local_data
589 b => matrix_b%local_data
590 c => matrix_c%local_data
592#if defined(__parallel)
594 desca(:) = matrix_a%matrix_struct%descriptor(:)
595 descb(:) = matrix_b%matrix_struct%descriptor(:)
596 descc(:) = matrix_c%matrix_struct%descriptor(:)
598 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)
602 lda = matrix_a%matrix_struct%local_leading_dimension
603 ldb = matrix_b%matrix_struct%local_leading_dimension
604 ldc = matrix_c%matrix_struct%local_leading_dimension
606 CALL dsymm(side, uplo, m, n, alpha, a(1, 1), lda, b(1, 1), ldb, beta, c(1, 1), ldc)
609 CALL timestop(handle)
622 REAL(kind=
dp) :: norm
624 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_frobenius_norm'
626 INTEGER :: handle, size_a
627 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
628 REAL(kind=
dp),
EXTERNAL :: ddot
629#if defined(__parallel)
633 CALL timeset(routinen, handle)
636 a => matrix_a%local_data
637 size_a =
SIZE(a, 1)*
SIZE(a, 2)
638 norm = ddot(size_a, a(1, 1), 1, a(1, 1), 1)
639#if defined(__parallel)
640 group = matrix_a%matrix_struct%para_env
645 CALL timestop(handle)
664 SUBROUTINE cp_fm_syrk(uplo, trans, k, alpha, matrix_a, ia, ja, beta, matrix_c)
665 CHARACTER(LEN=1),
INTENT(IN) :: uplo, trans
666 INTEGER,
INTENT(IN) :: k
667 REAL(kind=
dp),
INTENT(IN) :: alpha
669 INTEGER,
INTENT(IN) :: ia, ja
670 REAL(kind=
dp),
INTENT(IN) :: beta
673 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_syrk'
676 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
677#if defined(__parallel)
678 INTEGER,
DIMENSION(9) :: desca, descc
682#if defined (__HAS_IEEE_EXCEPTIONS)
683 LOGICAL,
DIMENSION(5) :: halt
686 CALL timeset(routinen, handle)
688 n = matrix_c%matrix_struct%nrow_global
690 a => matrix_a%local_data
691 c => matrix_c%local_data
693#if defined (__HAS_IEEE_EXCEPTIONS)
694 CALL ieee_get_halting_mode(ieee_all, halt)
695 CALL ieee_set_halting_mode(ieee_all, .false.)
697#if defined(__parallel)
698 desca(:) = matrix_a%matrix_struct%descriptor(:)
699 descc(:) = matrix_c%matrix_struct%descriptor(:)
701 CALL pdsyrk(uplo, trans, n, k, alpha, a(1, 1), ia, ja, desca, beta, c(1, 1), 1, 1, descc)
706 CALL dsyrk(uplo, trans, n, k, alpha, a(ia, ja), lda, beta, c(1, 1), ldc)
708#if defined (__HAS_IEEE_EXCEPTIONS)
709 CALL ieee_set_halting_mode(ieee_all, halt)
711 CALL timestop(handle)
725 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
727 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_schur_product'
729 INTEGER :: handle, icol_local, irow_local, mypcol, &
730 myprow, ncol_local, &
732 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
735 CALL timeset(routinen, handle)
737 context => matrix_a%matrix_struct%context
738 myprow = context%mepos(1)
739 mypcol = context%mepos(2)
741 a => matrix_a%local_data
742 b => matrix_b%local_data
743 c => matrix_c%local_data
745 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
746 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
748 DO icol_local = 1, ncol_local
749 DO irow_local = 1, nrow_local
750 c(irow_local, icol_local) = a(irow_local, icol_local)*b(irow_local, icol_local)
754 CALL timestop(handle)
771 SUBROUTINE cp_fm_trace_a0b0t0(matrix_a, matrix_b, trace)
773 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
774 REAL(KIND=
dp),
INTENT(OUT) :: trace
776 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a0b0t0'
778 INTEGER :: handle, mypcol, myprow, ncol_local, &
780 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: a, b
784 CALL timeset(routinen, handle)
786 context => matrix_a%matrix_struct%context
787 myprow = context%mepos(1)
788 mypcol = context%mepos(2)
790 group = matrix_a%matrix_struct%para_env
792 a => matrix_a%local_data
793 b => matrix_b%local_data
795 nrow_local = min(matrix_a%matrix_struct%nrow_locals(myprow), matrix_b%matrix_struct%nrow_locals(myprow))
796 ncol_local = min(matrix_a%matrix_struct%ncol_locals(mypcol), matrix_b%matrix_struct%ncol_locals(mypcol))
800 b(1:nrow_local, 1:ncol_local))
802 CALL group%sum(trace)
804 CALL timestop(handle)
806 END SUBROUTINE cp_fm_trace_a0b0t0
827 SUBROUTINE cp_fm_trace_a1b0t1_a (matrix_a, matrix_b, trace)
828 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
830 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
832 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b0t1_a'
834 INTEGER :: handle, imatrix, n_matrices, &
835 ncols_local, nrows_local
836 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
839 CALL timeset(routinen, handle)
841 n_matrices =
SIZE(trace)
842 cpassert(
SIZE(matrix_a) == n_matrices)
844 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
846 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
853 DO imatrix = 1, n_matrices
856 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
861 group = matrix_b%matrix_struct%para_env
862 CALL group%sum(trace)
864 CALL timestop(handle)
865 END SUBROUTINE cp_fm_trace_a1b0t1_a
866 SUBROUTINE cp_fm_trace_a1b0t1_p (matrix_a, matrix_b, trace)
867 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
869 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
871 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b0t1_p'
873 INTEGER :: handle, imatrix, n_matrices, &
874 ncols_local, nrows_local
875 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
878 CALL timeset(routinen, handle)
880 n_matrices =
SIZE(trace)
881 cpassert(
SIZE(matrix_a) == n_matrices)
883 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
885 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
892 DO imatrix = 1, n_matrices
895 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
900 group = matrix_b%matrix_struct%para_env
901 CALL group%sum(trace)
903 CALL timestop(handle)
904 END SUBROUTINE cp_fm_trace_a1b0t1_p
924 SUBROUTINE cp_fm_trace_a1b1t1_aa (matrix_a, matrix_b, trace, accurate)
925 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
926 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
927 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
928 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
930 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_aa'
932 INTEGER :: handle, imatrix, n_matrices, &
933 ncols_local, nrows_local
934 LOGICAL :: use_accurate_sum
935 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
938 CALL timeset(routinen, handle)
940 n_matrices =
SIZE(trace)
941 cpassert(
SIZE(matrix_a) == n_matrices)
942 cpassert(
SIZE(matrix_b) == n_matrices)
944 use_accurate_sum = .true.
945 IF (
PRESENT(accurate)) use_accurate_sum = accurate
951 DO imatrix = 1, n_matrices
952 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
955 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
956 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
957 IF (use_accurate_sum)
THEN
960 trace(imatrix) = sum(ldata_a*ldata_b)
965 group = matrix_a(1) %matrix_struct%para_env
966 CALL group%sum(trace)
968 CALL timestop(handle)
969 END SUBROUTINE cp_fm_trace_a1b1t1_aa
970 SUBROUTINE cp_fm_trace_a1b1t1_ap (matrix_a, matrix_b, trace, accurate)
971 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
972 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
973 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
974 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
976 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_ap'
978 INTEGER :: handle, imatrix, n_matrices, &
979 ncols_local, nrows_local
980 LOGICAL :: use_accurate_sum
981 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
984 CALL timeset(routinen, handle)
986 n_matrices =
SIZE(trace)
987 cpassert(
SIZE(matrix_a) == n_matrices)
988 cpassert(
SIZE(matrix_b) == n_matrices)
990 use_accurate_sum = .true.
991 IF (
PRESENT(accurate)) use_accurate_sum = accurate
997 DO imatrix = 1, n_matrices
998 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
1001 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1002 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1003 IF (use_accurate_sum)
THEN
1006 trace(imatrix) = sum(ldata_a*ldata_b)
1011 group = matrix_a(1) %matrix_struct%para_env
1012 CALL group%sum(trace)
1014 CALL timestop(handle)
1015 END SUBROUTINE cp_fm_trace_a1b1t1_ap
1016 SUBROUTINE cp_fm_trace_a1b1t1_pa (matrix_a, matrix_b, trace, accurate)
1017 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
1018 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
1019 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
1020 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1022 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_pa'
1024 INTEGER :: handle, imatrix, n_matrices, &
1025 ncols_local, nrows_local
1026 LOGICAL :: use_accurate_sum
1027 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1030 CALL timeset(routinen, handle)
1032 n_matrices =
SIZE(trace)
1033 cpassert(
SIZE(matrix_a) == n_matrices)
1034 cpassert(
SIZE(matrix_b) == n_matrices)
1036 use_accurate_sum = .true.
1037 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1043 DO imatrix = 1, n_matrices
1044 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1047 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1048 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1049 IF (use_accurate_sum)
THEN
1052 trace(imatrix) = sum(ldata_a*ldata_b)
1057 group = matrix_a(1) %matrix%matrix_struct%para_env
1058 CALL group%sum(trace)
1060 CALL timestop(handle)
1061 END SUBROUTINE cp_fm_trace_a1b1t1_pa
1062 SUBROUTINE cp_fm_trace_a1b1t1_pp (matrix_a, matrix_b, trace, accurate)
1063 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
1064 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
1065 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
1066 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1068 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_pp'
1070 INTEGER :: handle, imatrix, n_matrices, &
1071 ncols_local, nrows_local
1072 LOGICAL :: use_accurate_sum
1073 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1076 CALL timeset(routinen, handle)
1078 n_matrices =
SIZE(trace)
1079 cpassert(
SIZE(matrix_a) == n_matrices)
1080 cpassert(
SIZE(matrix_b) == n_matrices)
1082 use_accurate_sum = .true.
1083 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1089 DO imatrix = 1, n_matrices
1090 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1093 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1094 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1095 IF (use_accurate_sum)
THEN
1098 trace(imatrix) = sum(ldata_a*ldata_b)
1103 group = matrix_a(1) %matrix%matrix_struct%para_env
1104 CALL group%sum(trace)
1106 CALL timestop(handle)
1107 END SUBROUTINE cp_fm_trace_a1b1t1_pp
1116 SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa (matrix_a, matrix_b, trace, accurate)
1117 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1118 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1119 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1120 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1122 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_aa'
1124 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1126 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1127 LOGICAL :: use_accurate_sum
1129 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1132 CALL timeset(routinen, handle)
1134 nz =
SIZE(matrix_a, 1)
1135 cpassert(
SIZE(matrix_b, 1) == nz)
1137 na =
SIZE(matrix_a, 2)
1138 nb =
SIZE(matrix_b, 2)
1139 cpassert(
SIZE(trace, 1) == na)
1140 cpassert(
SIZE(trace, 2) == nb)
1142 use_accurate_sum = .true.
1143 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1148 na8 = int(na, kind=
int_8)
1154 DO itrace = 1, ntraces
1155 ib8 = (itrace - 1)/na8
1156 ia = int(itrace - ib8*na8)
1161 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1164 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1165 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1166 IF (use_accurate_sum)
THEN
1169 t = t + sum(ldata_a*ldata_b)
1176 group = matrix_a(1, 1) %matrix_struct%para_env
1177 CALL group%sum(trace)
1179 CALL timestop(handle)
1180 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa
1181 SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap (matrix_a, matrix_b, trace, accurate)
1182 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1183 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1184 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1185 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1187 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_ap'
1189 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1191 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1192 LOGICAL :: use_accurate_sum
1194 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1197 CALL timeset(routinen, handle)
1199 nz =
SIZE(matrix_a, 1)
1200 cpassert(
SIZE(matrix_b, 1) == nz)
1202 na =
SIZE(matrix_a, 2)
1203 nb =
SIZE(matrix_b, 2)
1204 cpassert(
SIZE(trace, 1) == na)
1205 cpassert(
SIZE(trace, 2) == nb)
1207 use_accurate_sum = .true.
1208 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1213 na8 = int(na, kind=
int_8)
1219 DO itrace = 1, ntraces
1220 ib8 = (itrace - 1)/na8
1221 ia = int(itrace - ib8*na8)
1226 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1229 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1230 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1231 IF (use_accurate_sum)
THEN
1234 t = t + sum(ldata_a*ldata_b)
1241 group = matrix_a(1, 1) %matrix_struct%para_env
1242 CALL group%sum(trace)
1244 CALL timestop(handle)
1245 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap
1246 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa (matrix_a, matrix_b, trace, accurate)
1247 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1248 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1249 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1250 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1252 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_pa'
1254 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1256 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1257 LOGICAL :: use_accurate_sum
1259 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1262 CALL timeset(routinen, handle)
1264 nz =
SIZE(matrix_a, 1)
1265 cpassert(
SIZE(matrix_b, 1) == nz)
1267 na =
SIZE(matrix_a, 2)
1268 nb =
SIZE(matrix_b, 2)
1269 cpassert(
SIZE(trace, 1) == na)
1270 cpassert(
SIZE(trace, 2) == nb)
1272 use_accurate_sum = .true.
1273 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1278 na8 = int(na, kind=
int_8)
1284 DO itrace = 1, ntraces
1285 ib8 = (itrace - 1)/na8
1286 ia = int(itrace - ib8*na8)
1291 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1294 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1295 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1296 IF (use_accurate_sum)
THEN
1299 t = t + sum(ldata_a*ldata_b)
1306 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1307 CALL group%sum(trace)
1309 CALL timestop(handle)
1310 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa
1311 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp (matrix_a, matrix_b, trace, accurate)
1312 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1313 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1314 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1315 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1317 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_pp'
1319 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1321 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1322 LOGICAL :: use_accurate_sum
1324 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1327 CALL timeset(routinen, handle)
1329 nz =
SIZE(matrix_a, 1)
1330 cpassert(
SIZE(matrix_b, 1) == nz)
1332 na =
SIZE(matrix_a, 2)
1333 nb =
SIZE(matrix_b, 2)
1334 cpassert(
SIZE(trace, 1) == na)
1335 cpassert(
SIZE(trace, 2) == nb)
1337 use_accurate_sum = .true.
1338 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1343 na8 = int(na, kind=
int_8)
1349 DO itrace = 1, ntraces
1350 ib8 = (itrace - 1)/na8
1351 ia = int(itrace - ib8*na8)
1356 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1359 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1360 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1361 IF (use_accurate_sum)
THEN
1364 t = t + sum(ldata_a*ldata_b)
1371 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1372 CALL group%sum(trace)
1374 CALL timestop(handle)
1375 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp
1411 transpose_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, &
1413 TYPE(
cp_fm_type),
INTENT(IN) :: triangular_matrix, matrix_b
1414 CHARACTER,
INTENT(IN),
OPTIONAL :: side
1415 LOGICAL,
INTENT(IN),
OPTIONAL :: transpose_tr, invert_tr
1416 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo_tr
1417 LOGICAL,
INTENT(IN),
OPTIONAL :: unit_diag_tr
1418 INTEGER,
INTENT(IN),
OPTIONAL :: n_rows, n_cols
1419 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: alpha
1421 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_triangular_multiply'
1423 CHARACTER :: side_char, transa, unit_diag, uplo
1424 INTEGER :: handle, mdim, m, n
1428 CALL timeset(routinen, handle)
1436 IF (
PRESENT(side)) side_char = side
1437 mdim = merge(1, 2,
'L' == side_char)
1438 IF (
PRESENT(invert_tr)) invert = invert_tr
1439 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1440 IF (
PRESENT(unit_diag_tr))
THEN
1441 IF (unit_diag_tr)
THEN
1447 IF (
PRESENT(transpose_tr))
THEN
1448 IF (transpose_tr)
THEN
1454 IF (
PRESENT(alpha)) al = alpha
1455 IF (
PRESENT(n_rows)) m = n_rows
1456 IF (
PRESENT(n_cols)) n = n_cols
1460#if defined(__parallel)
1461 CALL pdtrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1462 triangular_matrix%local_data(1, 1), 1, 1, &
1463 triangular_matrix%matrix_struct%descriptor, &
1464 matrix_b%local_data(1, 1), 1, 1, &
1465 matrix_b%matrix_struct%descriptor(1))
1467 CALL dtrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1468 triangular_matrix%local_data(1, 1), &
1469 SIZE(triangular_matrix%local_data, mdim), &
1470 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1475#if defined(__parallel)
1476 CALL pdtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1477 triangular_matrix%local_data(1, 1), 1, 1, &
1478 triangular_matrix%matrix_struct%descriptor, &
1479 matrix_b%local_data(1, 1), 1, 1, &
1480 matrix_b%matrix_struct%descriptor(1))
1482 CALL dtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1483 triangular_matrix%local_data(1, 1), &
1484 SIZE(triangular_matrix%local_data, mdim), &
1485 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1490 CALL timestop(handle)
1502 REAL(kind=
dp),
INTENT(IN) :: alpha
1505 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_scale'
1507 INTEGER :: handle, size_a
1508 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1510 CALL timeset(routinen, handle)
1514 a => matrix_a%local_data
1515 size_a =
SIZE(a, 1)*
SIZE(a, 2)
1517 CALL dscal(size_a, alpha, a, 1)
1519 CALL timestop(handle)
1532 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, matrixt
1534 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_transpose'
1536 INTEGER :: handle, ncol_global, &
1537 nrow_global, ncol_globalt, nrow_globalt
1538 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
1539#if defined(__parallel)
1540 INTEGER,
DIMENSION(9) :: desca, descc
1541#elif !defined(__MKL)
1545 nrow_global = matrix%matrix_struct%nrow_global
1546 ncol_global = matrix%matrix_struct%ncol_global
1547 nrow_globalt = matrixt%matrix_struct%nrow_global
1548 ncol_globalt = matrixt%matrix_struct%ncol_global
1549 cpassert(nrow_global == ncol_globalt)
1550 cpassert(nrow_globalt == ncol_global)
1552 CALL timeset(routinen, handle)
1554 a => matrix%local_data
1555 c => matrixt%local_data
1557#if defined(__parallel)
1558 desca(:) = matrix%matrix_struct%descriptor(:)
1559 descc(:) = matrixt%matrix_struct%descriptor(:)
1560 CALL pdtran(ncol_global, nrow_global, 1.0_dp, a(1, 1), 1, 1, desca, 0.0_dp, c(1, 1), 1, 1, descc)
1562 CALL mkl_domatcopy(
'C',
'T', nrow_global, ncol_global, 1.0_dp, a(1, 1), nrow_global, c(1, 1), ncol_global)
1564 DO j = 1, ncol_global
1565 DO i = 1, nrow_global
1570 CALL timestop(handle)
1586 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
1588 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_uplo_to_full'
1591 INTEGER :: handle, icol_global, irow_global, &
1592 mypcol, myprow, ncol_global, &
1594 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1597#if defined(__parallel)
1598 INTEGER :: icol_local, irow_local, &
1599 ncol_block, ncol_local, &
1600 nrow_block, nrow_local
1601 INTEGER,
DIMENSION(9) :: desca, descc
1602 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: c
1606 IF (
PRESENT(uplo)) myuplo = uplo
1608 nrow_global = matrix%matrix_struct%nrow_global
1609 ncol_global = matrix%matrix_struct%ncol_global
1610 cpassert(nrow_global == ncol_global)
1611 nrow_global = work%matrix_struct%nrow_global
1612 ncol_global = work%matrix_struct%ncol_global
1613 cpassert(nrow_global == ncol_global)
1615 CALL timeset(routinen, handle)
1617 context => matrix%matrix_struct%context
1618 myprow = context%mepos(1)
1619 mypcol = context%mepos(2)
1621#if defined(__parallel)
1623 nrow_block = matrix%matrix_struct%nrow_block
1624 ncol_block = matrix%matrix_struct%ncol_block
1626 nrow_local = matrix%matrix_struct%nrow_locals(myprow)
1627 ncol_local = matrix%matrix_struct%ncol_locals(mypcol)
1629 a => work%local_data
1630 desca(:) = work%matrix_struct%descriptor(:)
1631 c => matrix%local_data
1632 descc(:) = matrix%matrix_struct%descriptor(:)
1634 DO icol_local = 1, ncol_local
1635 icol_global = matrix%matrix_struct%col_indices(icol_local)
1636 DO irow_local = 1, nrow_local
1637 irow_global = matrix%matrix_struct%row_indices(irow_local)
1638 IF (merge(irow_global > icol_global, irow_global < icol_global, (myuplo ==
"U") .OR. (myuplo ==
"u")))
THEN
1639 c(irow_local, icol_local) = 0.0_dp
1640 ELSE IF (irow_global == icol_global)
THEN
1641 c(irow_local, icol_local) = 0.5_dp*c(irow_local, icol_local)
1646 DO icol_local = 1, ncol_local
1647 DO irow_local = 1, nrow_local
1648 a(irow_local, icol_local) = c(irow_local, icol_local)
1652 CALL pdtran(nrow_global, ncol_global, 1.0_dp, a(1, 1), 1, 1, desca, 1.0_dp, c(1, 1), 1, 1, descc)
1656 a => matrix%local_data
1658 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
1659 DO irow_global = 1, nrow_global
1660 DO icol_global = irow_global + 1, ncol_global
1661 a(icol_global, irow_global) = a(irow_global, icol_global)
1665 DO icol_global = 1, ncol_global
1666 DO irow_global = icol_global + 1, nrow_global
1667 a(irow_global, icol_global) = a(icol_global, irow_global)
1673 CALL timestop(handle)
1691 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: scaling
1693 INTEGER :: k, mypcol, myprow, n, ncol_global, &
1695 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1696#if defined(__parallel)
1697 INTEGER :: icol_global, icol_local, &
1698 ipcol, iprow, irow_local
1703 myprow = matrixa%matrix_struct%context%mepos(1)
1704 mypcol = matrixa%matrix_struct%context%mepos(2)
1705 nprow = matrixa%matrix_struct%context%num_pe(1)
1706 npcol = matrixa%matrix_struct%context%num_pe(2)
1708 ncol_global = matrixa%matrix_struct%ncol_global
1710 a => matrixa%local_data
1712 k = min(
SIZE(scaling), ncol_global)
1714#if defined(__parallel)
1716 DO icol_global = 1, k
1717 CALL infog2l(1, icol_global, matrixa%matrix_struct%descriptor, &
1718 nprow, npcol, myprow, mypcol, &
1719 irow_local, icol_local, iprow, ipcol)
1720 IF ((ipcol == mypcol))
THEN
1721 CALL dscal(n, scaling(icol_global), a(:, icol_local), 1)
1726 CALL dscal(n, scaling(i), a(:, i), 1)
1740 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: scaling
1742 INTEGER :: n, m, nrow_global, nrow_local, ncol_local
1743 INTEGER,
DIMENSION(:),
POINTER :: row_indices
1744 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1745#if defined(__parallel)
1746 INTEGER :: irow_global, icol, irow
1751 CALL cp_fm_get_info(matrixa, row_indices=row_indices, nrow_global=nrow_global, &
1752 nrow_local=nrow_local, ncol_local=ncol_local)
1753 cpassert(
SIZE(scaling) == nrow_global)
1755 a => matrixa%local_data
1759#if defined(__parallel)
1760 DO icol = 1, ncol_local
1761 DO irow = 1, nrow_local
1762 irow_global = row_indices(irow)
1763 a(irow, icol) = scaling(irow_global)*a(irow, icol)
1768 a(1:n, j) = scaling(1:n)*a(1:n, j)
1791 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_inverse
1792 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: det_a
1793 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: eps_svd
1794 REAL(kind=
dp),
DIMENSION(:),
POINTER, &
1795 INTENT(INOUT),
OPTIONAL :: eigval
1798 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
1799 REAL(kind=
dp) :: determinant, my_eps_svd
1800 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1803#if defined(__parallel)
1804 TYPE(
cp_fm_type) :: u, vt, sigma, inv_sigma_ut
1806 INTEGER :: i, info, liwork, lwork, exponent_of_minus_one
1807 INTEGER,
DIMENSION(9) :: desca
1809 REAL(kind=
dp) :: alpha, beta
1810 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
1811 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
1814 REAL(kind=
dp) :: eps1
1818 IF (
PRESENT(eps_svd)) my_eps_svd = eps_svd
1821 matrix_struct=matrix_a%matrix_struct, &
1825 a => matrix_lu%local_data
1826 n = matrix_lu%matrix_struct%nrow_global
1827 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
1829#if defined(__parallel)
1830 IF (my_eps_svd == 0.0_dp)
THEN
1834 desca(:) = matrix_lu%matrix_struct%descriptor(:)
1835 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
1837 IF (
PRESENT(det_a) .OR.
PRESENT(eigval))
THEN
1843 exponent_of_minus_one = 0
1844 determinant = 1.0_dp
1846 determinant = determinant*
diag(i)
1847 IF (ipivot(i) /= i)
THEN
1848 exponent_of_minus_one = exponent_of_minus_one + 1
1851 IF (
PRESENT(eigval))
THEN
1852 cpassert(.NOT.
ASSOCIATED(eigval))
1853 ALLOCATE (eigval(n))
1858 group = matrix_lu%matrix_struct%para_env
1859 CALL group%sum(exponent_of_minus_one)
1861 determinant = determinant*(-1.0_dp)**exponent_of_minus_one
1868 CALL pdgetrs(
'N', n, n, matrix_lu%local_data, 1, 1, desca, ipivot, matrix_inverse%local_data, 1, 1, desca, info)
1872 matrix_struct=matrix_a%matrix_struct, &
1873 name=
"LEFT_SINGULAR_MATRIX")
1876 matrix_struct=matrix_a%matrix_struct, &
1877 name=
"RIGHT_SINGULAR_MATRIX")
1881 desca(:) = matrix_lu%matrix_struct%descriptor(:)
1885 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca,
diag, u%local_data, &
1886 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
1887 lwork = int(work(1))
1889 ALLOCATE (work(lwork))
1891 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca,
diag, u%local_data, &
1892 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
1895 IF (info /= 0 .AND. info /= n + 1) &
1896 cpabort(
"Singular value decomposition of matrix failed.")
1899 matrix_struct=matrix_a%matrix_struct, &
1900 name=
"SINGULAR_VALUE_MATRIX")
1902 determinant = 1.0_dp
1904 IF (
PRESENT(eigval))
THEN
1905 cpassert(.NOT.
ASSOCIATED(eigval))
1906 ALLOCATE (eigval(n))
1910 IF (
diag(i) < my_eps_svd)
THEN
1914 determinant = determinant*
diag(i)
1921 CALL cp_warn(__location__, &
1922 "Linear dependencies were detected in the SVD inversion of matrix "//trim(adjustl(matrix_a%name))// &
1923 ". At least one singular value has been quenched.")
1926 matrix_struct=matrix_a%matrix_struct, &
1927 name=
"SINGULAR_VALUE_MATRIX")
1929 CALL pdgemm(
'N',
'T', n, n, n, 1.0_dp, sigma%local_data, 1, 1, desca, &
1930 u%local_data, 1, 1, desca, 0.0_dp, inv_sigma_ut%local_data, 1, 1, desca)
1933 CALL pdgemm(
'T',
'N', n, n, n, 1.0_dp, vt%local_data, 1, 1, desca, &
1934 inv_sigma_ut%local_data, 1, 1, desca, 0.0_dp, matrix_inverse%local_data, 1, 1, desca)
1943 IF (my_eps_svd == 0.0_dp)
THEN
1945 CALL invert_matrix(matrix_a%local_data, matrix_inverse%local_data, &
1947 CALL cp_fm_lu_decompose(matrix_lu, determinant, correct_sign=sign)
1948 IF (
PRESENT(eigval)) &
1949 CALL cp_abort(__location__, &
1950 "NYI. Eigenvalues not available for return without SCALAPACK.")
1953 determinant, eigval)
1958 IF (
PRESENT(det_a)) det_a = determinant
1970 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo_tr
1972 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_triangular_invert'
1974 CHARACTER :: unit_diag, uplo
1975 INTEGER :: handle, info, ncol_global
1976 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1977#if defined(__parallel)
1978 INTEGER,
DIMENSION(9) :: desca
1981 CALL timeset(routinen, handle)
1985 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1987 ncol_global = matrix_a%matrix_struct%ncol_global
1989 a => matrix_a%local_data
1991#if defined(__parallel)
1992 desca(:) = matrix_a%matrix_struct%descriptor(:)
1994 CALL pdtrtri(uplo, unit_diag, ncol_global, a(1, 1), 1, 1, desca, info)
1997 CALL dtrtri(uplo, unit_diag, ncol_global, a(1, 1), ncol_global, info)
2000 CALL timestop(handle)
2016 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_r
2017 INTEGER,
INTENT(IN),
OPTIONAL :: nrow_fact, ncol_fact, &
2018 first_row, first_col
2019 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
2021 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_qr_factorization'
2024 INTEGER :: handle, i, icol, info, irow, &
2025 j, lda, lwork, ncol, &
2027 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: tau, work
2028 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: r_mat
2029 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2030#if defined(__parallel)
2031 INTEGER,
DIMENSION(9) :: desca
2034 CALL timeset(routinen, handle)
2037 IF (
PRESENT(uplo)) myuplo = uplo
2039 ncol = matrix_a%matrix_struct%ncol_global
2040 nrow = matrix_a%matrix_struct%nrow_global
2043 a => matrix_a%local_data
2045 IF (
PRESENT(nrow_fact)) nrow = nrow_fact
2046 IF (
PRESENT(ncol_fact)) ncol = ncol_fact
2048 IF (
PRESENT(first_row)) irow = first_row
2050 IF (
PRESENT(first_col)) icol = first_col
2052 cpassert(nrow >= ncol)
2054 ALLOCATE (tau(ndim))
2056#if defined(__parallel)
2058 desca(:) = matrix_a%matrix_struct%descriptor(:)
2061 ALLOCATE (work(2*ndim))
2062 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2063 lwork = int(work(1))
2065 ALLOCATE (work(lwork))
2066 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2070 ALLOCATE (work(2*ndim))
2071 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2072 lwork = int(work(1))
2074 ALLOCATE (work(lwork))
2075 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2079 ALLOCATE (r_mat(ncol, ncol))
2081 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
2084 r_mat(j, i) = 0.0_dp
2090 r_mat(i, j) = 0.0_dp
2096 DEALLOCATE (tau, work, r_mat)
2098 CALL timestop(handle)
2109 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, general_a
2111 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_solve'
2113 INTEGER :: handle, info, n, nrhs
2114 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
2115 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, a_general
2116#if defined(__parallel)
2117 INTEGER,
DIMENSION(9) :: desca, descb
2122 CALL timeset(routinen, handle)
2124 a => matrix_a%local_data
2125 a_general => general_a%local_data
2126 n = matrix_a%matrix_struct%nrow_global
2127 nrhs = general_a%matrix_struct%ncol_global
2128 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
2130#if defined(__parallel)
2131 desca(:) = matrix_a%matrix_struct%descriptor(:)
2132 descb(:) = general_a%matrix_struct%descriptor(:)
2133 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
2134 CALL pdgetrs(
"N", n, nrhs, a, 1, 1, desca, ipivot, a_general, &
2139 ldb =
SIZE(a_general, 1)
2140 CALL dgetrf(n, n, a, lda, ipivot, info)
2141 CALL dgetrs(
"N", n, nrhs, a, lda, ipivot, a_general, ldb, info)
2147 CALL timestop(handle)
2178 SUBROUTINE cp_complex_fm_gemm(transa, transb, m, n, k, alpha, A_re, A_im, B_re, B_im, beta, &
2179 C_re, C_im, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, &
2181 CHARACTER(LEN=1),
INTENT(IN) :: transa, transb
2182 INTEGER,
INTENT(IN) :: m, n, k
2183 REAL(kind=
dp),
INTENT(IN) :: alpha
2184 TYPE(
cp_fm_type),
INTENT(IN) :: a_re, a_im, b_re, b_im
2185 REAL(kind=
dp),
INTENT(IN) :: beta
2187 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, b_first_col, &
2188 b_first_row, c_first_col, c_first_row
2190 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_complex_fm_gemm'
2194 CALL timeset(routinen, handle)
2196 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_re, b_re, beta, c_re, &
2197 a_first_col=a_first_col, &
2198 a_first_row=a_first_row, &
2199 b_first_col=b_first_col, &
2200 b_first_row=b_first_row, &
2201 c_first_col=c_first_col, &
2202 c_first_row=c_first_row)
2203 CALL cp_fm_gemm(transa, transb, m, n, k, -alpha, a_im, b_im, 1.0_dp, c_re, &
2204 a_first_col=a_first_col, &
2205 a_first_row=a_first_row, &
2206 b_first_col=b_first_col, &
2207 b_first_row=b_first_row, &
2208 c_first_col=c_first_col, &
2209 c_first_row=c_first_row)
2210 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_re, b_im, beta, c_im, &
2211 a_first_col=a_first_col, &
2212 a_first_row=a_first_row, &
2213 b_first_col=b_first_col, &
2214 b_first_row=b_first_row, &
2215 c_first_col=c_first_col, &
2216 c_first_row=c_first_row)
2217 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_im, b_re, 1.0_dp, c_im, &
2218 a_first_col=a_first_col, &
2219 a_first_row=a_first_row, &
2220 b_first_col=b_first_col, &
2221 b_first_row=b_first_row, &
2222 c_first_col=c_first_col, &
2223 c_first_row=c_first_row)
2225 CALL timestop(handle)
2236 SUBROUTINE cp_fm_lu_invert(matrix, info_out)
2238 INTEGER,
INTENT(OUT),
OPTIONAL :: info_out
2240 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_lu_invert'
2242 INTEGER :: nrows_global, handle, info, lwork
2243 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ipivot
2244 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: mat
2245 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2246#if defined(__parallel)
2248 INTEGER,
DIMENSION(9) :: desca
2249 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
2254 CALL timeset(routinen, handle)
2256 mat => matrix%local_data
2257 nrows_global = matrix%matrix_struct%nrow_global
2258 cpassert(nrows_global == matrix%matrix_struct%ncol_global)
2259 ALLOCATE (ipivot(nrows_global))
2261#if defined(__parallel)
2262 desca = matrix%matrix_struct%descriptor
2263 CALL pdgetrf(nrows_global, nrows_global, &
2264 mat, 1, 1, desca, ipivot, info)
2267 CALL dgetrf(nrows_global, nrows_global, &
2268 mat, lda, ipivot, info)
2271 CALL cp_abort(__location__,
"LU decomposition has failed")
2274#if defined(__parallel)
2276 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2277 ipivot, work, -1, iwork, -1, info)
2278 lwork = int(work(1))
2280 ALLOCATE (work(lwork))
2281 liwork = int(iwork(1))
2283 ALLOCATE (iwork(liwork))
2284 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2285 ipivot, work, lwork, iwork, liwork, info)
2288 CALL dgetri(nrows_global, mat, lda, &
2289 ipivot, work, -1, info)
2290 lwork = int(work(1))
2292 ALLOCATE (work(lwork))
2293 CALL dgetri(nrows_global, mat, lda, &
2294 ipivot, work, lwork, info)
2299 IF (
PRESENT(info_out))
THEN
2303 CALL cp_abort(__location__,
"LU inversion has failed")
2306 CALL timestop(handle)
2308 END SUBROUTINE cp_fm_lu_invert
2322 CHARACTER,
INTENT(IN) :: mode
2323 REAL(kind=
dp) :: res
2325 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_norm'
2327 INTEGER :: nrows, ncols, handle, lwork, nrows_local, ncols_local
2328 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2329 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2330#if defined(__parallel)
2331 INTEGER,
DIMENSION(9) :: desca
2336 CALL timeset(routinen, handle)
2339 nrow_global=nrows, &
2340 ncol_global=ncols, &
2341 nrow_local=nrows_local, &
2342 ncol_local=ncols_local)
2343 aa => matrix%local_data
2345#if defined(__parallel)
2346 desca = matrix%matrix_struct%descriptor
2350 CASE (
'1',
'O',
'o')
2354 CASE (
'F',
'f',
'E',
'e')
2357 cpabort(
"mode input is not valid")
2359 ALLOCATE (work(lwork))
2360 res = pdlange(mode, nrows, ncols, aa, 1, 1, desca, work)
2366 CASE (
'1',
'O',
'o')
2370 CASE (
'F',
'f',
'E',
'e')
2373 cpabort(
"mode input is not valid")
2375 ALLOCATE (work(lwork))
2377 res = dlange(mode, nrows, ncols, aa, lda, work)
2381 CALL timestop(handle)
2391 FUNCTION cp_fm_latra(matrix)
RESULT(res)
2393 REAL(kind=
dp) :: res
2395 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_latra'
2397 INTEGER :: nrows, ncols, handle
2398 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2399#if defined(__parallel)
2400 INTEGER,
DIMENSION(9) :: desca
2405 CALL timeset(routinen, handle)
2407 nrows = matrix%matrix_struct%nrow_global
2408 ncols = matrix%matrix_struct%ncol_global
2409 cpassert(nrows == ncols)
2410 aa => matrix%local_data
2412#if defined(__parallel)
2413 desca = matrix%matrix_struct%descriptor
2414 res = pdlatra(nrows, aa, 1, 1, desca)
2418 res = res + aa(ii, ii)
2422 CALL timestop(handle)
2424 END FUNCTION cp_fm_latra
2440 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2441 INTEGER,
INTENT(IN) :: nrow, ncol, first_row, first_col
2443 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdgeqpf'
2446 INTEGER :: info, lwork
2447 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
2448 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2449 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2450#if defined(__parallel)
2451 INTEGER,
DIMENSION(9) :: descc
2456 CALL timeset(routinen, handle)
2458 a => matrix%local_data
2460 ALLOCATE (work(2*nrow))
2461 ALLOCATE (ipiv(ncol))
2464#if defined(__parallel)
2465 descc(:) = matrix%matrix_struct%descriptor(:)
2467 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2468 lwork = int(work(1))
2470 ALLOCATE (work(lwork))
2475 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2477 cpassert(first_row == 1 .AND. first_col == 1)
2479 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2480 lwork = int(work(1))
2482 ALLOCATE (work(lwork))
2485 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2492 CALL timestop(handle)
2512 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2513 INTEGER,
INTENT(IN) :: nrow, first_row, first_col
2515 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdorgqr'
2518 INTEGER :: info, lwork
2519 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2520 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2521#if defined(__parallel)
2522 INTEGER,
DIMENSION(9) :: descc
2527 CALL timeset(routinen, handle)
2529 a => matrix%local_data
2531 ALLOCATE (work(2*nrow))
2534#if defined(__parallel)
2535 descc(:) = matrix%matrix_struct%descriptor(:)
2537 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2539 lwork = int(work(1))
2541 ALLOCATE (work(lwork))
2544 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2546 cpassert(first_row == 1 .AND. first_col == 1)
2548 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2549 lwork = int(work(1))
2551 ALLOCATE (work(lwork))
2552 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2557 CALL timestop(handle)
2572 INTEGER,
INTENT(IN) :: irow, jrow
2573 REAL(
dp),
INTENT(IN) :: cs, sn
2575 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_rows'
2576 INTEGER :: handle, ncol
2578#if defined(__parallel)
2579 INTEGER :: info, lwork
2580 INTEGER,
DIMENSION(9) :: desc
2581 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2583 CALL timeset(routinen, handle)
2585#if defined(__parallel)
2586 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
2588 ALLOCATE (work(lwork))
2589 desc(:) = matrix%matrix_struct%descriptor(:)
2591 matrix%local_data(1, 1), irow, 1, desc, ncol, &
2592 matrix%local_data(1, 1), jrow, 1, desc, ncol, &
2593 cs, sn, work, lwork, info)
2598 CALL drot(ncol, matrix%local_data(irow, 1), ncol, matrix%local_data(jrow, 1), ncol, cs, sn)
2599#if defined(__parallel)
2602 CALL timestop(handle)
2616 INTEGER,
INTENT(IN) :: icol, jcol
2617 REAL(
dp),
INTENT(IN) :: cs, sn
2619 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_cols'
2620 INTEGER :: handle, nrow
2622#if defined(__parallel)
2623 INTEGER :: info, lwork
2624 INTEGER,
DIMENSION(9) :: desc
2625 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2627 CALL timeset(routinen, handle)
2629#if defined(__parallel)
2630 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
2632 ALLOCATE (work(lwork))
2633 desc(:) = matrix%matrix_struct%descriptor(:)
2635 matrix%local_data(1, 1), 1, icol, desc, 1, &
2636 matrix%local_data(1, 1), 1, jcol, desc, 1, &
2637 cs, sn, work, lwork, info)
2642 CALL drot(nrow, matrix%local_data(1, icol), 1, matrix%local_data(1, jcol), 1, cs, sn)
2643#if defined(__parallel)
2646 CALL timestop(handle)
2664 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: b
2665 INTEGER,
INTENT(IN),
OPTIONAL :: nrows, ncols, start_row, start_col
2666 LOGICAL,
INTENT(IN),
OPTIONAL :: do_norm, do_print
2668 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_Gram_Schmidt_orthonorm'
2670 INTEGER :: end_col_global, end_col_local, end_row_global, end_row_local, handle, i, j, &
2671 j_col, ncol_global, ncol_local, nrow_global, nrow_local, start_col_global, &
2672 start_col_local, start_row_global, start_row_local, this_col, unit_nr
2673 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2674 LOGICAL :: my_do_norm, my_do_print
2675 REAL(kind=
dp) :: norm
2676 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2678 CALL timeset(routinen, handle)
2681 IF (
PRESENT(do_norm)) my_do_norm = do_norm
2683 my_do_print = .false.
2684 IF (
PRESENT(do_print) .AND. (my_do_norm)) my_do_print = do_print
2687 IF (my_do_print)
THEN
2689 IF (unit_nr < 1) my_do_print = .false.
2692 IF (
SIZE(b) /= 0)
THEN
2693 IF (
PRESENT(nrows))
THEN
2696 nrow_global =
SIZE(b, 1)
2699 IF (
PRESENT(ncols))
THEN
2702 ncol_global =
SIZE(b, 2)
2705 IF (
PRESENT(start_row))
THEN
2706 start_row_global = start_row
2708 start_row_global = 1
2711 IF (
PRESENT(start_col))
THEN
2712 start_col_global = start_col
2714 start_col_global = 1
2717 end_row_global = start_row_global + nrow_global - 1
2718 end_col_global = start_col_global + ncol_global - 1
2721 nrow_global=nrow_global, ncol_global=ncol_global, &
2722 nrow_local=nrow_local, ncol_local=ncol_local, &
2723 row_indices=row_indices, col_indices=col_indices)
2724 IF (end_row_global > nrow_global)
THEN
2725 end_row_global = nrow_global
2727 IF (end_col_global > ncol_global)
THEN
2728 end_col_global = ncol_global
2735 DO start_row_local = 1, nrow_local
2736 IF (row_indices(start_row_local) >= start_row_global)
EXIT
2739 DO end_row_local = start_row_local, nrow_local
2740 IF (row_indices(end_row_local) > end_row_global)
EXIT
2742 end_row_local = end_row_local - 1
2744 DO start_col_local = 1, ncol_local
2745 IF (col_indices(start_col_local) >= start_col_global)
EXIT
2748 DO end_col_local = start_col_local, ncol_local
2749 IF (col_indices(end_col_local) > end_col_global)
EXIT
2751 end_col_local = end_col_local - 1
2753 a => matrix_a%local_data
2755 this_col = col_indices(start_col_local) - start_col_global + 1
2757 b(:, this_col) = a(:, start_col_local)
2759 IF (my_do_norm)
THEN
2761 b(:, this_col) = b(:, this_col)/norm
2762 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
2765 DO i = start_col_local + 1, end_col_local
2766 this_col = col_indices(i) - start_col_global + 1
2767 b(:, this_col) = a(:, i)
2768 DO j = start_col_local, i - 1
2769 j_col = col_indices(j) - start_col_global + 1
2770 b(:, this_col) = b(:, this_col) - &
2775 IF (my_do_norm)
THEN
2777 b(:, this_col) = b(:, this_col)/norm
2778 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
2782 CALL matrix_a%matrix_struct%para_env%sum(b)
2785 CALL timestop(handle)
2797 INTEGER,
INTENT(IN) :: n
2798 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
2802 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2803#if defined(__parallel)
2804 INTEGER,
DIMENSION(9) :: desca
2808 IF (
PRESENT(uplo)) myuplo = uplo
2810 a => fm_matrix%local_data
2811#if defined(__parallel)
2812 desca(:) = fm_matrix%matrix_struct%descriptor(:)
2813 CALL pdpotrf(myuplo, n, a(1, 1), 1, 1, desca, info)
2815 CALL dpotrf(myuplo, n, a(1, 1),
SIZE(a, 1), info)
2818 cpabort(
"Cholesky decomposition failed. Matrix ill-conditioned?")
2830 INTEGER,
INTENT(IN) :: n
2831 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
2834 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2836#if defined(__parallel)
2837 INTEGER,
DIMENSION(9) :: desca
2841 IF (
PRESENT(uplo)) myuplo = uplo
2843 a => fm_matrix%local_data
2844#if defined(__parallel)
2845 desca(:) = fm_matrix%matrix_struct%descriptor(:)
2846 CALL pdpotri(myuplo, n, a(1, 1), 1, 1, desca, info)
2848 CALL dpotri(myuplo, n, a(1, 1),
SIZE(a, 1), info)
2863 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: xv
2864 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: yv
2865 REAL(kind=
dp),
OPTIONAL,
INTENT(IN) :: alpha, beta
2867 INTEGER :: na, nc, nx, ny
2868 REAL(kind=
dp) :: aval, bval
2869#if defined(__parallel)
2870 INTEGER :: nrl, ncl, ic, ir
2871 INTEGER,
DIMENSION(:),
POINTER :: rind, cind
2872 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: xvl, yvl, yvm
2876 IF (
PRESENT(alpha)) aval = alpha
2878 IF (
PRESENT(beta)) bval = beta
2883 IF ((nx /= ny) .OR. (nc /= nx))
THEN
2884 cpabort(
"cp_fm_matvec: incompatible dimensions")
2886#if defined(__parallel)
2888 row_indices=rind, col_indices=cind)
2889 ALLOCATE (xvl(ncl), yvl(nrl), yvm(ny))
2891 xvl(ic) = xv(cind(ic))
2893 yvl(1:nrl) = matmul(amat%local_data, xvl(1:ncl))
2896 yvm(rind(ir)) = yvl(ir)
2898 CALL amat%matrix_struct%para_env%sum(yvm)
2899 IF (bval == 0.0_dp)
THEN
2902 yv = bval*yv + aval*yvm
2905 IF (bval == 0.0_dp)
THEN
2906 yv = aval*matmul(amat%local_data, xv)
2908 yv = bval*yv + aval*matmul(amat%local_data, xv)
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_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_diag(matrix, diag)
returns the diagonal elements of a fm
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_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