LCOV - code coverage report
Current view: top level - src/dbx - cp_dbcsr_contrib.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 89.2 % 306 273
Test Date: 2025-12-04 06:27:48 Functions: 93.8 % 16 15

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 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_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
      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       320440 :    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        64088 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_a, block_b
      62              :       TYPE(dbcsr_iterator_type)                          :: iter
      63              : 
      64        64088 :       CALL timeset(routineN, handle)
      65        64088 :       CPASSERT(omp_get_num_threads() == 1)
      66              : 
      67        64088 :       CALL dbcsr_get_info(matrix_a, nblkrows_total=nblkrows_tot_a)
      68        64088 :       CALL dbcsr_get_info(matrix_b, nblkrows_total=nblkrows_tot_b)
      69        64088 :       CALL dbcsr_get_info(matrix_c, nblkrows_total=nblkrows_tot_c)
      70        64088 :       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        64088 :       CALL dbcsr_clear(matrix_c)
      75        64088 :       CALL dbcsr_iterator_readonly_start(iter, matrix_a)
      76       156813 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
      77        92725 :          CALL dbcsr_iterator_next_block(iter, row, col, block_a)
      78        92725 :          CALL dbcsr_get_readonly_block_p(matrix_b, row, col, block_b, found_b)
      79       156813 :          IF (found_b) THEN
      80     19311671 :             CALL dbcsr_put_block(matrix_c, row, col, block_a*block_b)
      81              :          END IF
      82              :       END DO
      83        64088 :       CALL dbcsr_iterator_stop(iter)
      84        64088 :       CALL dbcsr_finalize(matrix_c)
      85        64088 :       CALL timestop(handle)
      86        64088 :    END SUBROUTINE dbcsr_hadamard_product
      87              : 
      88              : ! **************************************************************************************************
      89              : !> \brief Compute the maxabs norm of a dbcsr matrix
      90              : !> \param matrix ...
      91              : !> \return ...
      92              : ! **************************************************************************************************
      93        38502 :    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        12834 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     101              :       TYPE(dbcsr_iterator_type)                          :: iter
     102              :       TYPE(mp_comm_type)                                 :: group
     103              : 
     104        12834 :       CALL timeset(routineN, handle)
     105        12834 :       CPASSERT(omp_get_num_threads() == 1)
     106              : 
     107        12834 :       norm = 0.0_dp
     108        12834 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     109       172370 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     110       159536 :          CALL dbcsr_iterator_next_block(iter, block=block)
     111      4059283 :          norm = MAX(norm, MAXVAL(ABS(block)))
     112              :       END DO
     113        12834 :       CALL dbcsr_iterator_stop(iter)
     114              : 
     115        12834 :       CALL dbcsr_get_info(matrix, group=group)
     116        12834 :       CALL group%max(norm)
     117              : 
     118        12834 :       CALL timestop(handle)
     119        12834 :    END FUNCTION dbcsr_maxabs
     120              : 
     121              : ! **************************************************************************************************
     122              : !> \brief Compute the frobenius norm of a dbcsr matrix
     123              : !> \param matrix ...
     124              : !> \return ...
     125              : ! **************************************************************************************************
     126      1101642 :    FUNCTION dbcsr_frobenius_norm(matrix) RESULT(norm)
     127              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     128              :       REAL(dp)                                           :: norm
     129              : 
     130              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_frobenius_norm'
     131              : 
     132              :       INTEGER                                            :: col, handle, row
     133              :       LOGICAL                                            :: has_symmetry
     134       367214 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     135              :       TYPE(dbcsr_iterator_type)                          :: iter
     136              :       TYPE(mp_comm_type)                                 :: group
     137              : 
     138       367214 :       CALL timeset(routineN, handle)
     139       367214 :       CPASSERT(omp_get_num_threads() == 1)
     140              : 
     141       367214 :       has_symmetry = dbcsr_has_symmetry(matrix)
     142       367214 :       norm = 0.0_dp
     143       367214 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     144      6366517 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     145      5999303 :          CALL dbcsr_iterator_next_block(iter, row, col, block)
     146      6366517 :          IF (has_symmetry .AND. row /= col) THEN
     147      5599820 :             norm = norm + 2.0_dp*SUM(block**2)
     148              :          ELSE
     149     73540241 :             norm = norm + SUM(block**2)
     150              :          END IF
     151              :       END DO
     152       367214 :       CALL dbcsr_iterator_stop(iter)
     153              : 
     154       367214 :       CALL dbcsr_get_info(matrix, group=group)
     155       367214 :       CALL group%sum(norm)
     156       367214 :       norm = SQRT(norm)
     157              : 
     158       367214 :       CALL timestop(handle)
     159       367214 :    END FUNCTION dbcsr_frobenius_norm
     160              : 
     161              : ! **************************************************************************************************
     162              : !> \brief Compute the gershgorin norm of a dbcsr matrix
     163              : !> \param matrix ...
     164              : !> \return ...
     165              : ! **************************************************************************************************
     166         8246 :    FUNCTION dbcsr_gershgorin_norm(matrix) RESULT(norm)
     167              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     168              :       REAL(dp)                                           :: norm
     169              : 
     170              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_gershgorin_norm'
     171              : 
     172              :       INTEGER                                            :: col, col_offset, handle, i, j, ncol, &
     173              :                                                             nrow, row, row_offset
     174              :       LOGICAL                                            :: has_symmetry
     175              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: buffer
     176         8246 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     177              :       TYPE(dbcsr_iterator_type)                          :: iter
     178              :       TYPE(mp_comm_type)                                 :: group
     179              : 
     180         8246 :       CALL timeset(routineN, handle)
     181         8246 :       CPASSERT(omp_get_num_threads() == 1)
     182              : 
     183         8246 :       has_symmetry = dbcsr_has_symmetry(matrix)
     184         8246 :       CALL dbcsr_get_info(matrix, nfullrows_total=nrow, nfullcols_total=ncol)
     185         8246 :       CPASSERT(nrow == ncol)
     186        24730 :       ALLOCATE (buffer(nrow))
     187       147462 :       buffer = 0.0_dp
     188              : 
     189         8246 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     190       195517 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     191       187271 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_offset=row_offset, col_offset=col_offset)
     192       623261 :          DO j = 1, SIZE(block, 2)
     193      4813759 :             DO i = 1, SIZE(block, 1)
     194      4198744 :                buffer(row_offset + i - 1) = buffer(row_offset + i - 1) + ABS(block(i, j))
     195      4626488 :                IF (has_symmetry .AND. row /= col) THEN
     196        40164 :                   buffer(col_offset + j - 1) = buffer(col_offset + j - 1) + ABS(block(i, j))
     197              :                END IF
     198              :             END DO
     199              :          END DO
     200              :       END DO
     201         8246 :       CALL dbcsr_iterator_stop(iter)
     202              : 
     203         8246 :       CALL dbcsr_get_info(matrix, group=group)
     204         8246 :       CALL group%sum(buffer)
     205       155708 :       norm = MAXVAL(buffer)
     206         8246 :       DEALLOCATE (buffer)
     207              : 
     208         8246 :       CALL timestop(handle)
     209        32984 :    END FUNCTION dbcsr_gershgorin_norm
     210              : 
     211              : ! **************************************************************************************************
     212              : !> \brief Fills the given matrix with random numbers.
     213              : !> \param matrix ...
     214              : !> \param keep_sparsity ...
     215              : ! **************************************************************************************************
     216          714 :    SUBROUTINE dbcsr_init_random(matrix, keep_sparsity)
     217              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     218              :       LOGICAL, OPTIONAL                                  :: keep_sparsity
     219              : 
     220              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_init_random'
     221              : 
     222              :       INTEGER                                            :: col, col_size, handle, ncol, nrow, row, &
     223              :                                                             row_size
     224              :       INTEGER, DIMENSION(4)                              :: iseed
     225              :       LOGICAL                                            :: my_keep_sparsity
     226          238 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     227              :       TYPE(dbcsr_iterator_type)                          :: iter
     228              : 
     229          238 :       CALL timeset(routineN, handle)
     230          238 :       CPASSERT(omp_get_num_threads() == 1)
     231              : 
     232          238 :       my_keep_sparsity = .FALSE.
     233          238 :       IF (PRESENT(keep_sparsity)) my_keep_sparsity = keep_sparsity
     234          238 :       IF (.NOT. my_keep_sparsity) CALL dbcsr_reserve_all_blocks(matrix)
     235          238 :       CALL dbcsr_get_info(matrix, nblkrows_total=nrow, nblkcols_total=ncol)
     236              : 
     237          238 :       CALL dbcsr_iterator_start(iter, matrix)
     238          700 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     239          462 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
     240              :          ! set the seed for dlarnv, is here to guarantee same value of the random numbers
     241              :          ! for all layouts (and block distributions)
     242          462 :          iseed = generate_larnv_seed(row, nrow, col, ncol, 1)
     243          700 :          CALL dlarnv(1, iseed, row_size*col_size, block(1, 1))
     244              :       END DO
     245          238 :       CALL dbcsr_iterator_stop(iter)
     246              : 
     247          238 :       CALL timestop(handle)
     248          238 :    END SUBROUTINE dbcsr_init_random
     249              : 
     250              : ! **************************************************************************************************
     251              : !> \brief Reserves all diagonal blocks.
     252              : !> \param matrix ...
     253              : ! **************************************************************************************************
     254       485403 :    SUBROUTINE dbcsr_reserve_diag_blocks(matrix)
     255              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     256              : 
     257              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_reserve_diag_blocks'
     258              : 
     259              :       INTEGER                                            :: handle, i, k, mynode, nblkcols_total, &
     260              :                                                             nblkrows_total, owner
     261       485403 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: local_diag
     262       485403 :       INTEGER, DIMENSION(:), POINTER                     :: local_rows
     263              :       TYPE(dbcsr_distribution_type)                      :: dist
     264              : 
     265       485403 :       CALL timeset(routineN, handle)
     266       485403 :       CPASSERT(omp_get_num_threads() == 1)
     267              : 
     268       485403 :       CALL dbcsr_get_info(matrix, nblkrows_total=nblkrows_total, nblkcols_total=nblkcols_total)
     269       485403 :       CPASSERT(nblkrows_total == nblkcols_total)
     270              : 
     271       485403 :       CALL dbcsr_get_info(matrix, local_rows=local_rows, distribution=dist)
     272       485403 :       CALL dbcsr_distribution_get(dist, mynode=mynode)
     273      1386703 :       ALLOCATE (local_diag(SIZE(local_rows)))
     274              : 
     275      1415565 :       k = 0
     276      1415565 :       DO i = 1, SIZE(local_rows)
     277       930162 :          CALL dbcsr_get_stored_coordinates(matrix, row=local_rows(i), column=local_rows(i), processor=owner)
     278      1415565 :          IF (owner == mynode) THEN
     279       930162 :             k = k + 1
     280       930162 :             local_diag(k) = local_rows(i)
     281              :          END IF
     282              :       END DO
     283              : 
     284       485403 :       CALL dbcsr_reserve_blocks(matrix, rows=local_diag(1:k), cols=local_diag(1:k))
     285       485403 :       DEALLOCATE (local_diag)
     286              : 
     287       485403 :       CALL timestop(handle)
     288      1456209 :    END SUBROUTINE dbcsr_reserve_diag_blocks
     289              : 
     290              : ! **************************************************************************************************
     291              : !> \brief Reserves all blocks.
     292              : !> \param matrix ...
     293              : ! **************************************************************************************************
     294      1676465 :    SUBROUTINE dbcsr_reserve_all_blocks(matrix)
     295              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     296              : 
     297              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_reserve_all_blocks'
     298              : 
     299              :       INTEGER                                            :: handle, i, j, k, n
     300      1676465 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: cols, rows
     301      1676465 :       INTEGER, DIMENSION(:), POINTER                     :: local_cols, local_rows
     302              : 
     303      1676465 :       CALL timeset(routineN, handle)
     304      1676465 :       CPASSERT(omp_get_num_threads() == 1)
     305              : 
     306      1676465 :       CALL dbcsr_get_info(matrix, local_rows=local_rows, local_cols=local_cols)
     307      1676465 :       n = SIZE(local_rows)*SIZE(local_cols)
     308      6406446 :       ALLOCATE (rows(n), cols(n))
     309              : 
     310      3871672 :       k = 0
     311      3871672 :       DO i = 1, SIZE(local_rows)
     312      7708479 :       DO j = 1, SIZE(local_cols)
     313      3836807 :          k = k + 1
     314      3836807 :          rows(k) = local_rows(i)
     315      6032014 :          cols(k) = local_cols(j)
     316              :       END DO
     317              :       END DO
     318              : 
     319      1676465 :       CALL dbcsr_reserve_blocks(matrix, rows=rows(1:k), cols=cols(1:k))
     320      1676465 :       DEALLOCATE (rows, cols)
     321              : 
     322      1676465 :       CALL timestop(handle)
     323      1676465 :    END SUBROUTINE dbcsr_reserve_all_blocks
     324              : 
     325              : ! **************************************************************************************************
     326              : !> \brief Adds the given scalar to the diagonal of the matrix. Reserves any missing diagonal blocks.
     327              : !> \param matrix ...
     328              : !> \param alpha ...
     329              : ! **************************************************************************************************
     330       870702 :    SUBROUTINE dbcsr_add_on_diag(matrix, alpha)
     331              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     332              :       REAL(kind=dp), INTENT(IN)                          :: alpha
     333              : 
     334              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_add_on_diag'
     335              : 
     336              :       INTEGER                                            :: col, col_size, handle, i, row, row_size
     337       435351 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     338              :       TYPE(dbcsr_iterator_type)                          :: iter
     339              : 
     340       435351 :       CALL timeset(routineN, handle)
     341       435351 :       CPASSERT(omp_get_num_threads() == 1)
     342              : 
     343       435351 :       CALL dbcsr_reserve_diag_blocks(matrix)
     344              : 
     345       435351 :       CALL dbcsr_iterator_start(iter, matrix)
     346      6417612 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     347      5982261 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
     348      6417612 :          IF (row == col) THEN
     349       843686 :             CPASSERT(row_size == col_size)
     350      4150696 :             DO i = 1, row_size
     351      4150696 :                block(i, i) = block(i, i) + alpha
     352              :             END DO
     353              :          END IF
     354              :       END DO
     355       435351 :       CALL dbcsr_iterator_stop(iter)
     356              : 
     357       435351 :       CALL timestop(handle)
     358       435351 :    END SUBROUTINE dbcsr_add_on_diag
     359              : 
     360              : ! **************************************************************************************************
     361              : !> \brief Computes the dot product of two matrices, also known as the trace of their matrix product.
     362              : !> \param matrix_a ...
     363              : !> \param matrix_b ...
     364              : !> \param trace ...
     365              : ! **************************************************************************************************
     366      5906145 :    SUBROUTINE dbcsr_dot(matrix_a, matrix_b, trace)
     367              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_a, matrix_b
     368              :       REAL(KIND=dp), INTENT(OUT)                         :: trace
     369              : 
     370              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_dot'
     371              : 
     372              :       INTEGER                                            :: col, handle, row
     373              :       LOGICAL                                            :: found_b, has_symmetry
     374      1968715 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_a, block_b
     375              :       TYPE(dbcsr_iterator_type)                          :: iter
     376              :       TYPE(mp_comm_type)                                 :: group
     377              : 
     378      1968715 :       CALL timeset(routineN, handle)
     379      1968715 :       CPASSERT(omp_get_num_threads() == 1)
     380              : 
     381      1968715 :       CPASSERT(dbcsr_has_symmetry(matrix_a) .EQV. dbcsr_has_symmetry(matrix_b))
     382      1968715 :       has_symmetry = dbcsr_has_symmetry(matrix_a)
     383              : 
     384      1968715 :       trace = 0.0_dp
     385      1968715 :       CALL dbcsr_iterator_readonly_start(iter, matrix_a)
     386     35746103 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     387     33777388 :          CALL dbcsr_iterator_next_block(iter, row, col, block_a)
     388    101332164 :          IF (SIZE(block_a) == 0) CYCLE ! Skip zero-sized blocks.
     389     33776340 :          CALL dbcsr_get_readonly_block_p(matrix_b, row, col, block_b, found_b)
     390     35745055 :          IF (found_b) THEN
     391     33400766 :             IF (has_symmetry .AND. row /= col) THEN
     392    969764692 :                trace = trace + 2.0_dp*SUM(block_a*block_b)
     393              :             ELSE
     394    646067463 :                trace = trace + SUM(block_a*block_b)
     395              :             END IF
     396              :          END IF
     397              :       END DO
     398      1968715 :       CALL dbcsr_iterator_stop(iter)
     399              : 
     400      1968715 :       CALL dbcsr_get_info(matrix_a, group=group)
     401      1968715 :       CALL group%sum(trace)
     402              : 
     403      1968715 :       CALL timestop(handle)
     404      1968715 :    END SUBROUTINE dbcsr_dot
     405              : 
     406              : ! **************************************************************************************************
     407              : !> \brief Computes the trace of the given matrix, also known as the sum of its diagonal elements.
     408              : !> \param matrix ...
     409              : !> \param trace ...
     410              : ! **************************************************************************************************
     411        50643 :    SUBROUTINE dbcsr_trace(matrix, trace)
     412              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     413              :       REAL(KIND=dp), INTENT(OUT)                         :: trace
     414              : 
     415              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_trace'
     416              : 
     417              :       INTEGER                                            :: col, col_size, handle, i, row, row_size
     418        16881 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     419              :       TYPE(dbcsr_iterator_type)                          :: iter
     420              :       TYPE(mp_comm_type)                                 :: group
     421              : 
     422        16881 :       CALL timeset(routineN, handle)
     423        16881 :       CPASSERT(omp_get_num_threads() == 1)
     424              : 
     425        16881 :       trace = 0.0_dp
     426        16881 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     427      1438742 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     428      1421861 :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
     429      1438742 :          IF (row == col) THEN
     430       123634 :             CPASSERT(row_size == col_size)
     431       518446 :             DO i = 1, row_size
     432       518446 :                trace = trace + block(i, i)
     433              :             END DO
     434              :          END IF
     435              :       END DO
     436        16881 :       CALL dbcsr_iterator_stop(iter)
     437              : 
     438        16881 :       CALL dbcsr_get_info(matrix, group=group)
     439        16881 :       CALL group%sum(trace)
     440              : 
     441        16881 :       CALL timestop(handle)
     442        16881 :    END SUBROUTINE dbcsr_trace
     443              : 
     444              : ! **************************************************************************************************
     445              : !> \brief Copies the diagonal blocks of matrix into diag.
     446              : !> \param matrix ...
     447              : !> \param diag ...
     448              : ! **************************************************************************************************
     449       208792 :    SUBROUTINE dbcsr_get_block_diag(matrix, diag)
     450              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     451              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: diag
     452              : 
     453              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_get_block_diag'
     454              : 
     455              :       CHARACTER(len=default_string_length)               :: name
     456              :       INTEGER                                            :: col, handle, row
     457       104396 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     458              :       TYPE(dbcsr_iterator_type)                          :: iter
     459              : 
     460       104396 :       CALL timeset(routineN, handle)
     461       104396 :       CPASSERT(omp_get_num_threads() == 1)
     462              : 
     463       104396 :       CALL dbcsr_get_info(matrix, name=name)
     464       104396 :       CALL dbcsr_create(diag, template=matrix, name='diag of '//name)
     465              : 
     466       104396 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     467      8569720 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     468      8465324 :          CALL dbcsr_iterator_next_block(iter, row, col, block)
     469      8569720 :          IF (row == col) THEN
     470       455711 :             CALL dbcsr_put_block(diag, row, col, block)
     471              :          END IF
     472              :       END DO
     473       104396 :       CALL dbcsr_iterator_stop(iter)
     474       104396 :       CALL dbcsr_finalize(diag)
     475              : 
     476       104396 :       CALL timestop(handle)
     477       104396 :    END SUBROUTINE dbcsr_get_block_diag
     478              : 
     479              : ! **************************************************************************************************
     480              : !> \brief Scales the rows/columns of given matrix.
     481              : !> \param matrix Matrix to be scaled in-place.
     482              : !> \param alpha Vector with scaling factors.
     483              : !> \param side Side from which to apply the vector. Allowed values are 'right' and 'left'.
     484              : ! **************************************************************************************************
     485       191261 :    SUBROUTINE dbcsr_scale_by_vector(matrix, alpha, side)
     486              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     487              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: alpha
     488              :       CHARACTER(LEN=*), INTENT(IN)                       :: side
     489              : 
     490              :       CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_scale_by_vector'
     491              : 
     492              :       INTEGER                                            :: col_offset, col_size, handle, i, &
     493              :                                                             nfullcols_total, nfullrows_total, &
     494              :                                                             row_offset, row_size
     495              :       LOGICAL                                            :: right
     496       191261 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     497              :       TYPE(dbcsr_iterator_type)                          :: iter
     498              : 
     499       191261 :       CALL timeset(routineN, handle)
     500       191261 :       CPASSERT(omp_get_num_threads() == 1)
     501              : 
     502       191261 :       IF (side == 'right') THEN
     503              :          right = .TRUE.
     504            0 :       ELSE IF (side == 'left') THEN
     505              :          right = .FALSE.
     506              :       ELSE
     507            0 :          CPABORT("Unknown side: "//TRIM(side))
     508              :       END IF
     509              : 
     510              :       ! Check that alpha and matrix have matching sizes.
     511       191261 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     512       191261 :       IF (right) THEN
     513       191261 :          CPASSERT(nfullcols_total == SIZE(alpha))
     514              :       ELSE
     515            0 :          CPASSERT(nfullrows_total == SIZE(alpha))
     516              :       END IF
     517              : 
     518       191261 :       CALL dbcsr_iterator_start(iter, matrix)
     519       819264 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     520              :          CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
     521       628003 :                                         row_offset=row_offset, col_offset=col_offset)
     522      1884009 :          IF (SIZE(block) == 0) CYCLE ! Skip zero-sized blocks.
     523       819264 :          IF (right) THEN
     524     13856646 :             DO i = 1, col_size
     525     76654208 :                block(:, i) = block(:, i)*alpha(col_offset + i - 1)
     526              :             END DO
     527              :          ELSE
     528            0 :             DO i = 1, row_size
     529            0 :                block(i, :) = block(i, :)*alpha(row_offset + i - 1)
     530              :             END DO
     531              :          END IF
     532              :       END DO
     533       191261 :       CALL dbcsr_iterator_stop(iter)
     534              : 
     535       191261 :       CALL timestop(handle)
     536       191261 :    END SUBROUTINE dbcsr_scale_by_vector
     537              : 
     538              : ! **************************************************************************************************
     539              : !> \brief Copies the diagonal elements from the given matrix into the given array.
     540              : !> \param matrix ...
     541              : !> \param diag ...
     542              : ! **************************************************************************************************
     543         2696 :    SUBROUTINE dbcsr_get_diag(matrix, diag)
     544              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     545              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: diag
     546              : 
     547              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_get_diag'
     548              : 
     549              :       INTEGER                                            :: col, col_size, handle, i, &
     550              :                                                             nfullcols_total, nfullrows_total, row, &
     551              :                                                             row_offset, row_size
     552         2696 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     553              :       TYPE(dbcsr_iterator_type)                          :: iter
     554              : 
     555         2696 :       CALL timeset(routineN, handle)
     556         2696 :       CPASSERT(omp_get_num_threads() == 1)
     557              : 
     558         2696 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     559         2696 :       CPASSERT(nfullrows_total == nfullcols_total)
     560         2696 :       CPASSERT(nfullrows_total == SIZE(diag))
     561              : 
     562        75640 :       diag(:) = 0.0_dp
     563         2696 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     564        67153 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     565              :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, &
     566        64457 :                                         col_size=col_size, row_offset=row_offset)
     567        67153 :          IF (row == col) THEN
     568         8676 :             CPASSERT(row_size == col_size)
     569        45188 :             DO i = 1, row_size
     570        45188 :                diag(row_offset + i - 1) = block(i, i)
     571              :             END DO
     572              :          END IF
     573              :       END DO
     574         2696 :       CALL dbcsr_iterator_stop(iter)
     575              : 
     576         2696 :       CALL timestop(handle)
     577         2696 :    END SUBROUTINE dbcsr_get_diag
     578              : 
     579              : ! **************************************************************************************************
     580              : !> \brief Copies the diagonal elements from the given array into the given matrix.
     581              : !> \param matrix ...
     582              : !> \param diag ...
     583              : ! **************************************************************************************************
     584         2954 :    SUBROUTINE dbcsr_set_diag(matrix, diag)
     585              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     586              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: diag
     587              : 
     588              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_set_diag'
     589              : 
     590              :       INTEGER                                            :: col, col_size, handle, i, &
     591              :                                                             nfullcols_total, nfullrows_total, row, &
     592              :                                                             row_offset, row_size
     593         2954 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     594              :       TYPE(dbcsr_iterator_type)                          :: iter
     595              : 
     596         2954 :       CALL timeset(routineN, handle)
     597         2954 :       CPASSERT(omp_get_num_threads() == 1)
     598              : 
     599         2954 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     600         2954 :       CPASSERT(nfullrows_total == nfullcols_total)
     601         2954 :       CPASSERT(nfullrows_total == SIZE(diag))
     602              : 
     603         2954 :       CALL dbcsr_reserve_diag_blocks(matrix)
     604              : 
     605         2954 :       CALL dbcsr_iterator_start(iter, matrix)
     606       137056 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     607              :          CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, &
     608       134102 :                                         col_size=col_size, row_offset=row_offset)
     609       137056 :          IF (row == col) THEN
     610        10966 :             CPASSERT(row_size == col_size)
     611        51978 :             DO i = 1, row_size
     612        51978 :                block(i, i) = diag(row_offset + i - 1)
     613              :             END DO
     614              :          END IF
     615              :       END DO
     616         2954 :       CALL dbcsr_iterator_stop(iter)
     617              : 
     618         2954 :       CALL timestop(handle)
     619         2954 :    END SUBROUTINE dbcsr_set_diag
     620              : 
     621              : ! **************************************************************************************************
     622              : !> \brief Calculates the checksum of a DBCSR matrix.
     623              : !> \param matrix ...
     624              : !> \param pos Enable position-dependent checksum.
     625              : !> \return ...
     626              : ! **************************************************************************************************
     627        48786 :    FUNCTION dbcsr_checksum(matrix, pos) RESULT(checksum)
     628              : 
     629              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     630              :       LOGICAL, INTENT(IN), OPTIONAL                      :: pos
     631              :       REAL(KIND=dp)                                      :: checksum
     632              : 
     633              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_checksum'
     634              : 
     635              :       INTEGER                                            :: col_offset, col_size, handle, i, j, &
     636              :                                                             row_offset, row_size
     637              :       LOGICAL                                            :: my_pos
     638              :       REAL(KIND=dp)                                      :: position_factor
     639        16262 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     640              :       TYPE(dbcsr_iterator_type)                          :: iter
     641              :       TYPE(mp_comm_type)                                 :: group
     642              : 
     643        16262 :       CALL timeset(routineN, handle)
     644        16262 :       CPASSERT(omp_get_num_threads() == 1)
     645              : 
     646        16262 :       my_pos = .FALSE.
     647        16262 :       IF (PRESENT(pos)) THEN
     648          314 :          my_pos = pos
     649              :       END IF
     650              : 
     651        16262 :       checksum = 0.0_dp
     652        16262 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     653       104746 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     654              :          CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
     655        88484 :                                         row_offset=row_offset, col_offset=col_offset)
     656       104746 :          IF (my_pos) THEN
     657        21996 :             DO i = 1, row_size
     658       222881 :             DO j = 1, col_size
     659       200885 :                position_factor = LOG(REAL((row_offset + i - 1)*(col_offset + j - 1), KIND=dp))
     660       220714 :                checksum = checksum + block(i, j)*position_factor
     661              :             END DO
     662              :             END DO
     663              :          ELSE
     664      3993843 :             checksum = checksum + SUM(block**2)
     665              :          END IF
     666              :       END DO
     667        16262 :       CALL dbcsr_iterator_stop(iter)
     668              : 
     669        16262 :       CALL dbcsr_get_info(matrix, group=group)
     670        16262 :       CALL group%sum(checksum)
     671              : 
     672        16262 :       CALL timestop(handle)
     673        16262 :    END FUNCTION dbcsr_checksum
     674              : 
     675              : ! **************************************************************************************************
     676              : !> \brief Prints given matrix in matlab format (only present blocks).
     677              : !> \param matrix ...
     678              : !> \param variable_name ...
     679              : !> \param unit_nr ...
     680              : ! **************************************************************************************************
     681            0 :    SUBROUTINE dbcsr_print(matrix, variable_name, unit_nr)
     682              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
     683              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: variable_name
     684              :       INTEGER, INTENT(IN), OPTIONAL                      :: unit_nr
     685              : 
     686              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dbcsr_print'
     687              : 
     688              :       CHARACTER(len=default_string_length)               :: my_variable_name, name
     689              :       INTEGER :: col_offset, col_size, handle, i, iw, j, nblkcols_total, nblkrows_total, &
     690              :          nfullcols_total, nfullrows_total, row_offset, row_size
     691            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     692              :       TYPE(dbcsr_iterator_type)                          :: iter
     693              : 
     694            0 :       CALL timeset(routineN, handle)
     695            0 :       CPASSERT(omp_get_num_threads() == 1)
     696              : 
     697            0 :       iw = default_output_unit
     698            0 :       IF (PRESENT(unit_nr)) iw = unit_nr
     699              : 
     700            0 :       my_variable_name = 'a'
     701            0 :       IF (PRESENT(variable_name)) my_variable_name = variable_name
     702              : 
     703              :       ! Print matrix properties.
     704              :       CALL dbcsr_get_info(matrix, name=name, &
     705              :                           nblkrows_total=nblkrows_total, nblkcols_total=nblkcols_total, &
     706            0 :                           nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     707            0 :       WRITE (iw, *) "===", routineN, "==="
     708            0 :       WRITE (iw, *) "Name:", name
     709            0 :       WRITE (iw, *) "Symmetry:", dbcsr_has_symmetry(matrix)
     710            0 :       WRITE (iw, *) "Number of blocks:", dbcsr_get_num_blocks(matrix)
     711            0 :       WRITE (iw, *) "Data size:", dbcsr_get_data_size(matrix)
     712            0 :       WRITE (iw, *) "Occupation:", dbcsr_get_occupation(matrix)
     713            0 :       WRITE (iw, *) "Full size:", nfullrows_total, "x", nfullcols_total
     714            0 :       WRITE (iw, *) "Blocked size:", nblkrows_total, "x", nblkcols_total
     715              : 
     716              :       ! Print matrix blocks.
     717            0 :       CALL dbcsr_iterator_readonly_start(iter, matrix)
     718            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     719              :          CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
     720            0 :                                         row_offset=row_offset, col_offset=col_offset)
     721            0 :          DO i = 1, row_size
     722            0 :          DO j = 1, col_size
     723            0 :             WRITE (iw, '(A,I4,A,I4,A,E23.16,A)') TRIM(my_variable_name)//'(', &
     724            0 :                row_offset + i - 1, ',', col_offset + j - 1, ')=', block(i, j), ';'
     725              :          END DO
     726              :          END DO
     727              :       END DO
     728            0 :       CALL dbcsr_iterator_stop(iter)
     729              : 
     730            0 :       CALL timestop(handle)
     731            0 :    END SUBROUTINE dbcsr_print
     732              : 
     733              : END MODULE cp_dbcsr_contrib
        

Generated by: LCOV version 2.0-1