35 #include "../base/base_uses.f90"
41 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_fm_types'
42 LOGICAL,
PARAMETER :: debug_this_module = .true.
43 INTEGER,
PARAMETER :: src_tag = 3, dest_tag = 5, send_tag = 7, recv_tag = 11
45 INTEGER,
PRIVATE :: mm_type = 1
47 PUBLIC :: cp_fm_type, &
48 cp_fm_p_type, copy_info_type
86 MODULE PROCEDURE cp_fm_to_fm_matrix, &
90 INTERFACE cp_fm_release
91 MODULE PROCEDURE cp_fm_release_aa0, &
118 CHARACTER(LEN=60) :: name =
""
119 LOGICAL :: use_sp = .false.
120 TYPE(cp_fm_struct_type),
POINTER :: matrix_struct => null()
121 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER,
CONTIGUOUS :: local_data => null()
122 REAL(KIND=
sp),
DIMENSION(:, :),
POINTER,
CONTIGUOUS :: local_data_sp => null()
133 TYPE(cp_fm_type),
POINTER :: matrix => null()
134 END TYPE cp_fm_p_type
143 INTEGER :: send_size = -1
144 INTEGER,
DIMENSION(2) :: nlocal_recv = -1, nblock_src = -1, src_num_pe = -1
145 TYPE(mp_request_type),
DIMENSION(:),
ALLOCATABLE :: send_request, recv_request
146 INTEGER,
DIMENSION(:),
ALLOCATABLE :: recv_disp
147 INTEGER,
DIMENSION(:),
POINTER :: recv_col_indices => null(), recv_row_indices => null()
148 INTEGER,
DIMENSION(:, :),
ALLOCATABLE :: src_blacs2mpi
149 REAL(KIND=
dp),
DIMENSION(:),
ALLOCATABLE :: recv_buf, send_buf
150 END TYPE copy_info_type
167 TYPE(cp_fm_type),
INTENT(OUT) :: matrix
168 TYPE(cp_fm_struct_type),
INTENT(IN),
TARGET :: matrix_struct
169 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: name
170 LOGICAL,
INTENT(in),
OPTIONAL :: use_sp
172 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_create'
174 INTEGER :: handle, ncol_local, npcol, nprow, &
176 TYPE(cp_blacs_env_type),
POINTER :: context
178 CALL timeset(routinen, handle)
180 #if defined(__parallel) && ! defined(__SCALAPACK)
181 cpabort(
"full matrices need scalapack for parallel runs")
184 context => matrix_struct%context
185 matrix%matrix_struct => matrix_struct
188 matrix%use_sp = .false.
189 IF (
PRESENT(use_sp)) matrix%use_sp = use_sp
191 nprow = context%num_pe(1)
192 npcol = context%num_pe(2)
193 NULLIFY (matrix%local_data)
194 NULLIFY (matrix%local_data_sp)
199 nrow_local = matrix_struct%local_leading_dimension
200 ncol_local = max(1, matrix_struct%ncol_locals(context%mepos(2)))
201 IF (matrix%use_sp)
THEN
202 ALLOCATE (matrix%local_data_sp(nrow_local, ncol_local))
204 ALLOCATE (matrix%local_data(nrow_local, ncol_local))
208 IF (matrix%use_sp)
THEN
209 matrix%local_data_sp(1:nrow_local, 1:ncol_local) = 0.0_sp
211 matrix%local_data(1:nrow_local, 1:ncol_local) = 0.0_dp
214 IF (
PRESENT(name))
THEN
217 matrix%name =
'full matrix'
220 CALL timestop(handle)
231 SUBROUTINE cp_fm_release_aa0(matrix)
232 TYPE(cp_fm_type),
INTENT(INOUT) :: matrix
234 IF (
ASSOCIATED(matrix%local_data))
THEN
235 DEALLOCATE (matrix%local_data)
236 NULLIFY (matrix%local_data)
238 IF (
ASSOCIATED(matrix%local_data_sp))
THEN
239 DEALLOCATE (matrix%local_data_sp)
240 NULLIFY (matrix%local_data_sp)
245 END SUBROUTINE cp_fm_release_aa0
251 SUBROUTINE cp_fm_release_aa1(matrices)
252 TYPE(cp_fm_type),
ALLOCATABLE,
DIMENSION(:) :: matrices
256 IF (
ALLOCATED(matrices))
THEN
257 DO i = 1,
SIZE(matrices)
258 CALL cp_fm_release(matrices(i))
260 DEALLOCATE (matrices)
262 END SUBROUTINE cp_fm_release_aa1
268 SUBROUTINE cp_fm_release_aa2(matrices)
269 TYPE(cp_fm_type),
ALLOCATABLE,
DIMENSION(:, :) :: matrices
273 IF (
ALLOCATED(matrices))
THEN
274 DO i = 1,
SIZE(matrices, 1)
275 DO j = 1,
SIZE(matrices, 2)
276 CALL cp_fm_release(matrices(i, j))
279 DEALLOCATE (matrices)
281 END SUBROUTINE cp_fm_release_aa2
287 SUBROUTINE cp_fm_release_aa3(matrices)
288 TYPE(cp_fm_type),
ALLOCATABLE,
DIMENSION(:, :, :) :: matrices
292 IF (
ALLOCATED(matrices))
THEN
293 DO i = 1,
SIZE(matrices, 1)
294 DO j = 1,
SIZE(matrices, 2)
295 DO k = 1,
SIZE(matrices, 3)
296 CALL cp_fm_release(matrices(i, j, k))
300 DEALLOCATE (matrices)
302 END SUBROUTINE cp_fm_release_aa3
308 SUBROUTINE cp_fm_release_pa1(matrices)
309 TYPE(cp_fm_type),
DIMENSION(:),
POINTER :: matrices
313 IF (
ASSOCIATED(matrices))
THEN
314 DO i = 1,
SIZE(matrices)
315 CALL cp_fm_release(matrices(i))
317 DEALLOCATE (matrices)
320 END SUBROUTINE cp_fm_release_pa1
326 SUBROUTINE cp_fm_release_pa2(matrices)
327 TYPE(cp_fm_type),
DIMENSION(:, :),
POINTER :: matrices
331 IF (
ASSOCIATED(matrices))
THEN
332 DO i = 1,
SIZE(matrices, 1)
333 DO j = 1,
SIZE(matrices, 2)
334 CALL cp_fm_release(matrices(i, j))
337 DEALLOCATE (matrices)
340 END SUBROUTINE cp_fm_release_pa2
346 SUBROUTINE cp_fm_release_pa3(matrices)
347 TYPE(cp_fm_type),
DIMENSION(:, :, :),
POINTER :: matrices
351 IF (
ASSOCIATED(matrices))
THEN
352 DO i = 1,
SIZE(matrices, 1)
353 DO j = 1,
SIZE(matrices, 2)
354 DO k = 1,
SIZE(matrices, 3)
355 CALL cp_fm_release(matrices(i, j, k))
359 DEALLOCATE (matrices)
362 END SUBROUTINE cp_fm_release_pa3
368 SUBROUTINE cp_fm_release_ap1(matrices)
369 TYPE(cp_fm_p_type),
ALLOCATABLE,
DIMENSION(:) :: matrices
373 IF (
ALLOCATED(matrices))
THEN
374 DO i = 1,
SIZE(matrices)
375 CALL cp_fm_release(matrices(i)%matrix)
376 DEALLOCATE (matrices(i)%matrix)
378 DEALLOCATE (matrices)
380 END SUBROUTINE cp_fm_release_ap1
386 SUBROUTINE cp_fm_release_ap2(matrices)
387 TYPE(cp_fm_p_type),
ALLOCATABLE,
DIMENSION(:, :) :: matrices
391 IF (
ALLOCATED(matrices))
THEN
392 DO i = 1,
SIZE(matrices, 1)
393 DO j = 1,
SIZE(matrices, 2)
394 CALL cp_fm_release(matrices(i, j)%matrix)
395 DEALLOCATE (matrices(i, j)%matrix)
398 DEALLOCATE (matrices)
400 END SUBROUTINE cp_fm_release_ap2
406 SUBROUTINE cp_fm_release_pp1(matrices)
407 TYPE(cp_fm_p_type),
DIMENSION(:),
POINTER :: matrices
411 IF (
ASSOCIATED(matrices))
THEN
412 DO i = 1,
SIZE(matrices)
413 CALL cp_fm_release(matrices(i)%matrix)
414 DEALLOCATE (matrices(i)%matrix)
416 DEALLOCATE (matrices)
419 END SUBROUTINE cp_fm_release_pp1
425 SUBROUTINE cp_fm_release_pp2(matrices)
426 TYPE(cp_fm_p_type),
DIMENSION(:, :),
POINTER :: matrices
430 IF (
ASSOCIATED(matrices))
THEN
431 DO i = 1,
SIZE(matrices, 1)
432 DO j = 1,
SIZE(matrices, 2)
433 CALL cp_fm_release(matrices(i, j)%matrix)
434 DEALLOCATE (matrices(i, j)%matrix)
437 DEALLOCATE (matrices)
440 END SUBROUTINE cp_fm_release_pp2
452 TYPE(cp_fm_type),
INTENT(IN) :: matrix
453 INTEGER,
INTENT(IN),
OPTIONAL :: ncol, start_col
455 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_init_random'
457 INTEGER :: handle, icol_global, icol_local, irow_local, my_ncol, my_start_col, ncol_global, &
458 ncol_local, nrow_global, nrow_local
459 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
460 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: buff
461 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
462 POINTER :: local_data
463 REAL(kind=
dp),
DIMENSION(3, 2),
SAVE :: &
464 seed = reshape((/1.0_dp, 2.0_dp, 3.0_dp, 4.0_dp, 5.0_dp, 6.0_dp/), (/3, 2/))
465 TYPE(rng_stream_type) :: rng
467 CALL timeset(routinen, handle)
470 CALL matrix%matrix_struct%para_env%bcast(seed, 0)
472 rng = rng_stream_type(
"cp_fm_init_random_stream", distribution_type=
uniform, &
473 extended_precision=.true., seed=seed)
475 cpassert(.NOT. matrix%use_sp)
477 CALL cp_fm_get_info(matrix, nrow_global=nrow_global, ncol_global=ncol_global, &
478 nrow_local=nrow_local, ncol_local=ncol_local, &
479 local_data=local_data, &
480 row_indices=row_indices, col_indices=col_indices)
483 IF (
PRESENT(start_col)) my_start_col = start_col
484 my_ncol = matrix%matrix_struct%ncol_global
485 IF (
PRESENT(ncol)) my_ncol = ncol
487 IF (ncol_global < (my_start_col + my_ncol - 1)) &
488 cpabort(
"ncol_global>=(my_start_col+my_ncol-1)")
490 ALLOCATE (buff(nrow_global))
496 DO icol_local = 1, ncol_local
497 cpassert(col_indices(icol_local) > icol_global)
499 CALL rng%reset_to_next_substream()
500 icol_global = icol_global + 1
501 IF (icol_global == col_indices(icol_local))
EXIT
504 DO irow_local = 1, nrow_local
505 local_data(irow_local, icol_local) = buff(row_indices(irow_local))
518 CALL rng%get(ig=seed)
520 CALL timestop(handle)
536 TYPE(cp_fm_type),
INTENT(IN) :: matrix
537 REAL(kind=
dp),
INTENT(IN) :: alpha
538 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: beta
540 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_set_all'
542 INTEGER :: handle, i, n
544 CALL timeset(routinen, handle)
546 IF (matrix%use_sp)
THEN
547 matrix%local_data_sp(:, :) = real(alpha,
sp)
549 matrix%local_data(:, :) = alpha
552 IF (
PRESENT(beta))
THEN
553 cpassert(.NOT. matrix%use_sp)
554 n = min(matrix%matrix_struct%nrow_global, matrix%matrix_struct%ncol_global)
560 CALL timestop(handle)
572 TYPE(cp_fm_type),
INTENT(IN) :: matrix
573 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: diag
576 INTEGER :: i, nrow_global
578 #if defined(__SCALAPACK)
579 INTEGER,
DIMENSION(9) :: desca
580 TYPE(cp_blacs_env_type),
POINTER :: context
581 INTEGER :: icol_local, ipcol, iprow, irow_local, mypcol, myprow, npcol, &
583 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
584 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: a_sp
589 #if defined(__SCALAPACK)
591 context => matrix%matrix_struct%context
592 myprow = context%mepos(1)
593 mypcol = context%mepos(2)
594 nprow = context%num_pe(1)
595 npcol = context%num_pe(2)
597 a => matrix%local_data
598 a_sp => matrix%local_data_sp
599 desca(:) = matrix%matrix_struct%descriptor(:)
601 DO i = 1, nrow_global
602 CALL infog2l(i, i, desca, nprow, npcol, myprow, mypcol, &
603 irow_local, icol_local, iprow, ipcol)
604 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
605 IF (matrix%use_sp)
THEN
606 diag(i) = real(a_sp(irow_local, icol_local),
dp)
608 diag(i) = a(irow_local, icol_local)
613 DO i = 1, nrow_global
614 IF (matrix%use_sp)
THEN
615 diag(i) = real(matrix%local_data_sp(i, i),
dp)
617 diag(i) = matrix%local_data(i, i)
621 CALL matrix%matrix_struct%para_env%sum(diag)
645 TYPE(cp_fm_type),
INTENT(IN) :: matrix
646 REAL(kind=
dp),
INTENT(OUT) :: alpha
647 INTEGER,
INTENT(IN) :: icol_global, &
649 LOGICAL,
INTENT(OUT),
OPTIONAL :: local
652 #if defined(__SCALAPACK)
653 INTEGER,
DIMENSION(9) :: desca
654 TYPE(cp_blacs_env_type),
POINTER :: context
655 INTEGER :: icol_local, ipcol, iprow, irow_local, mypcol, myprow, npcol, &
657 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
660 #if defined(__SCALAPACK)
661 context => matrix%matrix_struct%context
662 myprow = context%mepos(1)
663 mypcol = context%mepos(2)
664 nprow = context%num_pe(1)
665 npcol = context%num_pe(2)
667 a => matrix%local_data
668 desca(:) = matrix%matrix_struct%descriptor(:)
670 CALL infog2l(irow_global, icol_global, desca, nprow, npcol, myprow, mypcol, &
671 irow_local, icol_local, iprow, ipcol)
673 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
674 alpha = a(irow_local, icol_local)
675 CALL context%dgebs2d(
'All',
' ', 1, 1, alpha, 1)
676 IF (
PRESENT(local)) local = .true.
678 CALL context%dgebr2d(
'All',
' ', 1, 1, alpha, 1, iprow, ipcol)
679 IF (
PRESENT(local)) local = .false.
683 IF (
PRESENT(local)) local = .true.
684 alpha = matrix%local_data(irow_global, icol_global)
700 TYPE(cp_fm_type),
INTENT(IN) :: matrix
701 INTEGER,
INTENT(IN) :: irow_global, icol_global
702 REAL(kind=
dp),
INTENT(IN) :: alpha
704 INTEGER :: mypcol, myprow, npcol, nprow
705 TYPE(cp_blacs_env_type),
POINTER :: context
706 #if defined(__SCALAPACK)
707 INTEGER :: icol_local, ipcol, iprow, &
709 INTEGER,
DIMENSION(9) :: desca
710 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
713 context => matrix%matrix_struct%context
714 myprow = context%mepos(1)
715 mypcol = context%mepos(2)
716 nprow = context%num_pe(1)
717 npcol = context%num_pe(2)
719 cpassert(.NOT. matrix%use_sp)
721 #if defined(__SCALAPACK)
723 a => matrix%local_data
725 desca(:) = matrix%matrix_struct%descriptor(:)
727 CALL infog2l(irow_global, icol_global, desca, nprow, npcol, myprow, mypcol, &
728 irow_local, icol_local, iprow, ipcol)
730 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
731 a(irow_local, icol_local) = alpha
736 matrix%local_data(irow_global, icol_global) = alpha
767 start_col, n_rows, n_cols, alpha, beta, transpose)
768 TYPE(cp_fm_type),
INTENT(IN) :: fm
769 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(in) :: new_values
770 INTEGER,
INTENT(in),
OPTIONAL :: start_row, start_col, n_rows, n_cols
771 REAL(kind=
dp),
INTENT(in),
OPTIONAL :: alpha, beta
772 LOGICAL,
INTENT(in),
OPTIONAL :: transpose
774 INTEGER :: i, i0, j, j0, ncol, ncol_block, &
775 ncol_global, ncol_local, nrow, &
776 nrow_block, nrow_global, nrow_local, &
778 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
780 REAL(kind=
dp) :: al, be
781 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: full_block
783 al = 1.0_dp; be = 0.0_dp; i0 = 1; j0 = 1; tr_a = .false.
787 cpassert(.NOT. fm%use_sp)
789 IF (
PRESENT(alpha)) al = alpha
790 IF (
PRESENT(beta)) be = beta
791 IF (
PRESENT(start_row)) i0 = start_row
792 IF (
PRESENT(start_col)) j0 = start_col
793 IF (
PRESENT(transpose)) tr_a = transpose
795 nrow =
SIZE(new_values, 2)
796 ncol =
SIZE(new_values, 1)
798 nrow =
SIZE(new_values, 1)
799 ncol =
SIZE(new_values, 2)
801 IF (
PRESENT(n_rows)) nrow = n_rows
802 IF (
PRESENT(n_cols)) ncol = n_cols
804 full_block => fm%local_data
807 nrow_global=nrow_global, ncol_global=ncol_global, &
808 nrow_block=nrow_block, ncol_block=ncol_block, &
809 nrow_local=nrow_local, ncol_local=ncol_local, &
810 row_indices=row_indices, col_indices=col_indices)
812 IF (al == 1.0 .AND. be == 0.0)
THEN
814 this_col = col_indices(j) - j0 + 1
815 IF (this_col .GE. 1 .AND. this_col .LE. ncol)
THEN
817 IF (i0 == 1 .AND. nrow_global == nrow)
THEN
819 full_block(i, j) = new_values(this_col, row_indices(i))
823 this_row = row_indices(i) - i0 + 1
824 IF (this_row >= 1 .AND. this_row <= nrow)
THEN
825 full_block(i, j) = new_values(this_col, this_row)
830 IF (i0 == 1 .AND. nrow_global == nrow)
THEN
832 full_block(i, j) = new_values(row_indices(i), this_col)
836 this_row = row_indices(i) - i0 + 1
837 IF (this_row >= 1 .AND. this_row <= nrow)
THEN
838 full_block(i, j) = new_values(this_row, this_col)
847 this_col = col_indices(j) - j0 + 1
848 IF (this_col .GE. 1 .AND. this_col .LE. ncol)
THEN
851 this_row = row_indices(i) - i0 + 1
852 IF (this_row >= 1 .AND. this_row <= nrow)
THEN
853 full_block(i, j) = al*new_values(this_col, this_row) + &
859 this_row = row_indices(i) - i0 + 1
860 IF (this_row >= 1 .AND. this_row <= nrow)
THEN
861 full_block(i, j) = al*new_values(this_row, this_col) + &
900 start_col, n_rows, n_cols, transpose)
901 TYPE(cp_fm_type),
INTENT(IN) :: fm
902 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(out) :: target_m
903 INTEGER,
INTENT(in),
OPTIONAL :: start_row, start_col, n_rows, n_cols
904 LOGICAL,
INTENT(in),
OPTIONAL :: transpose
906 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_get_submatrix'
908 INTEGER :: handle, i, i0, j, j0, ncol, ncol_global, &
909 ncol_local, nrow, nrow_global, &
910 nrow_local, this_col, this_row
911 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
913 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: full_block
914 TYPE(mp_para_env_type),
POINTER :: para_env
916 CALL timeset(routinen, handle)
918 i0 = 1; j0 = 1; tr_a = .false.
920 cpassert(.NOT. fm%use_sp)
922 IF (
PRESENT(start_row)) i0 = start_row
923 IF (
PRESENT(start_col)) j0 = start_col
924 IF (
PRESENT(transpose)) tr_a = transpose
926 nrow =
SIZE(target_m, 2)
927 ncol =
SIZE(target_m, 1)
929 nrow =
SIZE(target_m, 1)
930 ncol =
SIZE(target_m, 2)
932 IF (
PRESENT(n_rows)) nrow = n_rows
933 IF (
PRESENT(n_cols)) ncol = n_cols
935 para_env => fm%matrix_struct%para_env
937 full_block => fm%local_data
938 #if defined(__SCALAPACK)
940 IF (
SIZE(target_m, 1)*
SIZE(target_m, 2) /= 0)
THEN
941 CALL dcopy(
SIZE(target_m, 1)*
SIZE(target_m, 2), [0.0_dp], 0, target_m, 1)
946 nrow_global=nrow_global, ncol_global=ncol_global, &
947 nrow_local=nrow_local, ncol_local=ncol_local, &
948 row_indices=row_indices, col_indices=col_indices)
951 this_col = col_indices(j) - j0 + 1
952 IF (this_col .GE. 1 .AND. this_col .LE. ncol)
THEN
954 IF (i0 == 1 .AND. nrow_global == nrow)
THEN
956 target_m(this_col, row_indices(i)) = full_block(i, j)
960 this_row = row_indices(i) - i0 + 1
961 IF (this_row >= 1 .AND. this_row <= nrow)
THEN
962 target_m(this_col, this_row) = full_block(i, j)
967 IF (i0 == 1 .AND. nrow_global == nrow)
THEN
969 target_m(row_indices(i), this_col) = full_block(i, j)
973 this_row = row_indices(i) - i0 + 1
974 IF (this_row >= 1 .AND. this_row <= nrow)
THEN
975 target_m(this_row, this_col) = full_block(i, j)
983 CALL para_env%sum(target_m)
985 CALL timestop(handle)
1013 nrow_block, ncol_block, nrow_local, ncol_local, &
1014 row_indices, col_indices, local_data, context, &
1015 nrow_locals, ncol_locals, matrix_struct, para_env)
1017 TYPE(cp_fm_type),
INTENT(IN) :: matrix
1018 CHARACTER(LEN=*),
INTENT(OUT),
OPTIONAL :: name
1019 INTEGER,
INTENT(OUT),
OPTIONAL :: nrow_global, ncol_global, nrow_block, &
1020 ncol_block, nrow_local, ncol_local
1021 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: row_indices, col_indices
1022 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1023 OPTIONAL,
POINTER :: local_data
1024 TYPE(cp_blacs_env_type),
OPTIONAL,
POINTER :: context
1025 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: nrow_locals, ncol_locals
1026 TYPE(cp_fm_struct_type),
OPTIONAL,
POINTER :: matrix_struct
1027 TYPE(mp_para_env_type),
OPTIONAL,
POINTER :: para_env
1029 IF (
PRESENT(name)) name = matrix%name
1030 IF (
PRESENT(matrix_struct)) matrix_struct => matrix%matrix_struct
1031 IF (
PRESENT(local_data)) local_data => matrix%local_data
1034 ncol_local=ncol_local, nrow_global=nrow_global, &
1035 ncol_global=ncol_global, nrow_block=nrow_block, &
1036 ncol_block=ncol_block, row_indices=row_indices, &
1037 col_indices=col_indices, nrow_locals=nrow_locals, &
1038 ncol_locals=ncol_locals, context=context, para_env=para_env)
1048 TYPE(cp_fm_type),
INTENT(IN) :: matrix
1049 INTEGER,
INTENT(IN) :: io_unit
1051 WRITE (io_unit,
'(/,A,A12)')
"CP_FM | Name: ", matrix%name
1064 TYPE(cp_fm_type),
INTENT(IN) :: matrix
1065 REAL(kind=
dp),
INTENT(OUT) :: a_max
1066 INTEGER,
INTENT(OUT),
OPTIONAL :: ir_max, ic_max
1068 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_maxabsval'
1070 INTEGER :: handle, i, ic_max_local, ir_max_local, &
1071 j, mepos, ncol_local, nrow_local, &
1073 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ic_max_vec, ir_max_vec
1074 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1076 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: a_max_vec
1077 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: my_block
1078 REAL(kind=
sp),
DIMENSION(:, :),
POINTER :: my_block_sp
1080 CALL timeset(routinen, handle)
1082 my_block => matrix%local_data
1083 my_block_sp => matrix%local_data_sp
1085 CALL cp_fm_get_info(matrix, nrow_local=nrow_local, ncol_local=ncol_local, &
1086 row_indices=row_indices, col_indices=col_indices)
1088 IF (matrix%use_sp)
THEN
1089 a_max = real(maxval(abs(my_block_sp(1:nrow_local, 1:ncol_local))),
dp)
1091 a_max = maxval(abs(my_block(1:nrow_local, 1:ncol_local)))
1094 IF (
PRESENT(ir_max))
THEN
1095 num_pe = matrix%matrix_struct%para_env%num_pe
1096 mepos = matrix%matrix_struct%para_env%mepos
1097 ALLOCATE (ir_max_vec(0:num_pe - 1))
1098 ir_max_vec(0:num_pe - 1) = 0
1099 ALLOCATE (ic_max_vec(0:num_pe - 1))
1100 ic_max_vec(0:num_pe - 1) = 0
1101 ALLOCATE (a_max_vec(0:num_pe - 1))
1102 a_max_vec(0:num_pe - 1) = 0.0_dp
1105 IF ((ncol_local > 0) .AND. (nrow_local > 0))
THEN
1106 DO i = 1, ncol_local
1107 DO j = 1, nrow_local
1108 IF (matrix%use_sp)
THEN
1109 IF (abs(my_block_sp(j, i)) > my_max)
THEN
1110 my_max = real(my_block_sp(j, i),
dp)
1115 IF (abs(my_block(j, i)) > my_max)
THEN
1116 my_max = my_block(j, i)
1124 a_max_vec(mepos) = my_max
1125 ir_max_vec(mepos) = row_indices(ir_max_local)
1126 ic_max_vec(mepos) = col_indices(ic_max_local)
1130 CALL matrix%matrix_struct%para_env%sum(a_max_vec)
1131 CALL matrix%matrix_struct%para_env%sum(ir_max_vec)
1132 CALL matrix%matrix_struct%para_env%sum(ic_max_vec)
1135 DO i = 0, num_pe - 1
1136 IF (a_max_vec(i) > my_max)
THEN
1137 ir_max = ir_max_vec(i)
1138 ic_max = ic_max_vec(i)
1142 DEALLOCATE (ir_max_vec, ic_max_vec, a_max_vec)
1143 cpassert(ic_max > 0)
1144 cpassert(ir_max > 0)
1148 CALL matrix%matrix_struct%para_env%max(a_max)
1150 CALL timestop(handle)
1166 TYPE(cp_fm_type),
INTENT(IN) :: matrix
1167 REAL(kind=
dp),
INTENT(OUT) :: a_max
1169 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_maxabsrownorm'
1171 INTEGER :: handle, i, j, ncol_local, nrow_global, &
1173 INTEGER,
DIMENSION(:),
POINTER :: row_indices
1174 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: values
1175 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: my_block
1177 CALL timeset(routinen, handle)
1179 my_block => matrix%local_data
1181 cpassert(.NOT. matrix%use_sp)
1183 CALL cp_fm_get_info(matrix, row_indices=row_indices, nrow_global=nrow_global, &
1184 nrow_local=nrow_local, ncol_local=ncol_local)
1187 ALLOCATE (values(nrow_global))
1189 DO j = 1, ncol_local
1190 DO i = 1, nrow_local
1191 values(row_indices(i)) = values(row_indices(i)) + abs(my_block(i, j))
1194 CALL matrix%matrix_struct%para_env%sum(values)
1195 a_max = maxval(values)
1198 CALL timestop(handle)
1207 TYPE(cp_fm_type),
INTENT(IN) :: matrix
1208 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: norm_array
1210 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_vectorsnorm'
1212 INTEGER :: handle, i, j, ncol_global, ncol_local, &
1214 INTEGER,
DIMENSION(:),
POINTER :: col_indices
1215 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: my_block
1217 CALL timeset(routinen, handle)
1219 my_block => matrix%local_data
1221 cpassert(.NOT. matrix%use_sp)
1223 CALL cp_fm_get_info(matrix, col_indices=col_indices, ncol_global=ncol_global, &
1224 nrow_local=nrow_local, ncol_local=ncol_local)
1228 DO j = 1, ncol_local
1229 DO i = 1, nrow_local
1230 norm_array(col_indices(j)) = norm_array(col_indices(j)) + my_block(i, j)*my_block(i, j)
1233 CALL matrix%matrix_struct%para_env%sum(norm_array)
1234 norm_array = sqrt(norm_array)
1236 CALL timestop(handle)
1252 TYPE(cp_fm_type),
INTENT(IN) :: matrix
1253 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: sum_array
1254 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: dir
1256 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_vectorssum'
1258 INTEGER :: handle, i, j, ncol_local, nrow_local
1259 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1261 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: my_block
1263 CALL timeset(routinen, handle)
1265 IF (
PRESENT(dir))
THEN
1266 IF (dir ==
'c' .OR. dir ==
'C')
THEN
1268 ELSEIF (dir ==
'r' .OR. dir ==
'R')
THEN
1271 cpabort(
'Wrong argument DIR')
1277 my_block => matrix%local_data
1279 cpassert(.NOT. matrix%use_sp)
1281 CALL cp_fm_get_info(matrix, col_indices=col_indices, row_indices=row_indices, &
1282 nrow_local=nrow_local, ncol_local=ncol_local)
1285 sum_array(:) = 0.0_dp
1287 DO j = 1, ncol_local
1288 DO i = 1, nrow_local
1289 sum_array(col_indices(j)) = sum_array(col_indices(j)) + my_block(i, j)
1293 DO j = 1, ncol_local
1294 DO i = 1, nrow_local
1295 sum_array(row_indices(i)) = sum_array(row_indices(i)) + my_block(i, j)
1299 CALL matrix%matrix_struct%para_env%sum(sum_array)
1301 CALL timestop(handle)
1311 SUBROUTINE cp_fm_to_fm_matrix(source, destination)
1313 TYPE(cp_fm_type),
INTENT(IN) :: source, destination
1315 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_to_fm_matrix'
1317 INTEGER :: handle, npcol, nprow
1319 CALL timeset(routinen, handle)
1321 nprow = source%matrix_struct%context%num_pe(1)
1322 npcol = source%matrix_struct%context%num_pe(2)
1326 destination%matrix_struct))
THEN
1327 IF (source%use_sp .AND. destination%use_sp)
THEN
1328 IF (
SIZE(source%local_data_sp, 1) /=
SIZE(destination%local_data_sp, 1) .OR. &
1329 SIZE(source%local_data_sp, 2) /=
SIZE(destination%local_data_sp, 2)) &
1330 CALL cp_abort(__location__, &
1331 "Cannot copy full matrix <"//trim(source%name)// &
1332 "> to full matrix <"//trim(destination%name)// &
1333 ">. The local_data blocks have different sizes.")
1334 CALL scopy(
SIZE(source%local_data_sp, 1)*
SIZE(source%local_data_sp, 2), &
1335 source%local_data_sp, 1, destination%local_data_sp, 1)
1336 ELSE IF (source%use_sp .AND. .NOT. destination%use_sp)
THEN
1337 IF (
SIZE(source%local_data_sp, 1) /=
SIZE(destination%local_data, 1) .OR. &
1338 SIZE(source%local_data_sp, 2) /=
SIZE(destination%local_data, 2)) &
1339 CALL cp_abort(__location__, &
1340 "Cannot copy full matrix <"//trim(source%name)// &
1341 "> to full matrix <"//trim(destination%name)// &
1342 ">. The local_data blocks have different sizes.")
1343 destination%local_data = real(source%local_data_sp,
dp)
1344 ELSE IF (.NOT. source%use_sp .AND. destination%use_sp)
THEN
1345 IF (
SIZE(source%local_data, 1) /=
SIZE(destination%local_data_sp, 1) .OR. &
1346 SIZE(source%local_data, 2) /=
SIZE(destination%local_data_sp, 2)) &
1347 CALL cp_abort(__location__, &
1348 "Cannot copy full matrix <"//trim(source%name)// &
1349 "> to full matrix <"//trim(destination%name)// &
1350 ">. The local_data blocks have different sizes.")
1351 destination%local_data_sp = real(source%local_data,
sp)
1353 IF (
SIZE(source%local_data, 1) /=
SIZE(destination%local_data, 1) .OR. &
1354 SIZE(source%local_data, 2) /=
SIZE(destination%local_data, 2)) &
1355 CALL cp_abort(__location__, &
1356 "Cannot copy full matrix <"//trim(source%name)// &
1357 "> to full matrix <"//trim(destination%name)// &
1358 ">. The local_data blocks have different sizes.")
1359 CALL dcopy(
SIZE(source%local_data, 1)*
SIZE(source%local_data, 2), &
1360 source%local_data, 1, destination%local_data, 1)
1363 cpabort(
"Data structures of source and target full matrix are not equivalent")
1366 CALL timestop(handle)
1368 END SUBROUTINE cp_fm_to_fm_matrix
1378 SUBROUTINE cp_fm_to_fm_columns(msource, mtarget, ncol, source_start, &
1381 TYPE(cp_fm_type),
INTENT(IN) :: msource, mtarget
1382 INTEGER,
INTENT(IN) :: ncol
1383 INTEGER,
INTENT(IN),
OPTIONAL :: source_start, target_start
1385 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_to_fm_columns'
1387 INTEGER :: handle, n, ss, ts
1388 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
1389 #if defined(__SCALAPACK)
1391 INTEGER,
DIMENSION(9) :: desca, descb
1394 CALL timeset(routinen, handle)
1399 IF (
PRESENT(source_start)) ss = source_start
1400 IF (
PRESENT(target_start)) ts = target_start
1402 n = msource%matrix_struct%nrow_global
1404 a => msource%local_data
1405 b => mtarget%local_data
1407 #if defined(__SCALAPACK)
1408 desca(:) = msource%matrix_struct%descriptor(:)
1409 descb(:) = mtarget%matrix_struct%descriptor(:)
1411 CALL pdcopy(n, a, 1, ss + i, desca, 1, b, 1, ts + i, descb, 1)
1414 CALL dcopy(ncol*n, a(:, ss), 1, b(:, ts), 1)
1417 CALL timestop(handle)
1419 END SUBROUTINE cp_fm_to_fm_columns
1429 TYPE(cp_fm_type),
INTENT(IN) :: msource, mtarget
1430 CHARACTER(LEN=*),
INTENT(IN) :: uplo
1432 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_to_fm_triangular'
1434 INTEGER :: handle, ncol, nrow
1435 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
1436 #if defined(__SCALAPACK)
1437 INTEGER,
DIMENSION(9) :: desca, descb
1440 CALL timeset(routinen, handle)
1442 nrow = msource%matrix_struct%nrow_global
1443 ncol = msource%matrix_struct%ncol_global
1445 a => msource%local_data
1446 b => mtarget%local_data
1448 #if defined(__SCALAPACK)
1449 desca(:) = msource%matrix_struct%descriptor(:)
1450 descb(:) = mtarget%matrix_struct%descriptor(:)
1451 CALL pdlacpy(uplo, nrow, ncol, a(1, 1), 1, 1, desca, b(1, 1), 1, 1, descb)
1453 CALL dlacpy(uplo, nrow, ncol, a(1, 1), nrow, b(1, 1), nrow)
1456 CALL timestop(handle)
1472 SUBROUTINE cp_fm_to_fm_submat(msource, mtarget, nrow, ncol, s_firstrow, s_firstcol, t_firstrow, t_firstcol)
1474 TYPE(cp_fm_type),
INTENT(IN) :: msource, mtarget
1475 INTEGER,
INTENT(IN) :: nrow, ncol, s_firstrow, &
1476 s_firstcol, t_firstrow, &
1479 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_to_fm_submat'
1481 INTEGER :: handle, i, na, nb, ss, ts
1482 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a, b
1483 #if defined(__SCALAPACK)
1484 INTEGER,
DIMENSION(9) :: desca, descb
1487 CALL timeset(routinen, handle)
1489 a => msource%local_data
1490 b => mtarget%local_data
1492 na = msource%matrix_struct%nrow_global
1493 nb = mtarget%matrix_struct%nrow_global
1496 cpabort(
"cannot copy because nrow > number of rows of source matrix")
1498 cpabort(
"cannot copy because nrow > number of rows of target matrix")
1499 na = msource%matrix_struct%ncol_global
1500 nb = mtarget%matrix_struct%ncol_global
1503 cpabort(
"cannot copy because nrow > number of rows of source matrix")
1505 cpabort(
"cannot copy because nrow > number of rows of target matrix")
1507 #if defined(__SCALAPACK)
1508 desca(:) = msource%matrix_struct%descriptor(:)
1509 descb(:) = mtarget%matrix_struct%descriptor(:)
1513 CALL pdcopy(nrow, a, s_firstrow, ss, desca, 1, b, t_firstrow, ts, descb, 1)
1519 CALL dcopy(nrow, a(s_firstrow:, ss), 1, b(t_firstrow:, ts), 1)
1523 CALL timestop(handle)
1538 TYPE(cp_fm_type),
INTENT(IN) :: source, destination
1539 TYPE(mp_para_env_type),
INTENT(IN) :: para_env
1541 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_copy_general'
1544 TYPE(copy_info_type) :: info
1546 CALL timeset(routinen, handle)
1549 IF (
ASSOCIATED(destination%matrix_struct))
THEN
1552 IF (
ASSOCIATED(source%matrix_struct))
THEN
1556 CALL timestop(handle)
1568 TYPE(cp_fm_type),
INTENT(IN) :: source, destination
1569 TYPE(mp_para_env_type),
INTENT(IN) :: para_env
1570 TYPE(copy_info_type),
INTENT(OUT) :: info
1572 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_start_copy_general'
1574 INTEGER :: dest_p_i, dest_q_j, global_rank, global_size, handle, i, j, k, mpi_rank, &
1575 ncol_block_dest, ncol_block_src, ncol_local_recv, ncol_local_send, ncols, &
1576 nrow_block_dest, nrow_block_src, nrow_local_recv, nrow_local_send, nrows, p, q, &
1577 recv_rank, recv_size, send_rank, send_size
1578 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: all_ranks, dest2global, dest_p, dest_q, &
1579 recv_count, send_count, send_disp, &
1580 source2global, src_p, src_q
1581 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: dest_blacs2mpi
1582 INTEGER,
DIMENSION(2) :: dest_block, dest_block_tmp, dest_num_pe, &
1583 src_block, src_block_tmp, src_num_pe
1584 INTEGER,
DIMENSION(:),
POINTER :: recv_col_indices, recv_row_indices, &
1585 send_col_indices, send_row_indices
1586 TYPE(cp_fm_struct_type),
POINTER :: recv_dist, send_dist
1587 TYPE(mp_request_type),
DIMENSION(6) :: recv_req, send_req
1589 CALL timeset(routinen, handle)
1593 nrow_local_send =
SIZE(source%local_data, 1)
1594 ncol_local_send =
SIZE(source%local_data, 2)
1595 ALLOCATE (info%send_buf(nrow_local_send*ncol_local_send))
1597 DO j = 1, ncol_local_send
1598 DO i = 1, nrow_local_send
1600 info%send_buf(k) = source%local_data(i, j)
1605 IF (source%use_sp) cpabort(
"only DP kind implemented")
1606 IF (destination%use_sp) cpabort(
"only DP kind implemented")
1608 NULLIFY (recv_dist, send_dist)
1609 NULLIFY (recv_col_indices, recv_row_indices, send_col_indices, send_row_indices)
1612 global_size = para_env%num_pe
1613 global_rank = para_env%mepos
1619 IF (
ASSOCIATED(destination%matrix_struct))
THEN
1620 recv_dist => destination%matrix_struct
1621 recv_rank = recv_dist%para_env%mepos
1626 IF (
ASSOCIATED(source%matrix_struct))
THEN
1627 send_dist => source%matrix_struct
1628 send_rank = send_dist%para_env%mepos
1634 ALLOCATE (all_ranks(0:global_size - 1))
1636 CALL para_env%allgather(send_rank, all_ranks)
1637 IF (
ASSOCIATED(recv_dist))
THEN
1638 ALLOCATE (source2global(0:count(all_ranks .NE.
mp_proc_null) - 1))
1639 DO i = 0, global_size - 1
1641 source2global(all_ranks(i)) = i
1646 CALL para_env%allgather(recv_rank, all_ranks)
1647 IF (
ASSOCIATED(send_dist))
THEN
1648 ALLOCATE (dest2global(0:count(all_ranks .NE.
mp_proc_null) - 1))
1649 DO i = 0, global_size - 1
1651 dest2global(all_ranks(i)) = i
1655 DEALLOCATE (all_ranks)
1662 IF (global_rank == 0)
THEN
1664 CALL para_env%irecv(src_block,
mp_any_source, recv_req(1), tag=src_tag)
1665 CALL para_env%irecv(dest_block,
mp_any_source, recv_req(2), tag=dest_tag)
1666 CALL para_env%irecv(src_num_pe,
mp_any_source, recv_req(3), tag=src_tag)
1667 CALL para_env%irecv(dest_num_pe,
mp_any_source, recv_req(4), tag=dest_tag)
1670 IF (
ASSOCIATED(send_dist))
THEN
1671 IF ((send_rank .EQ. 0))
THEN
1673 src_block_tmp = (/send_dist%nrow_block, send_dist%ncol_block/)
1674 CALL para_env%isend(src_block_tmp, 0, send_req(1), tag=src_tag)
1675 CALL para_env%isend(send_dist%context%num_pe, 0, send_req(2), tag=src_tag)
1679 IF (
ASSOCIATED(recv_dist))
THEN
1680 IF ((recv_rank .EQ. 0))
THEN
1681 dest_block_tmp = (/recv_dist%nrow_block, recv_dist%ncol_block/)
1682 CALL para_env%isend(dest_block_tmp, 0, send_req(3), tag=dest_tag)
1683 CALL para_env%isend(recv_dist%context%num_pe, 0, send_req(4), tag=dest_tag)
1687 IF (global_rank == 0)
THEN
1688 CALL mp_waitall(recv_req(1:4))
1690 ALLOCATE (info%src_blacs2mpi(0:src_num_pe(1) - 1, 0:src_num_pe(2) - 1), &
1691 dest_blacs2mpi(0:dest_num_pe(1) - 1, 0:dest_num_pe(2) - 1) &
1693 CALL para_env%irecv(info%src_blacs2mpi,
mp_any_source, recv_req(5), tag=src_tag)
1694 CALL para_env%irecv(dest_blacs2mpi,
mp_any_source, recv_req(6), tag=dest_tag)
1697 IF (
ASSOCIATED(send_dist))
THEN
1698 IF ((send_rank .EQ. 0))
THEN
1699 CALL para_env%isend(send_dist%context%blacs2mpi(:, :), 0, send_req(5), tag=src_tag)
1703 IF (
ASSOCIATED(recv_dist))
THEN
1704 IF ((recv_rank .EQ. 0))
THEN
1705 CALL para_env%isend(recv_dist%context%blacs2mpi(:, :), 0, send_req(6), tag=dest_tag)
1709 IF (global_rank == 0)
THEN
1710 CALL mp_waitall(recv_req(5:6))
1714 CALL para_env%bcast(src_block, 0)
1715 CALL para_env%bcast(dest_block, 0)
1716 CALL para_env%bcast(src_num_pe, 0)
1717 CALL para_env%bcast(dest_num_pe, 0)
1718 info%src_num_pe(1:2) = src_num_pe(1:2)
1719 info%nblock_src(1:2) = src_block(1:2)
1720 IF (global_rank .NE. 0)
THEN
1721 ALLOCATE (info%src_blacs2mpi(0:src_num_pe(1) - 1, 0:src_num_pe(2) - 1), &
1722 dest_blacs2mpi(0:dest_num_pe(1) - 1, 0:dest_num_pe(2) - 1) &
1725 CALL para_env%bcast(info%src_blacs2mpi, 0)
1726 CALL para_env%bcast(dest_blacs2mpi, 0)
1728 recv_size = dest_num_pe(1)*dest_num_pe(2)
1729 send_size = src_num_pe(1)*src_num_pe(2)
1730 info%send_size = send_size
1731 CALL mp_waitall(send_req(:))
1748 IF (
ASSOCIATED(recv_dist))
THEN
1750 col_indices=recv_col_indices &
1752 info%recv_col_indices => recv_col_indices
1753 info%recv_row_indices => recv_row_indices
1754 nrow_block_src = src_block(1)
1755 ncol_block_src = src_block(2)
1756 ALLOCATE (recv_count(0:send_size - 1), info%recv_disp(0:send_size - 1), info%recv_request(0:send_size - 1))
1759 nrow_local_recv = recv_dist%nrow_locals(recv_dist%context%mepos(1))
1760 ncol_local_recv = recv_dist%ncol_locals(recv_dist%context%mepos(2))
1761 info%nlocal_recv(1) = nrow_local_recv
1762 info%nlocal_recv(2) = ncol_local_recv
1764 ALLOCATE (src_p(nrow_local_recv), src_q(ncol_local_recv))
1765 DO i = 1, nrow_local_recv
1768 src_p(i) = mod(((recv_row_indices(i) - 1)/nrow_block_src), src_num_pe(1))
1770 DO j = 1, ncol_local_recv
1772 src_q(j) = mod(((recv_col_indices(j) - 1)/ncol_block_src), src_num_pe(2))
1776 DO q = 0, src_num_pe(2) - 1
1777 ncols = count(src_q .EQ. q)
1778 DO p = 0, src_num_pe(1) - 1
1779 nrows = count(src_p .EQ. p)
1781 recv_count(info%src_blacs2mpi(p, q)) = nrows*ncols
1784 DEALLOCATE (src_p, src_q)
1788 ALLOCATE (info%recv_buf(sum(recv_count(:))))
1789 info%recv_disp(0) = 0
1790 DO i = 1, send_size - 1
1791 info%recv_disp(i) = info%recv_disp(i - 1) + recv_count(i - 1)
1795 DO k = 0, send_size - 1
1796 IF (recv_count(k) .GT. 0)
THEN
1797 CALL para_env%irecv(info%recv_buf(info%recv_disp(k) + 1:info%recv_disp(k) + recv_count(k)), &
1798 source2global(k), info%recv_request(k))
1801 DEALLOCATE (source2global)
1805 IF (
ASSOCIATED(send_dist))
THEN
1807 col_indices=send_col_indices &
1809 nrow_block_dest = dest_block(1)
1810 ncol_block_dest = dest_block(2)
1811 ALLOCATE (send_count(0:recv_size - 1), send_disp(0:recv_size - 1), info%send_request(0:recv_size - 1))
1814 nrow_local_send = send_dist%nrow_locals(send_dist%context%mepos(1))
1815 ncol_local_send = send_dist%ncol_locals(send_dist%context%mepos(2))
1819 ALLOCATE (dest_p(nrow_local_send), dest_q(ncol_local_send))
1821 DO i = 1, nrow_local_send
1823 dest_p(i) = mod(((send_row_indices(i) - 1)/nrow_block_dest), dest_num_pe(1))
1825 DO j = 1, ncol_local_send
1826 dest_q(j) = mod(((send_col_indices(j) - 1)/ncol_block_dest), dest_num_pe(2))
1830 DO q = 0, dest_num_pe(2) - 1
1831 ncols = count(dest_q .EQ. q)
1832 DO p = 0, dest_num_pe(1) - 1
1833 nrows = count(dest_p .EQ. p)
1834 send_count(dest_blacs2mpi(p, q)) = nrows*ncols
1837 DEALLOCATE (dest_p, dest_q)
1840 ALLOCATE (info%send_buf(sum(send_count(:))))
1842 DO k = 1, recv_size - 1
1843 send_disp(k) = send_disp(k - 1) + send_count(k - 1)
1848 DO j = 1, ncol_local_send
1850 dest_q_j = mod(((send_col_indices(j) - 1)/ncol_block_dest), dest_num_pe(2))
1851 DO i = 1, nrow_local_send
1852 dest_p_i = mod(((send_row_indices(i) - 1)/nrow_block_dest), dest_num_pe(1))
1853 mpi_rank = dest_blacs2mpi(dest_p_i, dest_q_j)
1854 send_count(mpi_rank) = send_count(mpi_rank) + 1
1855 info%send_buf(send_disp(mpi_rank) + send_count(mpi_rank)) = source%local_data(i, j)
1860 DO k = 0, recv_size - 1
1861 IF (send_count(k) .GT. 0)
THEN
1862 CALL para_env%isend(info%send_buf(send_disp(k) + 1:send_disp(k) + send_count(k)), &
1863 dest2global(k), info%send_request(k))
1866 DEALLOCATE (send_count, send_disp, dest2global)
1868 DEALLOCATE (dest_blacs2mpi)
1872 CALL timestop(handle)
1882 TYPE(cp_fm_type),
INTENT(IN) :: destination
1883 TYPE(copy_info_type),
INTENT(INOUT) :: info
1885 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_finish_copy_general'
1887 INTEGER :: handle, i, j, k, mpi_rank, send_size, &
1889 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: recv_count
1890 INTEGER,
DIMENSION(2) :: nblock_src, nlocal_recv, src_num_pe
1891 INTEGER,
DIMENSION(:),
POINTER :: recv_col_indices, recv_row_indices
1893 CALL timeset(routinen, handle)
1898 DO j = 1,
SIZE(destination%local_data, 2)
1899 DO i = 1,
SIZE(destination%local_data, 1)
1901 destination%local_data(i, j) = info%send_buf(k)
1904 DEALLOCATE (info%send_buf)
1907 send_size = info%send_size
1908 nlocal_recv(1:2) = info%nlocal_recv(:)
1909 nblock_src(1:2) = info%nblock_src(:)
1910 src_num_pe(1:2) = info%src_num_pe(:)
1911 recv_col_indices => info%recv_col_indices
1912 recv_row_indices => info%recv_row_indices
1916 CALL mp_waitall(info%recv_request(:))
1917 ALLOCATE (recv_count(0:send_size - 1))
1921 DO j = 1, nlocal_recv(2)
1922 src_q_j = mod(((recv_col_indices(j) - 1)/nblock_src(2)), src_num_pe(2))
1923 DO i = 1, nlocal_recv(1)
1924 src_p_i = mod(((recv_row_indices(i) - 1)/nblock_src(1)), src_num_pe(1))
1925 mpi_rank = info%src_blacs2mpi(src_p_i, src_q_j)
1926 recv_count(mpi_rank) = recv_count(mpi_rank) + 1
1927 destination%local_data(i, j) = info%recv_buf(info%recv_disp(mpi_rank) + recv_count(mpi_rank))
1930 DEALLOCATE (recv_count, info%recv_disp, info%recv_request, info%recv_buf, info%src_blacs2mpi)
1932 NULLIFY (info%recv_col_indices, &
1933 info%recv_row_indices)
1937 CALL timestop(handle)
1946 TYPE(copy_info_type),
INTENT(INOUT) :: info
1948 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_cleanup_copy_general'
1952 CALL timeset(routinen, handle)
1960 IF (
ALLOCATED(info%src_blacs2mpi))
THEN
1961 DEALLOCATE (info%src_blacs2mpi)
1963 CALL mp_waitall(info%send_request)
1964 DEALLOCATE (info%send_request, info%send_buf)
1968 CALL timestop(handle)
2004 TYPE(cp_fm_type),
INTENT(IN) :: source, destination
2005 INTEGER,
INTENT(IN) :: nrows, ncols, s_firstrow, s_firstcol, &
2006 d_firstrow, d_firstcol
2008 CLASS(cp_blacs_type),
INTENT(IN) :: global_context
2010 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_to_fm_submat_general'
2014 #if defined(__SCALAPACK)
2015 INTEGER,
DIMENSION(9) :: desca, descb
2016 REAL(kind=
dp),
DIMENSION(1, 1),
TARGET :: dummy
2017 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: smat, dmat
2020 CALL timeset(routinen, handle)
2022 debug = debug_this_module
2035 NULLIFY (smat, dmat)
2037 IF (
ASSOCIATED(source%matrix_struct))
THEN
2038 desca = source%matrix_struct%descriptor
2039 IF (source%use_sp) cpabort(
"only DP kind implemented")
2040 IF (nrows .GT. source%matrix_struct%nrow_global) &
2041 cpabort(
"nrows is greater than nrow_global of source")
2042 IF (ncols .GT. source%matrix_struct%ncol_global) &
2043 cpabort(
"ncols is greater than ncol_global of source")
2044 smat => source%local_data
2050 IF (
ASSOCIATED(destination%matrix_struct))
THEN
2051 descb = destination%matrix_struct%descriptor
2052 IF (destination%use_sp) cpabort(
"only DP kind implemented")
2053 IF (nrows .GT. destination%matrix_struct%nrow_global) &
2054 cpabort(
"nrows is greater than nrow_global of destination")
2055 IF (ncols .GT. destination%matrix_struct%ncol_global) &
2056 cpabort(
"ncols is greater than ncol_global of destination")
2057 dmat => destination%local_data
2064 CALL pdgemr2d(nrows, &
2074 global_context%get_handle())
2076 mark_used(global_context)
2077 cpabort(
"this subroutine only supports SCALAPACK")
2081 CALL timestop(handle)
2099 TYPE(cp_fm_type),
INTENT(IN) :: matrix
2100 INTEGER,
INTENT(IN) :: irow_global, icol_global
2101 REAL(kind=
dp),
INTENT(IN) :: alpha
2103 INTEGER :: mypcol, myprow, npcol, nprow
2104 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a
2105 TYPE(cp_blacs_env_type),
POINTER :: context
2106 #if defined(__SCALAPACK)
2107 INTEGER :: icol_local, ipcol, iprow, &
2109 INTEGER,
DIMENSION(9) :: desca
2112 context => matrix%matrix_struct%context
2114 myprow = context%mepos(1)
2115 mypcol = context%mepos(2)
2117 nprow = context%num_pe(1)
2118 npcol = context%num_pe(2)
2120 a => matrix%local_data
2122 #if defined(__SCALAPACK)
2124 desca(:) = matrix%matrix_struct%descriptor(:)
2126 CALL infog2l(irow_global, icol_global, desca, nprow, npcol, myprow, mypcol, &
2127 irow_local, icol_local, iprow, ipcol)
2129 IF ((iprow == myprow) .AND. (ipcol == mypcol))
THEN
2130 a(irow_local, icol_local) = a(irow_local, icol_local) + alpha
2135 a(irow_global, icol_global) = a(irow_global, icol_global) + alpha
2147 TYPE(cp_fm_type),
INTENT(IN) :: fm
2148 INTEGER,
INTENT(IN) :: unit
2150 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_write_unformatted'
2152 INTEGER :: handle, j, max_block, &
2153 ncol_global, nrow_global
2154 TYPE(mp_para_env_type),
POINTER :: para_env
2155 #if defined(__SCALAPACK)
2156 INTEGER :: i, i_block, icol_local, &
2158 iprow, irow_local, &
2161 INTEGER,
DIMENSION(9) :: desc
2162 REAL(kind=
dp),
DIMENSION(:),
POINTER :: vecbuf
2163 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: newdat
2164 TYPE(cp_blacs_type) :: ictxt_loc
2165 INTEGER,
EXTERNAL :: numroc
2168 CALL timeset(routinen, handle)
2169 CALL cp_fm_get_info(fm, nrow_global=nrow_global, ncol_global=ncol_global, ncol_block=max_block, &
2172 #if defined(__SCALAPACK)
2173 num_pe = para_env%num_pe
2174 mepos = para_env%mepos
2178 CALL ictxt_loc%gridinit(para_env,
'R', 1, num_pe)
2179 CALL descinit(desc, nrow_global, ncol_global, rb, max_block, 0, 0, ictxt_loc%get_handle(), nrow_global, info)
2181 associate(nprow => ictxt_loc%num_pe(1), npcol => ictxt_loc%num_pe(2), &
2182 myprow => ictxt_loc%mepos(1), mypcol => ictxt_loc%mepos(2))
2183 in = numroc(ncol_global, max_block, mypcol, 0, npcol)
2185 ALLOCATE (newdat(nrow_global, max(1, in)))
2188 CALL pdgemr2d(nrow_global, ncol_global, fm%local_data, 1, 1, &
2189 fm%matrix_struct%descriptor, &
2190 newdat, 1, 1, desc, ictxt_loc%get_handle())
2192 ALLOCATE (vecbuf(nrow_global*max_block))
2193 vecbuf = huge(1.0_dp)
2195 DO i = 1, ncol_global, max(max_block, 1)
2196 i_block = min(max_block, ncol_global - i + 1)
2197 CALL infog2l(1, i, desc, nprow, npcol, myprow, mypcol, &
2198 irow_local, icol_local, iprow, ipcol)
2199 IF (ipcol == mypcol)
THEN
2201 vecbuf((j - 1)*nrow_global + 1:nrow_global*j) = newdat(:, icol_local + j - 1)
2205 IF (ipcol == 0)
THEN
2208 IF (ipcol == mypcol)
THEN
2209 CALL para_env%send(vecbuf(:), 0, tag)
2211 IF (mypcol == 0)
THEN
2212 CALL para_env%recv(vecbuf(:), ipcol, tag)
2218 WRITE (unit) vecbuf((j - 1)*nrow_global + 1:nrow_global*j)
2226 CALL ictxt_loc%gridexit()
2233 DO j = 1, ncol_global
2234 WRITE (unit) fm%local_data(:, j)
2239 CALL timestop(handle)
2251 TYPE(cp_fm_type),
INTENT(IN) :: fm
2252 INTEGER,
INTENT(IN) :: unit
2253 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL ::
header, value_format
2255 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_write_formatted'
2257 CHARACTER(LEN=21) :: my_value_format
2258 INTEGER :: handle, i, j, max_block, &
2259 ncol_global, nrow_global, &
2261 TYPE(mp_para_env_type),
POINTER :: para_env
2262 #if defined(__SCALAPACK)
2263 INTEGER :: i_block, icol_local, &
2265 iprow, irow_local, &
2266 mepos, num_pe, rb, tag, k, &
2268 INTEGER,
DIMENSION(9) :: desc
2269 REAL(kind=dp),
DIMENSION(:),
POINTER :: vecbuf
2270 REAL(kind=dp),
DIMENSION(:, :),
POINTER :: newdat
2271 TYPE(cp_blacs_type) :: ictxt_loc
2272 INTEGER,
EXTERNAL :: numroc
2275 CALL timeset(routinen, handle)
2276 CALL cp_fm_get_info(fm, nrow_global=nrow_global, ncol_global=ncol_global, ncol_block=max_block, &
2277 nrow_block=nrow_block, para_env=para_env)
2279 IF (
PRESENT(value_format))
THEN
2280 cpassert(len_trim(adjustl(value_format)) < 11)
2281 my_value_format =
"(I10, I10, "//trim(adjustl(value_format))//
")"
2283 my_value_format =
"(I10, I10, ES24.12)"
2288 WRITE (unit,
"(A2, A8, A10, A24)")
"#",
"Row",
"Column", adjustl(
"Value")
2291 #if defined(__SCALAPACK)
2292 num_pe = para_env%num_pe
2293 mepos = para_env%mepos
2297 CALL ictxt_loc%gridinit(para_env,
'R', 1, num_pe)
2298 CALL descinit(desc, nrow_global, ncol_global, rb, max_block, 0, 0, ictxt_loc%get_handle(), nrow_global, info)
2300 associate(nprow => ictxt_loc%num_pe(1), npcol => ictxt_loc%num_pe(2), &
2301 myprow => ictxt_loc%mepos(1), mypcol => ictxt_loc%mepos(2))
2302 in = numroc(ncol_global, max_block, mypcol, 0, npcol)
2304 ALLOCATE (newdat(nrow_global, max(1, in)))
2307 CALL pdgemr2d(nrow_global, ncol_global, fm%local_data, 1, 1, &
2308 fm%matrix_struct%descriptor, &
2309 newdat, 1, 1, desc, ictxt_loc%get_handle())
2311 ALLOCATE (vecbuf(nrow_global*max_block))
2312 vecbuf = huge(1.0_dp)
2316 DO i = 1, ncol_global, max(max_block, 1)
2317 i_block = min(max_block, ncol_global - i + 1)
2318 CALL infog2l(1, i, desc, nprow, npcol, myprow, mypcol, &
2319 irow_local, icol_local, iprow, ipcol)
2320 IF (ipcol == mypcol)
THEN
2322 vecbuf((j - 1)*nrow_global + 1:nrow_global*j) = newdat(:, icol_local + j - 1)
2326 IF (ipcol == 0)
THEN
2329 IF (ipcol == mypcol)
THEN
2330 CALL para_env%send(vecbuf(:), 0, tag)
2332 IF (mypcol == 0)
THEN
2333 CALL para_env%recv(vecbuf(:), ipcol, tag)
2339 DO k = (j - 1)*nrow_global + 1, nrow_global*j
2340 WRITE (unit=unit, fmt=my_value_format) irow, icol, vecbuf(k)
2342 IF (irow > nrow_global)
THEN
2354 CALL ictxt_loc%gridexit()
2361 DO j = 1, ncol_global
2362 DO i = 1, nrow_global
2363 WRITE (unit=unit, fmt=my_value_format) i, j, fm%local_data(i, j)
2369 CALL timestop(handle)
2379 TYPE(cp_fm_type),
INTENT(INOUT) :: fm
2380 INTEGER,
INTENT(IN) :: unit
2382 CHARACTER(len=*),
PARAMETER :: routinen =
'cp_fm_read_unformatted'
2384 INTEGER :: handle, j, max_block, &
2385 ncol_global, nrow_global
2386 TYPE(mp_para_env_type),
POINTER :: para_env
2387 #if defined(__SCALAPACK)
2388 INTEGER :: k, n_cols
2389 REAL(kind=dp),
DIMENSION(:, :),
POINTER :: vecbuf
2392 CALL timeset(routinen, handle)
2394 CALL cp_fm_get_info(fm, nrow_global=nrow_global, ncol_global=ncol_global, ncol_block=max_block, &
2397 #if defined(__SCALAPACK)
2401 ALLOCATE (vecbuf(nrow_global, max_block))
2403 DO j = 1, ncol_global, max_block
2405 n_cols = min(max_block, ncol_global - j + 1)
2406 IF (para_env%mepos == 0)
THEN
2408 READ (unit) vecbuf(:, k)
2411 CALL para_env%bcast(vecbuf, 0)
2420 DO j = 1, ncol_global
2421 READ (unit) fm%local_data(:, j)
2426 CALL timestop(handle)
2466 INTEGER,
INTENT(IN) :: indxglob, nb, iproc, isrcproc, nprocs
2469 #if defined(__SCALAPACK)
2470 INTEGER,
EXTERNAL :: indxg2p
2473 #if defined(__SCALAPACK)
2475 g2p = indxg2p(indxglob, nb, iproc, isrcproc, nprocs)
2525 INTEGER,
INTENT(IN) :: indxglob, nb, iproc, isrcproc, nprocs
2528 #if defined(__SCALAPACK)
2529 INTEGER,
EXTERNAL :: indxg2l
2532 #if defined(__SCALAPACK)
2534 g2l = indxg2l(indxglob, nb, iproc, isrcproc, nprocs)
2585 INTEGER,
INTENT(IN) :: indxloc, nb, iproc, isrcproc, nprocs
2588 #if defined(__SCALAPACK)
2589 INTEGER,
EXTERNAL :: indxl2g
2592 #if defined(__SCALAPACK)
2594 l2g = indxl2g(indxloc, nb, iproc, isrcproc, nprocs)
2613 INTEGER,
INTENT(IN) :: mult_type
2636 CHARACTER(LEN=1) :: prec
2638 #if defined(__SCALAPACK)
2640 res = pilaenv(ictxt, prec)
methods related to the blacs parallel environment
wrappers for the actual blacs calls. all functionality needed in the code should actually be provide ...
represent the structure of a full matrix
subroutine, public cp_fm_struct_get(fmstruct, para_env, context, descriptor, ncol_block, nrow_block, nrow_global, ncol_global, first_p_pos, row_indices, col_indices, nrow_local, ncol_local, nrow_locals, ncol_locals, local_leading_dimension)
returns the values of various attributes of the matrix structure
logical function, public cp_fm_struct_equivalent(fmstruct1, fmstruct2)
returns true if the two matrix structures are equivalent, false otherwise.
subroutine, public cp_fm_struct_retain(fmstruct)
retains a full matrix structure
subroutine, public cp_fm_struct_write_info(fmstruct, io_unit)
Write nicely formatted info about the FM struct to the given I/O unit.
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_copy_general(source, destination, para_env)
General copy of a fm matrix to another fm matrix. Uses non-blocking MPI rather than ScaLAPACK.
integer function, public cp_fm_indxl2g(INDXLOC, NB, IPROC, ISRCPROC, NPROCS)
wrapper to scalapack function INDXL2G that computes the global index of a distributed matrix entry po...
subroutine, public cp_fm_get_diag(matrix, diag)
returns the diagonal elements of a fm
subroutine, public cp_fm_start_copy_general(source, destination, para_env, info)
Initiates the copy operation: get distribution data, post MPI isend and irecvs.
integer function, public cp_fm_indxg2l(INDXGLOB, NB, IPROC, ISRCPROC, NPROCS)
wrapper to scalapack function INDXG2L that computes the local index of a distributed matrix entry poi...
subroutine, public cp_fm_cleanup_copy_general(info)
Completes the copy operation: wait for comms clean up MPI state.
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
integer function, public cp_fm_get_mm_type()
...
subroutine, public cp_fm_vectorssum(matrix, sum_array, dir)
summing up all the elements along the matrix's i-th index or
integer function, public cp_fm_indxg2p(INDXGLOB, NB, IPROC, ISRCPROC, NPROCS)
wrapper to scalapack function INDXG2P that computes the process coordinate which possesses the entry ...
subroutine, public cp_fm_write_unformatted(fm, unit)
...
subroutine, public cp_fm_get_element(matrix, irow_global, icol_global, alpha, local)
returns an element of a fm this value is valid on every cpu using this call is expensive
subroutine, public cp_fm_add_to_element(matrix, irow_global, icol_global, alpha)
...
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_read_unformatted(fm, unit)
...
subroutine, public cp_fm_vectorsnorm(matrix, norm_array)
find the inorm of each column norm_{j}= sqrt( \sum_{i} A_{ij}*A_{ij} )
subroutine, public cp_fm_setup(mult_type)
...
subroutine, public cp_fm_write_info(matrix, io_unit)
Write nicely formatted info about the FM to the given I/O unit (including the underlying FM struct)
subroutine, public cp_fm_maxabsrownorm(matrix, a_max)
find the maximum over the rows of the sum of the absolute values of the elements of a given row = || ...
subroutine, public cp_fm_to_fm_submat_general(source, destination, nrows, ncols, s_firstrow, s_firstcol, d_firstrow, d_firstcol, global_context)
General copy of a submatrix of fm matrix to a submatrix of another fm matrix. The two matrices can ha...
subroutine, public cp_fm_to_fm_submat(msource, mtarget, nrow, ncol, s_firstrow, s_firstcol, t_firstrow, t_firstcol)
copy just a part ot the matrix
subroutine, public cp_fm_maxabsval(matrix, a_max, ir_max, ic_max)
find the maximum absolute value of the matrix element maxval(abs(matrix))
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_finish_copy_general(destination, info)
Completes the copy operation: wait for comms, unpack, clean up MPI state.
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_init_random(matrix, ncol, start_col)
fills a matrix with random numbers
subroutine, public cp_fm_to_fm_triangular(msource, mtarget, uplo)
copy just a triangular matrix
integer function, public cp_fm_pilaenv(ictxt, prec)
...
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp)
creates a new full matrix with the given structure
subroutine, public cp_fm_write_formatted(fm, unit, header, value_format)
Write out a full matrix in plain text.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public sp
Interface to the message passing library MPI.
integer, parameter, public mp_proc_null
logical, parameter, public cp2k_is_parallel
integer, parameter, public mp_any_source
type(mp_request_type), parameter, public mp_request_null
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
integer, parameter, public uniform