31#include "../base/base_uses.f90"
36 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
37 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_cfm_basic_linalg'
58 REAL(kind=
dp),
EXTERNAL :: zlange, pzlange
61 MODULE PROCEDURE cp_cfm_dscale, cp_cfm_zscale
77 COMPLEX(KIND=dp),
INTENT(OUT) :: det_a
78 COMPLEX(KIND=dp) :: determinant
80 COMPLEX(KIND=dp),
DIMENSION(:, :),
POINTER :: a
81 INTEGER :: n, i, info, p
82 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
83 COMPLEX(KIND=dp),
DIMENSION(:),
POINTER :: diag
85#if defined(__parallel)
86 INTEGER :: myprow, nprow, npcol, nrow_local, irow_local, &
87 mypcol, ncol_local, icol_local, j
88 INTEGER,
DIMENSION(9) :: desca
92 matrix_struct=matrix_a%matrix_struct, &
96 a => matrix_lu%local_data
97 n = matrix_lu%matrix_struct%nrow_global
103#if defined(__parallel)
105 desca(:) = matrix_lu%matrix_struct%descriptor(:)
106 CALL pzgetrf(n, n, a(1, 1), 1, 1, desca, ipivot, info)
107 myprow = matrix_lu%matrix_struct%context%mepos(1)
108 mypcol = matrix_lu%matrix_struct%context%mepos(2)
109 nprow = matrix_lu%matrix_struct%context%num_pe(1)
110 npcol = matrix_lu%matrix_struct%context%num_pe(2)
111 nrow_local = matrix_lu%matrix_struct%nrow_locals(myprow)
112 ncol_local = matrix_lu%matrix_struct%ncol_locals(mypcol)
114 DO irow_local = 1, nrow_local
115 i = matrix_lu%matrix_struct%row_indices(irow_local)
116 DO icol_local = 1, ncol_local
117 j = matrix_lu%matrix_struct%col_indices(icol_local)
118 IF (i == j) diag(i) = matrix_lu%local_data(irow_local, icol_local)
121 CALL matrix_lu%matrix_struct%para_env%sum(diag)
122 determinant = product(diag)
123 DO irow_local = 1, nrow_local
124 i = matrix_lu%matrix_struct%row_indices(irow_local)
125 IF (ipivot(irow_local) /= i) p = p + 1
127 CALL matrix_lu%matrix_struct%para_env%sum(p)
131 CALL zgetrf(n, n, a(1, 1), n, ipivot, info)
133 diag(i) = matrix_lu%local_data(i, i)
135 determinant = product(diag)
137 IF (ipivot(i) /= i) p = p + 1
143 det_a = determinant*(-2*mod(p, 2) + 1.0_dp)
154 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
156 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_schur_product'
158 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b, c
159 INTEGER :: handle, icol_local, irow_local, mypcol, &
160 myprow, ncol_local, nrow_local
162 CALL timeset(routinen, handle)
164 myprow = matrix_a%matrix_struct%context%mepos(1)
165 mypcol = matrix_a%matrix_struct%context%mepos(2)
167 a => matrix_a%local_data
168 b => matrix_b%local_data
169 c => matrix_c%local_data
171 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
172 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
174 DO icol_local = 1, ncol_local
175 DO irow_local = 1, nrow_local
176 c(irow_local, icol_local) = a(irow_local, icol_local)*b(irow_local, icol_local)
180 CALL timestop(handle)
190 SUBROUTINE cp_cfm_schur_product_cc(matrix_a, matrix_b, matrix_c)
192 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b, matrix_c
194 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_schur_product_cc'
196 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b, c
197 INTEGER :: handle, icol_local, irow_local, mypcol, &
198 myprow, ncol_local, nrow_local
200 CALL timeset(routinen, handle)
202 myprow = matrix_a%matrix_struct%context%mepos(1)
203 mypcol = matrix_a%matrix_struct%context%mepos(2)
205 a => matrix_a%local_data
206 b => matrix_b%local_data
207 c => matrix_c%local_data
209 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
210 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
212 DO icol_local = 1, ncol_local
213 DO irow_local = 1, nrow_local
214 c(irow_local, icol_local) = a(irow_local, icol_local)*conjg(b(irow_local, icol_local))
218 CALL timestop(handle)
220 END SUBROUTINE cp_cfm_schur_product_cc
240 COMPLEX(kind=dp),
INTENT(in) :: alpha
242 COMPLEX(kind=dp),
INTENT(in),
OPTIONAL :: beta
243 TYPE(
cp_cfm_type),
INTENT(IN),
OPTIONAL :: matrix_b
245 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_scale_and_add'
247 COMPLEX(kind=dp) :: my_beta
248 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b
249 INTEGER :: handle, icol_local, irow_local, mypcol, &
250 myprow, ncol_local, nrow_local
252 CALL timeset(routinen, handle)
255 IF (
PRESENT(beta)) my_beta = beta
259 myprow = matrix_a%matrix_struct%context%mepos(1)
260 mypcol = matrix_a%matrix_struct%context%mepos(2)
262 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
263 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
265 a => matrix_a%local_data
267 IF (my_beta ==
z_zero)
THEN
271 ELSE IF (alpha ==
z_one)
THEN
272 CALL timestop(handle)
275 a(:, :) = alpha*a(:, :)
279 cpassert(
PRESENT(matrix_b))
280 IF (matrix_a%matrix_struct%context /= matrix_b%matrix_struct%context) &
281 cpabort(
"matrixes must be in the same blacs context")
284 matrix_b%matrix_struct))
THEN
286 b => matrix_b%local_data
289 IF (my_beta ==
z_one)
THEN
291 DO icol_local = 1, ncol_local
292 DO irow_local = 1, nrow_local
293 a(irow_local, icol_local) = b(irow_local, icol_local)
298 DO icol_local = 1, ncol_local
299 DO irow_local = 1, nrow_local
300 a(irow_local, icol_local) = my_beta*b(irow_local, icol_local)
304 ELSE IF (alpha ==
z_one)
THEN
305 IF (my_beta ==
z_one)
THEN
307 DO icol_local = 1, ncol_local
308 DO irow_local = 1, nrow_local
309 a(irow_local, icol_local) = a(irow_local, icol_local) + b(irow_local, icol_local)
314 DO icol_local = 1, ncol_local
315 DO irow_local = 1, nrow_local
316 a(irow_local, icol_local) = a(irow_local, icol_local) + my_beta*b(irow_local, icol_local)
322 DO icol_local = 1, ncol_local
323 DO irow_local = 1, nrow_local
324 a(irow_local, icol_local) = alpha*a(irow_local, icol_local) + my_beta*b(irow_local, icol_local)
329 CALL cp_abort(__location__, &
330 "cp_cfm_scale_and_add is not yet implemented for cases "// &
331 "where input two matrix structures are not equivalent")
334 CALL timestop(handle)
349 COMPLEX(kind=dp),
INTENT(in) :: alpha
351 COMPLEX(kind=dp),
INTENT(in) :: beta
354 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_scale_and_add_fm'
356 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
357 INTEGER :: handle, icol_local, irow_local, mypcol, &
358 myprow, ncol_local, nrow_local
359 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: b
361 CALL timeset(routinen, handle)
365 myprow = matrix_a%matrix_struct%context%mepos(1)
366 mypcol = matrix_a%matrix_struct%context%mepos(2)
368 nrow_local = matrix_a%matrix_struct%nrow_locals(myprow)
369 ncol_local = matrix_a%matrix_struct%ncol_locals(mypcol)
371 a => matrix_a%local_data
377 ELSE IF (alpha ==
z_one)
THEN
378 CALL timestop(handle)
381 a(:, :) = alpha*a(:, :)
385 IF (matrix_a%matrix_struct%context /= matrix_b%matrix_struct%context) &
386 cpabort(
"matrices must be in the same blacs context")
389 matrix_b%matrix_struct))
THEN
391 b => matrix_b%local_data
394 IF (beta ==
z_one)
THEN
396 DO icol_local = 1, ncol_local
397 DO irow_local = 1, nrow_local
398 a(irow_local, icol_local) = b(irow_local, icol_local)
403 DO icol_local = 1, ncol_local
404 DO irow_local = 1, nrow_local
405 a(irow_local, icol_local) = beta*b(irow_local, icol_local)
409 ELSE IF (alpha ==
z_one)
THEN
410 IF (beta ==
z_one)
THEN
412 DO icol_local = 1, ncol_local
413 DO irow_local = 1, nrow_local
414 a(irow_local, icol_local) = a(irow_local, icol_local) + b(irow_local, icol_local)
419 DO icol_local = 1, ncol_local
420 DO irow_local = 1, nrow_local
421 a(irow_local, icol_local) = a(irow_local, icol_local) + beta*b(irow_local, icol_local)
427 DO icol_local = 1, ncol_local
428 DO irow_local = 1, nrow_local
429 a(irow_local, icol_local) = alpha*a(irow_local, icol_local) + beta*b(irow_local, icol_local)
434 CALL cp_abort(__location__, &
435 "cp_cfm_scale_and_add_fm is not yet implemented for cases "// &
436 "where two input matrix structures are not equivalent")
439 CALL timestop(handle)
455 COMPLEX(kind=dp),
INTENT(out) :: determinant
457 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_lu_decompose'
459 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
460 INTEGER :: counter, handle, info, irow, nrow_global
461 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
463#if defined(__parallel)
464 INTEGER :: icol, ncol_local, nrow_local
465 INTEGER,
DIMENSION(9) :: desca
466 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
471 CALL timeset(routinen, handle)
473 nrow_global = matrix_a%matrix_struct%nrow_global
474 a => matrix_a%local_data
476 ALLOCATE (ipivot(nrow_global))
477#if defined(__parallel)
478 CALL cp_cfm_get_info(matrix_a, nrow_local=nrow_local, ncol_local=ncol_local, &
479 row_indices=row_indices, col_indices=col_indices)
481 desca(:) = matrix_a%matrix_struct%descriptor(:)
482 CALL pzgetrf(nrow_global, nrow_global, a(1, 1), 1, 1, desca, ipivot, info)
485 DO irow = 1, nrow_local
486 IF (ipivot(irow) /= row_indices(irow)) counter = counter + 1
489 IF (mod(counter, 2) == 0)
THEN
498 DO WHILE (irow <= nrow_local .AND. icol <= ncol_local)
499 IF (row_indices(irow) < col_indices(icol))
THEN
501 ELSE IF (row_indices(irow) > col_indices(icol))
THEN
504 determinant = determinant*a(irow, icol)
509 CALL matrix_a%matrix_struct%para_env%prod(determinant)
512 CALL zgetrf(nrow_global, nrow_global, a(1, 1), lda, ipivot, info)
515 DO irow = 1, nrow_global
516 IF (ipivot(irow) /= irow) counter = counter + 1
517 determinant = determinant*a(irow, irow)
519 IF (mod(counter, 2) == 1) determinant = -1.0_dp*determinant
526 CALL timestop(handle)
556 SUBROUTINE cp_cfm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, &
557 matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, &
559 CHARACTER(len=1),
INTENT(in) :: transa, transb
560 INTEGER,
INTENT(in) :: m, n, k
561 COMPLEX(kind=dp),
INTENT(in) :: alpha
562 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b
563 COMPLEX(kind=dp),
INTENT(in) :: beta
565 INTEGER,
INTENT(in),
OPTIONAL :: a_first_col, a_first_row, b_first_col, &
566 b_first_row, c_first_col, c_first_row
568 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_gemm'
570 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, b, c
571 INTEGER :: handle, i_a, i_b, i_c, j_a, j_b, j_c
572#if defined(__parallel)
573 INTEGER,
DIMENSION(9) :: desca, descb, descc
575 INTEGER :: lda, ldb, ldc
578 CALL timeset(routinen, handle)
579 a => matrix_a%local_data
580 b => matrix_b%local_data
581 c => matrix_c%local_data
584 IF (
PRESENT(a_first_row)) i_a = a_first_row
587 IF (
PRESENT(a_first_col)) j_a = a_first_col
590 IF (
PRESENT(b_first_row)) i_b = b_first_row
593 IF (
PRESENT(b_first_col)) j_b = b_first_col
596 IF (
PRESENT(c_first_row)) i_c = c_first_row
599 IF (
PRESENT(c_first_col)) j_c = c_first_col
601#if defined(__parallel)
602 desca(:) = matrix_a%matrix_struct%descriptor(:)
603 descb(:) = matrix_b%matrix_struct%descriptor(:)
604 descc(:) = matrix_c%matrix_struct%descriptor(:)
606 CALL pzgemm(transa, transb, m, n, k, alpha, a(1, 1), i_a, j_a, desca, &
607 b(1, 1), i_b, j_b, descb, beta, c(1, 1), i_c, j_c, descc)
614 CALL zgemm(transa, transb, m, n, k, alpha, a(i_a, j_a), &
615 lda, b(i_b, j_b), ldb, beta, c(i_c, j_c), ldc)
617 CALL timestop(handle)
630 COMPLEX(kind=dp),
DIMENSION(:),
INTENT(in) :: scaling
632 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_column_scale'
634 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
635 INTEGER :: handle, icol_local, ncol_local, &
637#if defined(__parallel)
638 INTEGER,
DIMENSION(:),
POINTER :: col_indices
641 CALL timeset(routinen, handle)
643 a => matrix_a%local_data
645#if defined(__parallel)
646 CALL cp_cfm_get_info(matrix_a, nrow_local=nrow_local, ncol_local=ncol_local, col_indices=col_indices)
647 ncol_local = min(ncol_local,
SIZE(scaling))
649 DO icol_local = 1, ncol_local
650 CALL zscal(nrow_local, scaling(col_indices(icol_local)), a(1, icol_local), 1)
653 nrow_local =
SIZE(a, 1)
654 ncol_local = min(
SIZE(a, 2),
SIZE(scaling))
656 DO icol_local = 1, ncol_local
657 CALL zscal(nrow_local, scaling(icol_local), a(1, icol_local), 1)
661 CALL timestop(handle)
670 SUBROUTINE cp_cfm_dscale(alpha, matrix_a)
671 REAL(kind=
dp),
INTENT(in) :: alpha
674 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_dscale'
676 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
679 CALL timeset(routinen, handle)
683 a => matrix_a%local_data
685 CALL zdscal(
SIZE(a), alpha, a(1, 1), 1)
687 CALL timestop(handle)
688 END SUBROUTINE cp_cfm_dscale
698 SUBROUTINE cp_cfm_zscale(alpha, matrix_a)
699 COMPLEX(kind=dp),
INTENT(IN) :: alpha
702 CHARACTER(len=*),
PARAMETER :: routineN =
'cp_cfm_zscale'
704 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a
705 INTEGER :: handle, size_a
707 CALL timeset(routinen, handle)
711 a => matrix_a%local_data
712 size_a =
SIZE(a, 1)*
SIZE(a, 2)
714 CALL zscal(size_a, alpha, a(1, 1), 1)
716 CALL timestop(handle)
717 END SUBROUTINE cp_cfm_zscale
729 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, general_a
730 COMPLEX(kind=dp),
OPTIONAL :: determinant
732 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_solve'
734 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: a, a_general
735 INTEGER :: counter, handle, info, irow, nrow_global
736 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
738#if defined(__parallel)
739 INTEGER :: icol, ncol_local, nrow_local
740 INTEGER,
DIMENSION(9) :: desca, descb
741 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
746 CALL timeset(routinen, handle)
748 a => matrix_a%local_data
749 a_general => general_a%local_data
750 nrow_global = matrix_a%matrix_struct%nrow_global
751 ALLOCATE (ipivot(nrow_global))
753#if defined(__parallel)
754 desca(:) = matrix_a%matrix_struct%descriptor(:)
755 descb(:) = general_a%matrix_struct%descriptor(:)
756 CALL pzgetrf(nrow_global, nrow_global, a(1, 1), 1, 1, desca, ipivot, info)
757 IF (
PRESENT(determinant))
THEN
758 CALL cp_cfm_get_info(matrix_a, nrow_local=nrow_local, ncol_local=ncol_local, &
759 row_indices=row_indices, col_indices=col_indices)
762 DO irow = 1, nrow_local
763 IF (ipivot(irow) /= row_indices(irow)) counter = counter + 1
766 IF (mod(counter, 2) == 0)
THEN
775 DO WHILE (irow <= nrow_local .AND. icol <= ncol_local)
776 IF (row_indices(irow) < col_indices(icol))
THEN
778 ELSE IF (row_indices(irow) > col_indices(icol))
THEN
781 determinant = determinant*a(irow, icol)
786 CALL matrix_a%matrix_struct%para_env%prod(determinant)
789 CALL pzgetrs(
"N", nrow_global, nrow_global, a(1, 1), 1, 1, desca, &
790 ipivot, a_general(1, 1), 1, 1, descb, info)
793 ldb =
SIZE(a_general, 1)
794 CALL zgetrf(nrow_global, nrow_global, a(1, 1), lda, ipivot, info)
795 IF (
PRESENT(determinant))
THEN
798 DO irow = 1, nrow_global
799 IF (ipivot(irow) /= irow) counter = counter + 1
800 determinant = determinant*a(irow, irow)
802 IF (mod(counter, 2) == 1) determinant = -1.0_dp*determinant
804 CALL zgetrs(
"N", nrow_global, nrow_global, a(1, 1), lda, ipivot, a_general(1, 1), ldb, info)
810 CALL timestop(handle)
822 INTEGER,
INTENT(out),
OPTIONAL :: info_out
824 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_lu_invert'
826 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: work
827 COMPLEX(kind=dp),
DIMENSION(1) :: work1
828 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: mat
829 INTEGER :: handle, info, lwork, nrows_global
830 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipivot
832#if defined(__parallel)
834 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
835 INTEGER,
DIMENSION(1) :: iwork1
836 INTEGER,
DIMENSION(9) :: desca
841 CALL timeset(routinen, handle)
843 mat => matrix%local_data
844 nrows_global = matrix%matrix_struct%nrow_global
845 cpassert(nrows_global == matrix%matrix_struct%ncol_global)
846 ALLOCATE (ipivot(nrows_global))
849#if defined(__parallel)
850 desca = matrix%matrix_struct%descriptor
851 CALL pzgetrf(nrows_global, nrows_global, &
852 mat(1, 1), 1, 1, desca, ipivot, info)
855 CALL zgetrf(nrows_global, nrows_global, &
856 mat(1, 1), lda, ipivot, info)
859 CALL cp_abort(__location__,
"LU decomposition has failed")
863#if defined(__parallel)
864 CALL pzgetri(nrows_global, mat(1, 1), 1, 1, desca, &
865 ipivot, work1, -1, iwork1, -1, info)
866 lwork = int(work1(1))
867 liwork = int(iwork1(1))
868 ALLOCATE (work(lwork))
869 ALLOCATE (iwork(liwork))
870 CALL pzgetri(nrows_global, mat(1, 1), 1, 1, desca, &
871 ipivot, work, lwork, iwork, liwork, info)
874 CALL zgetri(nrows_global, mat(1, 1), lda, ipivot, work1, -1, info)
875 lwork = int(work1(1))
876 ALLOCATE (work(lwork))
877 CALL zgetri(nrows_global, mat(1, 1), lda, ipivot, work, lwork, info)
882 IF (
PRESENT(info_out))
THEN
886 CALL cp_abort(__location__,
"LU inversion has failed")
889 CALL timestop(handle)
906 TYPE(
cp_cfm_type),
INTENT(IN) :: matrix_a, matrix_b
907 COMPLEX(kind=dp),
INTENT(out) :: trace
909 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_trace'
911 INTEGER :: handle, mypcol, myprow, ncol_local, &
912 npcol, nprow, nrow_local
916 CALL timeset(routinen, handle)
918 context => matrix_a%matrix_struct%context
919 myprow = context%mepos(1)
920 mypcol = context%mepos(2)
921 nprow = context%num_pe(1)
922 npcol = context%num_pe(2)
924 group = matrix_a%matrix_struct%para_env
926 nrow_local = min(matrix_a%matrix_struct%nrow_locals(myprow), matrix_b%matrix_struct%nrow_locals(myprow))
927 ncol_local = min(matrix_a%matrix_struct%ncol_locals(mypcol), matrix_b%matrix_struct%ncol_locals(mypcol))
931 matrix_b%local_data(1:nrow_local, 1:ncol_local))
933 CALL group%sum(trace)
935 CALL timestop(handle)
974 transa_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, &
976 TYPE(
cp_cfm_type),
INTENT(IN) :: triangular_matrix, matrix_b
977 CHARACTER,
INTENT(in),
OPTIONAL :: side, transa_tr
978 LOGICAL,
INTENT(in),
OPTIONAL :: invert_tr
979 CHARACTER,
INTENT(in),
OPTIONAL :: uplo_tr
980 LOGICAL,
INTENT(in),
OPTIONAL :: unit_diag_tr
981 INTEGER,
INTENT(in),
OPTIONAL :: n_rows, n_cols
982 COMPLEX(kind=dp),
INTENT(in),
OPTIONAL :: alpha
984 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_triangular_multiply'
986 CHARACTER :: side_char, transa, unit_diag, uplo
987 COMPLEX(kind=dp) :: al
988 INTEGER :: handle, m, n
991 CALL timeset(routinen, handle)
999 IF (
PRESENT(side)) side_char = side
1000 IF (
PRESENT(invert_tr)) invert = invert_tr
1001 IF (
PRESENT(uplo_tr)) uplo = uplo_tr
1002 IF (
PRESENT(unit_diag_tr))
THEN
1003 IF (unit_diag_tr)
THEN
1009 IF (
PRESENT(transa_tr)) transa = transa_tr
1010 IF (
PRESENT(alpha)) al = alpha
1011 IF (
PRESENT(n_rows)) m = n_rows
1012 IF (
PRESENT(n_cols)) n = n_cols
1016#if defined(__parallel)
1017 CALL pztrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1018 triangular_matrix%local_data(1, 1), 1, 1, &
1019 triangular_matrix%matrix_struct%descriptor, &
1020 matrix_b%local_data(1, 1), 1, 1, &
1021 matrix_b%matrix_struct%descriptor(1))
1023 CALL ztrsm(side_char, uplo, transa, unit_diag, m, n, al, &
1024 triangular_matrix%local_data(1, 1), &
1025 SIZE(triangular_matrix%local_data, 1), &
1026 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1031#if defined(__parallel)
1032 CALL pztrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1033 triangular_matrix%local_data(1, 1), 1, 1, &
1034 triangular_matrix%matrix_struct%descriptor, &
1035 matrix_b%local_data(1, 1), 1, 1, &
1036 matrix_b%matrix_struct%descriptor(1))
1038 CALL ztrmm(side_char, uplo, transa, unit_diag, m, n, al, &
1039 triangular_matrix%local_data(1, 1), &
1040 SIZE(triangular_matrix%local_data, 1), &
1041 matrix_b%local_data(1, 1),
SIZE(matrix_b%local_data, 1))
1046 CALL timestop(handle)
1059 CHARACTER,
INTENT(in),
OPTIONAL :: uplo
1060 INTEGER,
INTENT(out),
OPTIONAL :: info_out
1062 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_triangular_invert'
1064 CHARACTER :: unit_diag, my_uplo
1065 INTEGER :: handle, info, ncol_global
1066 COMPLEX(kind=dp),
DIMENSION(:, :), &
1068#if defined(__parallel)
1069 INTEGER,
DIMENSION(9) :: desca
1072 CALL timeset(routinen, handle)
1076 IF (
PRESENT(uplo)) my_uplo = uplo
1078 ncol_global = matrix_a%matrix_struct%ncol_global
1080 a => matrix_a%local_data
1082#if defined(__parallel)
1083 desca(:) = matrix_a%matrix_struct%descriptor(:)
1084 CALL pztrtri(my_uplo, unit_diag, ncol_global, a(1, 1), 1, 1, desca, info)
1086 CALL ztrtri(my_uplo, unit_diag, ncol_global, a(1, 1), ncol_global, info)
1089 IF (
PRESENT(info_out))
THEN
1093 CALL cp_abort(__location__, &
1094 "triangular invert failed: matrix is not positive definite or ill-conditioned")
1097 CALL timestop(handle)
1109 CHARACTER,
INTENT(in) :: trans
1112 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_transpose'
1114 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: aa, cc
1115 INTEGER :: handle, ncol_global, nrow_global
1116#if defined(__parallel)
1117 INTEGER,
DIMENSION(9) :: desca, descc
1118#elif !defined(__MKL)
1122 CALL timeset(routinen, handle)
1124 nrow_global = matrix%matrix_struct%nrow_global
1125 ncol_global = matrix%matrix_struct%ncol_global
1127 cpassert(matrixt%matrix_struct%nrow_global == ncol_global)
1128 cpassert(matrixt%matrix_struct%ncol_global == nrow_global)
1130 aa => matrix%local_data
1131 cc => matrixt%local_data
1133#if defined(__parallel)
1134 desca = matrix%matrix_struct%descriptor
1135 descc = matrixt%matrix_struct%descriptor
1138 CALL pztranu(nrow_global, ncol_global, &
1139 z_one, aa(1, 1), 1, 1, desca, &
1140 z_zero, cc(1, 1), 1, 1, descc)
1142 CALL pztranc(nrow_global, ncol_global, &
1143 z_one, aa(1, 1), 1, 1, desca, &
1144 z_zero, cc(1, 1), 1, 1, descc)
1146 cpabort(
"trans only accepts 'T' or 'C'")
1149 CALL mkl_zomatcopy(
'C', trans, nrow_global, ncol_global, 1.0_dp, aa(1, 1), nrow_global, cc(1, 1), ncol_global)
1153 DO jj = 1, ncol_global
1154 DO ii = 1, nrow_global
1155 cc(ii, jj) = aa(jj, ii)
1159 DO jj = 1, ncol_global
1160 DO ii = 1, nrow_global
1161 cc(ii, jj) = conjg(aa(jj, ii))
1165 cpabort(
"trans only accepts 'T' or 'C'")
1169 CALL timestop(handle)
1184 CHARACTER,
INTENT(IN) :: mode
1185 REAL(kind=
dp) :: res
1187 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_norm'
1189 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: aa
1190 INTEGER :: handle, lwork, ncols, ncols_local, &
1192 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
1194#if defined(__parallel)
1195 INTEGER,
DIMENSION(9) :: desca
1200 CALL timeset(routinen, handle)
1203 nrow_global=nrows, &
1204 ncol_global=ncols, &
1205 nrow_local=nrows_local, &
1206 ncol_local=ncols_local)
1207 aa => matrix%local_data
1212 CASE (
'1',
'O',
'o')
1213#if defined(__parallel)
1219#if defined(__parallel)
1224 CASE (
'F',
'f',
'E',
'e')
1227 cpabort(
"mode input is not valid")
1230 ALLOCATE (work(lwork))
1232#if defined(__parallel)
1233 desca = matrix%matrix_struct%descriptor
1234 res = pzlange(mode, nrows, ncols, aa(1, 1), 1, 1, desca, work)
1237 res = zlange(mode, nrows, ncols, aa(1, 1), lda, work)
1241 CALL timestop(handle)
1255 INTEGER,
INTENT(IN) :: irow, jrow
1256 REAL(
dp),
INTENT(IN) :: cs, sn
1258 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_rot_rows'
1259 INTEGER :: handle, ncol
1260 COMPLEX(KIND=dp) :: sn_cmplx
1262#if defined(__parallel)
1263 INTEGER :: info, lwork
1264 INTEGER,
DIMENSION(9) :: desc
1265 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
1267 CALL timeset(routinen, handle)
1269 sn_cmplx = cmplx(sn, 0.0_dp,
dp)
1270#if defined(__parallel)
1271 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
1273 ALLOCATE (work(lwork))
1274 desc(:) = matrix%matrix_struct%descriptor(:)
1277 matrix%local_data(1, 1), irow, 1, desc, ncol, &
1278 matrix%local_data(1, 1), jrow, 1, desc, ncol, &
1279 cs, sn_cmplx, work, lwork, info)
1284 CALL zrot(ncol, matrix%local_data(irow, 1), ncol, matrix%local_data(jrow, 1), ncol, cs, sn_cmplx)
1285#if defined(__parallel)
1288 CALL timestop(handle)
1302 INTEGER,
INTENT(IN) :: icol, jcol
1303 REAL(
dp),
INTENT(IN) :: cs, sn
1305 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_cfm_rot_cols'
1306 INTEGER :: handle, nrow
1307 COMPLEX(KIND=dp) :: sn_cmplx
1309#if defined(__parallel)
1310 INTEGER :: info, lwork
1311 INTEGER,
DIMENSION(9) :: desc
1312 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: work
1314 CALL timeset(routinen, handle)
1316 sn_cmplx = cmplx(sn, 0.0_dp,
dp)
1317#if defined(__parallel)
1318 IF (1 /= matrix%matrix_struct%context%n_pid)
THEN
1320 ALLOCATE (work(lwork))
1321 desc(:) = matrix%matrix_struct%descriptor(:)
1324 matrix%local_data(1, 1), 1, icol, desc, 1, &
1325 matrix%local_data(1, 1), 1, jcol, desc, 1, &
1326 cs, sn_cmplx, work, lwork, info)
1331 CALL zrot(nrow, matrix%local_data(1, icol), 1, matrix%local_data(1, jcol), 1, cs, sn_cmplx)
1332#if defined(__parallel)
1335 CALL timestop(handle)
1350 TYPE(
cp_cfm_type),
INTENT(IN),
OPTIONAL :: workspace
1351 CHARACTER,
INTENT(IN),
OPTIONAL :: uplo
1353 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_cfm_uplo_to_full'
1356 INTEGER :: handle, i_global, iib, j_global, jjb, &
1357 ncol_local, nrow_local
1358 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1361 CALL timeset(routinen, handle)
1363 IF (.NOT.
PRESENT(workspace))
THEN
1370 IF (
PRESENT(uplo)) myuplo = uplo
1374 nrow_local=nrow_local, &
1375 ncol_local=ncol_local, &
1376 row_indices=row_indices, &
1377 col_indices=col_indices)
1379 DO jjb = 1, ncol_local
1380 j_global = col_indices(jjb)
1381 DO iib = 1, nrow_local
1382 i_global = row_indices(iib)
1383 IF (merge(j_global < i_global, j_global > i_global, (myuplo ==
"U") .OR. (myuplo ==
"u")))
THEN
1384 matrix%local_data(iib, jjb) =
z_zero
1385 ELSE IF (j_global == i_global)
THEN
1386 matrix%local_data(iib, jjb) = matrix%local_data(iib, jjb)/(2.0_dp, 0.0_dp)
1395 IF (.NOT.
PRESENT(workspace))
THEN
1399 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.
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_uplo_to_full(matrix, workspace, uplo)
...
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.