23 USE kahan_sum,
ONLY: accurate_dot_product, &
32 #include "../base/base_uses.f90"
37 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
38 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_fm_basic_linalg'
46 cp_fm_contracted_trace, &
71 REAL(KIND=
dp),
EXTERNAL :: dlange, pdlange, pdlatra
72 REAL(KIND=
sp),
EXTERNAL :: slange, pslange, pslatra
75 MODULE PROCEDURE cp_fm_trace_a0b0t0
76 MODULE PROCEDURE cp_fm_trace_a1b0t1_a
77 MODULE PROCEDURE cp_fm_trace_a1b0t1_p
78 MODULE PROCEDURE cp_fm_trace_a1b1t1_aa
79 MODULE PROCEDURE cp_fm_trace_a1b1t1_ap
80 MODULE PROCEDURE cp_fm_trace_a1b1t1_pa
81 MODULE PROCEDURE cp_fm_trace_a1b1t1_pp
82 END INTERFACE cp_fm_trace
84 INTERFACE cp_fm_contracted_trace
85 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_aa
86 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_ap
87 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pa
88 MODULE PROCEDURE cp_fm_contracted_trace_a2b2t2_pp
89 END INTERFACE cp_fm_contracted_trace
98 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
99 REAL(kind=
dp),
INTENT(OUT) :: det_a
100 REAL(kind=
dp) :: determinant
101 TYPE(cp_fm_type) :: matrix_lu
102 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
103 INTEGER :: n, i, info, p
104 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
105 REAL(kind=
dp),
DIMENSION(:),
POINTER :: diag
107 #if defined(__SCALAPACK)
108 INTEGER,
EXTERNAL :: indxl2g
109 INTEGER :: myprow, nprow, npcol, nrow_local, nrow_block, irow_local
110 INTEGER,
DIMENSION(9) :: desca
114 matrix_struct=matrix_a%matrix_struct, &
115 name=
"A_lu"//trim(adjustl(cp_to_string(1)))//
"MATRIX")
116 CALL cp_fm_to_fm(matrix_a, matrix_lu)
118 a => matrix_lu%local_data
119 n = matrix_lu%matrix_struct%nrow_global
125 #if defined(__SCALAPACK)
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 = indxl2g(irow_local, nrow_block, myprow, matrix_lu%matrix_struct%first_p_pos(1), nprow)
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
153 CALL cp_fm_release(matrix_lu)
154 det_a = determinant*(-2*mod(p, 2) + 1.0_dp)
168 REAL(kind=
dp),
INTENT(IN) :: alpha
169 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
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)
182 IF (
PRESENT(matrix_b))
THEN
187 IF (
PRESENT(beta)) my_beta = beta
190 IF (
PRESENT(beta))
THEN
191 cpassert(
PRESENT(matrix_b))
192 IF (
ASSOCIATED(matrix_a%local_data, matrix_b%local_data))
THEN
193 cpwarn(
"Bad use of routine. Call cp_fm_scale instead")
195 CALL timestop(handle)
200 a => matrix_a%local_data
201 a_sp => matrix_a%local_data_sp
203 IF (matrix_a%use_sp)
THEN
204 size_a =
SIZE(a_sp, 1)*
SIZE(a_sp, 2)
206 size_a =
SIZE(a, 1)*
SIZE(a, 2)
209 IF (alpha /= 1.0_dp)
THEN
210 IF (matrix_a%use_sp)
THEN
211 CALL sscal(size_a, real(alpha,
sp), a_sp, 1)
213 CALL dscal(size_a, alpha, a, 1)
216 IF (my_beta .NE. 0.0_dp)
THEN
217 IF (matrix_a%matrix_struct%context /= matrix_b%matrix_struct%context) &
218 cpabort(
"matrixes must be in the same blacs context")
221 matrix_b%matrix_struct))
THEN
223 b => matrix_b%local_data
224 b_sp => matrix_b%local_data_sp
225 IF (matrix_b%use_sp)
THEN
226 size_b =
SIZE(b_sp, 1)*
SIZE(b_sp, 2)
228 size_b =
SIZE(b, 1)*
SIZE(b, 2)
230 IF (size_a /= size_b) &
231 cpabort(
"Matrixes must have same locale sizes")
233 IF (matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
234 CALL saxpy(size_a, real(my_beta,
sp), b_sp, 1, a_sp, 1)
235 ELSEIF (matrix_a%use_sp .AND. .NOT. matrix_b%use_sp)
THEN
236 CALL saxpy(size_a, real(my_beta,
sp), real(b,
sp), 1, a_sp, 1)
237 ELSEIF (.NOT. matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
238 CALL daxpy(size_a, my_beta, real(b_sp,
dp), 1, a, 1)
240 CALL daxpy(size_a, my_beta, b, 1, a, 1)
245 cpabort(
"to do (pdscal,pdcopy,pdaxpy)")
253 CALL timestop(handle)
274 REAL(kind=
dp),
INTENT(IN) :: alpha, beta
275 CHARACTER,
INTENT(IN) :: trans
276 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
278 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_geadd'
280 INTEGER :: nrow_global, ncol_global, handle
281 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa, bb
282 #if defined(__SCALAPACK)
283 INTEGER,
DIMENSION(9) :: desca, descb
288 CALL timeset(routinen, handle)
290 nrow_global = matrix_a%matrix_struct%nrow_global
291 ncol_global = matrix_a%matrix_struct%ncol_global
292 cpassert(nrow_global .EQ. matrix_b%matrix_struct%nrow_global)
293 cpassert(ncol_global .EQ. matrix_b%matrix_struct%ncol_global)
295 aa => matrix_a%local_data
296 bb => matrix_b%local_data
298 #if defined(__SCALAPACK)
299 desca = matrix_a%matrix_struct%descriptor
300 descb = matrix_b%matrix_struct%descriptor
301 CALL pdgeadd(trans, &
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)
353 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
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(__SCALAPACK)
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(__SCALAPACK)
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)
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
446 TYPE(cp_fm_type),
INTENT(IN) :: matrix_c
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(__SCALAPACK)
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
476 IF (
PRESENT(a_first_row))
THEN
481 IF (
PRESENT(a_first_col))
THEN
486 IF (
PRESENT(b_first_row))
THEN
491 IF (
PRESENT(b_first_col))
THEN
496 IF (
PRESENT(c_first_row))
THEN
501 IF (
PRESENT(c_first_col))
THEN
507 #if defined(__SCALAPACK)
509 desca(:) = matrix_a%matrix_struct%descriptor(:)
510 descb(:) = matrix_b%matrix_struct%descriptor(:)
511 descc(:) = matrix_c%matrix_struct%descriptor(:)
513 IF (matrix_a%use_sp .AND. matrix_b%use_sp .AND. matrix_c%use_sp)
THEN
515 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, &
516 descb, real(beta,
sp), c_sp(1, 1), i_c, j_c, descc)
518 ELSEIF ((.NOT. matrix_a%use_sp) .AND. (.NOT. matrix_b%use_sp) .AND. (.NOT. matrix_c%use_sp))
THEN
520 CALL pdgemm(transa, transb, m, n, k, alpha, a, i_a, j_a, desca, b, i_b, j_b, &
521 descb, beta, c, i_c, j_c, descc)
524 cpabort(
"Mixed precision gemm NYI")
528 IF (matrix_a%use_sp .AND. matrix_b%use_sp .AND. matrix_c%use_sp)
THEN
534 CALL sgemm(transa, transb, m, n, k, real(alpha,
sp), a_sp(i_a, j_a), lda, b_sp(i_b, j_b), ldb, &
535 REAL(beta,
sp), c_sp(i_c, j_c), ldc)
537 ELSEIF ((.NOT. matrix_a%use_sp) .AND. (.NOT. matrix_b%use_sp) .AND. (.NOT. matrix_c%use_sp))
THEN
543 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)
546 cpabort(
"Mixed precision gemm NYI")
550 CALL timestop(handle)
575 SUBROUTINE cp_fm_symm(side, uplo, m, n, alpha, matrix_a, matrix_b, beta, matrix_c)
577 CHARACTER(LEN=1),
INTENT(IN) :: side, uplo
578 INTEGER,
INTENT(IN) :: m, n
579 REAL(kind=
dp),
INTENT(IN) :: alpha
580 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
581 REAL(kind=
dp),
INTENT(IN) :: beta
582 TYPE(cp_fm_type),
INTENT(IN) :: matrix_c
584 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_symm'
587 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
588 #if defined(__SCALAPACK)
589 INTEGER,
DIMENSION(9) :: desca, descb, descc
591 INTEGER :: lda, ldb, ldc
594 CALL timeset(routinen, handle)
596 a => matrix_a%local_data
597 b => matrix_b%local_data
598 c => matrix_c%local_data
600 #if defined(__SCALAPACK)
602 desca(:) = matrix_a%matrix_struct%descriptor(:)
603 descb(:) = matrix_b%matrix_struct%descriptor(:)
604 descc(:) = matrix_c%matrix_struct%descriptor(:)
606 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)
610 lda = matrix_a%matrix_struct%local_leading_dimension
611 ldb = matrix_b%matrix_struct%local_leading_dimension
612 ldc = matrix_c%matrix_struct%local_leading_dimension
614 CALL dsymm(side, uplo, m, n, alpha, a(1, 1), lda, b(1, 1), ldb, beta, c(1, 1), ldc)
617 CALL timestop(handle)
629 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
630 REAL(kind=
dp) :: norm
632 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_frobenius_norm'
634 INTEGER :: handle, size_a
635 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
636 REAL(kind=
dp),
EXTERNAL :: ddot
637 #if defined(__SCALAPACK)
638 TYPE(mp_comm_type) :: group
641 CALL timeset(routinen, handle)
644 a => matrix_a%local_data
645 size_a =
SIZE(a, 1)*
SIZE(a, 2)
646 norm = ddot(size_a, a(1, 1), 1, a(1, 1), 1)
647 #if defined(__SCALAPACK)
648 group = matrix_a%matrix_struct%para_env
653 CALL timestop(handle)
674 SUBROUTINE cp_fm_syrk(uplo, trans, k, alpha, matrix_a, ia, ja, beta, matrix_c)
675 CHARACTER(LEN=1),
INTENT(IN) :: uplo, trans
676 INTEGER,
INTENT(IN) :: k
677 REAL(kind=
dp),
INTENT(IN) :: alpha
678 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
679 INTEGER,
INTENT(IN) :: ia, ja
680 REAL(kind=
dp),
INTENT(IN) :: beta
681 TYPE(cp_fm_type),
INTENT(IN) :: matrix_c
683 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_syrk'
686 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
687 #if defined(__SCALAPACK)
688 INTEGER,
DIMENSION(9) :: desca, descc
693 CALL timeset(routinen, handle)
695 n = matrix_c%matrix_struct%nrow_global
697 a => matrix_a%local_data
698 c => matrix_c%local_data
700 #if defined(__SCALAPACK)
702 desca(:) = matrix_a%matrix_struct%descriptor(:)
703 descc(:) = matrix_c%matrix_struct%descriptor(:)
705 CALL pdsyrk(uplo, trans, n, k, alpha, a(1, 1), ia, ja, desca, beta, c(1, 1), 1, 1, descc)
712 CALL dsyrk(uplo, trans, n, k, alpha, a(ia, ja), lda, beta, c(1, 1), ldc)
715 CALL timestop(handle)
729 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
731 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_schur_product'
733 INTEGER :: handle, icol_local, irow_local, mypcol, &
734 myprow, ncol_local, npcol, nprow, &
736 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, c
737 TYPE(cp_blacs_env_type),
POINTER :: context
739 CALL timeset(routinen, handle)
741 context => matrix_a%matrix_struct%context
742 myprow = context%mepos(1)
743 mypcol = context%mepos(2)
744 nprow = context%num_pe(1)
745 npcol = context%num_pe(2)
747 a => matrix_a%local_data
748 b => matrix_b%local_data
749 c => matrix_c%local_data
751 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
752 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
754 DO icol_local = 1, ncol_local
755 DO irow_local = 1, nrow_local
756 c(irow_local, icol_local) = a(irow_local, icol_local)*b(irow_local, icol_local)
760 CALL timestop(handle)
777 SUBROUTINE cp_fm_trace_a0b0t0(matrix_a, matrix_b, trace)
779 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a, matrix_b
780 REAL(kind=
dp),
INTENT(OUT) :: trace
782 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_trace_a0b0t0'
784 INTEGER :: handle, mypcol, myprow, ncol_local, &
785 npcol, nprow, nrow_local
786 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
787 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp, b_sp
788 TYPE(cp_blacs_env_type),
POINTER :: context
789 TYPE(mp_comm_type) :: group
791 CALL timeset(routinen, handle)
793 context => matrix_a%matrix_struct%context
794 myprow = context%mepos(1)
795 mypcol = context%mepos(2)
796 nprow = context%num_pe(1)
797 npcol = context%num_pe(2)
799 group = matrix_a%matrix_struct%para_env
801 a => matrix_a%local_data
802 b => matrix_b%local_data
804 a_sp => matrix_a%local_data_sp
805 b_sp => matrix_b%local_data_sp
807 nrow_local = min(matrix_a%matrix_struct%nrow_locals(myprow), matrix_b%matrix_struct%nrow_locals(myprow))
808 ncol_local = min(matrix_a%matrix_struct%ncol_locals(mypcol), matrix_b%matrix_struct%ncol_locals(mypcol))
811 IF (matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
812 trace = accurate_sum(real(a_sp(1:nrow_local, 1:ncol_local)* &
813 b_sp(1:nrow_local, 1:ncol_local),
dp))
814 ELSEIF (matrix_a%use_sp .AND. .NOT. matrix_b%use_sp)
THEN
815 trace = accurate_sum(real(a_sp(1:nrow_local, 1:ncol_local),
dp)* &
816 b(1:nrow_local, 1:ncol_local))
817 ELSEIF (.NOT. matrix_a%use_sp .AND. matrix_b%use_sp)
THEN
818 trace = accurate_sum(a(1:nrow_local, 1:ncol_local)* &
819 REAL(b_sp(1:nrow_local, 1:ncol_local),
dp))
821 trace = accurate_dot_product(a(1:nrow_local, 1:ncol_local), &
822 b(1:nrow_local, 1:ncol_local))
825 CALL group%sum(trace)
827 CALL timestop(handle)
829 END SUBROUTINE cp_fm_trace_a0b0t0
850 SUBROUTINE cp_fm_trace_a1b0t1_a (matrix_a, matrix_b, trace)
851 TYPE(cp_fm_type),
DIMENSION(:),
INTENT(in) :: matrix_a
852 TYPE(cp_fm_type),
INTENT(IN) :: matrix_b
853 REAL(kind=
dp),
DIMENSION(:),
INTENT(out) :: trace
855 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_trace_a1b0t1_a'
857 INTEGER :: handle, imatrix, n_matrices, &
858 ncols_local, nrows_local
859 LOGICAL :: use_sp_a, use_sp_b
860 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
861 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
862 TYPE(mp_comm_type) :: group
864 CALL timeset(routinen, handle)
866 n_matrices =
SIZE(trace)
867 cpassert(
SIZE(matrix_a) == n_matrices)
869 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
870 use_sp_b = matrix_b%use_sp
873 ldata_b_sp => matrix_b%local_data_sp(1:nrows_local, 1:ncols_local)
875 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
883 DO imatrix = 1, n_matrices
885 use_sp_a = matrix_a(imatrix) %use_sp
888 IF (use_sp_a .AND. use_sp_b)
THEN
889 ldata_a_sp => matrix_a(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
890 trace(imatrix) = accurate_dot_product(ldata_a_sp, ldata_b_sp)
891 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
892 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
893 trace(imatrix) = accurate_dot_product(ldata_a, ldata_b)
895 cpabort(
"Matrices A and B are of different types")
900 group = matrix_b%matrix_struct%para_env
901 CALL group%sum(trace)
903 CALL timestop(handle)
904 END SUBROUTINE cp_fm_trace_a1b0t1_a
905 SUBROUTINE cp_fm_trace_a1b0t1_p (matrix_a, matrix_b, trace)
906 TYPE(cp_fm_p_type),
DIMENSION(:),
INTENT(in) :: matrix_a
907 TYPE(cp_fm_type),
INTENT(IN) :: matrix_b
908 REAL(kind=
dp),
DIMENSION(:),
INTENT(out) :: trace
910 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_trace_a1b0t1_p'
912 INTEGER :: handle, imatrix, n_matrices, &
913 ncols_local, nrows_local
914 LOGICAL :: use_sp_a, use_sp_b
915 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
916 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
917 TYPE(mp_comm_type) :: group
919 CALL timeset(routinen, handle)
921 n_matrices =
SIZE(trace)
922 cpassert(
SIZE(matrix_a) == n_matrices)
924 CALL cp_fm_get_info(matrix_b, nrow_local=nrows_local, ncol_local=ncols_local)
925 use_sp_b = matrix_b%use_sp
928 ldata_b_sp => matrix_b%local_data_sp(1:nrows_local, 1:ncols_local)
930 ldata_b => matrix_b%local_data(1:nrows_local, 1:ncols_local)
938 DO imatrix = 1, n_matrices
940 use_sp_a = matrix_a(imatrix) %matrix%use_sp
943 IF (use_sp_a .AND. use_sp_b)
THEN
944 ldata_a_sp => matrix_a(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
945 trace(imatrix) = accurate_dot_product(ldata_a_sp, ldata_b_sp)
946 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
947 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
948 trace(imatrix) = accurate_dot_product(ldata_a, ldata_b)
950 cpabort(
"Matrices A and B are of different types")
955 group = matrix_b%matrix_struct%para_env
956 CALL group%sum(trace)
958 CALL timestop(handle)
959 END SUBROUTINE cp_fm_trace_a1b0t1_p
979 SUBROUTINE cp_fm_trace_a1b1t1_aa (matrix_a, matrix_b, trace, accurate)
980 TYPE(cp_fm_type),
DIMENSION(:),
INTENT(in) :: matrix_a
981 TYPE(cp_fm_type),
DIMENSION(:),
INTENT(in) :: matrix_b
982 REAL(kind=
dp),
DIMENSION(:),
INTENT(out) :: trace
983 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
985 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_trace_a1b1t1_aa'
987 INTEGER :: handle, imatrix, n_matrices, &
988 ncols_local, nrows_local
989 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
990 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
991 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
992 TYPE(mp_comm_type) :: group
994 CALL timeset(routinen, handle)
996 n_matrices =
SIZE(trace)
997 cpassert(
SIZE(matrix_a) == n_matrices)
998 cpassert(
SIZE(matrix_b) == n_matrices)
1000 use_accurate_sum = .true.
1001 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1007 DO imatrix = 1, n_matrices
1008 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
1010 use_sp_a = matrix_a(imatrix) %use_sp
1011 use_sp_b = matrix_b(imatrix) %use_sp
1014 IF (use_sp_a .AND. use_sp_b)
THEN
1015 ldata_a_sp => matrix_a(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1016 ldata_b_sp => matrix_b(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1017 IF (use_accurate_sum)
THEN
1018 trace(imatrix) = accurate_dot_product(ldata_a_sp, ldata_b_sp)
1020 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1022 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1023 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1024 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1025 IF (use_accurate_sum)
THEN
1026 trace(imatrix) = accurate_dot_product(ldata_a, ldata_b)
1028 trace(imatrix) = sum(ldata_a*ldata_b)
1031 cpabort(
"Matrices A and B are of different types")
1036 group = matrix_a(1) %matrix_struct%para_env
1037 CALL group%sum(trace)
1039 CALL timestop(handle)
1040 END SUBROUTINE cp_fm_trace_a1b1t1_aa
1041 SUBROUTINE cp_fm_trace_a1b1t1_ap (matrix_a, matrix_b, trace, accurate)
1042 TYPE(cp_fm_type),
DIMENSION(:),
INTENT(in) :: matrix_a
1043 TYPE(cp_fm_p_type),
DIMENSION(:),
INTENT(in) :: matrix_b
1044 REAL(kind=
dp),
DIMENSION(:),
INTENT(out) :: trace
1045 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1047 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_trace_a1b1t1_ap'
1049 INTEGER :: handle, imatrix, n_matrices, &
1050 ncols_local, nrows_local
1051 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1052 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1053 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1054 TYPE(mp_comm_type) :: group
1056 CALL timeset(routinen, handle)
1058 n_matrices =
SIZE(trace)
1059 cpassert(
SIZE(matrix_a) == n_matrices)
1060 cpassert(
SIZE(matrix_b) == n_matrices)
1062 use_accurate_sum = .true.
1063 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1069 DO imatrix = 1, n_matrices
1070 CALL cp_fm_get_info(matrix_a(imatrix) , nrow_local=nrows_local, ncol_local=ncols_local)
1072 use_sp_a = matrix_a(imatrix) %use_sp
1073 use_sp_b = matrix_b(imatrix) %matrix%use_sp
1076 IF (use_sp_a .AND. use_sp_b)
THEN
1077 ldata_a_sp => matrix_a(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1078 ldata_b_sp => matrix_b(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1079 IF (use_accurate_sum)
THEN
1080 trace(imatrix) = accurate_dot_product(ldata_a_sp, ldata_b_sp)
1082 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1084 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1085 ldata_a => matrix_a(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1086 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1087 IF (use_accurate_sum)
THEN
1088 trace(imatrix) = accurate_dot_product(ldata_a, ldata_b)
1090 trace(imatrix) = sum(ldata_a*ldata_b)
1093 cpabort(
"Matrices A and B are of different types")
1098 group = matrix_a(1) %matrix_struct%para_env
1099 CALL group%sum(trace)
1101 CALL timestop(handle)
1102 END SUBROUTINE cp_fm_trace_a1b1t1_ap
1103 SUBROUTINE cp_fm_trace_a1b1t1_pa (matrix_a, matrix_b, trace, accurate)
1104 TYPE(cp_fm_p_type),
DIMENSION(:),
INTENT(in) :: matrix_a
1105 TYPE(cp_fm_type),
DIMENSION(:),
INTENT(in) :: matrix_b
1106 REAL(kind=
dp),
DIMENSION(:),
INTENT(out) :: trace
1107 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1109 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_trace_a1b1t1_pa'
1111 INTEGER :: handle, imatrix, n_matrices, &
1112 ncols_local, nrows_local
1113 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1114 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1115 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1116 TYPE(mp_comm_type) :: group
1118 CALL timeset(routinen, handle)
1120 n_matrices =
SIZE(trace)
1121 cpassert(
SIZE(matrix_a) == n_matrices)
1122 cpassert(
SIZE(matrix_b) == n_matrices)
1124 use_accurate_sum = .true.
1125 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1131 DO imatrix = 1, n_matrices
1132 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1134 use_sp_a = matrix_a(imatrix) %matrix%use_sp
1135 use_sp_b = matrix_b(imatrix) %use_sp
1138 IF (use_sp_a .AND. use_sp_b)
THEN
1139 ldata_a_sp => matrix_a(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1140 ldata_b_sp => matrix_b(imatrix) %local_data_sp(1:nrows_local, 1:ncols_local)
1141 IF (use_accurate_sum)
THEN
1142 trace(imatrix) = accurate_dot_product(ldata_a_sp, ldata_b_sp)
1144 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1146 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1147 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1148 ldata_b => matrix_b(imatrix) %local_data(1:nrows_local, 1:ncols_local)
1149 IF (use_accurate_sum)
THEN
1150 trace(imatrix) = accurate_dot_product(ldata_a, ldata_b)
1152 trace(imatrix) = sum(ldata_a*ldata_b)
1155 cpabort(
"Matrices A and B are of different types")
1160 group = matrix_a(1) %matrix%matrix_struct%para_env
1161 CALL group%sum(trace)
1163 CALL timestop(handle)
1164 END SUBROUTINE cp_fm_trace_a1b1t1_pa
1165 SUBROUTINE cp_fm_trace_a1b1t1_pp (matrix_a, matrix_b, trace, accurate)
1166 TYPE(cp_fm_p_type),
DIMENSION(:),
INTENT(in) :: matrix_a
1167 TYPE(cp_fm_p_type),
DIMENSION(:),
INTENT(in) :: matrix_b
1168 REAL(kind=
dp),
DIMENSION(:),
INTENT(out) :: trace
1169 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1171 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_trace_a1b1t1_pp'
1173 INTEGER :: handle, imatrix, n_matrices, &
1174 ncols_local, nrows_local
1175 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1176 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1177 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1178 TYPE(mp_comm_type) :: group
1180 CALL timeset(routinen, handle)
1182 n_matrices =
SIZE(trace)
1183 cpassert(
SIZE(matrix_a) == n_matrices)
1184 cpassert(
SIZE(matrix_b) == n_matrices)
1186 use_accurate_sum = .true.
1187 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1193 DO imatrix = 1, n_matrices
1194 CALL cp_fm_get_info(matrix_a(imatrix) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1196 use_sp_a = matrix_a(imatrix) %matrix%use_sp
1197 use_sp_b = matrix_b(imatrix) %matrix%use_sp
1200 IF (use_sp_a .AND. use_sp_b)
THEN
1201 ldata_a_sp => matrix_a(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1202 ldata_b_sp => matrix_b(imatrix) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1203 IF (use_accurate_sum)
THEN
1204 trace(imatrix) = accurate_dot_product(ldata_a_sp, ldata_b_sp)
1206 trace(imatrix) = sum(ldata_a_sp*ldata_b_sp)
1208 ELSE IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1209 ldata_a => matrix_a(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1210 ldata_b => matrix_b(imatrix) %matrix%local_data(1:nrows_local, 1:ncols_local)
1211 IF (use_accurate_sum)
THEN
1212 trace(imatrix) = accurate_dot_product(ldata_a, ldata_b)
1214 trace(imatrix) = sum(ldata_a*ldata_b)
1217 cpabort(
"Matrices A and B are of different types")
1222 group = matrix_a(1) %matrix%matrix_struct%para_env
1223 CALL group%sum(trace)
1225 CALL timestop(handle)
1226 END SUBROUTINE cp_fm_trace_a1b1t1_pp
1235 SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa (matrix_a, matrix_b, trace, accurate)
1236 TYPE(cp_fm_type),
DIMENSION(:, :),
INTENT(in) :: matrix_a
1237 TYPE(cp_fm_type),
DIMENSION(:, :),
INTENT(in) :: matrix_b
1238 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(out) :: trace
1239 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1241 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_contracted_trace_a2b2t2_aa'
1243 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1245 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1246 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1248 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1249 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1250 TYPE(mp_comm_type) :: group
1252 CALL timeset(routinen, handle)
1254 nz =
SIZE(matrix_a, 1)
1255 cpassert(
SIZE(matrix_b, 1) == nz)
1257 na =
SIZE(matrix_a, 2)
1258 nb =
SIZE(matrix_b, 2)
1259 cpassert(
SIZE(trace, 1) == na)
1260 cpassert(
SIZE(trace, 2) == nb)
1262 use_accurate_sum = .true.
1263 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1268 na8 = int(na, kind=
int_8)
1274 DO itrace = 1, ntraces
1275 ib8 = (itrace - 1)/na8
1276 ia = int(itrace - ib8*na8)
1281 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1282 use_sp_a = matrix_a(iz, ia) %use_sp
1283 use_sp_b = matrix_b(iz, ib) %use_sp
1286 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1287 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1288 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1289 IF (use_accurate_sum)
THEN
1290 t = t + accurate_dot_product(ldata_a, ldata_b)
1292 t = t + sum(ldata_a*ldata_b)
1294 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1295 ldata_a_sp => matrix_a(iz, ia) %local_data_sp(1:nrows_local, 1:ncols_local)
1296 ldata_b_sp => matrix_b(iz, ib) %local_data_sp(1:nrows_local, 1:ncols_local)
1297 IF (use_accurate_sum)
THEN
1298 t = t + accurate_dot_product(ldata_a_sp, ldata_b_sp)
1300 t = t + sum(ldata_a_sp*ldata_b_sp)
1303 cpabort(
"Matrices A and B are of different types")
1310 group = matrix_a(1, 1) %matrix_struct%para_env
1311 CALL group%sum(trace)
1313 CALL timestop(handle)
1314 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_aa
1315 SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap (matrix_a, matrix_b, trace, accurate)
1316 TYPE(cp_fm_type),
DIMENSION(:, :),
INTENT(in) :: matrix_a
1317 TYPE(cp_fm_p_type),
DIMENSION(:, :),
INTENT(in) :: matrix_b
1318 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(out) :: trace
1319 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1321 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_contracted_trace_a2b2t2_ap'
1323 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1325 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1326 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1328 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1329 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1330 TYPE(mp_comm_type) :: group
1332 CALL timeset(routinen, handle)
1334 nz =
SIZE(matrix_a, 1)
1335 cpassert(
SIZE(matrix_b, 1) == nz)
1337 na =
SIZE(matrix_a, 2)
1338 nb =
SIZE(matrix_b, 2)
1339 cpassert(
SIZE(trace, 1) == na)
1340 cpassert(
SIZE(trace, 2) == nb)
1342 use_accurate_sum = .true.
1343 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1348 na8 = int(na, kind=
int_8)
1354 DO itrace = 1, ntraces
1355 ib8 = (itrace - 1)/na8
1356 ia = int(itrace - ib8*na8)
1361 CALL cp_fm_get_info(matrix_a(iz, ia) , nrow_local=nrows_local, ncol_local=ncols_local)
1362 use_sp_a = matrix_a(iz, ia) %use_sp
1363 use_sp_b = matrix_b(iz, ib) %matrix%use_sp
1366 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1367 ldata_a => matrix_a(iz, ia) %local_data(1:nrows_local, 1:ncols_local)
1368 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1369 IF (use_accurate_sum)
THEN
1370 t = t + accurate_dot_product(ldata_a, ldata_b)
1372 t = t + sum(ldata_a*ldata_b)
1374 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1375 ldata_a_sp => matrix_a(iz, ia) %local_data_sp(1:nrows_local, 1:ncols_local)
1376 ldata_b_sp => matrix_b(iz, ib) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1377 IF (use_accurate_sum)
THEN
1378 t = t + accurate_dot_product(ldata_a_sp, ldata_b_sp)
1380 t = t + sum(ldata_a_sp*ldata_b_sp)
1383 cpabort(
"Matrices A and B are of different types")
1390 group = matrix_a(1, 1) %matrix_struct%para_env
1391 CALL group%sum(trace)
1393 CALL timestop(handle)
1394 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_ap
1395 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa (matrix_a, matrix_b, trace, accurate)
1396 TYPE(cp_fm_p_type),
DIMENSION(:, :),
INTENT(in) :: matrix_a
1397 TYPE(cp_fm_type),
DIMENSION(:, :),
INTENT(in) :: matrix_b
1398 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(out) :: trace
1399 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1401 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_contracted_trace_a2b2t2_pa'
1403 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1405 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1406 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1408 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1409 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1410 TYPE(mp_comm_type) :: group
1412 CALL timeset(routinen, handle)
1414 nz =
SIZE(matrix_a, 1)
1415 cpassert(
SIZE(matrix_b, 1) == nz)
1417 na =
SIZE(matrix_a, 2)
1418 nb =
SIZE(matrix_b, 2)
1419 cpassert(
SIZE(trace, 1) == na)
1420 cpassert(
SIZE(trace, 2) == nb)
1422 use_accurate_sum = .true.
1423 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1428 na8 = int(na, kind=
int_8)
1434 DO itrace = 1, ntraces
1435 ib8 = (itrace - 1)/na8
1436 ia = int(itrace - ib8*na8)
1441 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1442 use_sp_a = matrix_a(iz, ia) %matrix%use_sp
1443 use_sp_b = matrix_b(iz, ib) %use_sp
1446 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1447 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1448 ldata_b => matrix_b(iz, ib) %local_data(1:nrows_local, 1:ncols_local)
1449 IF (use_accurate_sum)
THEN
1450 t = t + accurate_dot_product(ldata_a, ldata_b)
1452 t = t + sum(ldata_a*ldata_b)
1454 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1455 ldata_a_sp => matrix_a(iz, ia) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1456 ldata_b_sp => matrix_b(iz, ib) %local_data_sp(1:nrows_local, 1:ncols_local)
1457 IF (use_accurate_sum)
THEN
1458 t = t + accurate_dot_product(ldata_a_sp, ldata_b_sp)
1460 t = t + sum(ldata_a_sp*ldata_b_sp)
1463 cpabort(
"Matrices A and B are of different types")
1470 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1471 CALL group%sum(trace)
1473 CALL timestop(handle)
1474 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pa
1475 SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp (matrix_a, matrix_b, trace, accurate)
1476 TYPE(cp_fm_p_type),
DIMENSION(:, :),
INTENT(in) :: matrix_a
1477 TYPE(cp_fm_p_type),
DIMENSION(:, :),
INTENT(in) :: matrix_b
1478 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(out) :: trace
1479 LOGICAL,
INTENT(IN),
OPTIONAL :: accurate
1481 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_contracted_trace_a2b2t2_pp'
1483 INTEGER :: handle, ia, ib, iz, na, nb, ncols_local, &
1485 INTEGER(kind=int_8) :: ib8, itrace, na8, ntraces
1486 LOGICAL :: use_accurate_sum, use_sp_a, use_sp_b
1488 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ldata_a, ldata_b
1489 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: ldata_a_sp, ldata_b_sp
1490 TYPE(mp_comm_type) :: group
1492 CALL timeset(routinen, handle)
1494 nz =
SIZE(matrix_a, 1)
1495 cpassert(
SIZE(matrix_b, 1) == nz)
1497 na =
SIZE(matrix_a, 2)
1498 nb =
SIZE(matrix_b, 2)
1499 cpassert(
SIZE(trace, 1) == na)
1500 cpassert(
SIZE(trace, 2) == nb)
1502 use_accurate_sum = .true.
1503 IF (
PRESENT(accurate)) use_accurate_sum = accurate
1508 na8 = int(na, kind=
int_8)
1514 DO itrace = 1, ntraces
1515 ib8 = (itrace - 1)/na8
1516 ia = int(itrace - ib8*na8)
1521 CALL cp_fm_get_info(matrix_a(iz, ia) %matrix, nrow_local=nrows_local, ncol_local=ncols_local)
1522 use_sp_a = matrix_a(iz, ia) %matrix%use_sp
1523 use_sp_b = matrix_b(iz, ib) %matrix%use_sp
1526 IF (.NOT. use_sp_a .AND. .NOT. use_sp_b)
THEN
1527 ldata_a => matrix_a(iz, ia) %matrix%local_data(1:nrows_local, 1:ncols_local)
1528 ldata_b => matrix_b(iz, ib) %matrix%local_data(1:nrows_local, 1:ncols_local)
1529 IF (use_accurate_sum)
THEN
1530 t = t + accurate_dot_product(ldata_a, ldata_b)
1532 t = t + sum(ldata_a*ldata_b)
1534 ELSE IF (use_sp_a .AND. use_sp_b)
THEN
1535 ldata_a_sp => matrix_a(iz, ia) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1536 ldata_b_sp => matrix_b(iz, ib) %matrix%local_data_sp(1:nrows_local, 1:ncols_local)
1537 IF (use_accurate_sum)
THEN
1538 t = t + accurate_dot_product(ldata_a_sp, ldata_b_sp)
1540 t = t + sum(ldata_a_sp*ldata_b_sp)
1543 cpabort(
"Matrices A and B are of different types")
1550 group = matrix_a(1, 1) %matrix%matrix_struct%para_env
1551 CALL group%sum(trace)
1553 CALL timestop(handle)
1554 END SUBROUTINE cp_fm_contracted_trace_a2b2t2_pp
1590 transpose_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, &
1592 TYPE(cp_fm_type),
INTENT(IN) :: triangular_matrix, matrix_b
1593 CHARACTER,
INTENT(in),
OPTIONAL :: side
1594 LOGICAL,
INTENT(in),
OPTIONAL :: transpose_tr, invert_tr
1595 CHARACTER,
INTENT(in),
OPTIONAL :: uplo_tr
1596 LOGICAL,
INTENT(in),
OPTIONAL :: unit_diag_tr
1597 INTEGER,
INTENT(in),
OPTIONAL :: n_rows, n_cols
1598 REAL(kind=
dp),
INTENT(in),
OPTIONAL :: alpha
1600 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_triangular_multiply'
1602 CHARACTER :: side_char, transa, unit_diag, uplo
1603 INTEGER :: handle, m, n
1607 CALL timeset(routinen, handle)
1615 IF (
PRESENT(side)) side_char = side
1616 IF (
PRESENT(invert_tr)) invert = invert_tr
1617 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1618 IF (
PRESENT(unit_diag_tr))
THEN
1619 IF (unit_diag_tr)
THEN
1625 IF (
PRESENT(transpose_tr))
THEN
1626 IF (transpose_tr)
THEN
1632 IF (
PRESENT(alpha)) al = alpha
1633 IF (
PRESENT(n_rows)) m = n_rows
1634 IF (
PRESENT(n_cols)) n = n_cols
1638 #if defined(__SCALAPACK)
1639 CALL pdtrsm(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 dtrsm(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 #if defined(__SCALAPACK)
1654 CALL pdtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1655 triangular_matrix%local_data(1, 1), 1, 1, &
1656 triangular_matrix%matrix_struct%descriptor, &
1657 matrix_b%local_data(1, 1), 1, 1, &
1658 matrix_b%matrix_struct%descriptor(1))
1660 CALL dtrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1661 triangular_matrix%local_data(1, 1), &
1662 SIZE(triangular_matrix%local_data, 1), &
1663 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1668 CALL timestop(handle)
1680 REAL(kind=
dp),
INTENT(IN) :: alpha
1681 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
1683 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_scale'
1685 INTEGER :: handle, size_a
1686 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1688 CALL timeset(routinen, handle)
1692 a => matrix_a%local_data
1693 size_a =
SIZE(a, 1)*
SIZE(a, 2)
1695 CALL dscal(size_a, alpha, a, 1)
1697 CALL timestop(handle)
1710 TYPE(cp_fm_type),
INTENT(IN) :: matrix, matrixt
1712 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_transpose'
1714 INTEGER :: handle, ncol_global, &
1715 nrow_global, ncol_globalt, nrow_globalt
1716 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, c
1717 #if defined(__SCALAPACK)
1718 INTEGER,
DIMENSION(9) :: desca, descc
1723 nrow_global = matrix%matrix_struct%nrow_global
1724 ncol_global = matrix%matrix_struct%ncol_global
1725 nrow_globalt = matrixt%matrix_struct%nrow_global
1726 ncol_globalt = matrixt%matrix_struct%ncol_global
1727 cpassert(nrow_global == ncol_globalt)
1728 cpassert(nrow_globalt == ncol_global)
1730 CALL timeset(routinen, handle)
1732 a => matrix%local_data
1733 c => matrixt%local_data
1735 #if defined(__SCALAPACK)
1736 desca(:) = matrix%matrix_struct%descriptor(:)
1737 descc(:) = matrixt%matrix_struct%descriptor(:)
1738 CALL pdtran(ncol_global, nrow_global, 1.0_dp, a(1, 1), 1, 1, desca, 0.0_dp, c(1, 1), 1, 1, descc)
1740 DO j = 1, ncol_global
1741 DO i = 1, nrow_global
1746 CALL timestop(handle)
1760 TYPE(cp_fm_type),
INTENT(IN) :: matrix, work
1762 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_upper_to_full'
1764 INTEGER :: handle, icol_global, irow_global, &
1765 mypcol, myprow, ncol_global, &
1766 npcol, nprow, nrow_global
1767 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1768 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
1769 TYPE(cp_blacs_env_type),
POINTER :: context
1771 #if defined(__SCALAPACK)
1772 INTEGER :: icol_local, irow_local, &
1773 ncol_block, ncol_local, &
1774 nrow_block, nrow_local
1775 INTEGER,
DIMENSION(9) :: desca, descc
1776 INTEGER,
EXTERNAL :: indxl2g
1777 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: c
1778 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: c_sp
1781 nrow_global = matrix%matrix_struct%nrow_global
1782 ncol_global = matrix%matrix_struct%ncol_global
1783 cpassert(nrow_global == ncol_global)
1784 nrow_global = work%matrix_struct%nrow_global
1785 ncol_global = work%matrix_struct%ncol_global
1786 cpassert(nrow_global == ncol_global)
1787 cpassert(matrix%use_sp .EQV. work%use_sp)
1789 CALL timeset(routinen, handle)
1791 context => matrix%matrix_struct%context
1792 myprow = context%mepos(1)
1793 mypcol = context%mepos(2)
1794 nprow = context%num_pe(1)
1795 npcol = context%num_pe(2)
1797 #if defined(__SCALAPACK)
1799 nrow_block = matrix%matrix_struct%nrow_block
1800 ncol_block = matrix%matrix_struct%ncol_block
1802 nrow_local = matrix%matrix_struct%nrow_locals(myprow)
1803 ncol_local = matrix%matrix_struct%ncol_locals(mypcol)
1805 a => work%local_data
1806 a_sp => work%local_data_sp
1807 desca(:) = work%matrix_struct%descriptor(:)
1808 c => matrix%local_data
1809 c_sp => matrix%local_data_sp
1810 descc(:) = matrix%matrix_struct%descriptor(:)
1812 DO icol_local = 1, ncol_local
1813 icol_global = indxl2g(icol_local, ncol_block, mypcol, &
1814 matrix%matrix_struct%first_p_pos(2), npcol)
1815 DO irow_local = 1, nrow_local
1816 irow_global = indxl2g(irow_local, nrow_block, myprow, &
1817 matrix%matrix_struct%first_p_pos(1), nprow)
1818 IF (irow_global > icol_global)
THEN
1819 IF (matrix%use_sp)
THEN
1820 c_sp(irow_local, icol_local) = 0.0_sp
1822 c(irow_local, icol_local) = 0.0_dp
1824 ELSE IF (irow_global == icol_global)
THEN
1825 IF (matrix%use_sp)
THEN
1826 c_sp(irow_local, icol_local) = 0.5_sp*c_sp(irow_local, icol_local)
1828 c(irow_local, icol_local) = 0.5_dp*c(irow_local, icol_local)
1834 DO icol_local = 1, ncol_local
1835 DO irow_local = 1, nrow_local
1836 IF (matrix%use_sp)
THEN
1837 a_sp(irow_local, icol_local) = c_sp(irow_local, icol_local)
1839 a(irow_local, icol_local) = c(irow_local, icol_local)
1844 IF (matrix%use_sp)
THEN
1845 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)
1847 CALL pdtran(nrow_global, ncol_global, 1.0_dp, a(1, 1), 1, 1, desca, 1.0_dp, c(1, 1), 1, 1, descc)
1852 a => matrix%local_data
1853 a_sp => matrix%local_data_sp
1854 DO irow_global = 1, nrow_global
1855 DO icol_global = irow_global + 1, ncol_global
1856 IF (matrix%use_sp)
THEN
1857 a_sp(icol_global, irow_global) = a_sp(irow_global, icol_global)
1859 a(icol_global, irow_global) = a(irow_global, icol_global)
1865 CALL timestop(handle)
1882 TYPE(cp_fm_type),
INTENT(IN) :: matrixa
1883 REAL(kind=
dp),
DIMENSION(:),
INTENT(in) :: scaling
1885 INTEGER :: k, mypcol, myprow, n, ncol_global, &
1887 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1888 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
1889 #if defined(__SCALAPACK)
1890 INTEGER :: icol_global, icol_local, &
1891 ipcol, iprow, irow_local
1896 myprow = matrixa%matrix_struct%context%mepos(1)
1897 mypcol = matrixa%matrix_struct%context%mepos(2)
1898 nprow = matrixa%matrix_struct%context%num_pe(1)
1899 npcol = matrixa%matrix_struct%context%num_pe(2)
1901 ncol_global = matrixa%matrix_struct%ncol_global
1903 a => matrixa%local_data
1904 a_sp => matrixa%local_data_sp
1905 IF (matrixa%use_sp)
THEN
1910 k = min(
SIZE(scaling), ncol_global)
1912 #if defined(__SCALAPACK)
1914 DO icol_global = 1, k
1915 CALL infog2l(1, icol_global, matrixa%matrix_struct%descriptor, &
1916 nprow, npcol, myprow, mypcol, &
1917 irow_local, icol_local, iprow, ipcol)
1918 IF ((ipcol == mypcol))
THEN
1919 IF (matrixa%use_sp)
THEN
1920 CALL sscal(n, real(scaling(icol_global),
sp), a_sp(:, icol_local), 1)
1922 CALL dscal(n, scaling(icol_global), a(:, icol_local), 1)
1928 IF (matrixa%use_sp)
THEN
1929 CALL sscal(n, real(scaling(i),
sp), a_sp(:, i), 1)
1931 CALL dscal(n, scaling(i), a(:, i), 1)
1945 TYPE(cp_fm_type),
INTENT(IN) :: matrixa
1946 REAL(kind=
dp),
DIMENSION(:),
INTENT(in) :: scaling
1948 INTEGER :: n, m, nrow_global, nrow_local, ncol_local
1949 INTEGER,
DIMENSION(:),
POINTER :: row_indices
1950 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
1951 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
1952 #if defined(__SCALAPACK)
1953 INTEGER :: irow_global, icol, irow
1958 CALL cp_fm_get_info(matrixa, row_indices=row_indices, nrow_global=nrow_global, &
1959 nrow_local=nrow_local, ncol_local=ncol_local)
1960 cpassert(
SIZE(scaling) == nrow_global)
1962 a => matrixa%local_data
1963 a_sp => matrixa%local_data_sp
1964 IF (matrixa%use_sp)
THEN
1972 #if defined(__SCALAPACK)
1973 DO icol = 1, ncol_local
1974 IF (matrixa%use_sp)
THEN
1975 DO irow = 1, nrow_local
1976 irow_global = row_indices(irow)
1977 a(irow, icol) = real(scaling(irow_global),
dp)*a(irow, icol)
1980 DO irow = 1, nrow_local
1981 irow_global = row_indices(irow)
1982 a(irow, icol) = scaling(irow_global)*a(irow, icol)
1987 IF (matrixa%use_sp)
THEN
1989 a_sp(1:n, j) = real(scaling(1:n),
sp)*a_sp(1:n, j)
1993 a(1:n, j) = scaling(1:n)*a(1:n, j)
2016 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a, matrix_inverse
2017 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: det_a
2018 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: eps_svd
2019 REAL(kind=
dp),
DIMENSION(:),
POINTER, &
2020 INTENT(INOUT),
OPTIONAL :: eigval
2023 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
2024 REAL(kind=
dp) :: determinant, my_eps_svd
2025 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2026 TYPE(cp_fm_type) :: matrix_lu
2028 #if defined(__SCALAPACK)
2029 TYPE(cp_fm_type) :: u, vt, sigma, inv_sigma_ut
2030 TYPE(mp_comm_type) :: group
2031 INTEGER :: i, info, liwork, lwork, exponent_of_minus_one
2032 INTEGER,
DIMENSION(9) :: desca
2034 REAL(kind=
dp) :: alpha, beta
2035 REAL(kind=
dp),
DIMENSION(:),
POINTER :: diag
2036 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
2039 REAL(kind=
dp) :: eps1
2043 IF (
PRESENT(eps_svd)) my_eps_svd = eps_svd
2046 matrix_struct=matrix_a%matrix_struct, &
2047 name=
"A_lu"//trim(adjustl(cp_to_string(1)))//
"MATRIX")
2048 CALL cp_fm_to_fm(matrix_a, matrix_lu)
2050 a => matrix_lu%local_data
2051 n = matrix_lu%matrix_struct%nrow_global
2052 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
2054 #if defined(__SCALAPACK)
2055 IF (my_eps_svd .EQ. 0.0_dp)
THEN
2059 desca(:) = matrix_lu%matrix_struct%descriptor(:)
2060 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
2062 IF (
PRESENT(det_a) .OR.
PRESENT(eigval))
THEN
2068 exponent_of_minus_one = 0
2069 determinant = 1.0_dp
2071 determinant = determinant*diag(i)
2072 IF (ipivot(i) .NE. i)
THEN
2073 exponent_of_minus_one = exponent_of_minus_one + 1
2076 IF (
PRESENT(eigval))
THEN
2077 cpassert(.NOT.
ASSOCIATED(eigval))
2078 ALLOCATE (eigval(n))
2083 group = matrix_lu%matrix_struct%para_env
2084 CALL group%sum(exponent_of_minus_one)
2086 determinant = determinant*(-1.0_dp)**exponent_of_minus_one
2093 CALL pdgetrs(
'N', n, n, matrix_lu%local_data, 1, 1, desca, ipivot, matrix_inverse%local_data, 1, 1, desca, info)
2097 matrix_struct=matrix_a%matrix_struct, &
2098 name=
"LEFT_SINGULAR_MATRIX")
2101 matrix_struct=matrix_a%matrix_struct, &
2102 name=
"RIGHT_SINGULAR_MATRIX")
2106 desca(:) = matrix_lu%matrix_struct%descriptor(:)
2110 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca, diag, u%local_data, &
2111 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
2112 lwork = int(work(1))
2114 ALLOCATE (work(lwork))
2116 CALL pdgesvd(
'V',
'V', n, n, matrix_lu%local_data, 1, 1, desca, diag, u%local_data, &
2117 1, 1, desca, vt%local_data, 1, 1, desca, work, lwork, info)
2120 IF (info /= 0 .AND. info /= n + 1) &
2121 cpabort(
"Singular value decomposition of matrix failed.")
2124 matrix_struct=matrix_a%matrix_struct, &
2125 name=
"SINGULAR_VALUE_MATRIX")
2127 determinant = 1.0_dp
2129 IF (
PRESENT(eigval))
THEN
2130 cpassert(.NOT.
ASSOCIATED(eigval))
2131 ALLOCATE (eigval(n))
2135 IF (diag(i) < my_eps_svd)
THEN
2139 determinant = determinant*diag(i)
2140 diag(i) = 1.0_dp/diag(i)
2146 CALL cp_warn(__location__, &
2147 "Linear dependencies were detected in the SVD inversion of matrix "//trim(adjustl(matrix_a%name))// &
2148 ". At least one singular value has been quenched.")
2151 matrix_struct=matrix_a%matrix_struct, &
2152 name=
"SINGULAR_VALUE_MATRIX")
2154 CALL pdgemm(
'N',
'T', n, n, n, 1.0_dp, sigma%local_data, 1, 1, desca, &
2155 u%local_data, 1, 1, desca, 0.0_dp, inv_sigma_ut%local_data, 1, 1, desca)
2158 CALL pdgemm(
'T',
'N', n, n, n, 1.0_dp, vt%local_data, 1, 1, desca, &
2159 inv_sigma_ut%local_data, 1, 1, desca, 0.0_dp, matrix_inverse%local_data, 1, 1, desca)
2162 CALL cp_fm_release(u)
2163 CALL cp_fm_release(vt)
2164 CALL cp_fm_release(sigma)
2165 CALL cp_fm_release(inv_sigma_ut)
2168 IF (my_eps_svd .EQ. 0.0_dp)
THEN
2170 CALL invert_matrix(matrix_a%local_data, matrix_inverse%local_data, &
2172 CALL cp_fm_lu_decompose(matrix_lu, determinant, correct_sign=sign)
2173 IF (
PRESENT(eigval)) &
2174 CALL cp_abort(__location__, &
2175 "NYI. Eigenvalues not available for return without SCALAPACK.")
2178 determinant, eigval)
2181 CALL cp_fm_release(matrix_lu)
2183 IF (
PRESENT(det_a)) det_a = determinant
2194 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
2195 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo_tr
2197 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_triangular_invert'
2199 CHARACTER :: unit_diag, uplo
2200 INTEGER :: handle, info, ncol_global
2201 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2202 #if defined(__SCALAPACK)
2203 INTEGER,
DIMENSION(9) :: desca
2206 CALL timeset(routinen, handle)
2210 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
2212 ncol_global = matrix_a%matrix_struct%ncol_global
2214 a => matrix_a%local_data
2216 #if defined(__SCALAPACK)
2218 desca(:) = matrix_a%matrix_struct%descriptor(:)
2220 CALL pdtrtri(uplo, unit_diag, ncol_global, a(1, 1), 1, 1, desca, info)
2223 CALL dtrtri(uplo, unit_diag, ncol_global, a(1, 1), ncol_global, info)
2226 CALL timestop(handle)
2242 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a, matrix_r
2243 INTEGER,
INTENT(IN),
OPTIONAL :: nrow_fact, ncol_fact, &
2244 first_row, first_col
2246 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_qr_factorization'
2248 INTEGER :: handle, i, icol, info, irow, &
2249 j, lda, lwork, ncol, &
2251 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: tau, work
2252 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: r_mat
2253 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2254 #if defined(__SCALAPACK)
2255 INTEGER,
DIMENSION(9) :: desca
2258 CALL timeset(routinen, handle)
2260 ncol = matrix_a%matrix_struct%ncol_global
2261 nrow = matrix_a%matrix_struct%nrow_global
2264 a => matrix_a%local_data
2266 IF (
PRESENT(nrow_fact)) nrow = nrow_fact
2267 IF (
PRESENT(ncol_fact)) ncol = ncol_fact
2269 IF (
PRESENT(first_row)) irow = first_row
2271 IF (
PRESENT(first_col)) icol = first_col
2273 cpassert(nrow >= ncol)
2276 ALLOCATE (tau(ndim))
2278 #if defined(__SCALAPACK)
2280 desca(:) = matrix_a%matrix_struct%descriptor(:)
2283 ALLOCATE (work(2*ndim))
2284 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2285 lwork = int(work(1))
2287 ALLOCATE (work(lwork))
2288 CALL pdgeqrf(nrow, ncol, a, irow, icol, desca, tau, work, lwork, info)
2292 ALLOCATE (work(2*ndim))
2293 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2294 lwork = int(work(1))
2296 ALLOCATE (work(lwork))
2297 CALL dgeqrf(nrow, ncol, a, lda, tau, work, lwork, info)
2301 ALLOCATE (r_mat(ncol, ncol))
2305 r_mat(j, i) = 0.0_dp
2310 DEALLOCATE (tau, work, r_mat)
2312 CALL timestop(handle)
2324 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a, general_a
2326 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_solve'
2328 INTEGER :: handle, info, n
2329 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
2330 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, a_general
2331 #if defined(__SCALAPACK)
2332 INTEGER,
DIMENSION(9) :: desca, descb
2337 CALL timeset(routinen, handle)
2339 a => matrix_a%local_data
2340 a_general => general_a%local_data
2341 n = matrix_a%matrix_struct%nrow_global
2342 ALLOCATE (ipivot(n + matrix_a%matrix_struct%nrow_block))
2344 #if defined(__SCALAPACK)
2345 desca(:) = matrix_a%matrix_struct%descriptor(:)
2346 descb(:) = general_a%matrix_struct%descriptor(:)
2347 CALL pdgetrf(n, n, a, 1, 1, desca, ipivot, info)
2348 CALL pdgetrs(
"N", n, n, a, 1, 1, desca, ipivot, a_general, &
2353 ldb =
SIZE(a_general, 1)
2354 CALL dgetrf(n, n, a, lda, ipivot, info)
2355 CALL dgetrs(
"N", n, n, a, lda, ipivot, a_general, ldb, info)
2361 CALL timestop(handle)
2392 SUBROUTINE cp_complex_fm_gemm(transa, transb, m, n, k, alpha, A_re, A_im, B_re, B_im, beta, &
2393 C_re, C_im, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, &
2395 CHARACTER(LEN=1),
INTENT(IN) :: transa, transb
2396 INTEGER,
INTENT(IN) :: m, n, k
2397 REAL(kind=
dp),
INTENT(IN) :: alpha
2398 TYPE(cp_fm_type),
INTENT(IN) :: a_re, a_im, b_re, b_im
2399 REAL(kind=
dp),
INTENT(IN) :: beta
2400 TYPE(cp_fm_type),
INTENT(IN) :: c_re, c_im
2401 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, b_first_col, &
2402 b_first_row, c_first_col, c_first_row
2404 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_complex_fm_gemm'
2408 CALL timeset(routinen, handle)
2410 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_re, b_re, beta, c_re, &
2411 a_first_col=a_first_col, &
2412 a_first_row=a_first_row, &
2413 b_first_col=b_first_col, &
2414 b_first_row=b_first_row, &
2415 c_first_col=c_first_col, &
2416 c_first_row=c_first_row)
2417 CALL cp_fm_gemm(transa, transb, m, n, k, -alpha, a_im, b_im, 1.0_dp, c_re, &
2418 a_first_col=a_first_col, &
2419 a_first_row=a_first_row, &
2420 b_first_col=b_first_col, &
2421 b_first_row=b_first_row, &
2422 c_first_col=c_first_col, &
2423 c_first_row=c_first_row)
2424 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_re, b_im, beta, c_im, &
2425 a_first_col=a_first_col, &
2426 a_first_row=a_first_row, &
2427 b_first_col=b_first_col, &
2428 b_first_row=b_first_row, &
2429 c_first_col=c_first_col, &
2430 c_first_row=c_first_row)
2431 CALL cp_fm_gemm(transa, transb, m, n, k, alpha, a_im, b_re, 1.0_dp, c_im, &
2432 a_first_col=a_first_col, &
2433 a_first_row=a_first_row, &
2434 b_first_col=b_first_col, &
2435 b_first_row=b_first_row, &
2436 c_first_col=c_first_col, &
2437 c_first_row=c_first_row)
2439 CALL timestop(handle)
2450 SUBROUTINE cp_fm_lu_invert(matrix, info_out)
2451 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2452 INTEGER,
INTENT(OUT),
OPTIONAL :: info_out
2454 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_lu_invert'
2456 INTEGER :: nrows_global, handle, info, lwork
2457 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ipivot
2458 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: mat
2459 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: mat_sp
2460 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2461 REAL(kind=
sp),
DIMENSION(:),
ALLOCATABLE :: work_sp
2462 #if defined(__SCALAPACK)
2464 INTEGER,
DIMENSION(9) :: desca
2465 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
2470 CALL timeset(routinen, handle)
2472 mat => matrix%local_data
2473 mat_sp => matrix%local_data_sp
2474 nrows_global = matrix%matrix_struct%nrow_global
2475 cpassert(nrows_global .EQ. matrix%matrix_struct%ncol_global)
2476 ALLOCATE (ipivot(nrows_global))
2478 #if defined(__SCALAPACK)
2479 desca = matrix%matrix_struct%descriptor
2480 IF (matrix%use_sp)
THEN
2481 CALL psgetrf(nrows_global, nrows_global, &
2482 mat_sp, 1, 1, desca, ipivot, info)
2484 CALL pdgetrf(nrows_global, nrows_global, &
2485 mat, 1, 1, desca, ipivot, info)
2489 IF (matrix%use_sp)
THEN
2490 CALL sgetrf(nrows_global, nrows_global, &
2491 mat_sp, lda, ipivot, info)
2493 CALL dgetrf(nrows_global, nrows_global, &
2494 mat, lda, ipivot, info)
2498 CALL cp_abort(__location__,
"LU decomposition has failed")
2501 IF (matrix%use_sp)
THEN
2504 ALLOCATE (work_sp(1))
2506 #if defined(__SCALAPACK)
2508 IF (matrix%use_sp)
THEN
2509 CALL psgetri(nrows_global, mat_sp, 1, 1, desca, &
2510 ipivot, work_sp, -1, iwork, -1, info)
2511 lwork = int(work_sp(1))
2512 DEALLOCATE (work_sp)
2513 ALLOCATE (work_sp(lwork))
2515 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2516 ipivot, work, -1, iwork, -1, info)
2517 lwork = int(work(1))
2519 ALLOCATE (work(lwork))
2521 liwork = int(iwork(1))
2523 ALLOCATE (iwork(liwork))
2524 IF (matrix%use_sp)
THEN
2525 CALL psgetri(nrows_global, mat_sp, 1, 1, desca, &
2526 ipivot, work_sp, lwork, iwork, liwork, info)
2528 CALL pdgetri(nrows_global, mat, 1, 1, desca, &
2529 ipivot, work, lwork, iwork, liwork, info)
2533 IF (matrix%use_sp)
THEN
2534 CALL sgetri(nrows_global, mat_sp, lda, &
2535 ipivot, work_sp, -1, info)
2536 lwork = int(work_sp(1))
2537 DEALLOCATE (work_sp)
2538 ALLOCATE (work_sp(lwork))
2539 CALL sgetri(nrows_global, mat_sp, lda, &
2540 ipivot, work_sp, lwork, info)
2542 CALL dgetri(nrows_global, mat, lda, &
2543 ipivot, work, -1, info)
2544 lwork = int(work(1))
2546 ALLOCATE (work(lwork))
2547 CALL dgetri(nrows_global, mat, lda, &
2548 ipivot, work, lwork, info)
2551 IF (matrix%use_sp)
THEN
2552 DEALLOCATE (work_sp)
2558 IF (
PRESENT(info_out))
THEN
2562 CALL cp_abort(__location__,
"LU inversion has failed")
2565 CALL timestop(handle)
2567 END SUBROUTINE cp_fm_lu_invert
2580 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2581 CHARACTER,
INTENT(IN) :: mode
2582 REAL(kind=
dp) :: res
2584 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_norm'
2586 INTEGER :: nrows, ncols, handle, lwork, nrows_local, ncols_local
2587 REAL(kind=
sp) :: res_sp
2588 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2589 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: aa_sp
2590 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: work
2591 REAL(kind=
sp),
DIMENSION(:),
ALLOCATABLE :: work_sp
2592 #if defined(__SCALAPACK)
2593 INTEGER,
DIMENSION(9) :: desca
2598 CALL timeset(routinen, handle)
2601 nrow_global=nrows, &
2602 ncol_global=ncols, &
2603 nrow_local=nrows_local, &
2604 ncol_local=ncols_local)
2605 aa => matrix%local_data
2606 aa_sp => matrix%local_data_sp
2608 #if defined(__SCALAPACK)
2609 desca = matrix%matrix_struct%descriptor
2613 CASE (
'1',
'O',
'o')
2617 CASE (
'F',
'f',
'E',
'e')
2620 cpabort(
"mode input is not valid")
2622 IF (matrix%use_sp)
THEN
2623 ALLOCATE (work_sp(lwork))
2624 res_sp = pslange(mode, nrows, ncols, aa_sp, 1, 1, desca, work_sp)
2625 DEALLOCATE (work_sp)
2626 res = real(res_sp, kind=
dp)
2628 ALLOCATE (work(lwork))
2629 res = pdlange(mode, nrows, ncols, aa, 1, 1, desca, work)
2636 CASE (
'1',
'O',
'o')
2640 CASE (
'F',
'f',
'E',
'e')
2643 cpabort(
"mode input is not valid")
2645 IF (matrix%use_sp)
THEN
2646 ALLOCATE (work_sp(lwork))
2647 lda =
SIZE(aa_sp, 1)
2648 res_sp = slange(mode, nrows, ncols, aa_sp, lda, work_sp)
2649 DEALLOCATE (work_sp)
2650 res = real(res_sp, kind=
dp)
2652 ALLOCATE (work(lwork))
2654 res = dlange(mode, nrows, ncols, aa, lda, work)
2659 CALL timestop(handle)
2669 FUNCTION cp_fm_latra(matrix)
RESULT(res)
2670 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2671 REAL(kind=
dp) :: res
2673 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_latra'
2675 INTEGER :: nrows, ncols, handle
2676 REAL(kind=
sp) :: res_sp
2677 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: aa
2678 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: aa_sp
2679 #if defined(__SCALAPACK)
2680 INTEGER,
DIMENSION(9) :: desca
2685 CALL timeset(routinen, handle)
2687 nrows = matrix%matrix_struct%nrow_global
2688 ncols = matrix%matrix_struct%ncol_global
2689 cpassert(nrows .EQ. ncols)
2690 aa => matrix%local_data
2691 aa_sp => matrix%local_data_sp
2693 #if defined(__SCALAPACK)
2694 desca = matrix%matrix_struct%descriptor
2695 IF (matrix%use_sp)
THEN
2696 res_sp = pslatra(nrows, aa_sp, 1, 1, desca)
2697 res = real(res_sp, kind=
dp)
2699 res = pdlatra(nrows, aa, 1, 1, desca)
2702 IF (matrix%use_sp)
THEN
2705 res_sp = res_sp + aa_sp(ii, ii)
2707 res = real(res_sp, kind=
dp)
2711 res = res + aa(ii, ii)
2716 CALL timestop(handle)
2718 END FUNCTION cp_fm_latra
2733 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2734 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2735 INTEGER,
INTENT(IN) :: nrow, ncol, first_row, first_col
2737 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdgeqpf'
2740 INTEGER :: info, lwork
2741 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
2742 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2743 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2744 #if defined(__SCALAPACK)
2745 INTEGER,
DIMENSION(9) :: descc
2750 CALL timeset(routinen, handle)
2752 a => matrix%local_data
2754 ALLOCATE (work(2*nrow))
2755 ALLOCATE (ipiv(ncol))
2758 #if defined(__SCALAPACK)
2759 descc(:) = matrix%matrix_struct%descriptor(:)
2761 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2762 lwork = int(work(1))
2764 ALLOCATE (work(lwork))
2769 CALL pdgeqpf(nrow, ncol, a, first_row, first_col, descc, ipiv, tau, work, lwork, info)
2771 cpassert(first_row == 1 .AND. first_col == 1)
2773 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2774 lwork = int(work(1))
2776 ALLOCATE (work(lwork))
2779 CALL dgeqp3(nrow, ncol, a, lda, ipiv, tau, work, lwork, info)
2786 CALL timestop(handle)
2805 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2806 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tau
2807 INTEGER,
INTENT(IN) :: nrow, first_row, first_col
2809 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_pdorgqr'
2812 INTEGER :: info, lwork
2813 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2814 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
2815 #if defined(__SCALAPACK)
2816 INTEGER,
DIMENSION(9) :: descc
2821 CALL timeset(routinen, handle)
2823 a => matrix%local_data
2825 ALLOCATE (work(2*nrow))
2828 #if defined(__SCALAPACK)
2829 descc(:) = matrix%matrix_struct%descriptor(:)
2831 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2833 lwork = int(work(1))
2835 ALLOCATE (work(lwork))
2838 CALL pdorgqr(nrow, nrow, nrow, a, first_row, first_col, descc, tau, work, lwork, info)
2840 cpassert(first_row == 1 .AND. first_col == 1)
2842 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2843 lwork = int(work(1))
2845 ALLOCATE (work(lwork))
2846 CALL dorgqr(nrow, nrow, nrow, a, lda, tau, work, lwork, info)
2851 CALL timestop(handle)
2864 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2865 INTEGER,
INTENT(IN) :: irow, jrow
2866 REAL(
dp),
INTENT(IN) :: cs, sn
2868 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_rows'
2869 INTEGER :: handle, nrow, ncol
2871 #if defined(__SCALAPACK)
2872 INTEGER :: info, lwork
2873 INTEGER,
DIMENSION(9) :: desc
2874 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2877 CALL timeset(routinen, handle)
2880 #if defined(__SCALAPACK)
2882 ALLOCATE (work(lwork))
2883 desc(:) = matrix%matrix_struct%descriptor(:)
2885 matrix%local_data(1, 1), irow, 1, desc, ncol, &
2886 matrix%local_data(1, 1), jrow, 1, desc, ncol, &
2887 cs, sn, work, lwork, info)
2891 CALL drot(ncol, matrix%local_data(irow, 1), ncol, matrix%local_data(jrow, 1), ncol, cs, sn)
2894 CALL timestop(handle)
2906 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2907 INTEGER,
INTENT(IN) :: icol, jcol
2908 REAL(
dp),
INTENT(IN) :: cs, sn
2910 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_rot_cols'
2911 INTEGER :: handle, nrow, ncol
2913 #if defined(__SCALAPACK)
2914 INTEGER :: info, lwork
2915 INTEGER,
DIMENSION(9) :: desc
2916 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
2919 CALL timeset(routinen, handle)
2922 #if defined(__SCALAPACK)
2924 ALLOCATE (work(lwork))
2925 desc(:) = matrix%matrix_struct%descriptor(:)
2927 matrix%local_data(1, 1), 1, icol, desc, 1, &
2928 matrix%local_data(1, 1), 1, jcol, desc, 1, &
2929 cs, sn, work, lwork, info)
2933 CALL drot(nrow, matrix%local_data(1, icol), 1, matrix%local_data(1, jcol), 1, cs, sn)
2936 CALL timestop(handle)
2953 TYPE(cp_fm_type),
INTENT(IN) :: matrix_a
2954 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: b
2955 INTEGER,
INTENT(IN),
OPTIONAL :: nrows, ncols, start_row, start_col
2956 LOGICAL,
INTENT(IN),
OPTIONAL :: do_norm, do_print
2958 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_Gram_Schmidt_orthonorm'
2960 INTEGER :: end_col_global, end_col_local, end_row_global, end_row_local, handle, i, j, &
2961 j_col, ncol_global, ncol_local, nrow_global, nrow_local, start_col_global, &
2962 start_col_local, start_row_global, start_row_local, this_col, unit_nr
2963 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2964 LOGICAL :: my_do_norm, my_do_print
2965 REAL(kind=
dp) :: norm
2966 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2968 CALL timeset(routinen, handle)
2971 IF (
PRESENT(do_norm)) my_do_norm = do_norm
2973 my_do_print = .false.
2974 IF (
PRESENT(do_print) .AND. (my_do_norm)) my_do_print = do_print
2977 IF (my_do_print)
THEN
2979 IF (unit_nr < 1) my_do_print = .false.
2982 IF (
SIZE(b) /= 0)
THEN
2983 IF (
PRESENT(nrows))
THEN
2986 nrow_global =
SIZE(b, 1)
2989 IF (
PRESENT(ncols))
THEN
2992 ncol_global =
SIZE(b, 2)
2995 IF (
PRESENT(start_row))
THEN
2996 start_row_global = start_row
2998 start_row_global = 1
3001 IF (
PRESENT(start_col))
THEN
3002 start_col_global = start_col
3004 start_col_global = 1
3007 end_row_global = start_row_global + nrow_global - 1
3008 end_col_global = start_col_global + ncol_global - 1
3011 nrow_global=nrow_global, ncol_global=ncol_global, &
3012 nrow_local=nrow_local, ncol_local=ncol_local, &
3013 row_indices=row_indices, col_indices=col_indices)
3014 IF (end_row_global > nrow_global)
THEN
3015 end_row_global = nrow_global
3017 IF (end_col_global > ncol_global)
THEN
3018 end_col_global = ncol_global
3025 DO start_row_local = 1, nrow_local
3026 IF (row_indices(start_row_local) >= start_row_global)
EXIT
3029 DO end_row_local = start_row_local, nrow_local
3030 IF (row_indices(end_row_local) > end_row_global)
EXIT
3032 end_row_local = end_row_local - 1
3034 DO start_col_local = 1, ncol_local
3035 IF (col_indices(start_col_local) >= start_col_global)
EXIT
3038 DO end_col_local = start_col_local, ncol_local
3039 IF (col_indices(end_col_local) > end_col_global)
EXIT
3041 end_col_local = end_col_local - 1
3043 a => matrix_a%local_data
3045 this_col = col_indices(start_col_local) - start_col_global + 1
3047 b(:, this_col) = a(:, start_col_local)
3049 IF (my_do_norm)
THEN
3050 norm = sqrt(accurate_dot_product(b(:, this_col), b(:, this_col)))
3051 b(:, this_col) = b(:, this_col)/norm
3052 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
3055 DO i = start_col_local + 1, end_col_local
3056 this_col = col_indices(i) - start_col_global + 1
3057 b(:, this_col) = a(:, i)
3058 DO j = start_col_local, i - 1
3059 j_col = col_indices(j) - start_col_global + 1
3060 b(:, this_col) = b(:, this_col) - &
3061 accurate_dot_product(b(:, j_col), b(:, this_col))* &
3062 b(:, j_col)/accurate_dot_product(b(:, j_col), b(:, j_col))
3065 IF (my_do_norm)
THEN
3066 norm = sqrt(accurate_dot_product(b(:, this_col), b(:, this_col)))
3067 b(:, this_col) = b(:, this_col)/norm
3068 IF (my_do_print)
WRITE (unit_nr,
'(I3,F8.3)') this_col, norm
3072 CALL matrix_a%matrix_struct%para_env%sum(b)
3075 CALL timestop(handle)
3085 TYPE(cp_fm_type) :: fm_matrix
3086 INTEGER,
INTENT(in) :: n
3089 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
3090 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
3091 #if defined(__SCALAPACK)
3092 INTEGER,
DIMENSION(9) :: desca
3095 a => fm_matrix%local_data
3096 a_sp => fm_matrix%local_data_sp
3097 #if defined(__SCALAPACK)
3098 desca(:) = fm_matrix%matrix_struct%descriptor(:)
3099 IF (fm_matrix%use_sp)
THEN
3100 CALL pspotrf(
'U', n, a_sp(1, 1), 1, 1, desca, info)
3102 CALL pdpotrf(
'U', n, a(1, 1), 1, 1, desca, info)
3105 IF (fm_matrix%use_sp)
THEN
3106 CALL spotrf(
'U', n, a_sp(1, 1),
SIZE(a_sp, 1), info)
3108 CALL dpotrf(
'U', n, a(1, 1),
SIZE(a, 1), info)
3112 cpabort(
"Cholesky decomposition failed. Matrix ill conditioned ?")
3122 TYPE(cp_fm_type) :: fm_matrix
3123 INTEGER,
INTENT(in) :: n
3125 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
3126 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
3128 #if defined(__SCALAPACK)
3129 INTEGER,
DIMENSION(9) :: desca
3132 a => fm_matrix%local_data
3133 a_sp => fm_matrix%local_data_sp
3134 #if defined(__SCALAPACK)
3135 desca(:) = fm_matrix%matrix_struct%descriptor(:)
3136 IF (fm_matrix%use_sp)
THEN
3137 CALL pspotri(
'U', n, a_sp(1, 1), 1, 1, desca, info)
3139 CALL pdpotri(
'U', n, a(1, 1), 1, 1, desca, info)
3142 IF (fm_matrix%use_sp)
THEN
3143 CALL spotri(
'U', n, a_sp(1, 1),
SIZE(a_sp, 1), info)
3145 CALL dpotri(
'U', n, a(1, 1),
SIZE(a, 1), info)
3162 TYPE(cp_fm_type) :: fm_matrix
3163 TYPE(cp_fm_type) :: fm_matrixb
3164 TYPE(cp_fm_type) :: fm_matrixout
3165 INTEGER,
INTENT(IN) :: neig
3166 CHARACTER(LEN=*),
INTENT(IN) :: op
3167 CHARACTER(LEN=*),
INTENT(IN) :: pos
3168 CHARACTER(LEN=*),
INTENT(IN) :: transa
3170 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b, outm
3171 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp, b_sp, outm_sp
3173 REAL(kind=
dp) :: alpha
3174 #if defined(__SCALAPACK)
3176 INTEGER,
DIMENSION(9) :: desca, descb, descout
3180 a => fm_matrix%local_data
3181 b => fm_matrixb%local_data
3182 outm => fm_matrixout%local_data
3183 a_sp => fm_matrix%local_data_sp
3184 b_sp => fm_matrixb%local_data_sp
3185 outm_sp => fm_matrixout%local_data_sp
3187 n = fm_matrix%matrix_struct%nrow_global
3190 #if defined(__SCALAPACK)
3191 desca(:) = fm_matrix%matrix_struct%descriptor(:)
3192 descb(:) = fm_matrixb%matrix_struct%descriptor(:)
3193 descout(:) = fm_matrixout%matrix_struct%descriptor(:)
3196 IF (fm_matrix%use_sp)
THEN
3197 CALL pscopy(n, a_sp(1, 1), 1, i, desca, 1, outm_sp(1, 1), 1, i, descout, 1)
3199 CALL pdcopy(n, a(1, 1), 1, i, desca, 1, outm(1, 1), 1, i, descout, 1)
3202 IF (op .EQ.
"SOLVE")
THEN
3203 IF (fm_matrix%use_sp)
THEN
3204 CALL pstrsm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1), 1, 1, descb, &
3205 outm_sp(1, 1), 1, 1, descout)
3207 CALL pdtrsm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1), 1, 1, descb, outm(1, 1), 1, 1, descout)
3210 IF (fm_matrix%use_sp)
THEN
3211 CALL pstrmm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1), 1, 1, descb, &
3212 outm_sp(1, 1), 1, 1, descout)
3214 CALL pdtrmm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1), 1, 1, descb, outm(1, 1), 1, 1, descout)
3219 IF (fm_matrix%use_sp)
THEN
3220 CALL scopy(neig*n, a_sp(1, 1), 1, outm_sp(1, 1), 1)
3222 CALL dcopy(neig*n, a(1, 1), 1, outm(1, 1), 1)
3224 IF (op .EQ.
"SOLVE")
THEN
3225 IF (fm_matrix%use_sp)
THEN
3226 CALL strsm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1),
SIZE(b_sp, 1), outm_sp(1, 1), n)
3228 CALL dtrsm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1),
SIZE(b, 1), outm(1, 1), n)
3231 IF (fm_matrix%use_sp)
THEN
3232 CALL strmm(pos,
'U', transa,
'N', n, neig, real(alpha,
sp), b_sp(1, 1), n, outm_sp(1, 1), n)
3234 CALL dtrmm(pos,
'U', transa,
'N', n, neig, alpha, b(1, 1), n, outm(1, 1), n)
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_potrf(fm_matrix, n)
Cholesky decomposition.
subroutine, public cp_fm_solve(matrix_a, general_a)
computes the the solution to A*b=A_general using lu decomposition pay attention, both matrices are ov...
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_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_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_qr_factorization(matrix_a, matrix_r, nrow_fact, ncol_fact, first_row, first_col)
performs a QR factorization of the input rectangular matrix A or of a submatrix of A the computed upp...
subroutine, public cp_fm_transpose(matrix, matrixt)
transposes a matrix matrixt = matrix ^ T
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_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_upper_to_full(matrix, work)
given an upper triangular matrix computes the corresponding full matrix
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_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_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_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_potri(fm_matrix, n)
Invert trianguar matrix.
subroutine, public cp_fm_triangular_multiply(triangular_matrix, matrix_b, side, transpose_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, alpha)
multiplies in place by a triangular matrix: matrix_b = alpha op(triangular_matrix) matrix_b or (if si...
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
Interface to the message passing library MPI.