32#include "../base/base_uses.f90"
37 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
38 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_fm_basic_linalg'
72 REAL(KIND=
dp),
EXTERNAL :: dlange, pdlange, pdlatra
73 REAL(KIND=
sp),
EXTERNAL :: slange, pslange, pslatra
76 MODULE PROCEDURE cp_fm_trace_a0b0t0
77 MODULE PROCEDURE cp_fm_trace_a1b0t1_a
78 MODULE PROCEDURE cp_fm_trace_a1b0t1_p
79 MODULE PROCEDURE cp_fm_trace_a1b1t1_aa
80 MODULE PROCEDURE cp_fm_trace_a1b1t1_ap
81 MODULE PROCEDURE cp_fm_trace_a1b1t1_pa
82 MODULE PROCEDURE cp_fm_trace_a1b1t1_pp
86 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_aa
87 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_ap
88 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pa
89 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pp
100 REAL(kind=
dp),
INTENT(OUT) :: det_a
101 REAL(kind=
dp) :: determinant
103 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
104 INTEGER :: n, i, info, p
105 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
106 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
108#if defined(__parallel)
109 INTEGER :: myprow, nprow, npcol, nrow_local, nrow_block, irow_local
110 INTEGER,
DIMENSION(9) :: desca
114 matrix_struct=matrix_a%matrix_struct, &
118 a => matrix_lu%local_data
119 n = matrix_lu%matrix_struct%nrow_global
125#if defined(__parallel)
127 desca(:) = matrix_lu%matrix_struct%descriptor(:)
128 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
130 determinant = product(
diag)
131 myprow = matrix_lu%matrix_struct%context%mepos(1)
132 nprow = matrix_lu%matrix_struct%context%num_pe(1)
133 npcol = matrix_lu%matrix_struct%context%num_pe(2)
134 nrow_local = matrix_lu%matrix_struct%nrow_locals(myprow)
135 nrow_block = matrix_lu%matrix_struct%nrow_block
136 DO irow_local = 1, nrow_local
137 i = matrix_lu%matrix_struct%row_indices(irow_local)
138 IF (ipivot(irow_local) /= i) p = p + 1
140 CALL matrix_lu%matrix_struct%para_env%sum(p)
144 CALL dgetrf(n, n, a, n, ipivot, info)
146 determinant = product(
diag)
148 IF (ipivot(i) /= i) p = p + 1
154 det_a = determinant*(-2*mod(p, 2) + 1.0_dp)
168 REAL(kind=
dp),
INTENT(IN) :: alpha
170 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: beta
171 TYPE(
cp_fm_type),
INTENT(IN),
OPTIONAL :: matrix_b
173 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_scale_and_add'
175 INTEGER :: handle, size_a, size_b
176 REAL(kind=
dp) :: my_beta
177 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
178 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp, b_sp
180 CALL timeset(routinen, handle)
183 IF (
PRESENT(matrix_b)) my_beta = 1.0_dp
184 IF (
PRESENT(beta)) my_beta = beta
187 IF (
PRESENT(beta))
THEN
188 cpassert(
PRESENT(matrix_b))
189 IF (
ASSOCIATED(matrix_a%local_data, matrix_b%local_data))
THEN
190 cpwarn(
"Bad use of routine. Call cp_fm_scale instead")
192 CALL timestop(handle)
197 a => matrix_a%local_data
198 a_sp => matrix_a%local_data_sp
200 IF (matrix_a%use_sp)
THEN
201 size_a =
SIZE(a_sp, 1)*
SIZE(a_sp, 2)
203 size_a =
SIZE(a, 1)*
SIZE(a, 2)
206 IF (alpha .NE. 1.0_dp)
THEN
207 IF (matrix_a%use_sp)
THEN
208 CALL sscal(size_a, real(alpha,
sp), a_sp, 1)
210 CALL dscal(size_a, alpha, a, 1)
213 IF (my_beta .NE. 0.0_dp)
THEN
214 IF (matrix_a%matrix_struct%context .NE. matrix_b%matrix_struct%context) &
215 cpabort(
"Matrices must be in the same blacs context")
218 matrix_b%matrix_struct))
THEN
220 b => matrix_b%local_data
221 b_sp => matrix_b%local_data_sp
222 IF (matrix_b%use_sp)
THEN
223 size_b =
SIZE(b_sp, 1)*
SIZE(b_sp, 2)
225 size_b =
SIZE(b, 1)*
SIZE(b, 2)
227 IF (size_a .NE. size_b) &
228 cpabort(
"Matrices must have same local sizes")
230 IF (matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
231 CALL saxpy(size_a, real(my_beta,
sp), b_sp, 1, a_sp, 1)
232 ELSEIF (matrix_a%use_sp .AND. .NOT. matrix_b%use_sp)
THEN
233 CALL saxpy(size_a, real(my_beta,
sp), real(b,
sp), 1, a_sp, 1)
234 ELSEIF (.NOT. matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
235 CALL daxpy(size_a, my_beta, real(b_sp,
dp), 1, a, 1)
237 CALL daxpy(size_a, my_beta, b, 1, a, 1)
242 cpabort(
"to do (pdscal,pdcopy,pdaxpy)")
250 CALL timestop(handle)
271 REAL(kind=
dp),
INTENT(IN) :: alpha, beta
272 CHARACTER,
INTENT(IN) :: trans
273 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
275 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geadd'
277 INTEGER :: nrow_global, ncol_global, handle
278 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa, bb
279#if defined(__parallel)
280 INTEGER,
DIMENSION(9) :: desca, descb
285 CALL timeset(routinen, handle)
287 nrow_global = matrix_a%matrix_struct%nrow_global
288 ncol_global = matrix_a%matrix_struct%ncol_global
289 cpassert(nrow_global .EQ. matrix_b%matrix_struct%nrow_global)
290 cpassert(ncol_global .EQ. matrix_b%matrix_struct%ncol_global)
292 aa => matrix_a%local_data
293 bb => matrix_b%local_data
295#if defined(__parallel)
296 desca = matrix_a%matrix_struct%descriptor
297 descb = matrix_b%matrix_struct%descriptor
298 CALL pdgeadd(trans, &
310 CALL mkl_domatadd(
'C', trans,
'N', nrow_global, ncol_global, &
311 alpha, aa, nrow_global, beta, bb, nrow_global, bb, nrow_global)
317 DO jj = 1, ncol_global
318 DO ii = 1, nrow_global
319 bb(ii, jj) = beta*bb(ii, jj) + alpha*aa(jj, ii)
323 DO jj = 1, ncol_global
324 DO ii = 1, nrow_global
325 bb(ii, jj) = beta*bb(ii, jj) + alpha*aa(ii, jj)
331 CALL timestop(handle)
352 SUBROUTINE cp_fm_lu_decompose(matrix_a, almost_determinant, correct_sign)
354 REAL(kind=
dp),
INTENT(OUT) :: almost_determinant
355 LOGICAL,
INTENT(IN),
OPTIONAL :: correct_sign
357 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_lu_decompose'
359 INTEGER :: handle, i, info, n
360 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
361 REAL(kind=
dp) :: determinant
362 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
363#if defined(__parallel)
364 INTEGER,
DIMENSION(9) :: desca
365 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
370 CALL timeset(routinen, handle)
372 a => matrix_a%local_data
373 n = matrix_a%matrix_struct%nrow_global
374 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
376#if defined(__parallel)
377 mark_used(correct_sign)
378 desca(:) = matrix_a%matrix_struct%descriptor(:)
379 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
386 determinant = determinant*
diag(i)
391 CALL dgetrf(n, n, a, lda, ipivot, info)
393 IF (correct_sign)
THEN
395 IF (ipivot(i) .NE. i)
THEN
396 determinant = -determinant*a(i, i)
398 determinant = determinant*a(i, i)
403 determinant = determinant*a(i, i)
410 almost_determinant = determinant
411 CALL timestop(handle)
412 END SUBROUTINE cp_fm_lu_decompose
437 SUBROUTINE cp_fm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, &
438 matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, &
439 c_first_col, c_first_row)
441 CHARACTER(LEN=1),
INTENT(IN) :: transa, transb
442 INTEGER,
INTENT(IN) :: m, n, k
443 REAL(kind=
dp),
INTENT(IN) :: alpha
444 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
445 REAL(kind=
dp),
INTENT(IN) :: beta
447 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, &
448 b_first_col, b_first_row, &
449 c_first_col, c_first_row
451 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_gemm'
453 INTEGER :: handle, i_a, i_b, i_c, j_a, &
455 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
456 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp, b_sp, c_sp
457#if defined(__parallel)
458 INTEGER,
DIMENSION(9) :: desca, descb, descc
460 INTEGER :: lda, ldb, ldc
463 CALL timeset(routinen, handle)
468 a => matrix_a%local_data
469 b => matrix_b%local_data
470 c => matrix_c%local_data
472 a_sp => matrix_a%local_data_sp
473 b_sp => matrix_b%local_data_sp
474 c_sp => matrix_c%local_data_sp
477 IF (
PRESENT(a_first_row)) i_a = a_first_row
480 IF (
PRESENT(a_first_col)) j_a = a_first_col
483 IF (
PRESENT(b_first_row)) i_b = b_first_row
486 IF (
PRESENT(b_first_col)) j_b = b_first_col
489 IF (
PRESENT(c_first_row)) i_c = c_first_row
492 IF (
PRESENT(c_first_col)) j_c = c_first_col
494#if defined(__parallel)
496 desca(:) = matrix_a%matrix_struct%descriptor(:)
497 descb(:) = matrix_b%matrix_struct%descriptor(:)
498 descc(:) = matrix_c%matrix_struct%descriptor(:)
500 IF (matrix_a%use_sp .AND. matrix_b%use_sp .AND. matrix_c%use_sp)
THEN
502 CALL psgemm(transa, transb, m, n, k, real(alpha,
sp), a_sp(1, 1), i_a, j_a, desca, b_sp(1, 1), i_b, j_b, &
503 descb, real(beta,
sp), c_sp(1, 1), i_c, j_c, descc)
505 ELSEIF ((.NOT. matrix_a%use_sp) .AND. (.NOT. matrix_b%use_sp) .AND. (.NOT. matrix_c%use_sp))
THEN
507 CALL pdgemm(transa, transb, m, n, k, alpha, a, i_a, j_a, desca, b, i_b, j_b, &
508 descb, beta, c, i_c, j_c, descc)
511 cpabort(
"Mixed precision gemm NYI")
515 IF (matrix_a%use_sp .AND. matrix_b%use_sp .AND. matrix_c%use_sp)
THEN
521 CALL sgemm(transa, transb, m, n, k, real(alpha,
sp), a_sp(i_a, j_a), lda, b_sp(i_b, j_b), ldb, &
522 REAL(beta,
sp), c_sp(i_c, j_c), ldc)
524 ELSEIF ((.NOT. matrix_a%use_sp) .AND. (.NOT. matrix_b%use_sp) .AND. (.NOT. matrix_c%use_sp))
THEN
530 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)
533 cpabort(
"Mixed precision gemm NYI")
537 CALL timestop(handle)
562 SUBROUTINE cp_fm_symm(side, uplo, m, n, alpha, matrix_a, matrix_b, beta, matrix_c)
564 CHARACTER(LEN=1),
INTENT(IN) :: side, uplo
565 INTEGER,
INTENT(IN) :: m, n
566 REAL(kind=
dp),
INTENT(IN) :: alpha
567 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
568 REAL(kind=
dp),
INTENT(IN) :: beta
571 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_symm'
574 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
575#if defined(__parallel)
576 INTEGER,
DIMENSION(9) :: desca, descb, descc
578 INTEGER :: lda, ldb, ldc
581 CALL timeset(routinen, handle)
583 a => matrix_a%local_data
584 b => matrix_b%local_data
585 c => matrix_c%local_data
587#if defined(__parallel)
589 desca(:) = matrix_a%matrix_struct%descriptor(:)
590 descb(:) = matrix_b%matrix_struct%descriptor(:)
591 descc(:) = matrix_c%matrix_struct%descriptor(:)
593 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)
597 lda = matrix_a%matrix_struct%local_leading_dimension
598 ldb = matrix_b%matrix_struct%local_leading_dimension
599 ldc = matrix_c%matrix_struct%local_leading_dimension
601 CALL dsymm(side, uplo, m, n, alpha, a(1, 1), lda, b(1, 1), ldb, beta, c(1, 1), ldc)
604 CALL timestop(handle)
617 REAL(kind=
dp) :: norm
619 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_frobenius_norm'
621 INTEGER :: handle, size_a
622 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
623 REAL(kind=
dp),
EXTERNAL :: ddot
624#if defined(__parallel)
628 CALL timeset(routinen, handle)
631 a => matrix_a%local_data
632 size_a =
SIZE(a, 1)*
SIZE(a, 2)
633 norm = ddot(size_a, a(1, 1), 1, a(1, 1), 1)
634#if defined(__parallel)
635 group = matrix_a%matrix_struct%para_env
640 CALL timestop(handle)
659 SUBROUTINE cp_fm_syrk(uplo, trans, k, alpha, matrix_a, ia, ja, beta, matrix_c)
660 CHARACTER(LEN=1),
INTENT(IN) :: uplo, trans
661 INTEGER,
INTENT(IN) :: k
662 REAL(kind=
dp),
INTENT(IN) :: alpha
664 INTEGER,
INTENT(IN) :: ia, ja
665 REAL(kind=
dp),
INTENT(IN) :: beta
668 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_syrk'
671 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
672#if defined(__parallel)
673 INTEGER,
DIMENSION(9) :: desca, descc
678 CALL timeset(routinen, handle)
680 n = matrix_c%matrix_struct%nrow_global
682 a => matrix_a%local_data
683 c => matrix_c%local_data
685#if defined(__parallel)
687 desca(:) = matrix_a%matrix_struct%descriptor(:)
688 descc(:) = matrix_c%matrix_struct%descriptor(:)
690 CALL pdsyrk(uplo, trans, n, k, alpha, a(1, 1), ia, ja, desca, beta, c(1, 1), 1, 1, descc)
697 CALL dsyrk(uplo, trans, n, k, alpha, a(ia, ja), lda, beta, c(1, 1), ldc)
700 CALL timestop(handle)
714 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
716 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_schur_product'
718 INTEGER :: handle, icol_local, irow_local, mypcol, &
719 myprow, ncol_local, npcol, nprow, &
721 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
724 CALL timeset(routinen, handle)
726 context => matrix_a%matrix_struct%context
727 myprow = context%mepos(1)
728 mypcol = context%mepos(2)
729 nprow = context%num_pe(1)
730 npcol = context%num_pe(2)
732 a => matrix_a%local_data
733 b => matrix_b%local_data
734 c => matrix_c%local_data
736 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
737 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
739 DO icol_local = 1, ncol_local
740 DO irow_local = 1, nrow_local
741 c(irow_local, icol_local) = a(irow_local, icol_local)*b(irow_local, icol_local)
745 CALL timestop(handle)
762 SUBROUTINE cp_fm_trace_a0b0t0(matrix_a, matrix_b, trace)
764 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
765 REAL(KIND=
dp),
INTENT(OUT) :: trace
767 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a0b0t0'
769 INTEGER :: handle, mypcol, myprow, ncol_local, &
770 npcol, nprow, nrow_local
771 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: a, b
772 REAL(KIND=
sp),
DIMENSION(:, :),
POINTER :: a_sp, b_sp
776 CALL timeset(routinen, handle)
778 context => matrix_a%matrix_struct%context
779 myprow = context%mepos(1)
780 mypcol = context%mepos(2)
781 nprow = context%num_pe(1)
782 npcol = context%num_pe(2)
784 group = matrix_a%matrix_struct%para_env
786 a => matrix_a%local_data
787 b => matrix_b%local_data
789 a_sp => matrix_a%local_data_sp
790 b_sp => matrix_b%local_data_sp
792 nrow_local = min(matrix_a%matrix_struct%nrow_locals(myprow), matrix_b%matrix_struct%nrow_locals(myprow))
793 ncol_local = min(matrix_a%matrix_struct%ncol_locals(mypcol), matrix_b%matrix_struct%ncol_locals(mypcol))
796 IF (matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
797 trace =
accurate_sum(real(a_sp(1:nrow_local, 1:ncol_local)* &
798 b_sp(1:nrow_local, 1:ncol_local),
dp))
799 ELSEIF (matrix_a%use_sp .AND. .NOT. matrix_b%use_sp)
THEN
800 trace =
accurate_sum(real(a_sp(1:nrow_local, 1:ncol_local),
dp)* &
801 b(1:nrow_local, 1:ncol_local))
802 ELSEIF (.NOT. matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
804 REAL(b_sp(1:nrow_local, 1:ncol_local), dp))
807 b(1:nrow_local, 1:ncol_local))
810 CALL group%sum(trace)
812 CALL timestop(handle)
814 END SUBROUTINE cp_fm_trace_a0b0t0
835 SUBROUTINE cp_fm_trace_a1b0t1_a (matrix_a, matrix_b, trace)
836 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
838 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
840 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b0t1_a'
842 INTEGER :: handle, imatrix, n_matrices, &
843 ncols_local, nrows_local
844 LOGICAL :: use_sp_a, use_sp_b
845 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
846 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
849 CALL timeset(routinen, handle)
851 n_matrices =
SIZE(trace)
852 cpassert(
SIZE(matrix_a) == n_matrices)
854 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
855 use_sp_b = matrix_b%use_sp
858 ldata_b_sp => matrix_b%local_data_sp(1:nrows_local, 1:ncols_local)
860 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
868 DO imatrix = 1, n_matrices
870 use_sp_a = matrix_a(imatrix) %use_sp
873 IF (use_sp_a .AND. use_sp_b)
THEN
874 ldata_a_sp => matrix_a(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
876 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
877 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
880 cpabort(
"Matrices A and B are of different types")
885 group = matrix_b%matrix_struct%para_env
886 CALL group%sum(trace)
888 CALL timestop(handle)
889 END SUBROUTINE cp_fm_trace_a1b0t1_a
890 SUBROUTINE cp_fm_trace_a1b0t1_p (matrix_a, matrix_b, trace)
891 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
893 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
895 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b0t1_p'
897 INTEGER :: handle, imatrix, n_matrices, &
898 ncols_local, nrows_local
899 LOGICAL :: use_sp_a, use_sp_b
900 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
901 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
904 CALL timeset(routinen, handle)
906 n_matrices =
SIZE(trace)
907 cpassert(
SIZE(matrix_a) == n_matrices)
909 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
910 use_sp_b = matrix_b%use_sp
913 ldata_b_sp => matrix_b%local_data_sp(1:nrows_local, 1:ncols_local)
915 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
923 DO imatrix = 1, n_matrices
925 use_sp_a = matrix_a(imatrix) %matrix%use_sp
928 IF (use_sp_a .AND. use_sp_b)
THEN
929 ldata_a_sp => matrix_a(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
931 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
932 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
935 cpabort(
"Matrices A and B are of different types")
940 group = matrix_b%matrix_struct%para_env
941 CALL group%sum(trace)
943 CALL timestop(handle)
944 END SUBROUTINE cp_fm_trace_a1b0t1_p
964 SUBROUTINE cp_fm_trace_a1b1t1_aa (matrix_a, matrix_b, trace, accurate)
965 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
966 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
967 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
968 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
970 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_aa'
972 INTEGER :: handle, imatrix, n_matrices, &
973 ncols_local, nrows_local
974 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
975 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
976 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
979 CALL timeset(routinen, handle)
981 n_matrices =
SIZE(trace)
982 cpassert(
SIZE(matrix_a) == n_matrices)
983 cpassert(
SIZE(matrix_b) == n_matrices)
985 use_accurate_sum = .true.
986 IF (
PRESENT(accurate)) use_accurate_sum = accurate
992 DO imatrix = 1, n_matrices
993 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
995 use_sp_a = matrix_a(imatrix) %use_sp
996 use_sp_b = matrix_b(imatrix) %use_sp
999 IF (use_sp_a .AND. use_sp_b)
THEN
1000 ldata_a_sp => matrix_a(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1001 ldata_b_sp => matrix_b(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1002 IF (use_accurate_sum)
THEN
1005 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1007 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1008 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1009 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1010 IF (use_accurate_sum)
THEN
1013 trace(imatrix) = sum(ldata_a*ldata_b)
1016 cpabort(
"Matrices A and B are of different types")
1021 group = matrix_a(1) %matrix_struct%para_env
1022 CALL group%sum(trace)
1024 CALL timestop(handle)
1025 END SUBROUTINE cp_fm_trace_a1b1t1_aa
1026 SUBROUTINE cp_fm_trace_a1b1t1_ap (matrix_a, matrix_b, trace, accurate)
1027 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
1028 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
1029 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
1030 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1032 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_ap'
1034 INTEGER :: handle, imatrix, n_matrices, &
1035 ncols_local, nrows_local
1036 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1037 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1038 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1041 CALL timeset(routinen, handle)
1043 n_matrices =
SIZE(trace)
1044 cpassert(
SIZE(matrix_a) == n_matrices)
1045 cpassert(
SIZE(matrix_b) == n_matrices)
1047 use_accurate_sum = .true.
1048 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1054 DO imatrix = 1, n_matrices
1055 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
1057 use_sp_a = matrix_a(imatrix) %use_sp
1058 use_sp_b = matrix_b(imatrix) %matrix%use_sp
1061 IF (use_sp_a .AND. use_sp_b)
THEN
1062 ldata_a_sp => matrix_a(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1063 ldata_b_sp => matrix_b(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1064 IF (use_accurate_sum)
THEN
1067 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1069 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1070 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1071 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1072 IF (use_accurate_sum)
THEN
1075 trace(imatrix) = sum(ldata_a*ldata_b)
1078 cpabort(
"Matrices A and B are of different types")
1083 group = matrix_a(1) %matrix_struct%para_env
1084 CALL group%sum(trace)
1086 CALL timestop(handle)
1087 END SUBROUTINE cp_fm_trace_a1b1t1_ap
1088 SUBROUTINE cp_fm_trace_a1b1t1_pa (matrix_a, matrix_b, trace, accurate)
1089 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
1090 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
1091 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
1092 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1094 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_pa'
1096 INTEGER :: handle, imatrix, n_matrices, &
1097 ncols_local, nrows_local
1098 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1099 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1100 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1103 CALL timeset(routinen, handle)
1105 n_matrices =
SIZE(trace)
1106 cpassert(
SIZE(matrix_a) == n_matrices)
1107 cpassert(
SIZE(matrix_b) == n_matrices)
1109 use_accurate_sum = .true.
1110 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1116 DO imatrix = 1, n_matrices
1117 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1119 use_sp_a = matrix_a(imatrix) %matrix%use_sp
1120 use_sp_b = matrix_b(imatrix) %use_sp
1123 IF (use_sp_a .AND. use_sp_b)
THEN
1124 ldata_a_sp => matrix_a(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1125 ldata_b_sp => matrix_b(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1126 IF (use_accurate_sum)
THEN
1129 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1131 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1132 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1133 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1134 IF (use_accurate_sum)
THEN
1137 trace(imatrix) = sum(ldata_a*ldata_b)
1140 cpabort(
"Matrices A and B are of different types")
1145 group = matrix_a(1) %matrix%matrix_struct%para_env
1146 CALL group%sum(trace)
1148 CALL timestop(handle)
1149 END SUBROUTINE cp_fm_trace_a1b1t1_pa
1150 SUBROUTINE cp_fm_trace_a1b1t1_pp (matrix_a, matrix_b, trace, accurate)
1151 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_a
1152 TYPE(
cp_fm_p_type),
DIMENSION(:),
INTENT(IN) :: matrix_b
1153 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: trace
1154 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1156 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_trace_a1b1t1_pp'
1158 INTEGER :: handle, imatrix, n_matrices, &
1159 ncols_local, nrows_local
1160 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1161 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1162 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1165 CALL timeset(routinen, handle)
1167 n_matrices =
SIZE(trace)
1168 cpassert(
SIZE(matrix_a) == n_matrices)
1169 cpassert(
SIZE(matrix_b) == n_matrices)
1171 use_accurate_sum = .true.
1172 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1178 DO imatrix = 1, n_matrices
1179 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1181 use_sp_a = matrix_a(imatrix) %matrix%use_sp
1182 use_sp_b = matrix_b(imatrix) %matrix%use_sp
1185 IF (use_sp_a .AND. use_sp_b)
THEN
1186 ldata_a_sp => matrix_a(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1187 ldata_b_sp => matrix_b(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1188 IF (use_accurate_sum)
THEN
1191 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1193 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1194 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1195 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1196 IF (use_accurate_sum)
THEN
1199 trace(imatrix) = sum(ldata_a*ldata_b)
1202 cpabort(
"Matrices A and B are of different types")
1207 group = matrix_a(1) %matrix%matrix_struct%para_env
1208 CALL group%sum(trace)
1210 CALL timestop(handle)
1211 END SUBROUTINE cp_fm_trace_a1b1t1_pp
1220 SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa (matrix_a, matrix_b, trace, accurate)
1221 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1222 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1223 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1224 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1226 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_aa'
1228 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1230 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1231 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1233 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1234 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1237 CALL timeset(routinen, handle)
1239 nz =
SIZE(matrix_a, 1)
1240 cpassert(
SIZE(matrix_b, 1) == nz)
1242 na =
SIZE(matrix_a, 2)
1243 nb =
SIZE(matrix_b, 2)
1244 cpassert(
SIZE(trace, 1) == na)
1245 cpassert(
SIZE(trace, 2) == nb)
1247 use_accurate_sum = .true.
1248 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1253 na8 = int(na, kind=
int_8)
1259 DO itrace = 1, ntraces
1260 ib8 = (itrace - 1)/na8
1261 ia = int(itrace - ib8*na8)
1266 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1267 use_sp_a = matrix_a(iz, ia) %use_sp
1268 use_sp_b = matrix_b(iz, ib) %use_sp
1271 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1272 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1273 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1274 IF (use_accurate_sum)
THEN
1277 t = t + sum(ldata_a*ldata_b)
1279 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1280 ldata_a_sp => matrix_a(iz, ia) %local_data_sp(1:nrows_local, 1:ncols_local)
1281 ldata_b_sp => matrix_b(iz, ib) %local_data_sp(1:nrows_local, 1:ncols_local)
1282 IF (use_accurate_sum)
THEN
1285 t = t + sum(ldata_a_sp*ldata_b_sp)
1288 cpabort(
"Matrices A and B are of different types")
1295 group = matrix_a(1, 1) %matrix_struct%para_env
1296 CALL group%sum(trace)
1298 CALL timestop(handle)
1299 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa
1300 SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap (matrix_a, matrix_b, trace, accurate)
1301 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1302 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1303 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1304 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1306 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_ap'
1308 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1310 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1311 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1313 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1314 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1317 CALL timeset(routinen, handle)
1319 nz =
SIZE(matrix_a, 1)
1320 cpassert(
SIZE(matrix_b, 1) == nz)
1322 na =
SIZE(matrix_a, 2)
1323 nb =
SIZE(matrix_b, 2)
1324 cpassert(
SIZE(trace, 1) == na)
1325 cpassert(
SIZE(trace, 2) == nb)
1327 use_accurate_sum = .true.
1328 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1333 na8 = int(na, kind=
int_8)
1339 DO itrace = 1, ntraces
1340 ib8 = (itrace - 1)/na8
1341 ia = int(itrace - ib8*na8)
1346 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1347 use_sp_a = matrix_a(iz, ia) %use_sp
1348 use_sp_b = matrix_b(iz, ib) %matrix%use_sp
1351 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1352 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1353 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1354 IF (use_accurate_sum)
THEN
1357 t = t + sum(ldata_a*ldata_b)
1359 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1360 ldata_a_sp => matrix_a(iz, ia) %local_data_sp(1:nrows_local, 1:ncols_local)
1361 ldata_b_sp => matrix_b(iz, ib) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1362 IF (use_accurate_sum)
THEN
1365 t = t + sum(ldata_a_sp*ldata_b_sp)
1368 cpabort(
"Matrices A and B are of different types")
1375 group = matrix_a(1, 1) %matrix_struct%para_env
1376 CALL group%sum(trace)
1378 CALL timestop(handle)
1379 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap
1380 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa (matrix_a, matrix_b, trace, accurate)
1381 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1382 TYPE(
cp_fm_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1383 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1384 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1386 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_pa'
1388 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1390 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1391 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1393 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1394 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1397 CALL timeset(routinen, handle)
1399 nz =
SIZE(matrix_a, 1)
1400 cpassert(
SIZE(matrix_b, 1) == nz)
1402 na =
SIZE(matrix_a, 2)
1403 nb =
SIZE(matrix_b, 2)
1404 cpassert(
SIZE(trace, 1) == na)
1405 cpassert(
SIZE(trace, 2) == nb)
1407 use_accurate_sum = .true.
1408 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1413 na8 = int(na, kind=
int_8)
1419 DO itrace = 1, ntraces
1420 ib8 = (itrace - 1)/na8
1421 ia = int(itrace - ib8*na8)
1426 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1427 use_sp_a = matrix_a(iz, ia) %matrix%use_sp
1428 use_sp_b = matrix_b(iz, ib) %use_sp
1431 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1432 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1433 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1434 IF (use_accurate_sum)
THEN
1437 t = t + sum(ldata_a*ldata_b)
1439 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1440 ldata_a_sp => matrix_a(iz, ia) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1441 ldata_b_sp => matrix_b(iz, ib) %local_data_sp(1:nrows_local, 1:ncols_local)
1442 IF (use_accurate_sum)
THEN
1445 t = t + sum(ldata_a_sp*ldata_b_sp)
1448 cpabort(
"Matrices A and B are of different types")
1455 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1456 CALL group%sum(trace)
1458 CALL timestop(handle)
1459 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa
1460 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp (matrix_a, matrix_b, trace, accurate)
1461 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_a
1462 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: matrix_b
1463 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: trace
1464 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1466 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_fm_contracted_trace_a2b2t2_pp'
1468 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1470 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1471 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1473 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1474 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1477 CALL timeset(routinen, handle)
1479 nz =
SIZE(matrix_a, 1)
1480 cpassert(
SIZE(matrix_b, 1) == nz)
1482 na =
SIZE(matrix_a, 2)
1483 nb =
SIZE(matrix_b, 2)
1484 cpassert(
SIZE(trace, 1) == na)
1485 cpassert(
SIZE(trace, 2) == nb)
1487 use_accurate_sum = .true.
1488 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1493 na8 = int(na, kind=
int_8)
1499 DO itrace = 1, ntraces
1500 ib8 = (itrace - 1)/na8
1501 ia = int(itrace - ib8*na8)
1506 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1507 use_sp_a = matrix_a(iz, ia) %matrix%use_sp
1508 use_sp_b = matrix_b(iz, ib) %matrix%use_sp
1511 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1512 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1513 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1514 IF (use_accurate_sum)
THEN
1517 t = t + sum(ldata_a*ldata_b)
1519 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1520 ldata_a_sp => matrix_a(iz, ia) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1521 ldata_b_sp => matrix_b(iz, ib) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1522 IF (use_accurate_sum)
THEN
1525 t = t + sum(ldata_a_sp*ldata_b_sp)
1528 cpabort(
"Matrices A and B are of different types")
1535 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1536 CALL group%sum(trace)
1538 CALL timestop(handle)
1539 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp
1575 transpose_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, &
1577 TYPE(
cp_fm_type),
INTENT(IN) :: triangular_matrix, matrix_b
1578 CHARACTER,
INTENT(IN),
OPTIONAL :: side
1579 LOGICAL,
INTENT(IN),
OPTIONAL :: transpose_tr, invert_tr
1580 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo_tr
1581 LOGICAL,
INTENT(IN),
OPTIONAL :: unit_diag_tr
1582 INTEGER,
INTENT(IN),
OPTIONAL :: n_rows, n_cols
1583 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: alpha
1585 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_triangular_multiply'
1587 CHARACTER :: side_char, transa, unit_diag, uplo
1588 INTEGER :: handle, m, n
1592 CALL timeset(routinen, handle)
1600 IF (
PRESENT(side)) side_char = side
1601 IF (
PRESENT(invert_tr)) invert = invert_tr
1602 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1603 IF (
PRESENT(unit_diag_tr))
THEN
1604 IF (unit_diag_tr)
THEN
1610 IF (
PRESENT(transpose_tr))
THEN
1611 IF (transpose_tr)
THEN
1617 IF (
PRESENT(alpha)) al = alpha
1618 IF (
PRESENT(n_rows)) m = n_rows
1619 IF (
PRESENT(n_cols)) n = n_cols
1623#if defined(__parallel)
1624 CALL pdtrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1625 triangular_matrix%local_data(1, 1), 1, 1, &
1626 triangular_matrix%matrix_struct%descriptor, &
1627 matrix_b%local_data(1, 1), 1, 1, &
1628 matrix_b%matrix_struct%descriptor(1))
1630 CALL dtrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1631 triangular_matrix%local_data(1, 1), &
1632 SIZE(triangular_matrix%local_data, 1), &
1633 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1638#if defined(__parallel)
1639 CALL pdtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1640 triangular_matrix%local_data(1, 1), 1, 1, &
1641 triangular_matrix%matrix_struct%descriptor, &
1642 matrix_b%local_data(1, 1), 1, 1, &
1643 matrix_b%matrix_struct%descriptor(1))
1645 CALL dtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1646 triangular_matrix%local_data(1, 1), &
1647 SIZE(triangular_matrix%local_data, 1), &
1648 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1653 CALL timestop(handle)
1665 REAL(kind=
dp),
INTENT(IN) :: alpha
1668 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_scale'
1670 INTEGER :: handle, size_a
1671 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1673 CALL timeset(routinen, handle)
1677 a => matrix_a%local_data
1678 size_a =
SIZE(a, 1)*
SIZE(a, 2)
1680 CALL dscal(size_a, alpha, a, 1)
1682 CALL timestop(handle)
1695 TYPE(
cp_fm_type),
INTENT(IN) :: matrix, matrixt
1697 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_transpose'
1699 INTEGER :: handle, ncol_global, &
1700 nrow_global, ncol_globalt, nrow_globalt
1701 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
1702#if defined(__parallel)
1703 INTEGER,
DIMENSION(9) :: desca, descc
1704#elif !defined(__MKL)
1708 nrow_global = matrix%matrix_struct%nrow_global
1709 ncol_global = matrix%matrix_struct%ncol_global
1710 nrow_globalt = matrixt%matrix_struct%nrow_global
1711 ncol_globalt = matrixt%matrix_struct%ncol_global
1712 cpassert(nrow_global == ncol_globalt)
1713 cpassert(nrow_globalt == ncol_global)
1715 CALL timeset(routinen, handle)
1717 a => matrix%local_data
1718 c => matrixt%local_data
1720#if defined(__parallel)
1721 desca(:) = matrix%matrix_struct%descriptor(:)
1722 descc(:) = matrixt%matrix_struct%descriptor(:)
1723 CALL pdtran(ncol_global, nrow_global, 1.0_dp, a(1, 1), 1, 1, desca, 0.0_dp, c(1, 1), 1, 1, descc)
1725 CALL mkl_domatcopy(
'C',
'T', nrow_global, ncol_global, 1.0_dp, a(1, 1), nrow_global, c(1, 1), ncol_global)
1727 DO j = 1, ncol_global
1728 DO i = 1, nrow_global
1733 CALL timestop(handle)
1749 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
1751 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_uplo_to_full'
1754 INTEGER :: handle, icol_global, irow_global, &
1755 mypcol, myprow, ncol_global, &
1756 npcol, nprow, nrow_global
1757 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1758 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
1761#if defined(__parallel)
1762 INTEGER :: icol_local, irow_local, &
1763 ncol_block, ncol_local, &
1764 nrow_block, nrow_local
1765 INTEGER,
DIMENSION(9) :: desca, descc
1766 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: c
1767 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: c_sp
1771 IF (
PRESENT(uplo)) myuplo = uplo
1773 nrow_global = matrix%matrix_struct%nrow_global
1774 ncol_global = matrix%matrix_struct%ncol_global
1775 cpassert(nrow_global == ncol_global)
1776 nrow_global = work%matrix_struct%nrow_global
1777 ncol_global = work%matrix_struct%ncol_global
1778 cpassert(nrow_global == ncol_global)
1779 cpassert(matrix%use_sp .EQV. work%use_sp)
1781 CALL timeset(routinen, handle)
1783 context => matrix%matrix_struct%context
1784 myprow = context%mepos(1)
1785 mypcol = context%mepos(2)
1786 nprow = context%num_pe(1)
1787 npcol = context%num_pe(2)
1789#if defined(__parallel)
1791 nrow_block = matrix%matrix_struct%nrow_block
1792 ncol_block = matrix%matrix_struct%ncol_block
1794 nrow_local = matrix%matrix_struct%nrow_locals(myprow)
1795 ncol_local = matrix%matrix_struct%ncol_locals(mypcol)
1797 a => work%local_data
1798 a_sp => work%local_data_sp
1799 desca(:) = work%matrix_struct%descriptor(:)
1800 c => matrix%local_data
1801 c_sp => matrix%local_data_sp
1802 descc(:) = matrix%matrix_struct%descriptor(:)
1804 DO icol_local = 1, ncol_local
1805 icol_global = matrix%matrix_struct%col_indices(icol_local)
1806 DO irow_local = 1, nrow_local
1807 irow_global = matrix%matrix_struct%row_indices(irow_local)
1808 IF (merge(irow_global > icol_global, irow_global < icol_global, (myuplo ==
"U") .OR. (myuplo ==
"u")))
THEN
1809 IF (matrix%use_sp)
THEN
1810 c_sp(irow_local, icol_local) = 0.0_sp
1812 c(irow_local, icol_local) = 0.0_dp
1814 ELSE IF (irow_global == icol_global)
THEN
1815 IF (matrix%use_sp)
THEN
1816 c_sp(irow_local, icol_local) = 0.5_sp*c_sp(irow_local, icol_local)
1818 c(irow_local, icol_local) = 0.5_dp*c(irow_local, icol_local)
1824 DO icol_local = 1, ncol_local
1825 DO irow_local = 1, nrow_local
1826 IF (matrix%use_sp)
THEN
1827 a_sp(irow_local, icol_local) = c_sp(irow_local, icol_local)
1829 a(irow_local, icol_local) = c(irow_local, icol_local)
1834 IF (matrix%use_sp)
THEN
1835 CALL pstran(nrow_global, ncol_global, 1.0_sp, a_sp(1, 1), 1, 1, desca, 1.0_sp, c_sp(1, 1), 1, 1, descc)
1837 CALL pdtran(nrow_global, ncol_global, 1.0_dp, a(1, 1), 1, 1, desca, 1.0_dp, c(1, 1), 1, 1, descc)
1842 a => matrix%local_data
1843 a_sp => matrix%local_data_sp
1845 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
1846 DO irow_global = 1, nrow_global
1847 DO icol_global = irow_global + 1, ncol_global
1848 IF (matrix%use_sp)
THEN
1849 a_sp(icol_global, irow_global) = a_sp(irow_global, icol_global)
1851 a(icol_global, irow_global) = a(irow_global, icol_global)
1856 DO icol_global = 1, ncol_global
1857 DO irow_global = icol_global + 1, nrow_global
1858 IF (matrix%use_sp)
THEN
1859 a_sp(irow_global, icol_global) = a_sp(icol_global, irow_global)
1861 a(irow_global, icol_global) = a(icol_global, irow_global)
1868 CALL timestop(handle)
1886 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: scaling
1888 INTEGER :: k, mypcol, myprow, n, ncol_global, &
1890 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1891 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
1892#if defined(__parallel)
1893 INTEGER :: icol_global, icol_local, &
1894 ipcol, iprow, irow_local
1899 myprow = matrixa%matrix_struct%context%mepos(1)
1900 mypcol = matrixa%matrix_struct%context%mepos(2)
1901 nprow = matrixa%matrix_struct%context%num_pe(1)
1902 npcol = matrixa%matrix_struct%context%num_pe(2)
1904 ncol_global = matrixa%matrix_struct%ncol_global
1906 a => matrixa%local_data
1907 a_sp => matrixa%local_data_sp
1908 IF (matrixa%use_sp)
THEN
1913 k = min(
SIZE(scaling), ncol_global)
1915#if defined(__parallel)
1917 DO icol_global = 1, k
1918 CALL infog2l(1, icol_global, matrixa%matrix_struct%descriptor, &
1919 nprow, npcol, myprow, mypcol, &
1920 irow_local, icol_local, iprow, ipcol)
1921 IF ((ipcol == mypcol))
THEN
1922 IF (matrixa%use_sp)
THEN
1923 CALL sscal(n, real(scaling(icol_global),
sp), a_sp(:, icol_local), 1)
1925 CALL dscal(n, scaling(icol_global), a(:, icol_local), 1)
1931 IF (matrixa%use_sp)
THEN
1932 CALL sscal(n, real(scaling(i),
sp), a_sp(:, i), 1)
1934 CALL dscal(n, scaling(i), a(:, i), 1)
1949 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: scaling
1951 INTEGER :: n, m, nrow_global, nrow_local, ncol_local
1952 INTEGER,
DIMENSION(:),
POINTER :: row_indices
1953 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1954 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
1955#if defined(__parallel)
1956 INTEGER :: irow_global, icol, irow
1961 CALL cp_fm_get_info(matrixa, row_indices=row_indices, nrow_global=nrow_global, &
1962 nrow_local=nrow_local, ncol_local=ncol_local)
1963 cpassert(
SIZE(scaling) == nrow_global)
1965 a => matrixa%local_data
1966 a_sp => matrixa%local_data_sp
1967 IF (matrixa%use_sp)
THEN
1975#if defined(__parallel)
1976 DO icol = 1, ncol_local
1977 IF (matrixa%use_sp)
THEN
1978 DO irow = 1, nrow_local
1979 irow_global = row_indices(irow)
1980 a(irow, icol) = real(scaling(irow_global),
dp)*a(irow, icol)
1983 DO irow = 1, nrow_local
1984 irow_global = row_indices(irow)
1985 a(irow, icol) = scaling(irow_global)*a(irow, icol)
1990 IF (matrixa%use_sp)
THEN
1992 a_sp(1:n, j) = real(scaling(1:n),
sp)*a_sp(1:n, j)
1996 a(1:n, j) = scaling(1:n)*a(1:n, j)
2020 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_inverse
2021 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: det_a
2022 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: eps_svd
2023 REAL(kind=
dp),
DIMENSION(:),
POINTER, &
2024 INTENT(INOUT),
OPTIONAL :: eigval
2027 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
2028 REAL(kind=
dp) :: determinant, my_eps_svd
2029 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2032#if defined(__parallel)
2033 TYPE(
cp_fm_type) :: u, vt, sigma, inv_sigma_ut
2035 INTEGER :: i, info, liwork, lwork, exponent_of_minus_one
2036 INTEGER,
DIMENSION(9) :: desca
2038 REAL(kind=
dp) :: alpha, beta
2039 REAL(kind=
dp),
DIMENSION(:),
POINTER ::
diag
2040 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
2043 REAL(kind=
dp) :: eps1
2047 IF (
PRESENT(eps_svd)) my_eps_svd = eps_svd
2050 matrix_struct=matrix_a%matrix_struct, &
2054 a => matrix_lu%local_data
2055 n = matrix_lu%matrix_struct%nrow_global
2056 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
2058#if defined(__parallel)
2059 IF (my_eps_svd .EQ. 0.0_dp)
THEN
2063 desca(:) = matrix_lu%matrix_struct%descriptor(:)
2064 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
2066 IF (
PRESENT(det_a) .OR.
PRESENT(eigval))
THEN
2072 exponent_of_minus_one = 0
2073 determinant = 1.0_dp
2075 determinant = determinant*
diag(i)
2076 IF (ipivot(i) .NE. i)
THEN
2077 exponent_of_minus_one = exponent_of_minus_one + 1
2080 IF (
PRESENT(eigval))
THEN
2081 cpassert(.NOT.
ASSOCIATED(eigval))
2082 ALLOCATE (eigval(n))
2087 group = matrix_lu%matrix_struct%para_env
2088 CALL group%sum(exponent_of_minus_one)
2090 determinant = determinant*(-1.0_dp)**exponent_of_minus_one
2097 CALL pdgetrs(
'N', n, n, matrix_lu%local_data, 1, 1, desca, ipivot, matrix_inverse%local_data, 1, 1, desca, info)
2101 matrix_struct=matrix_a%matrix_struct, &
2102 name=
"LEFT_SINGULAR_MATRIX")
2105 matrix_struct=matrix_a%matrix_struct, &
2106 name=
"RIGHT_SINGULAR_MATRIX")
2110 desca(:) = matrix_lu%matrix_struct%descriptor(:)
2114 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca,
diag, u%local_data, &
2115 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
2116 lwork = int(work(1))
2118 ALLOCATE (work(lwork))
2120 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca,
diag, u%local_data, &
2121 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
2124 IF (info /= 0 .AND. info /= n + 1) &
2125 cpabort(
"Singular value decomposition of matrix failed.")
2128 matrix_struct=matrix_a%matrix_struct, &
2129 name=
"SINGULAR_VALUE_MATRIX")
2131 determinant = 1.0_dp
2133 IF (
PRESENT(eigval))
THEN
2134 cpassert(.NOT.
ASSOCIATED(eigval))
2135 ALLOCATE (eigval(n))
2139 IF (
diag(i) < my_eps_svd)
THEN
2143 determinant = determinant*
diag(i)
2150 CALL cp_warn(__location__, &
2151 "Linear dependencies were detected in the SVD inversion of matrix "//trim(adjustl(matrix_a%name))// &
2152 ". At least one singular value has been quenched.")
2155 matrix_struct=matrix_a%matrix_struct, &
2156 name=
"SINGULAR_VALUE_MATRIX")
2158 CALL pdgemm(
'N',
'T', n, n, n, 1.0_dp, sigma%local_data, 1, 1, desca, &
2159 u%local_data, 1, 1, desca, 0.0_dp, inv_sigma_ut%local_data, 1, 1, desca)
2162 CALL pdgemm(
'T',
'N', n, n, n, 1.0_dp, vt%local_data, 1, 1, desca, &
2163 inv_sigma_ut%local_data, 1, 1, desca, 0.0_dp, matrix_inverse%local_data, 1, 1, desca)
2172 IF (my_eps_svd .EQ. 0.0_dp)
THEN
2174 CALL invert_matrix(matrix_a%local_data, matrix_inverse%local_data, &
2176 CALL cp_fm_lu_decompose(matrix_lu, determinant, correct_sign=sign)
2177 IF (
PRESENT(eigval)) &
2178 CALL cp_abort(__location__, &
2179 "NYI. Eigenvalues not available for return without SCALAPACK.")
2182 determinant, eigval)
2187 IF (
PRESENT(det_a)) det_a = determinant
2199 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo_tr
2201 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_triangular_invert'
2203 CHARACTER :: unit_diag, uplo
2204 INTEGER :: handle, info, ncol_global
2205 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2206#if defined(__parallel)
2207 INTEGER,
DIMENSION(9) :: desca
2210 CALL timeset(routinen, handle)
2214 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
2216 ncol_global = matrix_a%matrix_struct%ncol_global
2218 a => matrix_a%local_data
2220#if defined(__parallel)
2221 desca(:) = matrix_a%matrix_struct%descriptor(:)
2223 CALL pdtrtri(uplo, unit_diag, ncol_global, a(1, 1), 1, 1, desca, info)
2226 CALL dtrtri(uplo, unit_diag, ncol_global, a(1, 1), ncol_global, info)
2229 CALL timestop(handle)
2245 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, matrix_r
2246 INTEGER,
INTENT(IN),
OPTIONAL :: nrow_fact, ncol_fact, &
2247 first_row, first_col
2248 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
2250 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_qr_factorization'
2253 INTEGER :: handle, i, icol, info, irow, &
2254 j, lda, lwork, ncol, &
2256 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: tau, work
2257 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: r_mat
2258 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2259#if defined(__parallel)
2260 INTEGER,
DIMENSION(9) :: desca
2263 CALL timeset(routinen, handle)
2266 IF (
PRESENT(uplo)) myuplo = uplo
2268 ncol = matrix_a%matrix_struct%ncol_global
2269 nrow = matrix_a%matrix_struct%nrow_global
2272 a => matrix_a%local_data
2274 IF (
PRESENT(nrow_fact)) nrow = nrow_fact
2275 IF (
PRESENT(ncol_fact)) ncol = ncol_fact
2277 IF (
PRESENT(first_row)) irow = first_row
2279 IF (
PRESENT(first_col)) icol = first_col
2281 cpassert(nrow >= ncol)
2283 ALLOCATE (tau(ndim))
2285#if defined(__parallel)
2287 desca(:) = matrix_a%matrix_struct%descriptor(:)
2290 ALLOCATE (work(2*ndim))
2291 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2292 lwork = int(work(1))
2294 ALLOCATE (work(lwork))
2295 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2299 ALLOCATE (work(2*ndim))
2300 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2301 lwork = int(work(1))
2303 ALLOCATE (work(lwork))
2304 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2308 ALLOCATE (r_mat(ncol, ncol))
2310 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
2313 r_mat(j, i) = 0.0_dp
2319 r_mat(i, j) = 0.0_dp
2325 DEALLOCATE (tau, work, r_mat)
2327 CALL timestop(handle)
2338 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_a, general_a
2340 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_solve'
2342 INTEGER :: handle, info, n, nrhs
2343 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
2344 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, a_general
2345#if defined(__parallel)
2346 INTEGER,
DIMENSION(9) :: desca, descb
2351 CALL timeset(routinen, handle)
2353 a => matrix_a%local_data
2354 a_general => general_a%local_data
2355 n = matrix_a%matrix_struct%nrow_global
2356 nrhs = general_a%matrix_struct%ncol_global
2357 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
2359#if defined(__parallel)
2360 desca(:) = matrix_a%matrix_struct%descriptor(:)
2361 descb(:) = general_a%matrix_struct%descriptor(:)
2362 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
2363 CALL pdgetrs(
"N", n, nrhs, a, 1, 1, desca, ipivot, a_general, &
2368 ldb =
SIZE(a_general, 1)
2369 CALL dgetrf(n, n, a, lda, ipivot, info)
2370 CALL dgetrs(
"N", n, nrhs, a, lda, ipivot, a_general, ldb, info)
2376 CALL timestop(handle)
2407 SUBROUTINE cp_complex_fm_gemm(transa, transb, m, n, k, alpha, A_re, A_im, B_re, B_im, beta, &
2408 C_re, C_im, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, &
2410 CHARACTER(LEN=1),
INTENT(IN) :: transa, transb
2411 INTEGER,
INTENT(IN) :: m, n, k
2412 REAL(kind=
dp),
INTENT(IN) :: alpha
2413 TYPE(
cp_fm_type),
INTENT(IN) :: a_re, a_im, b_re, b_im
2414 REAL(kind=
dp),
INTENT(IN) :: beta
2416 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, b_first_col, &
2417 b_first_row, c_first_col, c_first_row
2419 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_complex_fm_gemm'
2423 CALL timeset(routinen, handle)
2425 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_re, b_re, beta, c_re, &
2426 a_first_col=a_first_col, &
2427 a_first_row=a_first_row, &
2428 b_first_col=b_first_col, &
2429 b_first_row=b_first_row, &
2430 c_first_col=c_first_col, &
2431 c_first_row=c_first_row)
2432 CALL cp_fm_gemm(transa, transb, m, n, k, -alpha, a_im, b_im, 1.0_dp, c_re, &
2433 a_first_col=a_first_col, &
2434 a_first_row=a_first_row, &
2435 b_first_col=b_first_col, &
2436 b_first_row=b_first_row, &
2437 c_first_col=c_first_col, &
2438 c_first_row=c_first_row)
2439 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_re, b_im, beta, c_im, &
2440 a_first_col=a_first_col, &
2441 a_first_row=a_first_row, &
2442 b_first_col=b_first_col, &
2443 b_first_row=b_first_row, &
2444 c_first_col=c_first_col, &
2445 c_first_row=c_first_row)
2446 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_im, b_re, 1.0_dp, c_im, &
2447 a_first_col=a_first_col, &
2448 a_first_row=a_first_row, &
2449 b_first_col=b_first_col, &
2450 b_first_row=b_first_row, &
2451 c_first_col=c_first_col, &
2452 c_first_row=c_first_row)
2454 CALL timestop(handle)
2465 SUBROUTINE cp_fm_lu_invert(matrix, info_out)
2467 INTEGER,
INTENT(OUT),
OPTIONAL :: info_out
2469 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_lu_invert'
2471 INTEGER :: nrows_global, handle, info, lwork
2472 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ipivot
2473 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: mat
2474 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: mat_sp
2475 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2476 REAL(kind=
sp),
DIMENSION(:),
ALLOCATABLE :: work_sp
2477#if defined(__parallel)
2479 INTEGER,
DIMENSION(9) :: desca
2480 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
2485 CALL timeset(routinen, handle)
2487 mat => matrix%local_data
2488 mat_sp => matrix%local_data_sp
2489 nrows_global = matrix%matrix_struct%nrow_global
2490 cpassert(nrows_global .EQ. matrix%matrix_struct%ncol_global)
2491 ALLOCATE (ipivot(nrows_global))
2493#if defined(__parallel)
2494 desca = matrix%matrix_struct%descriptor
2495 IF (matrix%use_sp)
THEN
2496 CALL psgetrf(nrows_global, nrows_global, &
2497 mat_sp, 1, 1, desca, ipivot, info)
2499 CALL pdgetrf(nrows_global, nrows_global, &
2500 mat, 1, 1, desca, ipivot, info)
2504 IF (matrix%use_sp)
THEN
2505 CALL sgetrf(nrows_global, nrows_global, &
2506 mat_sp, lda, ipivot, info)
2508 CALL dgetrf(nrows_global, nrows_global, &
2509 mat, lda, ipivot, info)
2513 CALL cp_abort(__location__,
"LU decomposition has failed")
2516 IF (matrix%use_sp)
THEN
2519 ALLOCATE (work_sp(1))
2521#if defined(__parallel)
2523 IF (matrix%use_sp)
THEN
2524 CALL psgetri(nrows_global, mat_sp, 1, 1, desca, &
2525 ipivot, work_sp, -1, iwork, -1, info)
2526 lwork = int(work_sp(1))
2527 DEALLOCATE (work_sp)
2528 ALLOCATE (work_sp(lwork))
2530 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2531 ipivot, work, -1, iwork, -1, info)
2532 lwork = int(work(1))
2534 ALLOCATE (work(lwork))
2536 liwork = int(iwork(1))
2538 ALLOCATE (iwork(liwork))
2539 IF (matrix%use_sp)
THEN
2540 CALL psgetri(nrows_global, mat_sp, 1, 1, desca, &
2541 ipivot, work_sp, lwork, iwork, liwork, info)
2543 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2544 ipivot, work, lwork, iwork, liwork, info)
2548 IF (matrix%use_sp)
THEN
2549 CALL sgetri(nrows_global, mat_sp, lda, &
2550 ipivot, work_sp, -1, info)
2551 lwork = int(work_sp(1))
2552 DEALLOCATE (work_sp)
2553 ALLOCATE (work_sp(lwork))
2554 CALL sgetri(nrows_global, mat_sp, lda, &
2555 ipivot, work_sp, lwork, info)
2557 CALL dgetri(nrows_global, mat, lda, &
2558 ipivot, work, -1, info)
2559 lwork = int(work(1))
2561 ALLOCATE (work(lwork))
2562 CALL dgetri(nrows_global, mat, lda, &
2563 ipivot, work, lwork, info)
2566 IF (matrix%use_sp)
THEN
2567 DEALLOCATE (work_sp)
2573 IF (
PRESENT(info_out))
THEN
2577 CALL cp_abort(__location__,
"LU inversion has failed")
2580 CALL timestop(handle)
2582 END SUBROUTINE cp_fm_lu_invert
2596 CHARACTER,
INTENT(IN) :: mode
2597 REAL(kind=
dp) :: res
2599 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_norm'
2601 INTEGER :: nrows, ncols, handle, lwork, nrows_local, ncols_local
2602 REAL(kind=
sp) :: res_sp
2603 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2604 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: aa_sp
2605 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2606 REAL(kind=
sp),
DIMENSION(:),
ALLOCATABLE :: work_sp
2607#if defined(__parallel)
2608 INTEGER,
DIMENSION(9) :: desca
2613 CALL timeset(routinen, handle)
2616 nrow_global=nrows, &
2617 ncol_global=ncols, &
2618 nrow_local=nrows_local, &
2619 ncol_local=ncols_local)
2620 aa => matrix%local_data
2621 aa_sp => matrix%local_data_sp
2623#if defined(__parallel)
2624 desca = matrix%matrix_struct%descriptor
2628 CASE (
'1',
'O',
'o')
2632 CASE (
'F',
'f',
'E',
'e')
2635 cpabort(
"mode input is not valid")
2637 IF (matrix%use_sp)
THEN
2638 ALLOCATE (work_sp(lwork))
2639 res_sp = pslange(mode, nrows, ncols, aa_sp, 1, 1, desca, work_sp)
2640 DEALLOCATE (work_sp)
2641 res = real(res_sp, kind=
dp)
2643 ALLOCATE (work(lwork))
2644 res = pdlange(mode, nrows, ncols, aa, 1, 1, desca, work)
2651 CASE (
'1',
'O',
'o')
2655 CASE (
'F',
'f',
'E',
'e')
2658 cpabort(
"mode input is not valid")
2660 IF (matrix%use_sp)
THEN
2661 ALLOCATE (work_sp(lwork))
2662 lda =
SIZE(aa_sp, 1)
2663 res_sp = slange(mode, nrows, ncols, aa_sp, lda, work_sp)
2664 DEALLOCATE (work_sp)
2665 res = real(res_sp, kind=
dp)
2667 ALLOCATE (work(lwork))
2669 res = dlange(mode, nrows, ncols, aa, lda, work)
2674 CALL timestop(handle)
2684 FUNCTION cp_fm_latra(matrix)
RESULT(res)
2686 REAL(kind=
dp) :: res
2688 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_latra'
2690 INTEGER :: nrows, ncols, handle
2691 REAL(kind=
sp) :: res_sp
2692 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2693 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: aa_sp
2694#if defined(__parallel)
2695 INTEGER,
DIMENSION(9) :: desca
2700 CALL timeset(routinen, handle)
2702 nrows = matrix%matrix_struct%nrow_global
2703 ncols = matrix%matrix_struct%ncol_global
2704 cpassert(nrows .EQ. ncols)
2705 aa => matrix%local_data
2706 aa_sp => matrix%local_data_sp
2708#if defined(__parallel)
2709 desca = matrix%matrix_struct%descriptor
2710 IF (matrix%use_sp)
THEN
2711 res_sp = pslatra(nrows, aa_sp, 1, 1, desca)
2712 res = real(res_sp, kind=
dp)
2714 res = pdlatra(nrows, aa, 1, 1, desca)
2717 IF (matrix%use_sp)
THEN
2720 res_sp = res_sp + aa_sp(ii, ii)
2722 res = real(res_sp, kind=
dp)
2726 res = res + aa(ii, ii)
2731 CALL timestop(handle)
2733 END FUNCTION cp_fm_latra
2749 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2750 INTEGER,
INTENT(IN) :: nrow, ncol, first_row, first_col
2752 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdgeqpf'
2755 INTEGER :: info, lwork
2756 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
2757 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2758 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2759#if defined(__parallel)
2760 INTEGER,
DIMENSION(9) :: descc
2765 CALL timeset(routinen, handle)
2767 a => matrix%local_data
2769 ALLOCATE (work(2*nrow))
2770 ALLOCATE (ipiv(ncol))
2773#if defined(__parallel)
2774 descc(:) = matrix%matrix_struct%descriptor(:)
2776 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2777 lwork = int(work(1))
2779 ALLOCATE (work(lwork))
2784 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2786 cpassert(first_row == 1 .AND. first_col == 1)
2788 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2789 lwork = int(work(1))
2791 ALLOCATE (work(lwork))
2794 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2801 CALL timestop(handle)
2821 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2822 INTEGER,
INTENT(IN) :: nrow, first_row, first_col
2824 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdorgqr'
2827 INTEGER :: info, lwork
2828 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2829 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2830#if defined(__parallel)
2831 INTEGER,
DIMENSION(9) :: descc
2836 CALL timeset(routinen, handle)
2838 a => matrix%local_data
2840 ALLOCATE (work(2*nrow))
2843#if defined(__parallel)
2844 descc(:) = matrix%matrix_struct%descriptor(:)
2846 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2848 lwork = int(work(1))
2850 ALLOCATE (work(lwork))
2853 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2855 cpassert(first_row == 1 .AND. first_col == 1)
2857 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2858 lwork = int(work(1))
2860 ALLOCATE (work(lwork))
2861 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2866 CALL timestop(handle)
2880 INTEGER,
INTENT(IN) :: irow, jrow
2881 REAL(
dp),
INTENT(IN) :: cs, sn
2883 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_rows'
2884 INTEGER :: handle, nrow, ncol
2886#if defined(__parallel)
2887 INTEGER :: info, lwork
2888 INTEGER,
DIMENSION(9) :: desc
2889 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2892 CALL timeset(routinen, handle)
2895#if defined(__parallel)
2897 ALLOCATE (work(lwork))
2898 desc(:) = matrix%matrix_struct%descriptor(:)
2900 matrix%local_data(1, 1), irow, 1, desc, ncol, &
2901 matrix%local_data(1, 1), jrow, 1, desc, ncol, &
2902 cs, sn, work, lwork, info)
2906 CALL drot(ncol, matrix%local_data(irow, 1), ncol, matrix%local_data(jrow, 1), ncol, cs, sn)
2909 CALL timestop(handle)
2922 INTEGER,
INTENT(IN) :: icol, jcol
2923 REAL(
dp),
INTENT(IN) :: cs, sn
2925 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_cols'
2926 INTEGER :: handle, nrow, ncol
2928#if defined(__parallel)
2929 INTEGER :: info, lwork
2930 INTEGER,
DIMENSION(9) :: desc
2931 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2934 CALL timeset(routinen, handle)
2937#if defined(__parallel)
2939 ALLOCATE (work(lwork))
2940 desc(:) = matrix%matrix_struct%descriptor(:)
2942 matrix%local_data(1, 1), 1, icol, desc, 1, &
2943 matrix%local_data(1, 1), 1, jcol, desc, 1, &
2944 cs, sn, work, lwork, info)
2948 CALL drot(nrow, matrix%local_data(1, icol), 1, matrix%local_data(1, jcol), 1, cs, sn)
2951 CALL timestop(handle)
2969 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: b
2970 INTEGER,
INTENT(IN),
OPTIONAL :: nrows, ncols, start_row, start_col
2971 LOGICAL,
INTENT(IN),
OPTIONAL :: do_norm, do_print
2973 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_Gram_Schmidt_orthonorm'
2975 INTEGER :: end_col_global, end_col_local, end_row_global, end_row_local, handle, i, j, &
2976 j_col, ncol_global, ncol_local, nrow_global, nrow_local, start_col_global, &
2977 start_col_local, start_row_global, start_row_local, this_col, unit_nr
2978 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2979 LOGICAL :: my_do_norm, my_do_print
2980 REAL(kind=
dp) :: norm
2981 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2983 CALL timeset(routinen, handle)
2986 IF (
PRESENT(do_norm)) my_do_norm = do_norm
2988 my_do_print = .false.
2989 IF (
PRESENT(do_print) .AND. (my_do_norm)) my_do_print = do_print
2992 IF (my_do_print)
THEN
2994 IF (unit_nr < 1) my_do_print = .false.
2997 IF (
SIZE(b) /= 0)
THEN
2998 IF (
PRESENT(nrows))
THEN
3001 nrow_global =
SIZE(b, 1)
3004 IF (
PRESENT(ncols))
THEN
3007 ncol_global =
SIZE(b, 2)
3010 IF (
PRESENT(start_row))
THEN
3011 start_row_global = start_row
3013 start_row_global = 1
3016 IF (
PRESENT(start_col))
THEN
3017 start_col_global = start_col
3019 start_col_global = 1
3022 end_row_global = start_row_global + nrow_global - 1
3023 end_col_global = start_col_global + ncol_global - 1
3026 nrow_global=nrow_global, ncol_global=ncol_global, &
3027 nrow_local=nrow_local, ncol_local=ncol_local, &
3028 row_indices=row_indices, col_indices=col_indices)
3029 IF (end_row_global > nrow_global)
THEN
3030 end_row_global = nrow_global
3032 IF (end_col_global > ncol_global)
THEN
3033 end_col_global = ncol_global
3040 DO start_row_local = 1, nrow_local
3041 IF (row_indices(start_row_local) >= start_row_global)
EXIT
3044 DO end_row_local = start_row_local, nrow_local
3045 IF (row_indices(end_row_local) > end_row_global)
EXIT
3047 end_row_local = end_row_local - 1
3049 DO start_col_local = 1, ncol_local
3050 IF (col_indices(start_col_local) >= start_col_global)
EXIT
3053 DO end_col_local = start_col_local, ncol_local
3054 IF (col_indices(end_col_local) > end_col_global)
EXIT
3056 end_col_local = end_col_local - 1
3058 a => matrix_a%local_data
3060 this_col = col_indices(start_col_local) - start_col_global + 1
3062 b(:, this_col) = a(:, start_col_local)
3064 IF (my_do_norm)
THEN
3066 b(:, this_col) = b(:, this_col)/norm
3067 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
3070 DO i = start_col_local + 1, end_col_local
3071 this_col = col_indices(i) - start_col_global + 1
3072 b(:, this_col) = a(:, i)
3073 DO j = start_col_local, i - 1
3074 j_col = col_indices(j) - start_col_global + 1
3075 b(:, this_col) = b(:, this_col) - &
3080 IF (my_do_norm)
THEN
3082 b(:, this_col) = b(:, this_col)/norm
3083 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
3087 CALL matrix_a%matrix_struct%para_env%sum(b)
3090 CALL timestop(handle)
3102 INTEGER,
INTENT(IN) :: n
3103 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
3107 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
3108 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
3109#if defined(__parallel)
3110 INTEGER,
DIMENSION(9) :: desca
3114 IF (
PRESENT(uplo)) myuplo = uplo
3116 a => fm_matrix%local_data
3117 a_sp => fm_matrix%local_data_sp
3118#if defined(__parallel)
3119 desca(:) = fm_matrix%matrix_struct%descriptor(:)
3120 IF (fm_matrix%use_sp)
THEN
3121 CALL pspotrf(myuplo, n, a_sp(1, 1), 1, 1, desca, info)
3123 CALL pdpotrf(myuplo, n, a(1, 1), 1, 1, desca, info)
3126 IF (fm_matrix%use_sp)
THEN
3127 CALL spotrf(myuplo, n, a_sp(1, 1),
SIZE(a_sp, 1), info)
3129 CALL dpotrf(myuplo, n, a(1, 1),
SIZE(a, 1), info)
3133 cpabort(
"Cholesky decomposition failed. Matrix ill-conditioned?")
3145 INTEGER,
INTENT(IN) :: n
3146 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
3149 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
3150 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
3152#if defined(__parallel)
3153 INTEGER,
DIMENSION(9) :: desca
3157 IF (
PRESENT(uplo)) myuplo = uplo
3159 a => fm_matrix%local_data
3160 a_sp => fm_matrix%local_data_sp
3161#if defined(__parallel)
3162 desca(:) = fm_matrix%matrix_struct%descriptor(:)
3163 IF (fm_matrix%use_sp)
THEN
3164 CALL pspotri(myuplo, n, a_sp(1, 1), 1, 1, desca, info)
3166 CALL pdpotri(myuplo, n, a(1, 1), 1, 1, desca, info)
3169 IF (fm_matrix%use_sp)
THEN
3170 CALL spotri(myuplo, n, a_sp(1, 1),
SIZE(a_sp, 1), info)
3172 CALL dpotri(myuplo, n, a(1, 1),
SIZE(a, 1), info)
3192 INTEGER,
INTENT(IN) :: neig
3193 CHARACTER(LEN=*),
INTENT(IN) :: op
3194 CHARACTER(LEN=*),
INTENT(IN) :: pos
3195 CHARACTER(LEN=*),
INTENT(IN) :: transa
3197 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, outm
3198 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp, b_sp, outm_sp
3200 REAL(kind=
dp) :: alpha
3201#if defined(__parallel)
3203 INTEGER,
DIMENSION(9) :: desca, descb, descout
3207 a => fm_matrix%local_data
3208 b => fm_matrixb%local_data
3209 outm => fm_matrixout%local_data
3210 a_sp => fm_matrix%local_data_sp
3211 b_sp => fm_matrixb%local_data_sp
3212 outm_sp => fm_matrixout%local_data_sp
3214 n = fm_matrix%matrix_struct%nrow_global
3217#if defined(__parallel)
3218 desca(:) = fm_matrix%matrix_struct%descriptor(:)
3219 descb(:) = fm_matrixb%matrix_struct%descriptor(:)
3220 descout(:) = fm_matrixout%matrix_struct%descriptor(:)
3223 IF (fm_matrix%use_sp)
THEN
3224 CALL pscopy(n, a_sp(1, 1), 1, i, desca, 1, outm_sp(1, 1), 1, i, descout, 1)
3226 CALL pdcopy(n, a(1, 1), 1, i, desca, 1, outm(1, 1), 1, i, descout, 1)
3229 IF (op .EQ.
"SOLVE")
THEN
3230 IF (fm_matrix%use_sp)
THEN
3231 CALL pstrsm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1), 1, 1, descb, &
3232 outm_sp(1, 1), 1, 1, descout)
3234 CALL pdtrsm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1), 1, 1, descb, outm(1, 1), 1, 1, descout)
3237 IF (fm_matrix%use_sp)
THEN
3238 CALL pstrmm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1), 1, 1, descb, &
3239 outm_sp(1, 1), 1, 1, descout)
3241 CALL pdtrmm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1), 1, 1, descb, outm(1, 1), 1, 1, descout)
3246 IF (fm_matrix%use_sp)
THEN
3247 CALL scopy(neig*n, a_sp(1, 1), 1, outm_sp(1, 1), 1)
3249 CALL dcopy(neig*n, a(1, 1), 1, outm(1, 1), 1)
3251 IF (op .EQ.
"SOLVE")
THEN
3252 IF (fm_matrix%use_sp)
THEN
3253 CALL strsm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1),
SIZE(b_sp, 1), outm_sp(1, 1), n)
3255 CALL dtrsm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1),
SIZE(b, 1), outm(1, 1), n)
3258 IF (fm_matrix%use_sp)
THEN
3259 CALL strmm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1), n, outm_sp(1, 1), n)
3261 CALL dtrmm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1), n, outm(1, 1), n)
3278 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: xv
3279 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: yv
3280 REAL(kind=
dp),
OPTIONAL,
INTENT(IN) :: alpha, beta
3282 INTEGER :: na, nc, nx, ny
3283 REAL(kind=
dp) :: aval, bval
3284#if defined(__parallel)
3285 INTEGER :: nrl, ncl, ic, ir
3286 INTEGER,
DIMENSION(:),
POINTER :: rind, cind
3287 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: xvl, yvl, yvm
3290 IF (amat%use_sp)
THEN
3291 cpabort(
"cp_fm_matvec: SP option not available")
3294 IF (
PRESENT(alpha)) aval = alpha
3296 IF (
PRESENT(beta)) bval = beta
3301 IF ((nx /= ny) .OR. (nc /= nx))
THEN
3302 cpabort(
"cp_fm_matvec: incompatible dimensions")
3304#if defined(__parallel)
3306 row_indices=rind, col_indices=cind)
3307 ALLOCATE (xvl(ncl), yvl(nrl), yvm(ny))
3309 xvl(ic) = xv(cind(ic))
3311 yvl(1:nrl) = matmul(amat%local_data, xvl(1:ncl))
3314 yvm(rind(ir)) = yvl(ir)
3316 CALL amat%matrix_struct%para_env%sum(yvm)
3317 IF (bval == 0.0_dp)
THEN
3320 yv = bval*yv + aval*yvm
3323 IF (bval == 0.0_dp)
THEN
3324 yv = aval*matmul(amat%local_data, xv)
3326 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_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_cholesky_restore(fm_matrix, neig, fm_matrixb, fm_matrixout, op, pos, transa)
...
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_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
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp)
creates a new full matrix with the given structure
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
integer, parameter, public sp
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