dbcsr_make_undense Subroutine

public subroutine dbcsr_make_undense(matrix, undense_matrix, distribution, row_blk_offsets, col_blk_offsets, row_blk_sizes, col_blk_sizes, row_map, col_map)

Makes a blocked matrix from a dense matrix, inplace

Note

Used for making matrices dense/undense

Arguments

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

dense matrix

type(dbcsr_type), intent(inout) :: undense_matrix

matrix to make undense

type(dbcsr_distribution_obj), intent(in) :: distribution

distribution of non-dense rows and columns

type(array_i1d_obj), intent(in) :: row_blk_offsets

non-dense row block offsets non-dense column block offsets non-dense row block sizes non-dense column block sizes mapping from non-dense rows mapping from non-dense columns

type(array_i1d_obj), intent(in) :: col_blk_offsets

non-dense row block offsets non-dense column block offsets non-dense row block sizes non-dense column block sizes mapping from non-dense rows mapping from non-dense columns

type(array_i1d_obj), intent(in) :: row_blk_sizes

non-dense row block offsets non-dense column block offsets non-dense row block sizes non-dense column block sizes mapping from non-dense rows mapping from non-dense columns

type(array_i1d_obj), intent(in) :: col_blk_sizes

non-dense row block offsets non-dense column block offsets non-dense row block sizes non-dense column block sizes mapping from non-dense rows mapping from non-dense columns

type(array_i1d_obj), intent(in) :: row_map

non-dense row block offsets non-dense column block offsets non-dense row block sizes non-dense column block sizes mapping from non-dense rows mapping from non-dense columns

type(array_i1d_obj), intent(in) :: col_map

non-dense row block offsets non-dense column block offsets non-dense row block sizes non-dense column block sizes mapping from non-dense rows mapping from non-dense columns


Source Code

   SUBROUTINE dbcsr_make_undense(matrix, undense_matrix, distribution, &
                                 row_blk_offsets, col_blk_offsets, row_blk_sizes, col_blk_sizes, &
                                 row_map, col_map)
      !! Makes a blocked matrix from a dense matrix, inplace
      !! @note Used for making matrices dense/undense

      TYPE(dbcsr_type), INTENT(IN)                       :: matrix
         !! dense matrix
      TYPE(dbcsr_type), INTENT(INOUT)                    :: undense_matrix
         !! matrix to make undense
      TYPE(dbcsr_distribution_obj), INTENT(IN)           :: distribution
         !! distribution of non-dense rows and columns
      TYPE(array_i1d_obj), INTENT(IN)                    :: row_blk_offsets, col_blk_offsets, &
                                                            row_blk_sizes, col_blk_sizes, row_map, &
                                                            col_map
         !! non-dense row block offsets
         !! non-dense column block offsets
         !! non-dense row block sizes
         !! non-dense column block sizes
         !! mapping from non-dense rows
         !! mapping from non-dense columns

      CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_make_undense'
      LOGICAL, PARAMETER                                 :: dbg = .FALSE.

      INTEGER                                            :: handle, nblkcols_local, nblkcols_total, &
                                                            nblkrows_local, nblkrows_total, &
                                                            nfullcols_local, nfullrows_local
      INTEGER, ALLOCATABLE, DIMENSION(:) :: col_internal_offsets, dense_local_col_blk_offsets, &
                                            dense_local_row_blk_offsets, local_col_blk_offsets, local_row_blk_offsets, &
                                            row_internal_offsets
      INTEGER, DIMENSION(:), POINTER, CONTIGUOUS         :: local_cols, local_rows, meta
      REAL(kind=dp)                                      :: cs
      TYPE(dbcsr_data_obj)                               :: blocked_data, dense_data
      TYPE(dbcsr_distribution_obj)                       :: dense_distribution

!   ---------------------------------------------------------------------------

      CALL timeset(routineN, handle)
      IF (dbg) THEN
         cs = dbcsr_checksum(matrix)
         WRITE (*, *) routineN//" prod cs pre", cs
      END IF
      dense_distribution = dbcsr_distribution(matrix)
      nfullrows_local = matrix%nfullrows_local
      nfullcols_local = matrix%nfullcols_local
      nblkrows_local = dbcsr_distribution_nlocal_rows(distribution)
      nblkcols_local = dbcsr_distribution_nlocal_cols(distribution)
      nblkrows_total = dbcsr_distribution_nrows(distribution)
      nblkcols_total = dbcsr_distribution_ncols(distribution)
      local_rows => dbcsr_distribution_local_rows(distribution)
      local_cols => dbcsr_distribution_local_cols(distribution)
      CALL dbcsr_create(undense_matrix, template=matrix, &
                        dist=distribution, &
                        row_blk_size_obj=row_blk_sizes, &
                        col_blk_size_obj=col_blk_sizes)
      ! Restore previous offsets, just to try to keep the same memory.
      CALL array_release(undense_matrix%row_blk_offset)
      CALL array_release(undense_matrix%col_blk_offset)
      undense_matrix%row_blk_offset = row_blk_offsets
      undense_matrix%col_blk_offset = col_blk_offsets
      CALL array_hold(undense_matrix%row_blk_offset)
      CALL array_hold(undense_matrix%col_blk_offset)
      !
      ALLOCATE (local_row_blk_offsets(nblkrows_total + 1))
      ALLOCATE (local_col_blk_offsets(nblkcols_total + 1))
      CALL dbcsr_clearfrom_index_array(undense_matrix, dbcsr_slot_row_p)
      CALL dbcsr_clearfrom_index_array(undense_matrix, dbcsr_slot_col_i)
      CALL dbcsr_clearfrom_index_array(undense_matrix, dbcsr_slot_blk_p)
      CALL dbcsr_addto_index_array(undense_matrix, dbcsr_slot_row_p, &
                                   reservation=nblkrows_total + 1, extra=nblkrows_local*nblkcols_local*2)
      CALL dbcsr_addto_index_array(undense_matrix, dbcsr_slot_col_i, &
                                   reservation=nblkrows_local*nblkcols_local)
      CALL dbcsr_addto_index_array(undense_matrix, dbcsr_slot_blk_p, &
                                   reservation=nblkrows_local*nblkcols_local)
      meta => undense_matrix%index(1:dbcsr_meta_size)
      CALL dbcsr_pack_meta(undense_matrix, meta)
      meta(dbcsr_slot_nblks) = nblkrows_local*nblkcols_local
      meta(dbcsr_slot_nze) = nfullrows_local*nfullcols_local
      CALL global_offsets_to_local(array_data(row_blk_offsets), &
                                   local_rows, local_row_blk_offsets(1:nblkrows_local + 1))
      CALL global_offsets_to_local(array_data(col_blk_offsets), &
                                   local_cols, local_col_blk_offsets(1:nblkcols_local + 1))
      CALL make_undense_index(undense_matrix%row_p, undense_matrix%col_i, undense_matrix%blk_p, &
                              distribution, &
                              local_row_blk_offsets(1:nblkrows_local + 1), &
                              local_col_blk_offsets(1:nblkcols_local + 1), &
                              meta)
      CALL dbcsr_unpack_meta(undense_matrix, meta)
      !
      CALL global_offsets_to_local(array_data(row_blk_offsets), &
                                   local_rows, local_row_blk_offsets)
      CALL global_offsets_to_local(array_data(col_blk_offsets), &
                                   local_cols, local_col_blk_offsets)
      !
      ALLOCATE (dense_local_row_blk_offsets(1 + dbcsr_distribution_nrows(dense_distribution)))
      ALLOCATE (dense_local_col_blk_offsets(1 + dbcsr_distribution_ncols(dense_distribution)))
      CALL global_offsets_to_local(array_data(matrix%row_blk_offset), &
                                   dbcsr_distribution_local_rows(dense_distribution), &
                                   dense_local_row_blk_offsets)
      CALL global_offsets_to_local(array_data(matrix%col_blk_offset), &
                                   dbcsr_distribution_local_cols(dense_distribution), &
                                   dense_local_col_blk_offsets)
      ! Find the offset of blocks within dense rows/columns.  This is needed
      ! since the blocked rows/columns are not necessarily in the same order.
      ALLOCATE (row_internal_offsets(nblkrows_total))
      ALLOCATE (col_internal_offsets(nblkcols_total))
      CALL get_internal_offsets( &
         local_rows, array_data(row_map), &
         local_row_blk_offsets, &
         dense_local_row_blk_offsets, &
         row_internal_offsets)
      CALL get_internal_offsets( &
         local_cols, array_data(col_map), &
         local_col_blk_offsets, &
         dense_local_col_blk_offsets, &
         col_internal_offsets)
      !
      dense_data = matrix%data_area
      CALL dbcsr_data_hold(dense_data)
      CALL dbcsr_data_init(blocked_data)
      CALL dbcsr_data_new(blocked_data, dbcsr_data_get_type(dense_data), &
                          data_size=nfullrows_local*nfullcols_local, &
                          memory_type=dbcsr_data_get_memory_type(dense_data))
      CALL dbcsr_switch_data_area(undense_matrix, blocked_data)
      CALL dbcsr_data_release(blocked_data)
      ! Reshuffle the data
      CALL make_undense_data(undense_matrix, dense_data, &
                             nfullrows_local, nfullcols_local, &
                             dense_local_row_blk_offsets, dense_local_col_blk_offsets, &
                             array_data(row_map), array_data(col_map), &
                             row_internal_offsets, col_internal_offsets)
      CALL dbcsr_data_release(dense_data)
      IF (dbg) THEN
         cs = dbcsr_checksum(matrix)
         WRITE (*, *) routineN//" prod cs pst", cs
      END IF
      DEALLOCATE (local_row_blk_offsets)
      DEALLOCATE (local_col_blk_offsets)
      DEALLOCATE (dense_local_row_blk_offsets)
      DEALLOCATE (dense_local_col_blk_offsets)
      DEALLOCATE (row_internal_offsets)
      DEALLOCATE (col_internal_offsets)
      CALL timestop(handle)
   END SUBROUTINE dbcsr_make_undense