31#include "../base/base_uses.f90"
36 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
37 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_cfm_basic_linalg'
61 REAL(kind=
dp),
EXTERNAL :: zlange, pzlange
64 MODULE PROCEDURE cp_cfm_dscale, cp_cfm_zscale
80 COMPLEX(KIND=dp),
INTENT(OUT) :: det_a
81 COMPLEX(KIND=dp) :: determinant
83 COMPLEX(KIND=dp),
DIMENSION(:, :),
POINTER :: a
84 INTEGER :: n, i, info, p
85 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
86 COMPLEX(KIND=dp),
DIMENSION(:),
POINTER :: diag
88#if defined(__parallel)
89 INTEGER :: myprow, nprow, npcol, nrow_local, irow_local, &
90 mypcol, ncol_local, icol_local, j
91 INTEGER,
DIMENSION(9) :: desca
95 matrix_struct=matrix_a%matrix_struct, &
99 a => matrix_lu%local_data
100 n = matrix_lu%matrix_struct%nrow_global
106#if defined(__parallel)
108 desca(:) = matrix_lu%matrix_struct%descriptor(:)
109 CALL pzgetrf(n, n, a(1, 1), 1, 1, desca, ipivot, info)
110 myprow = matrix_lu%matrix_struct%context%mepos(1)
111 mypcol = matrix_lu%matrix_struct%context%mepos(2)
112 nprow = matrix_lu%matrix_struct%context%num_pe(1)
113 npcol = matrix_lu%matrix_struct%context%num_pe(2)
114 nrow_local = matrix_lu%matrix_struct%nrow_locals(myprow)
115 ncol_local = matrix_lu%matrix_struct%ncol_locals(mypcol)
117 DO irow_local = 1, nrow_local
118 i = matrix_lu%matrix_struct%row_indices(irow_local)
119 DO icol_local = 1, ncol_local
120 j = matrix_lu%matrix_struct%col_indices(icol_local)
121 IF (i == j) diag(i) = matrix_lu%local_data(irow_local, icol_local)
124 CALL matrix_lu%matrix_struct%para_env%sum(diag)
125 determinant = product(diag)
126 DO irow_local = 1, nrow_local
127 i = matrix_lu%matrix_struct%row_indices(irow_local)
128 IF (ipivot(irow_local) /= i) p = p + 1
130 CALL matrix_lu%matrix_struct%para_env%sum(p)
134 CALL zgetrf(n, n, a(1, 1), n, ipivot, info)
136 diag(i) = matrix_lu%local_data(i, i)
138 determinant = product(diag)
140 IF (ipivot(i) /= i) p = p + 1
146 det_a = determinant*(-2*mod(p, 2) + 1.0_dp)
157 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
159 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_schur_product'
161 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b, c
162 INTEGER :: handle, icol_local, irow_local, mypcol, &
163 myprow, ncol_local, nrow_local
165 CALL timeset(routinen, handle)
167 myprow = matrix_a%matrix_struct%context%mepos(1)
168 mypcol = matrix_a%matrix_struct%context%mepos(2)
170 a => matrix_a%local_data
171 b => matrix_b%local_data
172 c => matrix_c%local_data
174 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
175 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
177 DO icol_local = 1, ncol_local
178 DO irow_local = 1, nrow_local
179 c(irow_local, icol_local) = a(irow_local, icol_local)*b(irow_local, icol_local)
183 CALL timestop(handle)
193 SUBROUTINE cp_cfm_schur_product_cc(matrix_a, matrix_b, matrix_c)
195 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
197 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_schur_product_cc'
199 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b, c
200 INTEGER :: handle, icol_local, irow_local, mypcol, &
201 myprow, ncol_local, nrow_local
203 CALL timeset(routinen, handle)
205 myprow = matrix_a%matrix_struct%context%mepos(1)
206 mypcol = matrix_a%matrix_struct%context%mepos(2)
208 a => matrix_a%local_data
209 b => matrix_b%local_data
210 c => matrix_c%local_data
212 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
213 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
215 DO icol_local = 1, ncol_local
216 DO irow_local = 1, nrow_local
217 c(irow_local, icol_local) = a(irow_local, icol_local)*conjg(b(irow_local, icol_local))
221 CALL timestop(handle)
223 END SUBROUTINE cp_cfm_schur_product_cc
243 COMPLEX(kind=dp),
INTENT(in) :: alpha
245 COMPLEX(kind=dp),
INTENT(in),
OPTIONAL :: beta
246 TYPE(
cp_cfm_type),
INTENT(IN),
OPTIONAL :: matrix_b
248 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_scale_and_add'
250 COMPLEX(kind=dp) :: my_beta
251 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b
252 INTEGER :: handle, icol_local, irow_local, mypcol, &
253 myprow, ncol_local, nrow_local
255 CALL timeset(routinen, handle)
258 IF (
PRESENT(beta)) my_beta = beta
262 myprow = matrix_a%matrix_struct%context%mepos(1)
263 mypcol = matrix_a%matrix_struct%context%mepos(2)
265 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
266 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
268 a => matrix_a%local_data
270 IF (my_beta ==
z_zero)
THEN
274 ELSE IF (alpha ==
z_one)
THEN
275 CALL timestop(handle)
278 a(:, :) = alpha*a(:, :)
282 cpassert(
PRESENT(matrix_b))
283 IF (matrix_a%matrix_struct%context /= matrix_b%matrix_struct%context) &
284 cpabort(
"matrixes must be in the same blacs context")
287 matrix_b%matrix_struct))
THEN
289 b => matrix_b%local_data
292 IF (my_beta ==
z_one)
THEN
294 DO icol_local = 1, ncol_local
295 DO irow_local = 1, nrow_local
296 a(irow_local, icol_local) = b(irow_local, icol_local)
301 DO icol_local = 1, ncol_local
302 DO irow_local = 1, nrow_local
303 a(irow_local, icol_local) = my_beta*b(irow_local, icol_local)
307 ELSE IF (alpha ==
z_one)
THEN
308 IF (my_beta ==
z_one)
THEN
310 DO icol_local = 1, ncol_local
311 DO irow_local = 1, nrow_local
312 a(irow_local, icol_local) = a(irow_local, icol_local) + b(irow_local, icol_local)
317 DO icol_local = 1, ncol_local
318 DO irow_local = 1, nrow_local
319 a(irow_local, icol_local) = a(irow_local, icol_local) + my_beta*b(irow_local, icol_local)
325 DO icol_local = 1, ncol_local
326 DO irow_local = 1, nrow_local
327 a(irow_local, icol_local) = alpha*a(irow_local, icol_local) + my_beta*b(irow_local, icol_local)
332 CALL cp_abort(__location__, &
333 "cp_cfm_scale_and_add is not yet implemented for cases "// &
334 "where input two matrix structures are not equivalent")
337 CALL timestop(handle)
352 COMPLEX(kind=dp),
INTENT(in) :: alpha
354 COMPLEX(kind=dp),
INTENT(in) :: beta
357 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_scale_and_add_fm'
359 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
360 INTEGER :: handle, icol_local, irow_local, mypcol, &
361 myprow, ncol_local, nrow_local
362 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: b
364 CALL timeset(routinen, handle)
368 myprow = matrix_a%matrix_struct%context%mepos(1)
369 mypcol = matrix_a%matrix_struct%context%mepos(2)
371 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
372 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
374 a => matrix_a%local_data
380 ELSE IF (alpha ==
z_one)
THEN
381 CALL timestop(handle)
384 a(:, :) = alpha*a(:, :)
388 IF (matrix_a%matrix_struct%context /= matrix_b%matrix_struct%context) &
389 cpabort(
"matrices must be in the same blacs context")
392 matrix_b%matrix_struct))
THEN
394 b => matrix_b%local_data
397 IF (beta ==
z_one)
THEN
399 DO icol_local = 1, ncol_local
400 DO irow_local = 1, nrow_local
401 a(irow_local, icol_local) = b(irow_local, icol_local)
406 DO icol_local = 1, ncol_local
407 DO irow_local = 1, nrow_local
408 a(irow_local, icol_local) = beta*b(irow_local, icol_local)
412 ELSE IF (alpha ==
z_one)
THEN
413 IF (beta ==
z_one)
THEN
415 DO icol_local = 1, ncol_local
416 DO irow_local = 1, nrow_local
417 a(irow_local, icol_local) = a(irow_local, icol_local) + b(irow_local, icol_local)
422 DO icol_local = 1, ncol_local
423 DO irow_local = 1, nrow_local
424 a(irow_local, icol_local) = a(irow_local, icol_local) + beta*b(irow_local, icol_local)
430 DO icol_local = 1, ncol_local
431 DO irow_local = 1, nrow_local
432 a(irow_local, icol_local) = alpha*a(irow_local, icol_local) + beta*b(irow_local, icol_local)
437 CALL cp_abort(__location__, &
438 "cp_cfm_scale_and_add_fm is not yet implemented for cases "// &
439 "where two input matrix structures are not equivalent")
442 CALL timestop(handle)
458 COMPLEX(kind=dp),
INTENT(out) :: determinant
460 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_lu_decompose'
462 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
463 INTEGER :: counter, handle, info, irow, nrow_global
464 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
466#if defined(__parallel)
467 INTEGER :: icol, ncol_local, nrow_local
468 INTEGER,
DIMENSION(9) :: desca
469 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
474 CALL timeset(routinen, handle)
476 nrow_global = matrix_a%matrix_struct%nrow_global
477 a => matrix_a%local_data
479 ALLOCATE (ipivot(nrow_global))
480#if defined(__parallel)
481 CALL cp_cfm_get_info(matrix_a, nrow_local=nrow_local, ncol_local=ncol_local, &
482 row_indices=row_indices, col_indices=col_indices)
484 desca(:) = matrix_a%matrix_struct%descriptor(:)
485 CALL pzgetrf(nrow_global, nrow_global, a(1, 1), 1, 1, desca, ipivot, info)
488 DO irow = 1, nrow_local
489 IF (ipivot(irow) /= row_indices(irow)) counter = counter + 1
492 IF (mod(counter, 2) == 0)
THEN
501 DO WHILE (irow <= nrow_local .AND. icol <= ncol_local)
502 IF (row_indices(irow) < col_indices(icol))
THEN
504 ELSE IF (row_indices(irow) > col_indices(icol))
THEN
507 determinant = determinant*a(irow, icol)
512 CALL matrix_a%matrix_struct%para_env%prod(determinant)
515 CALL zgetrf(nrow_global, nrow_global, a(1, 1), lda, ipivot, info)
518 DO irow = 1, nrow_global
519 IF (ipivot(irow) /= irow) counter = counter + 1
520 determinant = determinant*a(irow, irow)
522 IF (mod(counter, 2) == 1) determinant = -1.0_dp*determinant
529 CALL timestop(handle)
559 SUBROUTINE cp_cfm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, &
560 matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, &
562 CHARACTER(len=1),
INTENT(IN) :: transa, transb
563 INTEGER,
INTENT(IN) :: m, n, k
564 COMPLEX(kind=dp),
INTENT(IN) :: alpha
565 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b
566 COMPLEX(kind=dp),
INTENT(IN) :: beta
568 INTEGER,
INTENT(IN),
OPTIONAL :: a_first_col, a_first_row, b_first_col, &
569 b_first_row, c_first_col, c_first_row
571 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_gemm'
573 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b, c
574 INTEGER :: handle, i_a, i_b, i_c, j_a, j_b, j_c
575#if defined(__parallel)
576 INTEGER,
DIMENSION(9) :: desca, descb, descc
578 INTEGER :: lda, ldb, ldc
581 CALL timeset(routinen, handle)
582 a => matrix_a%local_data
583 b => matrix_b%local_data
584 c => matrix_c%local_data
587 IF (
PRESENT(a_first_row)) i_a = a_first_row
590 IF (
PRESENT(a_first_col)) j_a = a_first_col
593 IF (
PRESENT(b_first_row)) i_b = b_first_row
596 IF (
PRESENT(b_first_col)) j_b = b_first_col
599 IF (
PRESENT(c_first_row)) i_c = c_first_row
602 IF (
PRESENT(c_first_col)) j_c = c_first_col
604#if defined(__parallel)
605 desca(:) = matrix_a%matrix_struct%descriptor(:)
606 descb(:) = matrix_b%matrix_struct%descriptor(:)
607 descc(:) = matrix_c%matrix_struct%descriptor(:)
609 CALL pzgemm(transa, transb, m, n, k, alpha, a(1, 1), i_a, j_a, desca, &
610 b(1, 1), i_b, j_b, descb, beta, c(1, 1), i_c, j_c, descc)
617 CALL zgemm(transa, transb, m, n, k, alpha, a(i_a, j_a), &
618 lda, b(i_b, j_b), ldb, beta, c(i_c, j_c), ldc)
620 CALL timestop(handle)
633 COMPLEX(kind=dp),
DIMENSION(:),
INTENT(IN) :: scaling
635 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_column_scale'
637 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
638 INTEGER :: handle, icol_local, ncol_local, &
640#if defined(__parallel)
641 INTEGER,
DIMENSION(:),
POINTER :: col_indices
644 CALL timeset(routinen, handle)
646 a => matrix_a%local_data
648#if defined(__parallel)
649 CALL cp_cfm_get_info(matrix_a, nrow_local=nrow_local, ncol_local=ncol_local, col_indices=col_indices)
650 ncol_local = min(ncol_local,
SIZE(scaling))
652 DO icol_local = 1, ncol_local
653 a(1:nrow_local, icol_local) = scaling(col_indices(icol_local))*a(1:nrow_local, icol_local)
656 nrow_local =
SIZE(a, 1)
657 ncol_local = min(
SIZE(a, 2),
SIZE(scaling))
659 DO icol_local = 1, ncol_local
660 a(1:nrow_local, icol_local) = scaling(icol_local)*a(1:nrow_local, icol_local)
664 CALL timestop(handle)
673 SUBROUTINE cp_cfm_dscale(alpha, matrix_a)
674 REAL(kind=
dp),
INTENT(IN) :: alpha
677 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_dscale'
679 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
682 CALL timeset(routinen, handle)
686 a => matrix_a%local_data
688 CALL zdscal(
SIZE(a), alpha, a(1, 1), 1)
690 CALL timestop(handle)
691 END SUBROUTINE cp_cfm_dscale
701 SUBROUTINE cp_cfm_zscale(alpha, matrix_a)
702 COMPLEX(kind=dp),
INTENT(IN) :: alpha
705 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_cfm_zscale'
707 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
710 CALL timeset(routinen, handle)
714 a => matrix_a%local_data
716 a(:, :) = alpha*a(:, :)
718 CALL timestop(handle)
719 END SUBROUTINE cp_cfm_zscale
731 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, general_a
732 COMPLEX(kind=dp),
OPTIONAL :: determinant
734 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_solve'
736 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, a_general
737 INTEGER :: counter, handle, info, irow, nrow_global
738 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
740#if defined(__parallel)
741 INTEGER :: icol, ncol_local, nrow_local
742 INTEGER,
DIMENSION(9) :: desca, descb
743 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
748 CALL timeset(routinen, handle)
750 a => matrix_a%local_data
751 a_general => general_a%local_data
752 nrow_global = matrix_a%matrix_struct%nrow_global
753 ALLOCATE (ipivot(nrow_global))
755#if defined(__parallel)
756 desca(:) = matrix_a%matrix_struct%descriptor(:)
757 descb(:) = general_a%matrix_struct%descriptor(:)
758 CALL pzgetrf(nrow_global, nrow_global, a(1, 1), 1, 1, desca, ipivot, info)
759 IF (
PRESENT(determinant))
THEN
760 CALL cp_cfm_get_info(matrix_a, nrow_local=nrow_local, ncol_local=ncol_local, &
761 row_indices=row_indices, col_indices=col_indices)
764 DO irow = 1, nrow_local
765 IF (ipivot(irow) /= row_indices(irow)) counter = counter + 1
768 IF (mod(counter, 2) == 0)
THEN
777 DO WHILE (irow <= nrow_local .AND. icol <= ncol_local)
778 IF (row_indices(irow) < col_indices(icol))
THEN
780 ELSE IF (row_indices(irow) > col_indices(icol))
THEN
783 determinant = determinant*a(irow, icol)
788 CALL matrix_a%matrix_struct%para_env%prod(determinant)
791 CALL pzgetrs(
"N", nrow_global, nrow_global, a(1, 1), 1, 1, desca, &
792 ipivot, a_general(1, 1), 1, 1, descb, info)
795 ldb =
SIZE(a_general, 1)
796 CALL zgetrf(nrow_global, nrow_global, a(1, 1), lda, ipivot, info)
797 IF (
PRESENT(determinant))
THEN
800 DO irow = 1, nrow_global
801 IF (ipivot(irow) /= irow) counter = counter + 1
802 determinant = determinant*a(irow, irow)
804 IF (mod(counter, 2) == 1) determinant = -1.0_dp*determinant
806 CALL zgetrs(
"N", nrow_global, nrow_global, a(1, 1), lda, ipivot, a_general(1, 1), ldb, info)
812 CALL timestop(handle)
824 INTEGER,
INTENT(out),
OPTIONAL :: info_out
826 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_lu_invert'
828 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: work
829 COMPLEX(kind=dp),
DIMENSION(1) :: work1
830 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: mat
831 INTEGER :: handle, info, lwork, nrows_global
832 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
834#if defined(__parallel)
836 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
837 INTEGER,
DIMENSION(1) :: iwork1
838 INTEGER,
DIMENSION(9) :: desca
843 CALL timeset(routinen, handle)
845 mat => matrix%local_data
846 nrows_global = matrix%matrix_struct%nrow_global
847 cpassert(nrows_global == matrix%matrix_struct%ncol_global)
848 ALLOCATE (ipivot(nrows_global))
851#if defined(__parallel)
852 desca = matrix%matrix_struct%descriptor
853 CALL pzgetrf(nrows_global, nrows_global, &
854 mat(1, 1), 1, 1, desca, ipivot, info)
857 CALL zgetrf(nrows_global, nrows_global, &
858 mat(1, 1), lda, ipivot, info)
861 CALL cp_abort(__location__,
"LU decomposition has failed")
865#if defined(__parallel)
866 CALL pzgetri(nrows_global, mat(1, 1), 1, 1, desca, &
867 ipivot, work1, -1, iwork1, -1, info)
868 lwork = int(work1(1))
869 liwork = int(iwork1(1))
870 ALLOCATE (work(lwork))
871 ALLOCATE (iwork(liwork))
872 CALL pzgetri(nrows_global, mat(1, 1), 1, 1, desca, &
873 ipivot, work, lwork, iwork, liwork, info)
876 CALL zgetri(nrows_global, mat(1, 1), lda, ipivot, work1, -1, info)
877 lwork = int(work1(1))
878 ALLOCATE (work(lwork))
879 CALL zgetri(nrows_global, mat(1, 1), lda, ipivot, work, lwork, info)
884 IF (
PRESENT(info_out))
THEN
888 CALL cp_abort(__location__,
"LU inversion has failed")
891 CALL timestop(handle)
908 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b
909 COMPLEX(kind=dp),
INTENT(out) :: trace
911 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_trace'
913 INTEGER :: handle, mypcol, myprow, ncol_local, &
914 npcol, nprow, nrow_local
918 CALL timeset(routinen, handle)
920 context => matrix_a%matrix_struct%context
921 myprow = context%mepos(1)
922 mypcol = context%mepos(2)
923 nprow = context%num_pe(1)
924 npcol = context%num_pe(2)
926 group = matrix_a%matrix_struct%para_env
928 nrow_local = min(matrix_a%matrix_struct%nrow_locals(myprow), matrix_b%matrix_struct%nrow_locals(myprow))
929 ncol_local = min(matrix_a%matrix_struct%ncol_locals(mypcol), matrix_b%matrix_struct%ncol_locals(mypcol))
933 matrix_b%local_data(1:nrow_local, 1:ncol_local))
935 CALL group%sum(trace)
937 CALL timestop(handle)
976 transa_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, &
978 TYPE(
cp_cfm_type),
INTENT(IN) :: triangular_matrix, matrix_b
979 CHARACTER,
INTENT(in),
OPTIONAL :: side, transa_tr
980 LOGICAL,
INTENT(in),
OPTIONAL :: invert_tr
981 CHARACTER,
INTENT(in),
OPTIONAL :: uplo_tr
982 LOGICAL,
INTENT(in),
OPTIONAL :: unit_diag_tr
983 INTEGER,
INTENT(in),
OPTIONAL :: n_rows, n_cols
984 COMPLEX(kind=dp),
INTENT(in),
OPTIONAL :: alpha
986 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_triangular_multiply'
988 CHARACTER :: side_char, transa, unit_diag, uplo
989 COMPLEX(kind=dp) :: al
990 INTEGER :: handle, m, n
993 CALL timeset(routinen, handle)
1001 IF (
PRESENT(side)) side_char = side
1002 IF (
PRESENT(invert_tr)) invert = invert_tr
1003 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1004 IF (
PRESENT(unit_diag_tr))
THEN
1005 IF (unit_diag_tr)
THEN
1011 IF (
PRESENT(transa_tr)) transa = transa_tr
1012 IF (
PRESENT(alpha)) al = alpha
1013 IF (
PRESENT(n_rows)) m = n_rows
1014 IF (
PRESENT(n_cols)) n = n_cols
1018#if defined(__parallel)
1019 CALL pztrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1020 triangular_matrix%local_data(1, 1), 1, 1, &
1021 triangular_matrix%matrix_struct%descriptor, &
1022 matrix_b%local_data(1, 1), 1, 1, &
1023 matrix_b%matrix_struct%descriptor(1))
1025 CALL ztrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1026 triangular_matrix%local_data(1, 1), &
1027 SIZE(triangular_matrix%local_data, 1), &
1028 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1033#if defined(__parallel)
1034 CALL pztrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1035 triangular_matrix%local_data(1, 1), 1, 1, &
1036 triangular_matrix%matrix_struct%descriptor, &
1037 matrix_b%local_data(1, 1), 1, 1, &
1038 matrix_b%matrix_struct%descriptor(1))
1040 CALL ztrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1041 triangular_matrix%local_data(1, 1), &
1042 SIZE(triangular_matrix%local_data, 1), &
1043 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1048 CALL timestop(handle)
1061 CHARACTER,
INTENT(in),
OPTIONAL :: uplo
1062 INTEGER,
INTENT(out),
OPTIONAL :: info_out
1064 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_triangular_invert'
1066 CHARACTER :: unit_diag, my_uplo
1067 INTEGER :: handle, info, ncol_global
1068 COMPLEX(kind=dp),
DIMENSION(:, :), &
1070#if defined(__parallel)
1071 INTEGER,
DIMENSION(9) :: desca
1074 CALL timeset(routinen, handle)
1078 IF (
PRESENT(uplo)) my_uplo = uplo
1080 ncol_global = matrix_a%matrix_struct%ncol_global
1082 a => matrix_a%local_data
1084#if defined(__parallel)
1085 desca(:) = matrix_a%matrix_struct%descriptor(:)
1086 CALL pztrtri(my_uplo, unit_diag, ncol_global, a(1, 1), 1, 1, desca, info)
1088 CALL ztrtri(my_uplo, unit_diag, ncol_global, a(1, 1), ncol_global, info)
1091 IF (
PRESENT(info_out))
THEN
1095 CALL cp_abort(__location__, &
1096 "triangular invert failed: matrix is not positive definite or ill-conditioned")
1099 CALL timestop(handle)
1111 CHARACTER,
INTENT(in) :: trans
1114 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_transpose'
1116 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: aa, cc
1117 INTEGER :: handle, ncol_global, nrow_global
1118#if defined(__parallel)
1119 INTEGER,
DIMENSION(9) :: desca, descc
1120#elif !defined(__MKL)
1124 CALL timeset(routinen, handle)
1126 nrow_global = matrix%matrix_struct%nrow_global
1127 ncol_global = matrix%matrix_struct%ncol_global
1129 cpassert(matrixt%matrix_struct%nrow_global == ncol_global)
1130 cpassert(matrixt%matrix_struct%ncol_global == nrow_global)
1132 aa => matrix%local_data
1133 cc => matrixt%local_data
1135#if defined(__parallel)
1136 desca = matrix%matrix_struct%descriptor
1137 descc = matrixt%matrix_struct%descriptor
1140 CALL pztranu(nrow_global, ncol_global, &
1141 z_one, aa(1, 1), 1, 1, desca, &
1142 z_zero, cc(1, 1), 1, 1, descc)
1144 CALL pztranc(nrow_global, ncol_global, &
1145 z_one, aa(1, 1), 1, 1, desca, &
1146 z_zero, cc(1, 1), 1, 1, descc)
1148 cpabort(
"trans only accepts 'T' or 'C'")
1151 CALL mkl_zomatcopy(
'C', trans, nrow_global, ncol_global, 1.0_dp, aa(1, 1), nrow_global, cc(1, 1), ncol_global)
1155 DO jj = 1, ncol_global
1156 DO ii = 1, nrow_global
1157 cc(ii, jj) = aa(jj, ii)
1161 DO jj = 1, ncol_global
1162 DO ii = 1, nrow_global
1163 cc(ii, jj) = conjg(aa(jj, ii))
1167 cpabort(
"trans only accepts 'T' or 'C'")
1171 CALL timestop(handle)
1186 CHARACTER,
INTENT(IN) :: mode
1187 REAL(kind=
dp) :: res
1189 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_norm'
1191 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: aa
1192 INTEGER :: handle, lwork, ncols, ncols_local, &
1194 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
1196#if defined(__parallel)
1197 INTEGER,
DIMENSION(9) :: desca
1202 CALL timeset(routinen, handle)
1205 nrow_global=nrows, &
1206 ncol_global=ncols, &
1207 nrow_local=nrows_local, &
1208 ncol_local=ncols_local)
1209 aa => matrix%local_data
1214 CASE (
'1',
'O',
'o')
1215#if defined(__parallel)
1221#if defined(__parallel)
1226 CASE (
'F',
'f',
'E',
'e')
1229 cpabort(
"mode input is not valid")
1232 ALLOCATE (work(lwork))
1234#if defined(__parallel)
1235 desca = matrix%matrix_struct%descriptor
1236 res = pzlange(mode, nrows, ncols, aa(1, 1), 1, 1, desca, work)
1239 res = zlange(mode, nrows, ncols, aa(1, 1), lda, work)
1243 CALL timestop(handle)
1257 INTEGER,
INTENT(IN) :: irow, jrow
1258 REAL(
dp),
INTENT(IN) :: cs, sn
1260 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_rot_rows'
1261 INTEGER :: handle, ncol
1262 COMPLEX(KIND=dp) :: sn_cmplx
1264#if defined(__parallel)
1265 INTEGER :: info, lwork
1266 INTEGER,
DIMENSION(9) :: desc
1267 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
1269 CALL timeset(routinen, handle)
1271 sn_cmplx = cmplx(sn, 0.0_dp,
dp)
1272#if defined(__parallel)
1273 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
1275 ALLOCATE (work(lwork))
1276 desc(:) = matrix%matrix_struct%descriptor(:)
1279 matrix%local_data(1, 1), irow, 1, desc, ncol, &
1280 matrix%local_data(1, 1), jrow, 1, desc, ncol, &
1281 cs, sn_cmplx, work, lwork, info)
1286 CALL zrot(ncol, matrix%local_data(irow, 1), ncol, matrix%local_data(jrow, 1), ncol, cs, sn_cmplx)
1287#if defined(__parallel)
1290 CALL timestop(handle)
1304 INTEGER,
INTENT(IN) :: icol, jcol
1305 REAL(
dp),
INTENT(IN) :: cs, sn
1307 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_rot_cols'
1308 INTEGER :: handle, nrow
1309 COMPLEX(KIND=dp) :: sn_cmplx
1311#if defined(__parallel)
1312 INTEGER :: info, lwork
1313 INTEGER,
DIMENSION(9) :: desc
1314 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
1316 CALL timeset(routinen, handle)
1318 sn_cmplx = cmplx(sn, 0.0_dp,
dp)
1319#if defined(__parallel)
1320 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
1322 ALLOCATE (work(lwork))
1323 desc(:) = matrix%matrix_struct%descriptor(:)
1326 matrix%local_data(1, 1), 1, icol, desc, 1, &
1327 matrix%local_data(1, 1), 1, jcol, desc, 1, &
1328 cs, sn_cmplx, work, lwork, info)
1333 CALL zrot(nrow, matrix%local_data(1, icol), 1, matrix%local_data(1, jcol), 1, cs, sn_cmplx)
1334#if defined(__parallel)
1337 CALL timestop(handle)
1352 TYPE(
cp_cfm_type),
INTENT(IN),
OPTIONAL :: workspace
1353 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
1355 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_cfm_uplo_to_full'
1358 INTEGER :: handle, i_global, iib, j_global, jjb, &
1359 ncol_local, nrow_local
1360 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1363 CALL timeset(routinen, handle)
1365 IF (.NOT.
PRESENT(workspace))
THEN
1372 IF (
PRESENT(uplo)) myuplo = uplo
1376 nrow_local=nrow_local, &
1377 ncol_local=ncol_local, &
1378 row_indices=row_indices, &
1379 col_indices=col_indices)
1381 DO jjb = 1, ncol_local
1382 j_global = col_indices(jjb)
1383 DO iib = 1, nrow_local
1384 i_global = row_indices(iib)
1385 IF (merge(j_global < i_global, j_global > i_global, (myuplo ==
"U") .OR. (myuplo ==
"u")))
THEN
1386 matrix%local_data(iib, jjb) =
z_zero
1387 ELSE IF (j_global == i_global)
THEN
1388 matrix%local_data(iib, jjb) = matrix%local_data(iib, jjb)/(2.0_dp, 0.0_dp)
1397 IF (.NOT.
PRESENT(workspace))
THEN
1401 CALL timestop(handle)
1413 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: norm_array
1415 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_cfm_vectorsnorm'
1417 INTEGER :: handle, i, j, ncol_local, nrow_local
1418 INTEGER,
DIMENSION(:),
POINTER :: col_indices
1420 CALL timeset(routinen, handle)
1422 CALL cp_cfm_get_info(matrix, col_indices=col_indices, nrow_local=nrow_local, &
1423 ncol_local=ncol_local)
1427 DO j = 1, ncol_local
1428 DO i = 1, nrow_local
1429 norm_array(col_indices(j)) = norm_array(col_indices(j)) + &
1430 REAL(matrix%local_data(i, j), kind=
dp)**2 + &
1431 aimag(matrix%local_data(i, j))**2
1434 CALL matrix%matrix_struct%para_env%sum(norm_array)
1435 norm_array = sqrt(norm_array)
1437 CALL timestop(handle)
1448 COMPLEX(KIND=dp),
INTENT(IN) :: alpha
1449 INTEGER,
INTENT(IN),
OPTIONAL :: n_active
1451 INTEGER :: i_row, j_col, max_index, ncol_local, &
1453 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1455 max_index = huge(max_index)
1456 IF (
PRESENT(n_active)) max_index = n_active
1458 CALL cp_cfm_get_info(matrix=matrix, nrow_local=nrow_local, ncol_local=ncol_local, &
1459 row_indices=row_indices, col_indices=col_indices)
1461 DO j_col = 1, ncol_local
1462 DO i_row = 1, nrow_local
1463 IF (row_indices(i_row) == col_indices(j_col) .AND. row_indices(i_row) <= max_index)
THEN
1464 matrix%local_data(i_row, j_col) = matrix%local_data(i_row, j_col) + alpha
1480 COMPLEX(KIND=dp),
DIMENSION(:),
INTENT(OUT) :: diag
1482 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_cfm_get_diag'
1484 INTEGER :: handle, i, j, ncol_local, nrow_local
1485 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1487 CALL timeset(routinen, handle)
1489 CALL cp_cfm_get_info(matrix, col_indices=col_indices, row_indices=row_indices, &
1490 nrow_local=nrow_local, ncol_local=ncol_local)
1493 DO j = 1, ncol_local
1494 DO i = 1, nrow_local
1495 IF (row_indices(i) == col_indices(j))
THEN
1496 diag(col_indices(j)) = matrix%local_data(i, j)
1500 CALL matrix%matrix_struct%para_env%sum(diag)
1502 CALL timestop(handle)
methods related to the blacs parallel environment
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_scale_and_add(alpha, matrix_a, beta, matrix_b)
Scale and add two BLACS matrices (a = alpha*a + beta*b).
subroutine, public cp_cfm_lu_invert(matrix, info_out)
Inverts a matrix using LU decomposition. The input matrix will be overwritten.
subroutine, public cp_cfm_get_diag(matrix, diag)
returns the diagonal of a complex full matrix: diag(i)= A_{ii}. Each diagonal entry is owned by one p...
real(kind=dp) function, public cp_cfm_norm(matrix, mode)
Norm of matrix using (p)zlange.
subroutine, public cp_cfm_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)
Performs one of the matrix-matrix operations: matrix_c = alpha * op1( matrix_a ) * op2( matrix_b ) + ...
subroutine, public cp_cfm_solve(matrix_a, general_a, determinant)
Solve the system of linear equations A*b=A_general using LU decomposition. Pay attention that both ma...
subroutine, public cp_cfm_transpose(matrix, trans, matrixt)
Transposes a BLACS distributed complex matrix.
subroutine, public cp_cfm_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_cfm_scale_and_add_fm(alpha, matrix_a, beta, matrix_b)
Scale and add two BLACS matrices (a = alpha*a + beta*b). where b is a real matrix (adapted from cp_cf...
subroutine, public cp_cfm_schur_product(matrix_a, matrix_b, matrix_c)
Computes the element-wise (Schur) product of two matrices: C = A \circ B .
subroutine, public cp_cfm_triangular_multiply(triangular_matrix, matrix_b, side, transa_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_cfm_vectorsnorm(matrix, norm_array)
find the norm of each column norm_{j}= sqrt( \sum_{i} A_{ij}*conjg(A_{ij}) ) Complex-valued mirror of...
subroutine, public cp_cfm_uplo_to_full(matrix, workspace, uplo)
...
subroutine, public cp_cfm_add_on_diag(matrix, alpha, n_active)
Adds a scalar to the diagonal of a distributed complex full matrix.
subroutine, public cp_cfm_det(matrix_a, det_a)
Computes the determinant (with a correct sign even in parallel environment!) of a complex square matr...
subroutine, public cp_cfm_column_scale(matrix_a, scaling)
Scales columns of the full matrix by corresponding factors.
subroutine, public cp_cfm_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_cfm_triangular_invert(matrix_a, uplo, info_out)
Inverts a triangular matrix.
subroutine, public cp_cfm_lu_decompose(matrix_a, determinant)
Computes LU decomposition of a given matrix.
subroutine, public cp_cfm_trace(matrix_a, matrix_b, trace)
Returns the trace of matrix_a^T matrix_b, i.e sum_{i,j}(matrix_a(i,j)*matrix_b(i,j)) .
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
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
various routines to log and control the output. The idea is that decisions about where to log should ...
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 dp
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public z_zero
Interface to the message passing library MPI.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.