Write a CSR matrix to file
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(csr_type), | intent(in) | :: | csr_mat | |||
integer, | intent(in) | :: | unit_nr |
unit number to which output is written |
||
logical, | intent(in), | optional | :: | upper_triangle |
If true (default: false), write only upper triangular part of matrix |
|
real(kind=real_8), | intent(in), | optional | :: | threshold |
threshold on the absolute value of the elements to be printed |
|
logical, | intent(in), | optional | :: | binary |
SUBROUTINE csr_write(csr_mat, unit_nr, upper_triangle, threshold, binary) !! Write a CSR matrix to file TYPE(csr_type), INTENT(IN) :: csr_mat INTEGER, INTENT(IN) :: unit_nr !! unit number to which output is written LOGICAL, INTENT(IN), OPTIONAL :: upper_triangle !! If true (default: false), write only upper triangular part of matrix REAL(KIND=real_8), INTENT(IN), OPTIONAL :: threshold !! threshold on the absolute value of the elements to be printed LOGICAL, INTENT(IN), OPTIONAL :: binary CHARACTER(LEN=*), PARAMETER :: routineN = 'csr_write' CHARACTER(LEN=default_string_length) :: data_format COMPLEX(KIND=real_4), ALLOCATABLE, DIMENSION(:) :: nzval_to_master_c_sp COMPLEX(KIND=real_8), ALLOCATABLE, DIMENSION(:) :: nzval_to_master_c_dp INTEGER :: handle, i, ii, k, l, m, mynode, & numnodes, rowind, tag1, tag2, tag3 INTEGER, ALLOCATABLE, DIMENSION(:) :: colind_to_master, nzerow_to_master, & sizes_numrowlocal, sizes_nzelocal LOGICAL :: bin, ut REAL(KIND=real_4), ALLOCATABLE, DIMENSION(:) :: nzval_to_master_r_sp REAL(KIND=real_8) :: thld REAL(KIND=real_8), ALLOCATABLE, DIMENSION(:) :: nzval_to_master_r_dp CALL timeset(routineN, handle) IF (PRESENT(upper_triangle)) THEN ut = upper_triangle ELSE ut = .FALSE. END IF IF (PRESENT(threshold)) THEN thld = threshold ELSE thld = 0.0_dp END IF IF (PRESENT(binary)) THEN bin = binary ELSE bin = .FALSE. END IF IF (.NOT. csr_mat%valid) & DBCSR_ABORT("can not write invalid CSR matrix") tag1 = 0 tag2 = 1 tag3 = 2 CALL mp_environ(numnodes, mynode, csr_mat%mp_group) ! gather sizes (number of local non-zero elements and number of local rows) ALLOCATE (sizes_nzelocal(numnodes)) ALLOCATE (sizes_numrowlocal(numnodes)) CALL mp_gather(csr_mat%nze_local, sizes_nzelocal, 0, csr_mat%mp_group) CALL mp_gather(csr_mat%nrows_local, sizes_numrowlocal, 0, csr_mat%mp_group) ! for each node, send matrix data to node 0 (master) and write data DO i = 0, numnodes - 1 ii = i IF (mynode .EQ. 0) THEN ! allocations for receiving data from node i ALLOCATE (colind_to_master(sizes_nzelocal(ii + 1))) ALLOCATE (nzerow_to_master(sizes_numrowlocal(ii + 1))) SELECT CASE (csr_mat%nzval_local%data_type) CASE (dbcsr_type_real_4) data_format = "(2(I8),E23.6E2)" ALLOCATE (nzval_to_master_r_sp(sizes_nzelocal(ii + 1))) CASE (dbcsr_type_real_8) data_format = "(2(I8),E23.14E3)" ALLOCATE (nzval_to_master_r_dp(sizes_nzelocal(ii + 1))) CASE (dbcsr_type_complex_4) data_format = "(2(I8),2(E23.6E2))" ALLOCATE (nzval_to_master_c_sp(sizes_nzelocal(ii + 1))) CASE (dbcsr_type_complex_8) data_format = "(2(I8),2(E23.14E3))" ALLOCATE (nzval_to_master_c_dp(sizes_nzelocal(ii + 1))) END SELECT END IF IF (mynode .EQ. 0) THEN ! receive at node 0 IF (ii .EQ. 0) THEN ! data from node 0, no need for mpi routines colind_to_master(:) = csr_mat%colind_local(:) nzerow_to_master(:) = csr_mat%nzerow_local(:) SELECT CASE (csr_mat%nzval_local%data_type) CASE (dbcsr_type_real_4) nzval_to_master_r_sp(:) = csr_mat%nzval_local%r_sp(:) CASE (dbcsr_type_real_8) nzval_to_master_r_dp(:) = csr_mat%nzval_local%r_dp(:) CASE (dbcsr_type_complex_4) nzval_to_master_c_sp(:) = csr_mat%nzval_local%c_sp(:) CASE (dbcsr_type_complex_8) nzval_to_master_c_dp(:) = csr_mat%nzval_local%c_dp(:) END SELECT ELSE ! receive data from nodes with rank > 0 CALL mp_recv(colind_to_master, ii, tag1, csr_mat%mp_group) CALL mp_recv(nzerow_to_master, ii, tag2, csr_mat%mp_group) SELECT CASE (csr_mat%nzval_local%data_type) CASE (dbcsr_type_real_4) CALL mp_recv(nzval_to_master_r_sp, ii, tag3, csr_mat%mp_group) CASE (dbcsr_type_real_8) CALL mp_recv(nzval_to_master_r_dp, ii, tag3, csr_mat%mp_group) CASE (dbcsr_type_complex_4) CALL mp_recv(nzval_to_master_c_sp, ii, tag3, csr_mat%mp_group) CASE (dbcsr_type_complex_8) CALL mp_recv(nzval_to_master_c_dp, ii, tag3, csr_mat%mp_group) END SELECT END IF END IF IF ((mynode .EQ. ii) .AND. (ii .NE. 0)) THEN ! send from nodes with rank > 0 CALL mp_send(csr_mat%colind_local, 0, tag1, csr_mat%mp_group) CALL mp_send(csr_mat%nzerow_local, 0, tag2, csr_mat%mp_group) SELECT CASE (csr_mat%nzval_local%data_type) CASE (dbcsr_type_real_4) CALL mp_send(csr_mat%nzval_local%r_sp, 0, tag3, csr_mat%mp_group) CASE (dbcsr_type_real_8) CALL mp_send(csr_mat%nzval_local%r_dp, 0, tag3, csr_mat%mp_group) CASE (dbcsr_type_complex_4) CALL mp_send(csr_mat%nzval_local%c_sp, 0, tag3, csr_mat%mp_group) CASE (dbcsr_type_complex_8) CALL mp_send(csr_mat%nzval_local%c_dp, 0, tag3, csr_mat%mp_group) END SELECT END IF IF (mynode .EQ. 0) THEN ! write data received at node 0 !WRITE(unit_nr,"(A27)") "#row ind, col ind, value" m = 0 DO k = 1, sizes_numrowlocal(ii + 1) rowind = k + SUM(sizes_numrowlocal(1:ii)) ! row index: local to global DO l = 1, nzerow_to_master(k) m = m + 1 IF ((.NOT. ut) .OR. (rowind .LE. colind_to_master(m))) THEN SELECT CASE (csr_mat%nzval_local%data_type) CASE (dbcsr_type_real_4) IF (ABS(nzval_to_master_r_sp(m)) .GE. thld) THEN IF (bin) THEN WRITE (unit_nr) rowind, colind_to_master(m), nzval_to_master_r_sp(m) ELSE WRITE (unit_nr, data_format) rowind, colind_to_master(m), & nzval_to_master_r_sp(m) END IF END IF CASE (dbcsr_type_real_8) IF (ABS(nzval_to_master_r_dp(m)) .GE. thld) THEN IF (bin) THEN WRITE (unit_nr) rowind, colind_to_master(m), nzval_to_master_r_dp(m) ELSE WRITE (unit_nr, data_format) rowind, colind_to_master(m), & nzval_to_master_r_dp(m) END IF END IF CASE (dbcsr_type_complex_4) IF (ABS(nzval_to_master_c_sp(m)) .GE. thld) THEN IF (bin) THEN WRITE (unit_nr) rowind, colind_to_master(m), nzval_to_master_c_sp(m) ELSE WRITE (unit_nr, data_format) rowind, colind_to_master(m), & nzval_to_master_c_sp(m) END IF END IF CASE (dbcsr_type_complex_8) IF (ABS(nzval_to_master_c_dp(m)) .GE. thld) THEN IF (bin) THEN WRITE (unit_nr) rowind, colind_to_master(m), nzval_to_master_c_dp(m) ELSE WRITE (unit_nr, data_format) rowind, colind_to_master(m), & nzval_to_master_c_dp(m) END IF END IF END SELECT END IF END DO END DO DEALLOCATE (colind_to_master) DEALLOCATE (nzerow_to_master) SELECT CASE (csr_mat%nzval_local%data_type) CASE (dbcsr_type_real_4) DEALLOCATE (nzval_to_master_r_sp) CASE (dbcsr_type_real_8) DEALLOCATE (nzval_to_master_r_dp) CASE (dbcsr_type_complex_4) DEALLOCATE (nzval_to_master_c_sp) CASE (dbcsr_type_complex_8) DEALLOCATE (nzval_to_master_c_dp) END SELECT END IF END DO CALL timestop(handle) END SUBROUTINE csr_write