dbcsr_binary_write Subroutine

public subroutine dbcsr_binary_write(matrix, filepath)

Writes a DBCSR matrix in a file file's header consists of 3 sub-headers: sub-header1 contains: 1 string: (of length version_len) the current version of this routine, 1 string: (of length default_string_length) matrix_name, 1 character: matrix_type, 4 integers: numnodes, data_type, nblkrows_total, nblkcols_total, 2 vectors: row_blk_size (length = nblkrows_total), col_blk_size (length = nblkcols_total), sub-header2 contains: 2 integers: nblks, data_area_size, sub-header3 contains: 3 vectors: row_p (length = nblkrows_total+1), col_i (length = nblks), blk_p (length = nblks); and the file's body contains the block data

Arguments

Type IntentOptional Attributes Name
type(dbcsr_type), intent(in) :: matrix

DBCSR matrix

character(len=*), intent(in) :: filepath

path to the file


Source Code

   SUBROUTINE dbcsr_binary_write(matrix, filepath)
      !! Writes a DBCSR matrix in a file
      !! file's header consists of 3 sub-headers:
      !! sub-header1 contains:
      !! 1 string: (of length version_len) the current version of this routine,
      !! 1 string: (of length default_string_length) matrix_name,
      !! 1 character: matrix_type,
      !! 4 integers: numnodes, data_type, nblkrows_total, nblkcols_total,
      !! 2 vectors:  row_blk_size (length = nblkrows_total),
      !! col_blk_size (length = nblkcols_total),
      !! sub-header2 contains:
      !! 2 integers: nblks, data_area_size,
      !! sub-header3 contains:
      !! 3 vectors:  row_p (length = nblkrows_total+1),
      !! col_i (length = nblks),
      !! blk_p (length = nblks);
      !! and the file's body contains the block data

      IMPLICIT NONE

      TYPE(dbcsr_type), INTENT(IN)           :: matrix
         !! DBCSR matrix
      CHARACTER(len=*), INTENT(IN)         :: filepath
         !! path to the file

      CHARACTER(LEN=*), PARAMETER :: routineN = 'dbcsr_binary_write'

      INTEGER                               :: nblkrows_total, nblkcols_total, &
                                               nblks, size_of_pgrid, &
                                               i, sendbuf, data_area_size, &
                                               data_type, type_size, &
                                               mynode, numnodes, &
                                               ginfo_size, linfo_size, handle
      INTEGER, DIMENSION(:), POINTER        :: row_p, col_i, blk_p, &
                                               row_blk_size, col_blk_size
      INTEGER, DIMENSION(:, :), POINTER      :: pgrid
      TYPE(mp_type_descriptor_type)         :: mp_type
      TYPE(dbcsr_mp_obj)                    :: mp_env
      TYPE(dbcsr_distribution_obj)          :: distribution
      TYPE(dbcsr_data_obj)                  :: data_area
      COMPLEX(sp), DIMENSION(:), POINTER      :: c_sp
      COMPLEX(dp), DIMENSION(:), POINTER      :: c_dp
      REAL(sp), DIMENSION(:), POINTER         :: r_sp
      REAL(dp), DIMENSION(:), POINTER         :: r_dp
      CHARACTER                             :: matrix_type
      CHARACTER(LEN=80)                     :: matrix_name_v_1_0
      CHARACTER(LEN=default_string_length)  :: matrix_name
      TYPE(mp_comm_type)                    :: mp_group
      TYPE(mp_file_type)                    :: thefile
      INTEGER, PARAMETER                    :: version_len = 10
      CHARACTER(LEN=version_len), PARAMETER :: version = "DBCSRv_1.0"
      INTEGER, ALLOCATABLE, DIMENSION(:) :: linfo_sizes, da_sizes
      INTEGER(kind=file_offset), ALLOCATABLE, DIMENSION(:) :: bdata_disps, bdata_offsets, &
                                                              subh2_disps, subh2_offsets, &
                                                              subh3_disps, subh3_offsets
      INTEGER(kind=file_offset), PARAMETER                 :: BOF = 0
      INTEGER, PARAMETER          :: char_count = version_len + default_string_length + 1 !version, matrix_name, matrix_type

      CALL timeset(routineN, handle)

      IF (default_string_length /= 80) &
         CALL dbcsr_warn(__LOCATION__, "Changing the default string length affects "// &
                         "the format of the written matrix. Version needs to be adjusted")

      nblkrows_total = dbcsr_nblkrows_total(matrix)
      nblkcols_total = dbcsr_nblkcols_total(matrix)
      distribution = dbcsr_distribution(matrix)
      matrix_name = dbcsr_name(matrix)
      data_area = dbcsr_data_area(matrix)
      matrix_type = dbcsr_get_matrix_type(matrix)
      data_type = dbcsr_get_data_type(matrix)
      mp_env = dbcsr_distribution_mp(distribution)
      mp_group = dbcsr_mp_group(mp_env)
      nblks = dbcsr_get_num_blocks(matrix)
      row_p => matrix%row_p
      col_i => matrix%col_i
      blk_p => matrix%blk_p
      row_blk_size => array_data(matrix%row_blk_size)
      col_blk_size => array_data(matrix%col_blk_size)
      pgrid => dbcsr_mp_pgrid(mp_env)
      size_of_pgrid = SIZE(pgrid)

      CALL mp_environ(numnodes, mynode, mp_group)

      ALLOCATE (linfo_sizes(numnodes), da_sizes(numnodes), &
                subh2_disps(numnodes), subh2_offsets(numnodes), &
                subh3_disps(numnodes), subh3_offsets(numnodes), &
                bdata_disps(numnodes), bdata_offsets(numnodes))
      subh2_disps(:) = (/((i - 1)*2, i=1, numnodes)/)
      subh3_disps = BOF
      bdata_disps = BOF
      linfo_sizes = BOF
      subh2_offsets = BOF
      subh3_offsets = BOF
      bdata_offsets = BOF
      da_sizes = BOF

      ginfo_size = char_count + 4 + nblkrows_total + nblkcols_total
      linfo_size = 1 + nblkrows_total + 2*nblks

      sendbuf = linfo_size
      CALL mp_allgather(sendbuf, linfo_sizes, mp_group)
      CALL cumsum_l(INT(linfo_sizes, kind=file_offset), subh3_disps)
      subh3_disps(:) = CSHIFT(subh3_disps, shift=-1) + ginfo_size + 2*numnodes
      subh3_disps(1) = ginfo_size + 2*numnodes

      data_area_size = dbcsr_data_get_size_referenced(matrix%data_area)
      sendbuf = data_area_size
      CALL mp_allgather(sendbuf, da_sizes, mp_group)
      CALL cumsum_l(INT(da_sizes, kind=file_offset), bdata_disps)
      bdata_disps(:) = CSHIFT(bdata_disps, shift=-1) + SUM(INT(linfo_sizes, KIND=file_offset)) + &
                       ginfo_size + numnodes*2
      bdata_disps(1) = SUM(INT(linfo_sizes, KIND=file_offset)) + ginfo_size + numnodes*2

      CALL mp_file_open(mp_group, thefile, filepath, file_amode_create + file_amode_wronly)

      IF (mynode .EQ. 0) THEN
         CALL mp_file_write_at(thefile, BOF, version)
         matrix_name_v_1_0 = matrix_name
         CALL mp_file_write_at(thefile, BOF + version_len*mpi_character_size, matrix_name_v_1_0)
         CALL mp_file_write_at(thefile, BOF + (version_len + default_string_length)*mpi_character_size, matrix_type)
         CALL mp_file_write_at(thefile, BOF + char_count*mpi_character_size, &
                               (/size_of_pgrid, data_type, &
                                 nblkrows_total, nblkcols_total, &
                                 row_blk_size, col_blk_size/))
      END IF
! write sub-header2
      subh2_disps(:) = subh2_disps(:) + ginfo_size
      subh2_offsets(:) = BOF + (subh2_disps - char_count)*mpi_integer_size + &
                         char_count*mpi_character_size
      CALL mp_file_write_at_all(thefile, subh2_offsets(mynode + 1), (/nblks, data_area_size/))
! write sub-header3
      subh3_offsets(:) = BOF + (subh3_disps - char_count)*mpi_integer_size + &
                         char_count*mpi_character_size
      CALL mp_file_write_at_all(thefile, subh3_offsets(mynode + 1), (/row_p, col_i, blk_p/))
! write block data
      mp_type = dbcsr_mp_type_from_anytype(data_area)
      CALL mp_type_size(mp_type, type_size)
      bdata_offsets(:) = BOF + (/((bdata_disps(i) - bdata_disps(1))*type_size, i=1, numnodes)/) + &
                         (bdata_disps(1) - char_count)*mpi_integer_size + &
                         char_count*mpi_character_size
      SELECT CASE (data_type)
      CASE (dbcsr_type_real_4)
         r_sp => data_area%d%r_sp
         CALL mp_file_write_at_all(thefile, bdata_offsets(mynode + 1), r_sp, msglen=data_area_size)
      CASE (dbcsr_type_real_8)
         r_dp => data_area%d%r_dp
         CALL mp_file_write_at_all(thefile, bdata_offsets(mynode + 1), r_dp, msglen=data_area_size)
      CASE (dbcsr_type_complex_4)
         c_sp => data_area%d%c_sp
         CALL mp_file_write_at_all(thefile, bdata_offsets(mynode + 1), c_sp, msglen=data_area_size)
      CASE (dbcsr_type_complex_8)
         c_dp => data_area%d%c_dp
         CALL mp_file_write_at_all(thefile, bdata_offsets(mynode + 1), c_dp, msglen=data_area_size)
      END SELECT
      CALL mp_file_close(thefile)

      DEALLOCATE (linfo_sizes, da_sizes)
      DEALLOCATE (subh2_disps, subh2_offsets, subh3_disps, subh3_offsets)
      DEALLOCATE (bdata_disps, bdata_offsets)

      CALL timestop(handle)

   CONTAINS
      SUBROUTINE cumsum_l(arr, cumsum)
         INTEGER(kind=file_offset), DIMENSION(:), &
            INTENT(IN)                                      :: arr
         INTEGER(kind=file_offset), DIMENSION(SIZE(arr)), &
            INTENT(OUT)                                     :: cumsum

         INTEGER                                            :: i

         cumsum(1) = arr(1)
         DO i = 2, SIZE(arr)
            cumsum(i) = cumsum(i - 1) + arr(i)
         END DO
      END SUBROUTINE cumsum_l
   END SUBROUTINE dbcsr_binary_write