LCOV - code coverage report
Current view: top level - src/dbx - cp_dbcsr_contrib.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 89.3 % 291 260
Test Date: 2026-11-04 00:58:17 Functions: 94.1 % 17 16

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : MODULE cp_dbcsr_contrib
       9              :    USE OMP_LIB,                         ONLY: omp_get_num_threads
      10              :    USE cp_dbcsr_api,                    ONLY: &
      11              :         dbcsr_clear, dbcsr_create, dbcsr_distribution_get, dbcsr_distribution_type, &
      12              :         dbcsr_finalize, dbcsr_get_data_size, dbcsr_get_info, dbcsr_get_num_blocks, &
      13              :         dbcsr_get_occupation, dbcsr_get_readonly_block_p, dbcsr_get_stored_coordinates, &
      14              :         dbcsr_has_symmetry, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      15              :         dbcsr_iterator_readonly_start, dbcsr_iterator_start, dbcsr_iterator_stop, &
      16              :         dbcsr_iterator_type, dbcsr_p_type, dbcsr_put_block, dbcsr_reserve_blocks, dbcsr_type
      17              :    USE dbm_tests,                       ONLY: generate_larnv_seed
      18              :    USE kinds,                           ONLY: default_string_length,&
      19              :                                               dp
      20              :    USE machine,                         ONLY: default_output_unit
      21              :    USE message_passing,                 ONLY: mp_comm_type
      22              : #include "../base/base_uses.f90"
      23              : 
      24              :    IMPLICIT NONE
      25              :    PRIVATE
      26              : 
      27              :    PUBLIC :: dbcsr_hadamard_product
      28              :    PUBLIC :: dbcsr_maxabs
      29              :    PUBLIC :: dbcsr_frobenius_norm
      30              :    PUBLIC :: dbcsr_gershgorin_norm
      31              :    PUBLIC :: dbcsr_init_random
      32              :    PUBLIC :: dbcsr_reserve_diag_blocks
      33              :    PUBLIC :: dbcsr_reserve_all_blocks
      34              :    PUBLIC :: dbcsr_add_on_diag
      35              :    PUBLIC :: dbcsr_dot, dbcsr_dot_batch
      36              :    PUBLIC :: dbcsr_trace
      37              :    PUBLIC :: dbcsr_get_block_diag
      38              :    PUBLIC :: dbcsr_scale_by_vector
      39              :    PUBLIC :: dbcsr_get_diag
      40              :    PUBLIC :: dbcsr_set_diag
      41              :    PUBLIC :: dbcsr_checksum
      42              :    PUBLIC :: dbcsr_print
      43              : 
      44              : CONTAINS
      45              : 
      46              : ! **************************************************************************************************
      47              : !> \brief Hadamard product: C = A . B (C needs to be different from A and B)
      48              : !> \param matrix_a ...
      49              : !> \param matrix_b ...
      50              : !> \param matrix_c ...
      51              : ! **************************************************************************************************
      52       397520 :    SUBROUTINE dbcsr_hadamard_product(matrix_a, matrix_b, matrix_c)
      53              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_a, matrix_b
      54              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix_c
      55              : 
      56              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_hadamard_product'
      57              : 
      58              :       INTEGER                                            :: col, handle, nblkrows_tot_a, &
      59              :                                                             nblkrows_tot_b, nblkrows_tot_c, row
      60              :       LOGICAL                                            :: found_b
      61        79504 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_a, block_b
      62              :       TYPE(dbcsr_iterator_type)                          :: iter
      63              : 
      64        79504 :       CALL timeset(routineN, handle)
      65        79504 :       CPASSERT(omp_get_num_threads() == 1)
      66              : 
      67        79504 :       CALL dbcsr_get_info(matrix_a, nblkrows_total=nblkrows_tot_a)
      68        79504 :       CALL dbcsr_get_info(matrix_b, nblkrows_total=nblkrows_tot_b)
      69        79504 :       CALL dbcsr_get_info(matrix_c, nblkrows_total=nblkrows_tot_c)
      70        79504 :       IF (nblkrows_tot_a /= nblkrows_tot_b .OR. nblkrows_tot_a /= nblkrows_tot_c) THEN
      71            0 :          CPABORT("matrices not consistent")
      72              :       END IF
      73              : 
      74        79504 :       CALL dbcsr_clear(matrix_c)
      75        79504 :       CALL dbcsr_iterator_readonly_start(iter, matrix_a)
      76       179315 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
      77        99811 :          CALL dbcsr_iterator_next_block(iter, row, col, block_a)
      78        99811 :          CALL dbcsr_get_readonly_block_p(matrix_b, row, col, block_b, found_b)
      79       179315 :          IF (found_b) THEN
      80     19326781 :             CALL dbcsr_put_block(matrix_c, row, col, block_a*block_b)
      81              :          END IF
      82              :       END DO
      83        79504 :       CALL dbcsr_iterator_stop(iter)
      84        79504 :       CALL dbcsr_finalize(matrix_c)
      85        79504 :       CALL timestop(handle)
      86        79504 :    END SUBROUTINE dbcsr_hadamard_product
      87              : 
      88              : ! **************************************************************************************************
      89              : !> \brief Compute the maxabs norm of a dbcsr matrix
      90              : !> \param matrix ...
      91              : !> \return ...
      92              : ! **************************************************************************************************
      93        27044 :    FUNCTION dbcsr_maxabs(matrix) RESULT(norm)
      94              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
      95              :       REAL(dp)                                           :: norm
      96              : 
      97              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_maxabs'
      98              : 
      99              :       INTEGER                                            :: handle
     100        13522 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     101              :       TYPE(dbcsr_iterator_type)                          :: iter
     102              :       TYPE(mp_comm_type)                                 :: group
     103              : 
     104        13522 :       CALL timeset(routineN, handle)
     105        13522 :       CPASSERT(omp_get_num_threads() == 1)
     106              : 
     107              :       norm = 0.0_dp
     108        13522 : !$OMP PARALLEL DEFAULT(NONE) SHARED(matrix) PRIVATE(iter, block) REDUCTION(MAX:norm)
     109              :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     110              :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     111              :          CALL dbcsr_iterator_next_block(iter, block=block)
     112              :          norm = MAX(norm, MAXVAL(ABS(block)))
     113              :       END DO
     114              :       CALL dbcsr_iterator_stop(iter)
     115              : !$OMP END PARALLEL
     116              : 
     117        13522 :       CALL dbcsr_get_info(matrix, group=group)
     118        13522 :       CALL group%max(norm)
     119              : 
     120        13522 :       CALL timestop(handle)
     121        13522 :    END FUNCTION dbcsr_maxabs
     122              : 
     123              : ! **************************************************************************************************
     124              : !> \brief Compute the frobenius norm of a dbcsr matrix
     125              : !> \param matrix ...
     126              : !> \return ...
     127              : ! **************************************************************************************************
     128       388756 :    FUNCTION dbcsr_frobenius_norm(matrix) RESULT(norm)
     129              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     130              :       REAL(dp)                                           :: norm
     131              : 
     132              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_frobenius_norm'
     133              : 
     134              :       INTEGER                                            :: col, handle, row
     135              :       LOGICAL                                            :: has_symmetry
     136       194378 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     137              :       TYPE(dbcsr_iterator_type)                          :: iter
     138              :       TYPE(mp_comm_type)                                 :: group
     139              : 
     140       194378 :       CALL timeset(routineN, handle)
     141       194378 :       CPASSERT(omp_get_num_threads() == 1)
     142              : 
     143       194378 :       has_symmetry = dbcsr_has_symmetry(matrix)
     144              :       norm = 0.0_dp
     145              : !$OMP PARALLEL DEFAULT(NONE) SHARED(matrix, has_symmetry) &
     146       194378 : !$OMP PRIVATE(iter, row, col, block) REDUCTION(+:norm)
     147              :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     148              :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     149              :          CALL dbcsr_iterator_next_block(iter, row, col, block)
     150              :          IF (has_symmetry .AND. row /= col) THEN
     151              :             norm = norm + 2.0_dp*SUM(block**2)
     152              :          ELSE
     153              :             norm = norm + SUM(block**2)
     154              :          END IF
     155              :       END DO
     156              :       CALL dbcsr_iterator_stop(iter)
     157              : !$OMP END PARALLEL
     158              : 
     159       194378 :       CALL dbcsr_get_info(matrix, group=group)
     160       194378 :       CALL group%sum(norm)
     161       194378 :       norm = SQRT(norm)
     162              : 
     163       194378 :       CALL timestop(handle)
     164       194378 :    END FUNCTION dbcsr_frobenius_norm
     165              : 
     166              : ! **************************************************************************************************
     167              : !> \brief Compute the gershgorin norm of a dbcsr matrix
     168              : !> \param matrix ...
     169              : !> \return ...
     170              : ! **************************************************************************************************
     171         9906 :    FUNCTION dbcsr_gershgorin_norm(matrix) RESULT(norm)
     172              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     173              :       REAL(dp)                                           :: norm
     174              : 
     175              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_gershgorin_norm'
     176              : 
     177              :       INTEGER                                            :: col, col_offset, handle, i, j, ncol, &
     178              :                                                             nrow, row, row_offset
     179              :       LOGICAL                                            :: has_symmetry
     180              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: buffer
     181         9906 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     182              :       TYPE(dbcsr_iterator_type)                          :: iter
     183              :       TYPE(mp_comm_type)                                 :: group
     184              : 
     185         9906 :       CALL timeset(routineN, handle)
     186         9906 :       CPASSERT(omp_get_num_threads() == 1)
     187              : 
     188         9906 :       has_symmetry = dbcsr_has_symmetry(matrix)
     189         9906 :       CALL dbcsr_get_info(matrix, nfullrows_total=nrow, nfullcols_total=ncol)
     190         9906 :       CPASSERT(nrow == ncol)
     191        29710 :       ALLOCATE (buffer(nrow))
     192         9906 :       buffer = 0.0_dp
     193              : 
     194         9906 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     195       204271 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     196       194365 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_offset=row_offset, col_offset=col_offset)
     197       650608 :          DO j = 1, SIZE(block, 2)
     198      4951087 :             DO i = 1, SIZE(block, 1)
     199      4310385 :                buffer(row_offset + i - 1) = buffer(row_offset + i - 1) + ABS(block(i, j))
     200      4756722 :                IF (has_symmetry .AND. row /= col) THEN
     201        53764 :                   buffer(col_offset + j - 1) = buffer(col_offset + j - 1) + ABS(block(i, j))
     202              :                END IF
     203              :             END DO
     204              :          END DO
     205              :       END DO
     206         9906 :       CALL dbcsr_iterator_stop(iter)
     207              : 
     208         9906 :       CALL dbcsr_get_info(matrix, group=group)
     209         9906 :       CALL group%sum(buffer)
     210       159604 :       norm = MAXVAL(buffer)
     211         9906 :       DEALLOCATE (buffer)
     212              : 
     213         9906 :       CALL timestop(handle)
     214        39624 :    END FUNCTION dbcsr_gershgorin_norm
     215              : 
     216              : ! **************************************************************************************************
     217              : !> \brief Fills the given matrix with random numbers.
     218              : !> \param matrix ...
     219              : !> \param keep_sparsity ...
     220              : ! **************************************************************************************************
     221         1302 :    SUBROUTINE dbcsr_init_random(matrix, keep_sparsity)
     222              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     223              :       LOGICAL, OPTIONAL                                  :: keep_sparsity
     224              : 
     225              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_init_random'
     226              : 
     227              :       INTEGER                                            :: col, col_size, handle, ncol, nrow, row, &
     228              :                                                             row_size
     229              :       INTEGER, DIMENSION(4)                              :: iseed
     230              :       LOGICAL                                            :: my_keep_sparsity
     231          434 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     232              :       TYPE(dbcsr_iterator_type)                          :: iter
     233              : 
     234          434 :       CALL timeset(routineN, handle)
     235          434 :       CPASSERT(omp_get_num_threads() == 1)
     236              : 
     237          434 :       my_keep_sparsity = .FALSE.
     238          434 :       IF (PRESENT(keep_sparsity)) my_keep_sparsity = keep_sparsity
     239          434 :       IF (.NOT. my_keep_sparsity) CALL dbcsr_reserve_all_blocks(matrix)
     240          434 :       CALL dbcsr_get_info(matrix, nblkrows_total=nrow, nblkcols_total=ncol)
     241              : 
     242          434 :       CALL dbcsr_iterator_start(iter, matrix)
     243          982 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     244          548 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
     245              :          ! set the seed for dlarnv, is here to guarantee same value of the random numbers
     246              :          ! for all layouts (and block distributions)
     247          548 :          iseed = generate_larnv_seed(row, nrow, col, ncol, 1)
     248          982 :          CALL dlarnv(1, iseed, row_size*col_size, block(1, 1))
     249              :       END DO
     250          434 :       CALL dbcsr_iterator_stop(iter)
     251              : 
     252          434 :       CALL timestop(handle)
     253          434 :    END SUBROUTINE dbcsr_init_random
     254              : 
     255              : ! **************************************************************************************************
     256              : !> \brief Reserves all diagonal blocks.
     257              : !> \param matrix ...
     258              : ! **************************************************************************************************
     259       356508 :    SUBROUTINE dbcsr_reserve_diag_blocks(matrix)
     260              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     261              : 
     262              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_reserve_diag_blocks'
     263              : 
     264              :       INTEGER                                            :: handle, i, k, mynode, nblkcols_total, &
     265              :                                                             nblkrows_total, owner
     266       356508 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: local_diag
     267       356508 :       INTEGER, DIMENSION(:), POINTER                     :: local_rows
     268              :       TYPE(dbcsr_distribution_type)                      :: dist
     269              : 
     270       356508 :       CALL timeset(routineN, handle)
     271       356508 :       CPASSERT(omp_get_num_threads() == 1)
     272              : 
     273       356508 :       CALL dbcsr_get_info(matrix, nblkrows_total=nblkrows_total, nblkcols_total=nblkcols_total)
     274       356508 :       CPASSERT(nblkrows_total == nblkcols_total)
     275              : 
     276       356508 :       CALL dbcsr_get_info(matrix, local_rows=local_rows, distribution=dist)
     277       356508 :       CALL dbcsr_distribution_get(dist, mynode=mynode)
     278       990645 :       ALLOCATE (local_diag(SIZE(local_rows)))
     279              : 
     280      1088315 :       k = 0
     281      1088315 :       DO i = 1, SIZE(local_rows)
     282       731807 :          CALL dbcsr_get_stored_coordinates(matrix, row=local_rows(i), column=local_rows(i), processor=owner)
     283      1088315 :          IF (owner == mynode) THEN
     284       731807 :             k = k + 1
     285       731807 :             local_diag(k) = local_rows(i)
     286              :          END IF
     287              :       END DO
     288              : 
     289       356508 :       CALL dbcsr_reserve_blocks(matrix, rows=local_diag(1:k), cols=local_diag(1:k))
     290       356508 :       DEALLOCATE (local_diag)
     291              : 
     292       356508 :       CALL timestop(handle)
     293      1069524 :    END SUBROUTINE dbcsr_reserve_diag_blocks
     294              : 
     295              : ! **************************************************************************************************
     296              : !> \brief Reserves all blocks.
     297              : !> \param matrix ...
     298              : ! **************************************************************************************************
     299      1971573 :    SUBROUTINE dbcsr_reserve_all_blocks(matrix)
     300              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     301              : 
     302              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_reserve_all_blocks'
     303              : 
     304              :       INTEGER                                            :: handle, i, j, k, n
     305      1971573 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: cols, rows
     306      1971573 :       INTEGER, DIMENSION(:), POINTER                     :: local_cols, local_rows
     307              : 
     308      1971573 :       CALL timeset(routineN, handle)
     309      1971573 :       CPASSERT(omp_get_num_threads() == 1)
     310              : 
     311      1971573 :       CALL dbcsr_get_info(matrix, local_rows=local_rows, local_cols=local_cols)
     312      1971573 :       n = SIZE(local_rows)*SIZE(local_cols)
     313      7530506 :       ALLOCATE (rows(n), cols(n))
     314              : 
     315      4550754 :       k = 0
     316      4550754 :       DO i = 1, SIZE(local_rows)
     317      9123586 :       DO j = 1, SIZE(local_cols)
     318      4572832 :          k = k + 1
     319      4572832 :          rows(k) = local_rows(i)
     320      7152013 :          cols(k) = local_cols(j)
     321              :       END DO
     322              :       END DO
     323              : 
     324      1971573 :       CALL dbcsr_reserve_blocks(matrix, rows=rows(1:k), cols=cols(1:k))
     325      1971573 :       DEALLOCATE (rows, cols)
     326              : 
     327      1971573 :       CALL timestop(handle)
     328      1971573 :    END SUBROUTINE dbcsr_reserve_all_blocks
     329              : 
     330              : ! **************************************************************************************************
     331              : !> \brief Adds the given scalar to the diagonal of the matrix. Reserves any missing diagonal blocks.
     332              : !> \param matrix ...
     333              : !> \param alpha ...
     334              : ! **************************************************************************************************
     335       654172 :    SUBROUTINE dbcsr_add_on_diag(matrix, alpha)
     336              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     337              :       REAL(kind=dp), INTENT(IN)                          :: alpha
     338              : 
     339              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_add_on_diag'
     340              : 
     341              :       INTEGER                                            :: col, col_size, handle, i, row, row_size
     342       327086 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     343              :       TYPE(dbcsr_iterator_type)                          :: iter
     344              : 
     345       327086 :       CALL timeset(routineN, handle)
     346       327086 :       CPASSERT(omp_get_num_threads() == 1)
     347              : 
     348       327086 :       CALL dbcsr_reserve_diag_blocks(matrix)
     349              : 
     350       327086 :       CALL dbcsr_iterator_start(iter, matrix)
     351      6024907 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     352      5697821 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
     353      6024907 :          IF (row == col) THEN
     354       675373 :             CPASSERT(row_size == col_size)
     355      3103721 :             DO i = 1, row_size
     356      3103721 :                block(i, i) = block(i, i) + alpha
     357              :             END DO
     358              :          END IF
     359              :       END DO
     360       327086 :       CALL dbcsr_iterator_stop(iter)
     361              : 
     362       327086 :       CALL timestop(handle)
     363       327086 :    END SUBROUTINE dbcsr_add_on_diag
     364              : 
     365              : ! **************************************************************************************************
     366              : !> \brief Computes the dot product of two matrices, also known as the trace of their matrix product.
     367              : !> \param matrix_a ...
     368              : !> \param matrix_b ...
     369              : !> \param trace ...
     370              : ! **************************************************************************************************
     371       783456 :    SUBROUTINE dbcsr_dot(matrix_a, matrix_b, trace)
     372              :       TYPE(dbcsr_type), INTENT(IN), TARGET               :: matrix_a, matrix_b
     373              :       REAL(KIND=dp), INTENT(OUT)                         :: trace
     374              : 
     375              :       REAL(KIND=dp)                                      :: values(1)
     376      3133824 :       TYPE(dbcsr_p_type)                                 :: a(1), b(1)
     377              : 
     378       783456 :       a(1)%matrix => matrix_a
     379       783456 :       b(1)%matrix => matrix_b
     380       783456 :       CALL dbcsr_dot_batch(a, b, values)
     381       783456 :       trace = values(1)
     382       783456 :    END SUBROUTINE dbcsr_dot
     383              : 
     384              : ! **************************************************************************************************
     385              : !> \brief Evaluate several dot products in one OpenMP region; MPI reductions remain outside it.
     386              : !> \param matrix_a first operands, in reduction order
     387              : !> \param matrix_b second operands
     388              : !> \param trace dot products
     389              : !> \param comm optional common communicator; all operands must use this exact communicator
     390              : ! **************************************************************************************************
     391      1586205 :    SUBROUTINE dbcsr_dot_batch(matrix_a, matrix_b, trace, comm)
     392              :       TYPE(dbcsr_p_type), INTENT(IN)                     :: matrix_a(:), matrix_b(:)
     393              :       REAL(KIND=dp), INTENT(OUT)                         :: trace(SIZE(matrix_a))
     394              : 
     395              :       CLASS(mp_comm_type), INTENT(IN), OPTIONAL          :: comm
     396              : 
     397              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_dot_batch'
     398              : 
     399              :       INTEGER                                            :: col, handle, i, row
     400              :       LOGICAL                                            :: found_b, has_symmetry
     401      1586205 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_a, block_b
     402              :       TYPE(dbcsr_iterator_type)                          :: iter
     403              :       TYPE(mp_comm_type)                                 :: group
     404              : 
     405      1586205 :       CALL timeset(routineN, handle)
     406      1586205 :       CPASSERT(omp_get_num_threads() == 1)
     407              : 
     408      1586205 :       CPASSERT(SIZE(matrix_a) == SIZE(matrix_b))
     409      8407806 :       DO i = 1, SIZE(matrix_a)
     410      6821601 :          has_symmetry = dbcsr_has_symmetry(matrix_a(i)%matrix)
     411      6821601 :          CPASSERT(has_symmetry .EQV. dbcsr_has_symmetry(matrix_b(i)%matrix))
     412      8407806 :          IF (PRESENT(comm)) THEN
     413      6038145 :             CALL dbcsr_get_info(matrix_a(i)%matrix, group=group)
     414      6038145 :             CPASSERT(group == comm)
     415              :          END IF
     416              :       END DO
     417              : 
     418      8407806 :       trace = 0.0_dp
     419              : !$OMP PARALLEL DEFAULT(NONE) SHARED(matrix_a, matrix_b) &
     420      1586205 : !$OMP PRIVATE(i, iter, row, col, block_a, block_b, found_b, has_symmetry) REDUCTION(+:trace)
     421              :       DO i = 1, SIZE(matrix_a)
     422              :          has_symmetry = dbcsr_has_symmetry(matrix_a(i)%matrix)
     423              :          CALL dbcsr_iterator_readonly_start(iter, matrix_a(i)%matrix)
     424              :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     425              :             CALL dbcsr_iterator_next_block(iter, row, col, block_a)
     426              :             IF (SIZE(block_a) == 0) CYCLE ! Skip zero-sized blocks.
     427              :             CALL dbcsr_get_readonly_block_p(matrix_b(i)%matrix, row, col, block_b, found_b)
     428              :             IF (found_b) THEN
     429              :                IF (has_symmetry .AND. row /= col) THEN
     430              :                   trace(i) = trace(i) + 2.0_dp*SUM(block_a*block_b)
     431              :                ELSE
     432              :                   trace(i) = trace(i) + SUM(block_a*block_b)
     433              :                END IF
     434              :             END IF
     435              :          END DO
     436              :          CALL dbcsr_iterator_stop(iter)
     437              :       END DO
     438              : !$OMP END PARALLEL
     439              : 
     440      1586205 :       IF (PRESENT(comm)) THEN
     441      1585075 :          IF (SIZE(trace) > 0 .AND. comm%num_pe > 1) CALL comm%sum(trace)
     442              :       ELSE
     443      1566912 :          DO i = 1, SIZE(matrix_a)
     444       783456 :             CALL dbcsr_get_info(matrix_a(i)%matrix, group=group)
     445      1566912 :             IF (group%num_pe > 1) CALL group%sum(trace(i))
     446              :          END DO
     447              :       END IF
     448              : 
     449      1586205 :       CALL timestop(handle)
     450      1586205 :    END SUBROUTINE dbcsr_dot_batch
     451              : 
     452              : ! **************************************************************************************************
     453              : !> \brief Computes the trace of the given matrix, also known as the sum of its diagonal elements.
     454              : !> \param matrix ...
     455              : !> \param trace ...
     456              : ! **************************************************************************************************
     457        79977 :    SUBROUTINE dbcsr_trace(matrix, trace)
     458              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     459              :       REAL(KIND=dp), INTENT(OUT)                         :: trace
     460              : 
     461              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_trace'
     462              : 
     463              :       INTEGER                                            :: col, col_size, handle, i, row, row_size
     464        26659 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     465              :       TYPE(dbcsr_iterator_type)                          :: iter
     466              :       TYPE(mp_comm_type)                                 :: group
     467              : 
     468        26659 :       CALL timeset(routineN, handle)
     469        26659 :       CPASSERT(omp_get_num_threads() == 1)
     470              : 
     471        26659 :       trace = 0.0_dp
     472        26659 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     473      1648909 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     474      1622250 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
     475      1648909 :          IF (row == col) THEN
     476       144064 :             CPASSERT(row_size == col_size)
     477       617441 :             DO i = 1, row_size
     478       617441 :                trace = trace + block(i, i)
     479              :             END DO
     480              :          END IF
     481              :       END DO
     482        26659 :       CALL dbcsr_iterator_stop(iter)
     483              : 
     484        26659 :       CALL dbcsr_get_info(matrix, group=group)
     485        26659 :       CALL group%sum(trace)
     486              : 
     487        26659 :       CALL timestop(handle)
     488        26659 :    END SUBROUTINE dbcsr_trace
     489              : 
     490              : ! **************************************************************************************************
     491              : !> \brief Copies the diagonal blocks of matrix into diag.
     492              : !> \param matrix ...
     493              : !> \param diag ...
     494              : ! **************************************************************************************************
     495       232940 :    SUBROUTINE dbcsr_get_block_diag(matrix, diag)
     496              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     497              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: diag
     498              : 
     499              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_get_block_diag'
     500              : 
     501              :       CHARACTER(len=default_string_length)               :: name
     502              :       INTEGER                                            :: col, handle, row
     503       116470 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     504              :       TYPE(dbcsr_iterator_type)                          :: iter
     505              : 
     506       116470 :       CALL timeset(routineN, handle)
     507       116470 :       CPASSERT(omp_get_num_threads() == 1)
     508              : 
     509       116470 :       CALL dbcsr_get_info(matrix, name=name)
     510       116470 :       CALL dbcsr_create(diag, template=matrix, name='diag of '//name)
     511              : 
     512       116470 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     513      8649083 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     514      8532613 :          CALL dbcsr_iterator_next_block(iter, row, col, block)
     515      8649083 :          IF (row == col) THEN
     516       474651 :             CALL dbcsr_put_block(diag, row, col, block)
     517              :          END IF
     518              :       END DO
     519       116470 :       CALL dbcsr_iterator_stop(iter)
     520       116470 :       CALL dbcsr_finalize(diag)
     521              : 
     522       116470 :       CALL timestop(handle)
     523       116470 :    END SUBROUTINE dbcsr_get_block_diag
     524              : 
     525              : ! **************************************************************************************************
     526              : !> \brief Scales the rows/columns of given matrix.
     527              : !> \param matrix Matrix to be scaled in-place.
     528              : !> \param alpha Vector with scaling factors.
     529              : !> \param side Side from which to apply the vector. Allowed values are 'right' and 'left'.
     530              : ! **************************************************************************************************
     531       227399 :    SUBROUTINE dbcsr_scale_by_vector(matrix, alpha, side)
     532              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     533              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: alpha
     534              :       CHARACTER(LEN=*), INTENT(IN)                       :: side
     535              : 
     536              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_scale_by_vector'
     537              : 
     538              :       INTEGER                                            :: col_offset, col_size, handle, i, &
     539              :                                                             nfullcols_total, nfullrows_total, &
     540              :                                                             row_offset, row_size
     541              :       LOGICAL                                            :: right
     542       227399 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     543              :       TYPE(dbcsr_iterator_type)                          :: iter
     544              : 
     545       227399 :       CALL timeset(routineN, handle)
     546       227399 :       CPASSERT(omp_get_num_threads() == 1)
     547              : 
     548       227399 :       IF (side == 'right') THEN
     549              :          right = .TRUE.
     550            0 :       ELSE IF (side == 'left') THEN
     551              :          right = .FALSE.
     552              :       ELSE
     553            0 :          CPABORT("Unknown side: "//TRIM(side))
     554              :       END IF
     555              : 
     556              :       ! Check that alpha and matrix have matching sizes.
     557       227399 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     558       227399 :       IF (right) THEN
     559       227399 :          CPASSERT(nfullcols_total == SIZE(alpha))
     560              :       ELSE
     561            0 :          CPASSERT(nfullrows_total == SIZE(alpha))
     562              :       END IF
     563              : 
     564              : !$OMP PARALLEL DEFAULT(NONE) SHARED(matrix, alpha, right) &
     565       227399 : !$OMP PRIVATE(iter, block, row_size, col_size, row_offset, col_offset, i)
     566              :       CALL dbcsr_iterator_start(iter, matrix)
     567              :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     568              :          CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
     569              :                                         row_offset=row_offset, col_offset=col_offset)
     570              :          IF (SIZE(block) == 0) CYCLE ! Skip zero-sized blocks.
     571              :          IF (right) THEN
     572              :             DO i = 1, col_size
     573              :                block(:, i) = block(:, i)*alpha(col_offset + i - 1)
     574              :             END DO
     575              :          ELSE
     576              :             DO i = 1, row_size
     577              :                block(i, :) = block(i, :)*alpha(row_offset + i - 1)
     578              :             END DO
     579              :          END IF
     580              :       END DO
     581              :       CALL dbcsr_iterator_stop(iter)
     582              : !$OMP END PARALLEL
     583              : 
     584       227399 :       CALL timestop(handle)
     585       227399 :    END SUBROUTINE dbcsr_scale_by_vector
     586              : 
     587              : ! **************************************************************************************************
     588              : !> \brief Copies the diagonal elements from the given matrix into the given array.
     589              : !> \param matrix ...
     590              : !> \param diag ...
     591              : ! **************************************************************************************************
     592        11356 :    SUBROUTINE dbcsr_get_diag(matrix, diag)
     593              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     594              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: diag
     595              : 
     596              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_get_diag'
     597              : 
     598              :       INTEGER                                            :: col, col_size, handle, i, &
     599              :                                                             nfullcols_total, nfullrows_total, row, &
     600              :                                                             row_offset, row_size
     601        11356 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     602              :       TYPE(dbcsr_iterator_type)                          :: iter
     603              : 
     604        11356 :       CALL timeset(routineN, handle)
     605        11356 :       CPASSERT(omp_get_num_threads() == 1)
     606              : 
     607        11356 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     608        11356 :       CPASSERT(nfullrows_total == nfullcols_total)
     609        11356 :       CPASSERT(nfullrows_total == SIZE(diag))
     610              : 
     611      1229026 :       diag(:) = 0.0_dp
     612        11356 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     613       279568 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     614              :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, &
     615       268212 :                                         col_size=col_size, row_offset=row_offset)
     616       279568 :          IF (row == col) THEN
     617        34615 :             CPASSERT(row_size == col_size)
     618       646412 :             DO i = 1, row_size
     619       646412 :                diag(row_offset + i - 1) = block(i, i)
     620              :             END DO
     621              :          END IF
     622              :       END DO
     623        11356 :       CALL dbcsr_iterator_stop(iter)
     624              : 
     625        11356 :       CALL timestop(handle)
     626        11356 :    END SUBROUTINE dbcsr_get_diag
     627              : 
     628              : ! **************************************************************************************************
     629              : !> \brief Copies the diagonal elements from the given array into the given matrix.
     630              : !> \param matrix ...
     631              : !> \param diag ...
     632              : ! **************************************************************************************************
     633         6020 :    SUBROUTINE dbcsr_set_diag(matrix, diag)
     634              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     635              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: diag
     636              : 
     637              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_set_diag'
     638              : 
     639              :       INTEGER                                            :: col, col_size, handle, i, &
     640              :                                                             nfullcols_total, nfullrows_total, row, &
     641              :                                                             row_offset, row_size
     642         6020 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     643              :       TYPE(dbcsr_iterator_type)                          :: iter
     644              : 
     645         6020 :       CALL timeset(routineN, handle)
     646         6020 :       CPASSERT(omp_get_num_threads() == 1)
     647              : 
     648         6020 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     649         6020 :       CPASSERT(nfullrows_total == nfullcols_total)
     650         6020 :       CPASSERT(nfullrows_total == SIZE(diag))
     651              : 
     652         6020 :       CALL dbcsr_reserve_diag_blocks(matrix)
     653              : 
     654         6020 :       CALL dbcsr_iterator_start(iter, matrix)
     655       153759 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     656              :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, &
     657       147739 :                                         col_size=col_size, row_offset=row_offset)
     658       153759 :          IF (row == col) THEN
     659        16572 :             CPASSERT(row_size == col_size)
     660        95784 :             DO i = 1, row_size
     661        95784 :                block(i, i) = diag(row_offset + i - 1)
     662              :             END DO
     663              :          END IF
     664              :       END DO
     665         6020 :       CALL dbcsr_iterator_stop(iter)
     666              : 
     667         6020 :       CALL timestop(handle)
     668         6020 :    END SUBROUTINE dbcsr_set_diag
     669              : 
     670              : ! **************************************************************************************************
     671              : !> \brief Calculates the checksum of a DBCSR matrix.
     672              : !> \param matrix ...
     673              : !> \param pos Enable position-dependent checksum.
     674              : !> \return ...
     675              : ! **************************************************************************************************
     676        55680 :    FUNCTION dbcsr_checksum(matrix, pos) RESULT(checksum)
     677              : 
     678              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     679              :       LOGICAL, INTENT(IN), OPTIONAL                      :: pos
     680              :       REAL(KIND=dp)                                      :: checksum
     681              : 
     682              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_checksum'
     683              : 
     684              :       INTEGER                                            :: col_offset, col_size, handle, i, j, &
     685              :                                                             row_offset, row_size
     686              :       LOGICAL                                            :: my_pos
     687              :       REAL(KIND=dp)                                      :: position_factor
     688        18560 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     689              :       TYPE(dbcsr_iterator_type)                          :: iter
     690              :       TYPE(mp_comm_type)                                 :: group
     691              : 
     692        18560 :       CALL timeset(routineN, handle)
     693        18560 :       CPASSERT(omp_get_num_threads() == 1)
     694              : 
     695        18560 :       my_pos = .FALSE.
     696        18560 :       IF (PRESENT(pos)) THEN
     697          286 :          my_pos = pos
     698              :       END IF
     699              : 
     700        18560 :       checksum = 0.0_dp
     701        18560 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     702       115034 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     703              :          CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
     704        96474 :                                         row_offset=row_offset, col_offset=col_offset)
     705       115034 :          IF (my_pos) THEN
     706        21372 :             DO i = 1, row_size
     707       218025 :             DO j = 1, col_size
     708       196653 :                position_factor = LOG(REAL((row_offset + i - 1)*(col_offset + j - 1), KIND=dp))
     709       215930 :                checksum = checksum + block(i, j)*position_factor
     710              :             END DO
     711              :             END DO
     712              :          ELSE
     713      4419117 :             checksum = checksum + SUM(block**2)
     714              :          END IF
     715              :       END DO
     716        18560 :       CALL dbcsr_iterator_stop(iter)
     717              : 
     718        18560 :       CALL dbcsr_get_info(matrix, group=group)
     719        18560 :       CALL group%sum(checksum)
     720              : 
     721        18560 :       CALL timestop(handle)
     722        18560 :    END FUNCTION dbcsr_checksum
     723              : 
     724              : ! **************************************************************************************************
     725              : !> \brief Prints given matrix in matlab format (only present blocks).
     726              : !> \param matrix ...
     727              : !> \param variable_name ...
     728              : !> \param unit_nr ...
     729              : ! **************************************************************************************************
     730            0 :    SUBROUTINE dbcsr_print(matrix, variable_name, unit_nr)
     731              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     732              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: variable_name
     733              :       INTEGER, INTENT(IN), OPTIONAL                      :: unit_nr
     734              : 
     735              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_print'
     736              : 
     737              :       CHARACTER(len=default_string_length)               :: my_variable_name, name
     738              :       INTEGER :: col_offset, col_size, handle, i, iw, j, nblkcols_total, nblkrows_total, &
     739              :          nfullcols_total, nfullrows_total, row_offset, row_size
     740            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     741              :       TYPE(dbcsr_iterator_type)                          :: iter
     742              : 
     743            0 :       CALL timeset(routineN, handle)
     744            0 :       CPASSERT(omp_get_num_threads() == 1)
     745              : 
     746            0 :       iw = default_output_unit
     747            0 :       IF (PRESENT(unit_nr)) iw = unit_nr
     748              : 
     749            0 :       my_variable_name = 'a'
     750            0 :       IF (PRESENT(variable_name)) my_variable_name = variable_name
     751              : 
     752              :       ! Print matrix properties.
     753              :       CALL dbcsr_get_info(matrix, name=name, &
     754              :                           nblkrows_total=nblkrows_total, nblkcols_total=nblkcols_total, &
     755            0 :                           nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     756            0 :       WRITE (iw, *) "===", routineN, "==="
     757            0 :       WRITE (iw, *) "Name:", name
     758            0 :       WRITE (iw, *) "Symmetry:", dbcsr_has_symmetry(matrix)
     759            0 :       WRITE (iw, *) "Number of blocks:", dbcsr_get_num_blocks(matrix)
     760            0 :       WRITE (iw, *) "Data size:", dbcsr_get_data_size(matrix)
     761            0 :       WRITE (iw, *) "Occupation:", dbcsr_get_occupation(matrix)
     762            0 :       WRITE (iw, *) "Full size:", nfullrows_total, "x", nfullcols_total
     763            0 :       WRITE (iw, *) "Blocked size:", nblkrows_total, "x", nblkcols_total
     764              : 
     765              :       ! Print matrix blocks.
     766            0 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     767            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     768              :          CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
     769            0 :                                         row_offset=row_offset, col_offset=col_offset)
     770            0 :          DO i = 1, row_size
     771            0 :          DO j = 1, col_size
     772            0 :             WRITE (iw, '(A,I4,A,I4,A,E23.16,A)') TRIM(my_variable_name)//'(', &
     773            0 :                row_offset + i - 1, ',', col_offset + j - 1, ')=', block(i, j), ';'
     774              :          END DO
     775              :          END DO
     776              :       END DO
     777            0 :       CALL dbcsr_iterator_stop(iter)
     778              : 
     779            0 :       CALL timestop(handle)
     780            0 :    END SUBROUTINE dbcsr_print
     781              : 
     782              : END MODULE cp_dbcsr_contrib
        

Generated by: LCOV version 2.0-1