LCOV - code coverage report
Current view: top level - src/dbm - dbm_api.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 94.7 % 190 180
Test Date: 2025-12-04 06:27:48 Functions: 86.7 % 45 39

            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: BSD-3-Clause                                                          !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : MODULE dbm_api
       9              :    USE ISO_C_BINDING, ONLY: C_ASSOCIATED, C_BOOL, C_CHAR, C_DOUBLE, C_F_POINTER, C_FUNLOC, C_FUNPTR, &
      10              :                             C_INT, C_INT64_T, C_NULL_CHAR, C_NULL_PTR, C_PTR
      11              :    USE kinds, ONLY: default_string_length, &
      12              :                     dp, &
      13              :                     int_8
      14              :    USE message_passing, ONLY: mp_cart_type, &
      15              :                               mp_comm_type
      16              : 
      17              : ! Uncomment the following line to enable validation.
      18              : !#define DBM_VALIDATE_AGAINST_DBCSR
      19              : #define DBM_VALIDATE_NBLOCKS_MATCH .TRUE.
      20              : #define DBM_VALIDATE_THRESHOLD 5e-10_dp
      21              : 
      22              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
      23              :    USE dbcsr_block_access, ONLY: dbcsr_get_block_p, &
      24              :                                  dbcsr_put_block, &
      25              :                                  dbcsr_reserve_blocks
      26              :    USE dbcsr_dist_methods, ONLY: dbcsr_distribution_col_dist, &
      27              :                                  dbcsr_distribution_hold, &
      28              :                                  dbcsr_distribution_new, &
      29              :                                  dbcsr_distribution_release, &
      30              :                                  dbcsr_distribution_row_dist
      31              :    USE dbcsr_dist_operations, ONLY: dbcsr_get_stored_coordinates
      32              :    USE dbcsr_dist_util, ONLY: dbcsr_checksum
      33              :    USE dbcsr_iterator_operations, ONLY: dbcsr_iterator_blocks_left, &
      34              :                                         dbcsr_iterator_next_block, &
      35              :                                         dbcsr_iterator_start, &
      36              :                                         dbcsr_iterator_stop
      37              :    USE dbcsr_methods, ONLY: dbcsr_col_block_sizes, &
      38              :                             dbcsr_get_num_blocks, &
      39              :                             dbcsr_get_nze, &
      40              :                             dbcsr_mp_release, &
      41              :                             dbcsr_release, &
      42              :                             dbcsr_row_block_sizes
      43              :    USE dbcsr_mp_methods, ONLY: dbcsr_mp_new
      44              :    USE dbcsr_multiply_api, ONLY: dbcsr_multiply
      45              :    USE dbcsr_operations, ONLY: dbcsr_add, &
      46              :                                dbcsr_clear, &
      47              :                                dbcsr_copy, &
      48              :                                dbcsr_filter, &
      49              :                                dbcsr_get_info, &
      50              :                                dbcsr_maxabs, &
      51              :                                dbcsr_scale, &
      52              :                                dbcsr_zero
      53              :    USE dbcsr_transformations, ONLY: dbcsr_redistribute
      54              :    USE dbcsr_types, ONLY: dbcsr_distribution_obj, &
      55              :                           dbcsr_iterator, &
      56              :                           dbcsr_mp_obj, &
      57              :                           dbcsr_no_transpose, &
      58              :                           dbcsr_transpose, &
      59              :                           dbcsr_type, &
      60              :                           dbcsr_type_no_symmetry, &
      61              :                           dbcsr_type_real_8
      62              :    USE dbcsr_work_operations, ONLY: dbcsr_create, &
      63              :                                     dbcsr_finalize
      64              :    USE dbcsr_data_methods, ONLY: dbcsr_scalar
      65              : #endif
      66              : 
      67              : #include "../base/base_uses.f90"
      68              : 
      69              :    IMPLICIT NONE
      70              : 
      71              :    PRIVATE
      72              : 
      73              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbm_api'
      74              : 
      75              :    PUBLIC :: dbm_distribution_obj
      76              :    PUBLIC :: dbm_distribution_new
      77              :    PUBLIC :: dbm_distribution_hold
      78              :    PUBLIC :: dbm_distribution_release
      79              :    PUBLIC :: dbm_distribution_col_dist
      80              :    PUBLIC :: dbm_distribution_row_dist
      81              : 
      82              :    PUBLIC :: dbm_iterator
      83              :    PUBLIC :: dbm_iterator_start
      84              :    PUBLIC :: dbm_iterator_stop
      85              :    PUBLIC :: dbm_iterator_num_blocks
      86              :    PUBLIC :: dbm_iterator_blocks_left
      87              :    PUBLIC :: dbm_iterator_next_block
      88              : 
      89              :    PUBLIC :: dbm_type
      90              :    PUBLIC :: dbm_release
      91              :    PUBLIC :: dbm_create
      92              :    PUBLIC :: dbm_create_from_template
      93              :    PUBLIC :: dbm_clear
      94              :    PUBLIC :: dbm_scale
      95              :    PUBLIC :: dbm_get_block_p
      96              :    PUBLIC :: dbm_put_block
      97              :    PUBLIC :: dbm_reserve_blocks
      98              :    PUBLIC :: dbm_filter
      99              :    PUBLIC :: dbm_finalize
     100              :    PUBLIC :: dbm_multiply
     101              :    PUBLIC :: dbm_redistribute
     102              :    PUBLIC :: dbm_copy
     103              :    PUBLIC :: dbm_add
     104              :    PUBLIC :: dbm_maxabs
     105              :    PUBLIC :: dbm_zero
     106              :    PUBLIC :: dbm_checksum
     107              :    PUBLIC :: dbm_get_name
     108              :    PUBLIC :: dbm_get_distribution
     109              :    PUBLIC :: dbm_get_num_blocks
     110              :    PUBLIC :: dbm_get_nze
     111              :    PUBLIC :: dbm_get_stored_coordinates
     112              :    PUBLIC :: dbm_get_row_block_sizes
     113              :    PUBLIC :: dbm_get_col_block_sizes
     114              :    PUBLIC :: dbm_get_local_rows
     115              :    PUBLIC :: dbm_get_local_cols
     116              : 
     117              :    PUBLIC :: dbm_library_init
     118              :    PUBLIC :: dbm_library_finalize
     119              :    PUBLIC :: dbm_library_print_stats
     120              : 
     121              :    TYPE dbm_distribution_obj
     122              :       PRIVATE
     123              :       TYPE(C_PTR)                          :: c_ptr = C_NULL_PTR
     124              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     125              :       TYPE(dbcsr_distribution_obj)         :: dbcsr
     126              : #endif
     127              :    END TYPE dbm_distribution_obj
     128              : 
     129              :    TYPE dbm_type
     130              :       PRIVATE
     131              :       TYPE(C_PTR)                          :: c_ptr = C_NULL_PTR
     132              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     133              :       TYPE(dbcsr_type)                     :: dbcsr
     134              : #endif
     135              :    END TYPE dbm_type
     136              : 
     137              :    TYPE dbm_iterator
     138              :       PRIVATE
     139              :       TYPE(C_PTR)                          :: c_ptr = C_NULL_PTR
     140              :    END TYPE dbm_iterator
     141              : 
     142              : CONTAINS
     143              : 
     144              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     145              : ! **************************************************************************************************
     146              : !> \brief Compates the given DBM matrix against its shadow DBCSR matrics.
     147              : !> \param matrix ...
     148              : !> \author Ole Schuett
     149              : ! **************************************************************************************************
     150              :    SUBROUTINE validate(matrix)
     151              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
     152              : 
     153              :       INTEGER                                            :: col, col_size, col_size_dbcsr, i, j, &
     154              :                                                             num_blocks, num_blocks_dbcsr, &
     155              :                                                             num_blocks_diff, row, row_size, &
     156              :                                                             row_size_dbcsr
     157              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: local_cols, local_rows
     158              :       LOGICAL                                            :: transposed
     159              :       REAL(dp)                                           :: norm2, rel_diff
     160              :       REAL(dp), DIMENSION(:, :), POINTER                 :: block, block_dbcsr
     161              :       TYPE(C_PTR)                                        :: block_c
     162              :       TYPE(dbcsr_iterator)                               :: iter
     163              :       INTERFACE
     164              :          SUBROUTINE dbm_get_block_p_c(matrix, row, col, block, row_size, col_size) &
     165              :             BIND(C, name="dbm_get_block_p")
     166              :             IMPORT :: C_PTR, C_INT
     167              :             TYPE(C_PTR), VALUE                        :: matrix
     168              :             INTEGER(kind=C_INT), VALUE                :: row
     169              :             INTEGER(kind=C_INT), VALUE                :: col
     170              :             TYPE(C_PTR)                               :: block
     171              :             INTEGER(kind=C_INT)                       :: row_size
     172              :             INTEGER(kind=C_INT)                       :: col_size
     173              :          END SUBROUTINE dbm_get_block_p_c
     174              :       END INTERFACE
     175              : 
     176              :       ! Call some getters to run their validation code.
     177              :       CALL dbm_get_local_rows(matrix, local_rows)
     178              :       CALL dbm_get_local_cols(matrix, local_cols)
     179              : 
     180              :       num_blocks_dbcsr = dbcsr_get_num_blocks(matrix%dbcsr)
     181              :       num_blocks = dbm_get_num_blocks(matrix)
     182              :       num_blocks_diff = ABS(num_blocks - num_blocks_dbcsr)
     183              :       IF (num_blocks_diff /= 0) THEN
     184              :          WRITE (*, *) "num_blocks mismatch dbcsr:", num_blocks_dbcsr, "new:", num_blocks
     185              :          IF (DBM_VALIDATE_NBLOCKS_MATCH) &
     186              :             CPABORT("num_blocks mismatch")
     187              :       END IF
     188              : 
     189              :       IF (DBM_VALIDATE_NBLOCKS_MATCH) THEN
     190              :          CPASSERT(dbm_get_nze(matrix) == dbcsr_get_nze(matrix%dbcsr))
     191              :       END IF
     192              : 
     193              :       ! check all dbcsr blocks
     194              :       norm2 = 0.0_dp
     195              :       CALL dbcsr_iterator_start(iter, matrix%dbcsr)
     196              :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     197              :          CALL dbcsr_iterator_next_block(iter, row=row, column=col, block=block_dbcsr, &
     198              :                                         transposed=transposed, &
     199              :                                         row_size=row_size_dbcsr, col_size=col_size_dbcsr)
     200              :          CPASSERT(.NOT. transposed)
     201              :          CALL dbm_get_block_p_c(matrix=matrix%c_ptr, row=row - 1, col=col - 1, &
     202              :                                 block=block_c, row_size=row_size, col_size=col_size)
     203              : 
     204              :          CPASSERT(row_size == row_size_dbcsr .AND. col_size == col_size_dbcsr)
     205              :          IF (SIZE(block_dbcsr) == 0) THEN
     206              :             CYCLE
     207              :          END IF
     208              :          IF (.NOT. C_ASSOCIATED(block_c)) THEN
     209              :             CPASSERT(MAXVAL(ABS(block_dbcsr)) < DBM_VALIDATE_THRESHOLD)
     210              :             CYCLE
     211              :          END IF
     212              : 
     213              :          CALL C_F_POINTER(block_c, block, shape=[row_size, col_size])
     214              :          DO i = 1, row_size
     215              :             DO j = 1, col_size
     216              :                rel_diff = ABS(block(i, j) - block_dbcsr(i, j))/MAX(1.0_dp, ABS(block_dbcsr(i, j)))
     217              :                IF (rel_diff > DBM_VALIDATE_THRESHOLD) THEN
     218              :                   WRITE (*, *) "row:", row, "col:", col, "i:", i, "j:", j, "rel_diff:", rel_diff
     219              :                   WRITE (*, *) "values dbcsr:", block_dbcsr(i, j), "new:", block(i, j)
     220              :                   CPABORT("block value mismatch")
     221              :                END IF
     222              :             END DO
     223              :          END DO
     224              :          norm2 = norm2 + SUM(block**2)
     225              :          block_dbcsr(:, :) = block(:, :) ! quench numerical noise
     226              :       END DO
     227              :       CALL dbcsr_iterator_stop(iter)
     228              : 
     229              :       ! Can not call dbcsr_get_block_p because it's INTENT(INOUT) :-(
     230              : 
     231              :       !! At least check that the norm (=checksum) of excesive blocks is small.
     232              :       !TODO: sum norm2 across all mpi ranks.
     233              :       !TODO: re-add INTERFACE to dbm_checksum_c, which got removed by prettify.
     234              :       !rel_diff = ABS(dbm_checksum_c(matrix%c_ptr) - norm2)/MAX(1.0_dp, norm2)
     235              :       !IF (rel_diff > DBM_VALIDATE_THRESHOLD) THEN
     236              :       !   WRITE (*, *) "num_blocks dbcsr:", num_blocks_dbcsr, "new:", num_blocks
     237              :       !   WRITE (*, *) "norm2: ", norm2
     238              :       !   WRITE (*, *) "relative residual norm diff: ", rel_diff
     239              :       !   CPABORT("residual norm diff")
     240              :       !END IF
     241              :    END SUBROUTINE validate
     242              : 
     243              : #else
     244              : 
     245              : ! **************************************************************************************************
     246              : !> \brief Dummy for when DBM_VALIDATE_AGAINST_DBCSR is not defined.
     247              : !> \param matrix ...
     248              : ! **************************************************************************************************
     249            0 :    SUBROUTINE validate(matrix)
     250              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
     251              : 
     252              :       MARK_USED(matrix)
     253            0 :    END SUBROUTINE validate
     254              : #endif
     255              : 
     256              : ! **************************************************************************************************
     257              : !> \brief Creates a new matrix from given template, reusing dist and row/col_block_sizes.
     258              : !> \param matrix ...
     259              : !> \param name ...
     260              : !> \param template ...
     261              : !> \author Ole Schuett
     262              : ! **************************************************************************************************
     263       931835 :    SUBROUTINE dbm_create_from_template(matrix, name, template)
     264              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     265              :       CHARACTER(len=*), INTENT(IN)                       :: name
     266              :       TYPE(dbm_type), INTENT(IN)                         :: template
     267              : 
     268       931835 :       INTEGER, CONTIGUOUS, DIMENSION(:), POINTER         :: col_block_sizes, row_block_sizes
     269              : 
     270              :       ! Store pointers in intermediate variables to workaround a CCE error.
     271      1863670 :       row_block_sizes => dbm_get_row_block_sizes(template)
     272       931835 :       col_block_sizes => dbm_get_col_block_sizes(template)
     273              : 
     274              :       CALL dbm_create(matrix, &
     275              :                       name=name, &
     276              :                       dist=dbm_get_distribution(template), &
     277              :                       row_block_sizes=row_block_sizes, &
     278       931835 :                       col_block_sizes=col_block_sizes)
     279              : 
     280       931835 :    END SUBROUTINE dbm_create_from_template
     281              : 
     282              : ! **************************************************************************************************
     283              : !> \brief Creates a new matrix.
     284              : !> \param matrix ...
     285              : !> \param name ...
     286              : !> \param dist ...
     287              : !> \param row_block_sizes ...
     288              : !> \param col_block_sizes ...
     289              : !> \author Ole Schuett
     290              : ! **************************************************************************************************
     291      1717896 :    SUBROUTINE dbm_create(matrix, name, dist, row_block_sizes, col_block_sizes)
     292              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     293              :       CHARACTER(len=*), INTENT(IN)                       :: name
     294              :       TYPE(dbm_distribution_obj), INTENT(IN)             :: dist
     295              :       INTEGER, CONTIGUOUS, DIMENSION(:), INTENT(IN), &
     296              :          POINTER                                         :: row_block_sizes, col_block_sizes
     297              : 
     298              :       INTERFACE
     299              :          SUBROUTINE dbm_create_c(matrix, dist, name, nrows, ncols, row_sizes, col_sizes) &
     300              :             BIND(C, name="dbm_create")
     301              :             IMPORT :: C_PTR, C_CHAR, C_INT
     302              :             TYPE(C_PTR)                               :: matrix
     303              :             TYPE(C_PTR), VALUE                        :: dist
     304              :             CHARACTER(kind=C_CHAR), DIMENSION(*)      :: name
     305              :             INTEGER(kind=C_INT), VALUE                :: nrows
     306              :             INTEGER(kind=C_INT), VALUE                :: ncols
     307              :             INTEGER(kind=C_INT), DIMENSION(*)         :: row_sizes
     308              :             INTEGER(kind=C_INT), DIMENSION(*)         :: col_sizes
     309              :          END SUBROUTINE dbm_create_c
     310              :       END INTERFACE
     311              : 
     312      1717896 :       CPASSERT(.NOT. C_ASSOCIATED(matrix%c_ptr))
     313              :       CALL dbm_create_c(matrix=matrix%c_ptr, &
     314              :                         dist=dist%c_ptr, &
     315              :                         name=TRIM(name)//C_NULL_CHAR, &
     316              :                         nrows=SIZE(row_block_sizes), &
     317              :                         ncols=SIZE(col_block_sizes), &
     318              :                         row_sizes=row_block_sizes, &
     319      1717896 :                         col_sizes=col_block_sizes)
     320      1717896 :       CPASSERT(C_ASSOCIATED(matrix%c_ptr))
     321              : 
     322              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     323              :       CALL dbcsr_create(matrix%dbcsr, name=name, dist=dist%dbcsr, &
     324              :                         matrix_type=dbcsr_type_no_symmetry, &
     325              :                         row_blk_size=row_block_sizes, col_blk_size=col_block_sizes, &
     326              :                         data_type=dbcsr_type_real_8)
     327              : 
     328              :       CALL validate(matrix)
     329              : #endif
     330      1717896 :    END SUBROUTINE dbm_create
     331              : 
     332              : ! **************************************************************************************************
     333              : !> \brief Needed to be called for DBCSR after blocks where inserted. For DBM it's a no-opt.
     334              : !> \param matrix ...
     335              : !> \author Ole Schuett
     336              : ! **************************************************************************************************
     337      2243105 :    SUBROUTINE dbm_finalize(matrix)
     338              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     339              : 
     340              :       MARK_USED(matrix) ! New implementation does not need finalize.
     341              : 
     342              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     343              :       CALL dbcsr_finalize(matrix%dbcsr)
     344              : #endif
     345      2243105 :    END SUBROUTINE dbm_finalize
     346              : 
     347              : ! **************************************************************************************************
     348              : !> \brief Releases a matrix and all its ressources.
     349              : !> \param matrix ...
     350              : !> \author Ole Schuett
     351              : ! **************************************************************************************************
     352      1717896 :    SUBROUTINE dbm_release(matrix)
     353              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     354              : 
     355              :       INTERFACE
     356              :          SUBROUTINE dbm_release_c(matrix) &
     357              :             BIND(C, name="dbm_release")
     358              :             IMPORT :: C_PTR
     359              :             TYPE(C_PTR), VALUE                               :: matrix
     360              :          END SUBROUTINE dbm_release_c
     361              :       END INTERFACE
     362              : 
     363      1717896 :       CALL dbm_release_c(matrix=matrix%c_ptr)
     364      1717896 :       matrix%c_ptr = C_NULL_PTR
     365              : 
     366              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     367              :       CALL dbcsr_release(matrix%dbcsr)
     368              : #endif
     369      1717896 :    END SUBROUTINE dbm_release
     370              : 
     371              : ! **************************************************************************************************
     372              : !> \brief Copies content of matrix_b into matrix_a.
     373              : !>        Matrices must have the same row/col block sizes and distribution.
     374              : !> \param matrix_a ...
     375              : !> \param matrix_b ...
     376              : !> \author Ole Schuett
     377              : ! **************************************************************************************************
     378       431186 :    SUBROUTINE dbm_copy(matrix_a, matrix_b)
     379              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix_a
     380              :       TYPE(dbm_type), INTENT(IN)                         :: matrix_b
     381              : 
     382              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbm_copy'
     383              : 
     384              :       INTEGER                                            :: handle
     385              :       INTERFACE
     386              :          SUBROUTINE dbm_copy_c(matrix_a, matrix_b) &
     387              :             BIND(C, name="dbm_copy")
     388              :             IMPORT :: C_PTR
     389              :             TYPE(C_PTR), VALUE                               :: matrix_a
     390              :             TYPE(C_PTR), VALUE                               :: matrix_b
     391              :          END SUBROUTINE dbm_copy_c
     392              :       END INTERFACE
     393              : 
     394       431186 :       CALL timeset(routineN, handle)
     395       431186 :       CALL dbm_copy_c(matrix_a=matrix_a%c_ptr, matrix_b=matrix_b%c_ptr)
     396              : 
     397              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     398              :       CALL dbcsr_copy(matrix_a%dbcsr, matrix_b%dbcsr)
     399              :       CALL validate(matrix_a)
     400              : #endif
     401       431186 :       CALL timestop(handle)
     402       431186 :    END SUBROUTINE dbm_copy
     403              : 
     404              : ! **************************************************************************************************
     405              : !> \brief Copies content of matrix_b into matrix_a. Matrices may have different distributions.
     406              : !> \param matrix ...
     407              : !> \param redist ...
     408              : !> \author Ole Schuett
     409              : ! **************************************************************************************************
     410          144 :    SUBROUTINE dbm_redistribute(matrix, redist)
     411              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
     412              :       TYPE(dbm_type), INTENT(INOUT)                      :: redist
     413              : 
     414              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbm_redistribute'
     415              : 
     416              :       INTEGER                                            :: handle
     417              :       INTERFACE
     418              :          SUBROUTINE dbm_redistribute_c(matrix, redist) &
     419              :             BIND(C, name="dbm_redistribute")
     420              :             IMPORT :: C_PTR
     421              :             TYPE(C_PTR), VALUE                               :: matrix
     422              :             TYPE(C_PTR), VALUE                               :: redist
     423              :          END SUBROUTINE dbm_redistribute_c
     424              :       END INTERFACE
     425              : 
     426          144 :       CALL timeset(routineN, handle)
     427          144 :       CALL dbm_redistribute_c(matrix=matrix%c_ptr, redist=redist%c_ptr)
     428              : 
     429              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     430              :       CALL dbcsr_redistribute(matrix%dbcsr, redist%dbcsr)
     431              :       CALL validate(redist)
     432              : #endif
     433          144 :       CALL timestop(handle)
     434          144 :    END SUBROUTINE dbm_redistribute
     435              : 
     436              : ! **************************************************************************************************
     437              : !> \brief Looks up a block from given matrics. This routine is thread-safe.
     438              : !>        If the block is not found then a null pointer is returned.
     439              : !> \param matrix ...
     440              : !> \param row ...
     441              : !> \param col ...
     442              : !> \param block ...
     443              : !> \param row_size ...
     444              : !> \param col_size ...
     445              : !> \author Ole Schuett
     446              : ! **************************************************************************************************
     447     21397733 :    SUBROUTINE dbm_get_block_p(matrix, row, col, block, row_size, col_size)
     448              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     449              :       INTEGER, INTENT(IN)                                :: row, col
     450              :       REAL(dp), DIMENSION(:, :), INTENT(OUT), POINTER    :: block
     451              :       INTEGER, INTENT(OUT), OPTIONAL                     :: row_size, col_size
     452              : 
     453              :       INTEGER                                            :: my_col_size, my_row_size
     454              :       TYPE(C_PTR)                                        :: block_c
     455              :       INTERFACE
     456              :          SUBROUTINE dbm_get_block_p_c(matrix, row, col, block, row_size, col_size) &
     457              :             BIND(C, name="dbm_get_block_p")
     458              :             IMPORT :: C_PTR, C_INT
     459              :             TYPE(C_PTR), VALUE                        :: matrix
     460              :             INTEGER(kind=C_INT), VALUE                :: row
     461              :             INTEGER(kind=C_INT), VALUE                :: col
     462              :             TYPE(C_PTR)                               :: block
     463              :             INTEGER(kind=C_INT)                       :: row_size
     464              :             INTEGER(kind=C_INT)                       :: col_size
     465              :          END SUBROUTINE dbm_get_block_p_c
     466              :       END INTERFACE
     467              : 
     468              :       CALL dbm_get_block_p_c(matrix=matrix%c_ptr, row=row - 1, col=col - 1, &
     469     21397733 :                              block=block_c, row_size=my_row_size, col_size=my_col_size)
     470     21397733 :       IF (C_ASSOCIATED(block_c)) THEN
     471     59492007 :          CALL C_F_POINTER(block_c, block, shape=[my_row_size, my_col_size])
     472              :       ELSE
     473      1567064 :          NULLIFY (block)  ! block not found
     474              :       END IF
     475     21397733 :       IF (PRESENT(row_size)) row_size = my_row_size
     476     21397733 :       IF (PRESENT(col_size)) col_size = my_col_size
     477     21397733 :    END SUBROUTINE dbm_get_block_p
     478              : 
     479              : ! **************************************************************************************************
     480              : !> \brief Adds a block to given matrix. This routine is thread-safe.
     481              : !>        If block already exist then it gets overwritten (or summed).
     482              : !> \param matrix ...
     483              : !> \param row ...
     484              : !> \param col ...
     485              : !> \param block ...
     486              : !> \param summation ...
     487              : !> \author Ole Schuett
     488              : ! **************************************************************************************************
     489     34053876 :    SUBROUTINE dbm_put_block(matrix, row, col, block, summation)
     490              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     491              :       INTEGER, INTENT(IN)                                :: row, col
     492              :       REAL(dp), CONTIGUOUS, DIMENSION(:, :), INTENT(IN)  :: block
     493              :       LOGICAL, INTENT(IN), OPTIONAL                      :: summation
     494              : 
     495              :       LOGICAL                                            :: my_summation
     496              :       INTERFACE
     497              :          SUBROUTINE dbm_put_block_c(matrix, row, col, summation, block) &
     498              :             BIND(C, name="dbm_put_block")
     499              :             IMPORT :: C_PTR, C_INT, C_BOOL, C_DOUBLE
     500              :             TYPE(C_PTR), VALUE                        :: matrix
     501              :             INTEGER(kind=C_INT), VALUE                :: row
     502              :             INTEGER(kind=C_INT), VALUE                :: col
     503              :             LOGICAL(kind=C_BOOL), VALUE               :: summation
     504              :             REAL(kind=C_DOUBLE), DIMENSION(*)         :: block
     505              :          END SUBROUTINE dbm_put_block_c
     506              :       END INTERFACE
     507              : 
     508     34053876 :       my_summation = .FALSE.
     509     34053876 :       IF (PRESENT(summation)) my_summation = summation
     510              : 
     511              :       CALL dbm_put_block_c(matrix=matrix%c_ptr, &
     512              :                            row=row - 1, col=col - 1, &
     513              :                            summation=LOGICAL(my_summation, C_BOOL), &
     514     34053876 :                            block=block)
     515              : 
     516              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     517              :       CALL dbcsr_put_block(matrix%dbcsr, row, col, block, summation=summation)
     518              :       ! Can not call validate(matrix) because the dbcsr matrix needs to be finalized first.
     519              : #endif
     520     34053876 :    END SUBROUTINE dbm_put_block
     521              : 
     522              : ! **************************************************************************************************
     523              : !> \brief Remove all blocks from given matrix, but does not release the underlying memory.
     524              : !> \param matrix ...
     525              : !> \author Ole Schuett
     526              : ! **************************************************************************************************
     527      2048252 :    SUBROUTINE dbm_clear(matrix)
     528              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     529              : 
     530              :       INTERFACE
     531              :          SUBROUTINE dbm_clear_c(matrix) &
     532              :             BIND(C, name="dbm_clear")
     533              :             IMPORT :: C_PTR
     534              :             TYPE(C_PTR), VALUE                               :: matrix
     535              :          END SUBROUTINE dbm_clear_c
     536              :       END INTERFACE
     537              : 
     538      2048252 :       CALL dbm_clear_c(matrix=matrix%c_ptr)
     539              : 
     540              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     541              :       CALL dbcsr_clear(matrix%dbcsr)
     542              :       CALL validate(matrix)
     543              : #endif
     544      2048252 :    END SUBROUTINE dbm_clear
     545              : 
     546              : ! **************************************************************************************************
     547              : !> \brief Removes all blocks from the given matrix whose block norm is below the given threshold.
     548              : !>        Blocks of size zero are always kept.
     549              : !> \param matrix ...
     550              : !> \param eps ...
     551              : !> \author Ole Schuett
     552              : ! **************************************************************************************************
     553       394673 :    SUBROUTINE dbm_filter(matrix, eps)
     554              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     555              :       REAL(dp), INTENT(IN)                               :: eps
     556              : 
     557              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbm_filter'
     558              : 
     559              :       INTEGER                                            :: handle
     560              :       INTERFACE
     561              :          SUBROUTINE dbm_filter_c(matrix, eps) &
     562              :             BIND(C, name="dbm_filter")
     563              :             IMPORT :: C_PTR, C_DOUBLE
     564              :             TYPE(C_PTR), VALUE                        :: matrix
     565              :             REAL(kind=C_DOUBLE), VALUE                :: eps
     566              :          END SUBROUTINE dbm_filter_c
     567              :       END INTERFACE
     568              : 
     569       394673 :       CALL timeset(routineN, handle)
     570              :       CALL validate(matrix)
     571       394673 :       CALL dbm_filter_c(matrix=matrix%c_ptr, eps=eps)
     572              : 
     573              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     574              :       CALL dbcsr_filter(matrix%dbcsr, eps)
     575              :       CALL validate(matrix)
     576              : #endif
     577       394673 :       CALL timestop(handle)
     578       394673 :    END SUBROUTINE dbm_filter
     579              : 
     580              : ! **************************************************************************************************
     581              : !> \brief Adds given list of blocks efficiently. The blocks will be filled with zeros.
     582              : !> \param matrix ...
     583              : !> \param rows ...
     584              : !> \param cols ...
     585              : !> \author Ole Schuett
     586              : ! **************************************************************************************************
     587      1445667 :    SUBROUTINE dbm_reserve_blocks(matrix, rows, cols)
     588              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     589              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: rows, cols
     590              : 
     591              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_reserve_blocks'
     592              : 
     593              :       INTEGER                                            :: handle
     594      2891334 :       INTEGER(kind=C_INT), DIMENSION(SIZE(rows))         :: cols_c, rows_c
     595              :       INTERFACE
     596              :          SUBROUTINE dbm_reserve_blocks_c(matrix, nblocks, rows, cols) &
     597              :             BIND(C, name="dbm_reserve_blocks")
     598              :             IMPORT :: C_PTR, C_INT
     599              :             TYPE(C_PTR), VALUE                        :: matrix
     600              :             INTEGER(kind=C_INT), VALUE                :: nblocks
     601              :             INTEGER(kind=C_INT), DIMENSION(*)         :: rows
     602              :             INTEGER(kind=C_INT), DIMENSION(*)         :: cols
     603              :          END SUBROUTINE dbm_reserve_blocks_c
     604              :       END INTERFACE
     605              : 
     606      1445667 :       CALL timeset(routineN, handle)
     607      1445667 :       CPASSERT(SIZE(rows) == SIZE(cols))
     608     30386751 :       rows_c = rows - 1
     609     30386751 :       cols_c = cols - 1
     610              : 
     611              :       CALL dbm_reserve_blocks_c(matrix=matrix%c_ptr, &
     612              :                                 nblocks=SIZE(rows), &
     613              :                                 rows=rows_c, &
     614      1445667 :                                 cols=cols_c)
     615              : 
     616              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     617              :       CALL dbcsr_reserve_blocks(matrix%dbcsr, rows, cols)
     618              :       CALL validate(matrix)
     619              : #endif
     620      1445667 :       CALL timestop(handle)
     621      1445667 :    END SUBROUTINE dbm_reserve_blocks
     622              : 
     623              : ! **************************************************************************************************
     624              : !> \brief Multiplies all entries in the given matrix by the given factor alpha.
     625              : !> \param matrix ...
     626              : !> \param alpha ...
     627              : !> \author Ole Schuett
     628              : ! **************************************************************************************************
     629       253076 :    SUBROUTINE dbm_scale(matrix, alpha)
     630              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     631              :       REAL(dp), INTENT(IN)                               :: alpha
     632              : 
     633              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbm_scale'
     634              : 
     635              :       INTEGER                                            :: handle
     636              :       INTERFACE
     637              :          SUBROUTINE dbm_scale_c(matrix, alpha) &
     638              :             BIND(C, name="dbm_scale")
     639              :             IMPORT :: C_PTR, C_DOUBLE
     640              :             TYPE(C_PTR), VALUE                              :: matrix
     641              :             REAL(kind=C_DOUBLE), VALUE                      :: alpha
     642              :          END SUBROUTINE dbm_scale_c
     643              :       END INTERFACE
     644              : 
     645       253076 :       CALL timeset(routineN, handle)
     646       253076 :       CALL dbm_scale_c(matrix=matrix%c_ptr, alpha=alpha)
     647              : 
     648              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     649              :       CALL dbcsr_scale(matrix%dbcsr, alpha)
     650              :       CALL validate(matrix)
     651              : #endif
     652       253076 :       CALL timestop(handle)
     653       253076 :    END SUBROUTINE dbm_scale
     654              : 
     655              : ! **************************************************************************************************
     656              : !> \brief Sets all blocks in the given matrix to zero.
     657              : !> \param matrix ...
     658              : !> \author Ole Schuett
     659              : ! **************************************************************************************************
     660            0 :    SUBROUTINE dbm_zero(matrix)
     661              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     662              : 
     663              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbm_zero'
     664              : 
     665              :       INTEGER                                            :: handle
     666              :       INTERFACE
     667              :          SUBROUTINE dbm_zero_c(matrix) &
     668              :             BIND(C, name="dbm_zero")
     669              :             IMPORT :: C_PTR
     670              :             TYPE(C_PTR), VALUE                               :: matrix
     671              :          END SUBROUTINE dbm_zero_c
     672              :       END INTERFACE
     673              : 
     674            0 :       CALL timeset(routineN, handle)
     675            0 :       CALL dbm_zero_c(matrix=matrix%c_ptr)
     676              : 
     677              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     678              :       CALL dbcsr_zero(matrix%dbcsr)
     679              :       CALL validate(matrix)
     680              : #endif
     681            0 :       CALL timestop(handle)
     682            0 :    END SUBROUTINE dbm_zero
     683              : 
     684              : ! **************************************************************************************************
     685              : !> \brief Adds matrix_b to matrix_a.
     686              : !> \param matrix_a ...
     687              : !> \param matrix_b ...
     688              : !> \author Ole Schuett
     689              : ! **************************************************************************************************
     690       213222 :    SUBROUTINE dbm_add(matrix_a, matrix_b)
     691              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix_a
     692              :       TYPE(dbm_type), INTENT(IN)                         :: matrix_b
     693              : 
     694              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbm_add'
     695              : 
     696              :       INTEGER                                            :: handle
     697              :       INTERFACE
     698              :          SUBROUTINE dbm_add_c(matrix_a, matrix_b) &
     699              :             BIND(C, name="dbm_add")
     700              :             IMPORT :: C_PTR, C_DOUBLE
     701              :             TYPE(C_PTR), VALUE                               :: matrix_a
     702              :             TYPE(C_PTR), VALUE                               :: matrix_b
     703              :          END SUBROUTINE dbm_add_c
     704              :       END INTERFACE
     705              : 
     706       213222 :       CALL timeset(routineN, handle)
     707              :       CALL validate(matrix_a)
     708              :       CALL validate(matrix_b)
     709       213222 :       CALL dbm_add_c(matrix_a=matrix_a%c_ptr, matrix_b=matrix_b%c_ptr)
     710              : 
     711              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     712              :       CALL dbcsr_add(matrix_a%dbcsr, matrix_b%dbcsr)
     713              :       CALL validate(matrix_a)
     714              : #endif
     715       213222 :       CALL timestop(handle)
     716       213222 :    END SUBROUTINE dbm_add
     717              : 
     718              : ! **************************************************************************************************
     719              : !> \brief Computes matrix product: matrix_c = alpha * matrix_a * matrix_b + beta * matrix_c.
     720              : !> \param transa ...
     721              : !> \param transb ...
     722              : !> \param alpha ...
     723              : !> \param matrix_a ...
     724              : !> \param matrix_b ...
     725              : !> \param beta ...
     726              : !> \param matrix_c ...
     727              : !> \param retain_sparsity ...
     728              : !> \param filter_eps ...
     729              : !> \param flop ...
     730              : !> \author Ole Schuett
     731              : ! **************************************************************************************************
     732       213252 :    SUBROUTINE dbm_multiply(transa, transb, &
     733              :                            alpha, matrix_a, matrix_b, beta, matrix_c, &
     734              :                            retain_sparsity, filter_eps, flop)
     735              :       LOGICAL, INTENT(IN)                                :: transa, transb
     736              :       REAL(kind=dp), INTENT(IN)                          :: alpha
     737              :       TYPE(dbm_type), INTENT(IN)                         :: matrix_a, matrix_b
     738              :       REAL(kind=dp), INTENT(IN)                          :: beta
     739              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix_c
     740              :       LOGICAL, INTENT(IN), OPTIONAL                      :: retain_sparsity
     741              :       REAL(kind=dp), INTENT(IN), OPTIONAL                :: filter_eps
     742              :       INTEGER(int_8), INTENT(OUT), OPTIONAL              :: flop
     743              : 
     744              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbm_multiply'
     745              : 
     746              :       CHARACTER(LEN=1)                                   :: transa_char, transb_char
     747              :       INTEGER                                            :: handle
     748              :       INTEGER(int_8)                                     :: flop_dbcsr, my_flop
     749              :       LOGICAL                                            :: my_retain_sparsity
     750              :       REAL(kind=dp)                                      :: my_filter_eps
     751              :       INTERFACE
     752              :          SUBROUTINE dbm_multiply_c(transa, transb, alpha, &
     753              :                                    matrix_a, matrix_b, &
     754              :                                    beta, matrix_c, &
     755              :                                    retain_sparsity, filter_eps, flop) &
     756              :             BIND(C, name="dbm_multiply")
     757              :             IMPORT :: C_PTR, C_DOUBLE, C_BOOL, C_INT64_T
     758              :             LOGICAL(kind=C_BOOL), VALUE                      :: transa
     759              :             LOGICAL(kind=C_BOOL), VALUE                      :: transb
     760              :             REAL(kind=C_DOUBLE), VALUE                       :: alpha
     761              :             TYPE(C_PTR), VALUE                               :: matrix_a
     762              :             TYPE(C_PTR), VALUE                               :: matrix_b
     763              :             REAL(kind=C_DOUBLE), VALUE                       :: beta
     764              :             TYPE(C_PTR), VALUE                               :: matrix_c
     765              :             LOGICAL(kind=C_BOOL), VALUE                      :: retain_sparsity
     766              :             REAL(kind=C_DOUBLE), VALUE                       :: filter_eps
     767              :             INTEGER(kind=C_INT64_T)                          :: flop
     768              :          END SUBROUTINE dbm_multiply_c
     769              :       END INTERFACE
     770              : 
     771       213252 :       CALL timeset(routineN, handle)
     772              : 
     773       213252 :       IF (PRESENT(retain_sparsity)) THEN
     774         4824 :          my_retain_sparsity = retain_sparsity
     775              :       ELSE
     776              :          my_retain_sparsity = .FALSE.
     777              :       END IF
     778              : 
     779       213252 :       IF (PRESENT(filter_eps)) THEN
     780       213226 :          my_filter_eps = filter_eps
     781              :       ELSE
     782              :          my_filter_eps = 0.0_dp
     783              :       END IF
     784              : 
     785              :       CALL validate(matrix_a)
     786              :       CALL validate(matrix_b)
     787              :       CALL validate(matrix_c)
     788              :       CALL dbm_multiply_c(transa=LOGICAL(transa, C_BOOL), &
     789              :                           transb=LOGICAL(transb, C_BOOL), &
     790              :                           alpha=alpha, &
     791              :                           matrix_a=matrix_a%c_ptr, &
     792              :                           matrix_b=matrix_b%c_ptr, &
     793              :                           beta=beta, &
     794              :                           matrix_c=matrix_c%c_ptr, &
     795              :                           retain_sparsity=LOGICAL(my_retain_sparsity, C_BOOL), &
     796              :                           filter_eps=my_filter_eps, &
     797       213252 :                           flop=my_flop)
     798              : 
     799       213252 :       IF (PRESENT(flop)) THEN
     800       119123 :          flop = my_flop
     801              :       END IF
     802              : 
     803              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     804              :       IF (transa) THEN
     805              :          transa_char = dbcsr_transpose
     806              :       ELSE
     807              :          transa_char = dbcsr_no_transpose
     808              :       END IF
     809              :       IF (transb) THEN
     810              :          transb_char = dbcsr_transpose
     811              :       ELSE
     812              :          transb_char = dbcsr_no_transpose
     813              :       END IF
     814              :       CALL dbcsr_multiply(transa=transa_char, transb=transb_char, &
     815              :                           alpha=alpha, matrix_a=matrix_a%dbcsr, &
     816              :                           matrix_b=matrix_b%dbcsr, beta=beta, matrix_c=matrix_c%dbcsr, &
     817              :                           retain_sparsity=retain_sparsity, filter_eps=filter_eps, flop=flop_dbcsr)
     818              :       CPASSERT(my_flop == flop_dbcsr)
     819              :       CALL validate(matrix_c)
     820              : #else
     821              :       ! Can not use preprocessor's ifdefs before INTERFACE because it confuses prettify.
     822              :       MARK_USED(transa_char)
     823              :       MARK_USED(transb_char)
     824              :       MARK_USED(flop_dbcsr)
     825              : #endif
     826       213252 :       CALL timestop(handle)
     827       213252 :    END SUBROUTINE dbm_multiply
     828              : 
     829              : ! **************************************************************************************************
     830              : !> \brief Creates an iterator for the blocks of the given matrix. The iteration order is not stable.
     831              : !> \param iterator ...
     832              : !> \param matrix ...
     833              : !> \author Ole Schuett
     834              : ! **************************************************************************************************
     835      3385070 :    SUBROUTINE dbm_iterator_start(iterator, matrix)
     836              :       TYPE(dbm_iterator), INTENT(OUT)                    :: iterator
     837              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
     838              : 
     839              :       INTERFACE
     840              :          SUBROUTINE dbm_iterator_start_c(iterator, matrix) &
     841              :             BIND(C, name="dbm_iterator_start")
     842              :             IMPORT :: C_PTR
     843              :             TYPE(C_PTR)                               :: iterator
     844              :             TYPE(C_PTR), VALUE                        :: matrix
     845              :          END SUBROUTINE dbm_iterator_start_c
     846              :       END INTERFACE
     847              : 
     848              :       CPASSERT(.NOT. C_ASSOCIATED(iterator%c_ptr))
     849      3385070 :       CALL dbm_iterator_start_c(iterator=iterator%c_ptr, matrix=matrix%c_ptr)
     850      3385070 :       CPASSERT(C_ASSOCIATED(iterator%c_ptr))
     851              :       CALL validate(matrix)
     852      3385070 :    END SUBROUTINE dbm_iterator_start
     853              : 
     854              : ! **************************************************************************************************
     855              : !> \brief Returns number of blocks the iterator will provide to calling thread.
     856              : !> \param iterator ...
     857              : !> \return ...
     858              : !> \author Ole Schuett
     859              : ! **************************************************************************************************
     860       639233 :    FUNCTION dbm_iterator_num_blocks(iterator) RESULT(num_blocks)
     861              :       TYPE(dbm_iterator), INTENT(IN)                     :: iterator
     862              :       INTEGER                                            :: num_blocks
     863              : 
     864              :       INTERFACE
     865              :          FUNCTION dbm_iterator_num_blocks_c(iterator) &
     866              :             BIND(C, name="dbm_iterator_num_blocks")
     867              :             IMPORT :: C_PTR, C_INT
     868              :             TYPE(C_PTR), VALUE                        :: iterator
     869              :             INTEGER(kind=C_INT)                       :: dbm_iterator_num_blocks_c
     870              :          END FUNCTION dbm_iterator_num_blocks_c
     871              :       END INTERFACE
     872              : 
     873       639233 :       num_blocks = dbm_iterator_num_blocks_c(iterator%c_ptr)
     874       639233 :    END FUNCTION dbm_iterator_num_blocks
     875              : 
     876              : ! **************************************************************************************************
     877              : !> \brief Tests whether the given iterator has any block left.
     878              : !> \param iterator ...
     879              : !> \return ...
     880              : !> \author Ole Schuett
     881              : ! **************************************************************************************************
     882     59763668 :    FUNCTION dbm_iterator_blocks_left(iterator) RESULT(blocks_left)
     883              :       TYPE(dbm_iterator), INTENT(IN)                     :: iterator
     884              :       LOGICAL                                            :: blocks_left
     885              : 
     886              :       INTERFACE
     887              :          FUNCTION dbm_iterator_blocks_left_c(iterator) &
     888              :             BIND(C, name="dbm_iterator_blocks_left")
     889              :             IMPORT :: C_PTR, C_BOOL
     890              :             TYPE(C_PTR), VALUE                        :: iterator
     891              :             LOGICAL(C_BOOL)                           :: dbm_iterator_blocks_left_c
     892              :          END FUNCTION dbm_iterator_blocks_left_c
     893              :       END INTERFACE
     894              : 
     895     59763668 :       blocks_left = dbm_iterator_blocks_left_c(iterator%c_ptr)
     896     59763668 :    END FUNCTION dbm_iterator_blocks_left
     897              : 
     898              : ! **************************************************************************************************
     899              : !> \brief Returns the next block from the given iterator.
     900              : !> \param iterator ...
     901              : !> \param row ...
     902              : !> \param column ...
     903              : !> \param block ...
     904              : !> \param row_size ...
     905              : !> \param col_size ...
     906              : !> \author Ole Schuett
     907              : ! **************************************************************************************************
     908     66410153 :    SUBROUTINE dbm_iterator_next_block(iterator, row, column, block, row_size, col_size)
     909              :       TYPE(dbm_iterator), INTENT(INOUT)                  :: iterator
     910              :       INTEGER, INTENT(OUT)                               :: row, column
     911              :       REAL(dp), DIMENSION(:, :), INTENT(OUT), OPTIONAL, &
     912              :          POINTER                                         :: block
     913              :       INTEGER, INTENT(OUT), OPTIONAL                     :: row_size, col_size
     914              : 
     915              :       INTEGER                                            :: col0, my_col_size, my_row_size, row0
     916              :       TYPE(C_PTR)                                        :: block_c
     917              :       INTERFACE
     918              :          SUBROUTINE dbm_iterator_next_block_c(iterator, row, col, block, row_size, col_size) &
     919              :             BIND(C, name="dbm_iterator_next_block")
     920              :             IMPORT :: C_PTR, C_INT
     921              :             TYPE(C_PTR), VALUE                        :: iterator
     922              :             INTEGER(kind=C_INT)                       :: row
     923              :             INTEGER(kind=C_INT)                       :: col
     924              :             TYPE(C_PTR)                               :: block
     925              :             INTEGER(kind=C_INT)                       :: row_size
     926              :             INTEGER(kind=C_INT)                       :: col_size
     927              :          END SUBROUTINE dbm_iterator_next_block_c
     928              :       END INTERFACE
     929              : 
     930              :       CALL dbm_iterator_next_block_c(iterator%c_ptr, row=row0, col=col0, block=block_c, &
     931     66410153 :                                      row_size=my_row_size, col_size=my_col_size)
     932              : 
     933     66410153 :       CPASSERT(C_ASSOCIATED(block_c))
     934     95173641 :       IF (PRESENT(block)) CALL C_F_POINTER(block_c, block, shape=[my_row_size, my_col_size])
     935     66410153 :       row = row0 + 1
     936     66410153 :       column = col0 + 1
     937     66410153 :       IF (PRESENT(row_size)) row_size = my_row_size
     938     66410153 :       IF (PRESENT(col_size)) col_size = my_col_size
     939     66410153 :    END SUBROUTINE dbm_iterator_next_block
     940              : 
     941              : ! **************************************************************************************************
     942              : !> \brief Releases the given iterator.
     943              : !> \param iterator ...
     944              : !> \author Ole Schuett
     945              : ! **************************************************************************************************
     946      3385070 :    SUBROUTINE dbm_iterator_stop(iterator)
     947              :       TYPE(dbm_iterator), INTENT(INOUT)                  :: iterator
     948              : 
     949              :       INTERFACE
     950              :          SUBROUTINE dbm_iterator_stop_c(iterator) &
     951              :             BIND(C, name="dbm_iterator_stop")
     952              :             IMPORT :: C_PTR
     953              :             TYPE(C_PTR), VALUE                        :: iterator
     954              :          END SUBROUTINE dbm_iterator_stop_c
     955              :       END INTERFACE
     956              : 
     957      3385070 :       CALL dbm_iterator_stop_c(iterator%c_ptr)
     958      3385070 :       iterator%c_ptr = C_NULL_PTR
     959      3385070 :    END SUBROUTINE dbm_iterator_stop
     960              : 
     961              : ! **************************************************************************************************
     962              : !> \brief Computes a checksum of the given matrix.
     963              : !> \param matrix ...
     964              : !> \return ...
     965              : !> \author Ole Schuett
     966              : ! **************************************************************************************************
     967          190 :    FUNCTION dbm_checksum(matrix) RESULT(res)
     968              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
     969              :       REAL(KIND=dp)                                      :: res
     970              : 
     971              :       INTERFACE
     972              :          FUNCTION dbm_checksum_c(matrix) &
     973              :             BIND(C, name="dbm_checksum")
     974              :             IMPORT :: C_PTR, C_DOUBLE
     975              :             TYPE(C_PTR), VALUE                        :: matrix
     976              :             REAL(C_DOUBLE)                            :: dbm_checksum_c
     977              :          END FUNCTION dbm_checksum_c
     978              :       END INTERFACE
     979              : 
     980              :       CALL validate(matrix)
     981          190 :       res = dbm_checksum_c(matrix%c_ptr)
     982              : 
     983              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
     984              :       CPASSERT(ABS(res - dbcsr_checksum(matrix%dbcsr))/MAX(1.0_dp, ABS(res)) < DBM_VALIDATE_THRESHOLD)
     985              : #endif
     986          190 :    END FUNCTION dbm_checksum
     987              : 
     988              : ! **************************************************************************************************
     989              : !> \brief Returns the absolute value of the larges element of the entire given matrix.
     990              : !> \param matrix ...
     991              : !> \return ...
     992              : !> \author Ole Schuett
     993              : ! **************************************************************************************************
     994           48 :    FUNCTION dbm_maxabs(matrix) RESULT(res)
     995              :       TYPE(dbm_type), INTENT(INOUT)                      :: matrix
     996              :       REAL(KIND=dp)                                      :: res
     997              : 
     998              :       INTERFACE
     999              :          FUNCTION dbm_maxabs_c(matrix) &
    1000              :             BIND(C, name="dbm_maxabs")
    1001              :             IMPORT :: C_PTR, C_DOUBLE
    1002              :             TYPE(C_PTR), VALUE                        :: matrix
    1003              :             REAL(C_DOUBLE)                            :: dbm_maxabs_c
    1004              :          END FUNCTION dbm_maxabs_c
    1005              :       END INTERFACE
    1006              : 
    1007              :       CALL validate(matrix)
    1008           48 :       res = dbm_maxabs_c(matrix%c_ptr)
    1009              : 
    1010              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1011              :       CPASSERT(ABS(res - dbcsr_maxabs(matrix%dbcsr))/MAX(1.0_dp, ABS(res)) < DBM_VALIDATE_THRESHOLD)
    1012              : #endif
    1013           48 :    END FUNCTION dbm_maxabs
    1014              : 
    1015              : ! **************************************************************************************************
    1016              : !> \brief Returns the name of the matrix of the given matrix.
    1017              : !> \param matrix ...
    1018              : !> \return ...
    1019              : !> \author Ole Schuett
    1020              : ! **************************************************************************************************
    1021      1787429 :    FUNCTION dbm_get_name(matrix) RESULT(res)
    1022              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1023              :       CHARACTER(len=default_string_length)               :: res
    1024              : 
    1025              :       CHARACTER(LEN=1, KIND=C_CHAR), DIMENSION(:), &
    1026      1787429 :          POINTER                                         :: name_f
    1027              :       INTEGER                                            :: i
    1028              :       TYPE(C_PTR)                                        :: name_c
    1029              :       INTERFACE
    1030              :          FUNCTION dbm_get_name_c(matrix) BIND(C, name="dbm_get_name")
    1031              :             IMPORT :: C_PTR
    1032              :             TYPE(C_PTR), VALUE                        :: matrix
    1033              :             TYPE(C_PTR)                               :: dbm_get_name_c
    1034              :          END FUNCTION dbm_get_name_c
    1035              :       END INTERFACE
    1036              : 
    1037      1787429 :       name_c = dbm_get_name_c(matrix%c_ptr)
    1038              : 
    1039      3574858 :       CALL C_F_POINTER(name_c, name_f, shape=[default_string_length])
    1040              : 
    1041      1787429 :       res = ""
    1042     36873639 :       DO i = 1, default_string_length
    1043     36873639 :          IF (name_f(i) == C_NULL_CHAR) EXIT
    1044     36873639 :          res(i:i) = name_f(i)
    1045              :       END DO
    1046              : 
    1047      1787429 :    END FUNCTION dbm_get_name
    1048              : 
    1049              : ! **************************************************************************************************
    1050              : !> \brief Returns the number of local Non-Zero Elements of the given matrix.
    1051              : !> \param matrix ...
    1052              : !> \return ...
    1053              : !> \author Ole Schuett
    1054              : ! **************************************************************************************************
    1055      1885694 :    PURE FUNCTION dbm_get_nze(matrix) RESULT(res)
    1056              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1057              :       INTEGER                                            :: res
    1058              : 
    1059              :       INTERFACE
    1060              :          PURE FUNCTION dbm_get_nze_c(matrix) &
    1061              :             BIND(C, name="dbm_get_nze")
    1062              :             IMPORT :: C_PTR, C_INT
    1063              :             TYPE(C_PTR), VALUE, INTENT(IN)            :: matrix
    1064              :             INTEGER(C_INT)                            :: dbm_get_nze_c
    1065              :          END FUNCTION dbm_get_nze_c
    1066              :       END INTERFACE
    1067              : 
    1068      1885694 :       res = dbm_get_nze_c(matrix%c_ptr)
    1069              : 
    1070      1885694 :    END FUNCTION dbm_get_nze
    1071              : 
    1072              : ! **************************************************************************************************
    1073              : !> \brief Returns the number of local blocks of the given matrix.
    1074              : !> \param matrix ...
    1075              : !> \return ...
    1076              : !> \author Ole Schuett
    1077              : ! **************************************************************************************************
    1078      1029546 :    PURE FUNCTION dbm_get_num_blocks(matrix) RESULT(res)
    1079              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1080              :       INTEGER                                            :: res
    1081              : 
    1082              :       INTERFACE
    1083              :          PURE FUNCTION dbm_get_num_blocks_c(matrix) &
    1084              :             BIND(C, name="dbm_get_num_blocks")
    1085              :             IMPORT :: C_PTR, C_INT
    1086              :             TYPE(C_PTR), VALUE, INTENT(IN)            :: matrix
    1087              :             INTEGER(C_INT)                            :: dbm_get_num_blocks_c
    1088              :          END FUNCTION dbm_get_num_blocks_c
    1089              :       END INTERFACE
    1090              : 
    1091      1029546 :       res = dbm_get_num_blocks_c(matrix%c_ptr)
    1092              : 
    1093      1029546 :    END FUNCTION dbm_get_num_blocks
    1094              : 
    1095              : ! **************************************************************************************************
    1096              : !> \brief Returns the row block sizes of the given matrix.
    1097              : !> \param matrix ...
    1098              : !> \return ...
    1099              : !> \author Ole Schuett
    1100              : ! **************************************************************************************************
    1101      3883139 :    FUNCTION dbm_get_row_block_sizes(matrix) RESULT(res)
    1102              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1103              :       INTEGER, CONTIGUOUS, DIMENSION(:), POINTER         :: res
    1104              : 
    1105              :       INTEGER                                            :: nrows
    1106              :       TYPE(C_PTR)                                        :: row_sizes
    1107              :       INTERFACE
    1108              :          SUBROUTINE dbm_get_row_sizes_c(matrix, nrows, row_sizes) &
    1109              :             BIND(C, name="dbm_get_row_sizes")
    1110              :             IMPORT :: C_PTR, C_INT
    1111              :             TYPE(C_PTR), VALUE                        :: matrix
    1112              :             INTEGER(C_INT)                            :: nrows
    1113              :             TYPE(C_PTR)                               :: row_sizes
    1114              :          END SUBROUTINE dbm_get_row_sizes_c
    1115              :       END INTERFACE
    1116              : 
    1117      3883139 :       CALL dbm_get_row_sizes_c(matrix%c_ptr, nrows, row_sizes)
    1118      7766278 :       CALL C_F_POINTER(row_sizes, res, shape=[nrows])
    1119              :       ! TODO: maybe return an ALLOCATABLE
    1120      3883139 :    END FUNCTION dbm_get_row_block_sizes
    1121              : 
    1122              : ! **************************************************************************************************
    1123              : !> \brief Returns the column block sizes of the given matrix.
    1124              : !> \param matrix ...
    1125              : !> \return ...
    1126              : !> \author Ole Schuett
    1127              : ! **************************************************************************************************
    1128      2643885 :    FUNCTION dbm_get_col_block_sizes(matrix) RESULT(res)
    1129              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1130              :       INTEGER, CONTIGUOUS, DIMENSION(:), POINTER         :: res
    1131              : 
    1132              :       INTEGER                                            :: ncols
    1133              :       TYPE(C_PTR)                                        :: col_sizes
    1134              :       INTERFACE
    1135              :          SUBROUTINE dbm_get_col_sizes_c(matrix, ncols, col_sizes) &
    1136              :             BIND(C, name="dbm_get_col_sizes")
    1137              :             IMPORT :: C_PTR, C_INT
    1138              :             TYPE(C_PTR), VALUE                        :: matrix
    1139              :             INTEGER(C_INT)                            :: ncols
    1140              :             TYPE(C_PTR)                               :: col_sizes
    1141              :          END SUBROUTINE dbm_get_col_sizes_c
    1142              :       END INTERFACE
    1143              : 
    1144      2643885 :       CALL dbm_get_col_sizes_c(matrix%c_ptr, ncols, col_sizes)
    1145      5287770 :       CALL C_F_POINTER(col_sizes, res, shape=[ncols])
    1146              :       ! TODO: maybe return an ALLOCATABLE
    1147      2643885 :    END FUNCTION dbm_get_col_block_sizes
    1148              : 
    1149              : ! **************************************************************************************************
    1150              : !> \brief Returns the local row block sizes of the given matrix.
    1151              : !> \param matrix ...
    1152              : !> \param local_rows ...
    1153              : !> \return ...
    1154              : !> \author Ole Schuett
    1155              : ! **************************************************************************************************
    1156       271476 :    SUBROUTINE dbm_get_local_rows(matrix, local_rows)
    1157              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1158              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: local_rows
    1159              : 
    1160              :       INTEGER                                            :: nlocal_rows
    1161       271476 :       INTEGER, DIMENSION(:), POINTER                     :: local_rows_dbcsr, local_rows_ptr
    1162              :       TYPE(C_PTR)                                        :: local_rows_c
    1163              :       INTERFACE
    1164              :          SUBROUTINE dbm_get_local_rows_c(matrix, nlocal_rows, local_rows) &
    1165              :             BIND(C, name="dbm_get_local_rows")
    1166              :             IMPORT :: C_PTR, C_INT
    1167              :             TYPE(C_PTR), VALUE                        :: matrix
    1168              :             INTEGER(C_INT)                            :: nlocal_rows
    1169              :             TYPE(C_PTR)                               :: local_rows
    1170              :          END SUBROUTINE dbm_get_local_rows_c
    1171              :       END INTERFACE
    1172              : 
    1173       271476 :       CALL dbm_get_local_rows_c(matrix%c_ptr, nlocal_rows, local_rows_c)
    1174       542952 :       CALL C_F_POINTER(local_rows_c, local_rows_ptr, shape=[nlocal_rows])
    1175       814404 :       ALLOCATE (local_rows(nlocal_rows))
    1176      3731798 :       local_rows(:) = local_rows_ptr(:) + 1
    1177              : 
    1178              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1179              :       CALL dbcsr_get_info(matrix%dbcsr, local_rows=local_rows_dbcsr)
    1180              :       CPASSERT(ALL(local_rows == local_rows_dbcsr))
    1181              : #else
    1182              :       MARK_USED(local_rows_dbcsr)
    1183              : #endif
    1184       271476 :    END SUBROUTINE dbm_get_local_rows
    1185              : 
    1186              : ! **************************************************************************************************
    1187              : !> \brief Returns the local column block sizes of the given matrix.
    1188              : !> \param matrix ...
    1189              : !> \param local_cols ...
    1190              : !> \return ...
    1191              : !> \author Ole Schuett
    1192              : ! **************************************************************************************************
    1193       125400 :    SUBROUTINE dbm_get_local_cols(matrix, local_cols)
    1194              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1195              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: local_cols
    1196              : 
    1197              :       INTEGER                                            :: nlocal_cols
    1198       125400 :       INTEGER, DIMENSION(:), POINTER                     :: local_cols_dbcsr, local_cols_ptr
    1199              :       TYPE(C_PTR)                                        :: local_cols_c
    1200              :       INTERFACE
    1201              :          SUBROUTINE dbm_get_local_cols_c(matrix, nlocal_cols, local_cols) &
    1202              :             BIND(C, name="dbm_get_local_cols")
    1203              :             IMPORT :: C_PTR, C_INT
    1204              :             TYPE(C_PTR), VALUE                        :: matrix
    1205              :             INTEGER(C_INT)                            :: nlocal_cols
    1206              :             TYPE(C_PTR)                               :: local_cols
    1207              :          END SUBROUTINE dbm_get_local_cols_c
    1208              :       END INTERFACE
    1209              : 
    1210       125400 :       CALL dbm_get_local_cols_c(matrix%c_ptr, nlocal_cols, local_cols_c)
    1211       250800 :       CALL C_F_POINTER(local_cols_c, local_cols_ptr, shape=[nlocal_cols])
    1212       373036 :       ALLOCATE (local_cols(nlocal_cols))
    1213     29273790 :       local_cols(:) = local_cols_ptr(:) + 1
    1214              : 
    1215              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1216              :       CALL dbcsr_get_info(matrix%dbcsr, local_cols=local_cols_dbcsr)
    1217              :       CPASSERT(ALL(local_cols == local_cols_dbcsr))
    1218              : #else
    1219              :       MARK_USED(local_cols_dbcsr)
    1220              : #endif
    1221       125400 :    END SUBROUTINE dbm_get_local_cols
    1222              : 
    1223              : ! **************************************************************************************************
    1224              : !> \brief Returns the MPI rank on which the given block should be stored.
    1225              : !> \param matrix ...
    1226              : !> \param row ...
    1227              : !> \param column ...
    1228              : !> \param processor ...
    1229              : !> \author Ole Schuett
    1230              : ! **************************************************************************************************
    1231      2610178 :    SUBROUTINE dbm_get_stored_coordinates(matrix, row, column, processor)
    1232              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1233              :       INTEGER, INTENT(IN)                                :: row, column
    1234              :       INTEGER, INTENT(OUT)                               :: processor
    1235              : 
    1236              :       INTEGER                                            :: processor_dbcsr
    1237              :       INTERFACE
    1238              :          PURE FUNCTION dbm_get_stored_coordinates_c(matrix, row, col) &
    1239              :             BIND(C, name="dbm_get_stored_coordinates")
    1240              :             IMPORT :: C_PTR, C_INT
    1241              :             TYPE(C_PTR), VALUE, INTENT(IN)            :: matrix
    1242              :             INTEGER(C_INT), VALUE, INTENT(IN)         :: row
    1243              :             INTEGER(C_INT), VALUE, INTENT(IN)         :: col
    1244              :             INTEGER(C_INT)                            :: dbm_get_stored_coordinates_c
    1245              :          END FUNCTION dbm_get_stored_coordinates_c
    1246              :       END INTERFACE
    1247              : 
    1248      2610178 :       processor = dbm_get_stored_coordinates_c(matrix%c_ptr, row=row - 1, col=column - 1)
    1249              : 
    1250              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1251              :       CALL dbcsr_get_stored_coordinates(matrix%dbcsr, row, column, processor_dbcsr)
    1252              :       CPASSERT(processor == processor_dbcsr)
    1253              : #else
    1254              :       MARK_USED(processor_dbcsr)
    1255              : #endif
    1256      2610178 :    END SUBROUTINE dbm_get_stored_coordinates
    1257              : 
    1258              : ! **************************************************************************************************
    1259              : !> \brief Returns the distribution of the given matrix.
    1260              : !> \param matrix ...
    1261              : !> \return ...
    1262              : !> \author Ole Schuett
    1263              : ! **************************************************************************************************
    1264      1270981 :    FUNCTION dbm_get_distribution(matrix) RESULT(res)
    1265              :       TYPE(dbm_type), INTENT(IN)                         :: matrix
    1266              :       TYPE(dbm_distribution_obj)                         :: res
    1267              : 
    1268              :       INTERFACE
    1269              :          FUNCTION dbm_get_distribution_c(matrix) BIND(C, name="dbm_get_distribution")
    1270              :             IMPORT :: C_PTR
    1271              :             TYPE(C_PTR), VALUE                        :: matrix
    1272              :             TYPE(C_PTR)                               :: dbm_get_distribution_c
    1273              :          END FUNCTION dbm_get_distribution_c
    1274              :       END INTERFACE
    1275              : 
    1276      2541962 :       res%c_ptr = dbm_get_distribution_c(matrix%c_ptr)
    1277              : 
    1278              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1279              :       CALL dbcsr_get_info(matrix%dbcsr, distribution=res%dbcsr)
    1280              : #endif
    1281              : 
    1282      1270981 :    END FUNCTION dbm_get_distribution
    1283              : 
    1284              : ! **************************************************************************************************
    1285              : !> \brief Creates a new two dimensional distribution.
    1286              : !> \param dist ...
    1287              : !> \param mp_comm ...
    1288              : !> \param row_dist_block ...
    1289              : !> \param col_dist_block ...
    1290              : !> \author Ole Schuett
    1291              : ! **************************************************************************************************
    1292       831384 :    SUBROUTINE dbm_distribution_new(dist, mp_comm, row_dist_block, col_dist_block)
    1293              :       TYPE(dbm_distribution_obj), INTENT(OUT)            :: dist
    1294              : 
    1295              :       CLASS(mp_comm_type), INTENT(IN)                     :: mp_comm
    1296              :       INTEGER, CONTIGUOUS, DIMENSION(:), INTENT(IN), &
    1297              :          POINTER                                         :: row_dist_block, col_dist_block
    1298              : 
    1299              :       INTERFACE
    1300              :          SUBROUTINE dbm_distribution_new_c(dist, fortran_comm, nrows, ncols, row_dist, col_dist) &
    1301              :             BIND(C, name="dbm_distribution_new")
    1302              :             IMPORT :: C_PTR, C_CHAR, C_INT
    1303              :             TYPE(C_PTR)                               :: dist
    1304              :             INTEGER(kind=C_INT), VALUE                :: fortran_comm
    1305              :             INTEGER(kind=C_INT), VALUE                :: nrows
    1306              :             INTEGER(kind=C_INT), VALUE                :: ncols
    1307              :             INTEGER(kind=C_INT), DIMENSION(*)         :: row_dist
    1308              :             INTEGER(kind=C_INT), DIMENSION(*)         :: col_dist
    1309              :          END SUBROUTINE dbm_distribution_new_c
    1310              :       END INTERFACE
    1311              : 
    1312              :       CPASSERT(.NOT. C_ASSOCIATED(dist%c_ptr))
    1313              :       CALL dbm_distribution_new_c(dist=dist%c_ptr, &
    1314              :                                   fortran_comm=mp_comm%get_handle(), &
    1315              :                                   nrows=SIZE(row_dist_block), &
    1316              :                                   ncols=SIZE(col_dist_block), &
    1317              :                                   row_dist=row_dist_block, &
    1318       831384 :                                   col_dist=col_dist_block)
    1319       831384 :       CPASSERT(C_ASSOCIATED(dist%c_ptr))
    1320              : 
    1321              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1322              :       CALL dbcsr_distribution_new_wrapper(dist, mp_comm, row_dist_block, col_dist_block)
    1323              : #endif
    1324       831384 :    END SUBROUTINE dbm_distribution_new
    1325              : 
    1326              : ! **************************************************************************************************
    1327              : !> \brief Helper for creating a new DBCSR distribution. Only needed for DBM_VALIDATE_AGAINST_DBCSR.
    1328              : !> \param dist ...
    1329              : !> \param mp_comm ...
    1330              : !> \param row_dist_block ...
    1331              : !> \param col_dist_block ...
    1332              : !> \author Ole Schuett
    1333              : ! **************************************************************************************************
    1334            0 :    SUBROUTINE dbcsr_distribution_new_wrapper(dist, mp_comm, row_dist_block, col_dist_block)
    1335              :       TYPE(dbm_distribution_obj), INTENT(INOUT)          :: dist
    1336              :       TYPE(mp_cart_type), INTENT(IN)                     :: mp_comm
    1337              :       INTEGER, CONTIGUOUS, DIMENSION(:), INTENT(IN), &
    1338              :          POINTER                                         :: row_dist_block, col_dist_block
    1339              : 
    1340              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1341              :       INTEGER                                            :: mynode, numnodes, pcol, prow
    1342              :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: pgrid
    1343              :       INTEGER, DIMENSION(2)                              :: coord, mycoord, npdims
    1344              :       TYPE(dbcsr_mp_obj)                                 :: mp_env
    1345              : 
    1346              :       ! Create a dbcsr mp environment from communicator
    1347              :       CALL mp_comm%get_info_cart(npdims, mycoord)
    1348              :       CALL mp_comm%get_size(numnodes)
    1349              :       CALL mp_comm%get_rank(mynode)
    1350              :       ALLOCATE (pgrid(0:npdims(1) - 1, 0:npdims(2) - 1))
    1351              :       DO prow = 0, npdims(1) - 1
    1352              :          DO pcol = 0, npdims(2) - 1
    1353              :             coord = [prow, pcol]
    1354              :             CALL mp_comm%rank_cart(coord, pgrid(prow, pcol))
    1355              :          END DO
    1356              :       END DO
    1357              :       CPASSERT(mynode == pgrid(mycoord(1), mycoord(2)))
    1358              : 
    1359              :       CALL dbcsr_mp_new(mp_env, mp_comm%get_handle(), pgrid, mynode, numnodes, mycoord(1), mycoord(2))
    1360              :       CALL dbcsr_distribution_new(dist=dist%dbcsr, mp_env=mp_env, &
    1361              :                                   row_dist_block=row_dist_block, col_dist_block=col_dist_block)
    1362              :       CALL dbcsr_mp_release(mp_env)
    1363              : #else
    1364              :       MARK_USED(dist)
    1365              :       MARK_USED(mp_comm)
    1366              :       MARK_USED(row_dist_block)
    1367              :       MARK_USED(col_dist_block)
    1368              : #endif
    1369            0 :    END SUBROUTINE dbcsr_distribution_new_wrapper
    1370              : 
    1371              : ! **************************************************************************************************
    1372              : !> \brief Increases the reference counter of the given distribution.
    1373              : !> \param dist ...
    1374              : !> \author Ole Schuett
    1375              : ! **************************************************************************************************
    1376       691890 :    SUBROUTINE dbm_distribution_hold(dist)
    1377              :       TYPE(dbm_distribution_obj)                         :: dist
    1378              : 
    1379              :       INTERFACE
    1380              :          SUBROUTINE dbm_distribution_hold_c(dist) &
    1381              :             BIND(C, name="dbm_distribution_hold")
    1382              :             IMPORT :: C_PTR
    1383              :             TYPE(C_PTR), VALUE                        :: dist
    1384              :          END SUBROUTINE dbm_distribution_hold_c
    1385              :       END INTERFACE
    1386              : 
    1387       691890 :       CALL dbm_distribution_hold_c(dist%c_ptr)
    1388              : 
    1389              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1390              :       CALL dbcsr_distribution_hold(dist%dbcsr)
    1391              : #endif
    1392       691890 :    END SUBROUTINE dbm_distribution_hold
    1393              : 
    1394              : ! **************************************************************************************************
    1395              : !> \brief Decreases the reference counter of the given distribution.
    1396              : !> \param dist ...
    1397              : !> \author Ole Schuett
    1398              : ! **************************************************************************************************
    1399      1523274 :    SUBROUTINE dbm_distribution_release(dist)
    1400              :       TYPE(dbm_distribution_obj)                         :: dist
    1401              : 
    1402              :       INTERFACE
    1403              :          SUBROUTINE dbm_distribution_release_c(dist) &
    1404              :             BIND(C, name="dbm_distribution_release")
    1405              :             IMPORT :: C_PTR
    1406              :             TYPE(C_PTR), VALUE                        :: dist
    1407              :          END SUBROUTINE dbm_distribution_release_c
    1408              :       END INTERFACE
    1409              : 
    1410      1523274 :       CALL dbm_distribution_release_c(dist%c_ptr)
    1411              : 
    1412              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1413              :       CALL dbcsr_distribution_release(dist%dbcsr)
    1414              : #endif
    1415      1523274 :    END SUBROUTINE dbm_distribution_release
    1416              : 
    1417              : ! **************************************************************************************************
    1418              : !> \brief Returns the rows of the given distribution.
    1419              : !> \param dist ...
    1420              : !> \return ...
    1421              : !> \author Ole Schuett
    1422              : ! **************************************************************************************************
    1423       339146 :    FUNCTION dbm_distribution_row_dist(dist) RESULT(res)
    1424              :       TYPE(dbm_distribution_obj), INTENT(IN)             :: dist
    1425              :       INTEGER, CONTIGUOUS, DIMENSION(:), POINTER         :: res
    1426              : 
    1427              :       INTEGER                                            :: nrows
    1428              :       TYPE(C_PTR)                                        :: row_dist
    1429              :       INTERFACE
    1430              :          SUBROUTINE dbm_distribution_row_dist_c(dist, nrows, row_dist) &
    1431              :             BIND(C, name="dbm_distribution_row_dist")
    1432              :             IMPORT :: C_PTR, C_INT
    1433              :             TYPE(C_PTR), VALUE                        :: dist
    1434              :             INTEGER(C_INT)                            :: nrows
    1435              :             TYPE(C_PTR)                               :: row_dist
    1436              :          END SUBROUTINE dbm_distribution_row_dist_c
    1437              :       END INTERFACE
    1438              : 
    1439       339146 :       CALL dbm_distribution_row_dist_c(dist%c_ptr, nrows, row_dist)
    1440       678292 :       CALL C_F_POINTER(row_dist, res, shape=[nrows])
    1441              : 
    1442              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1443              :       CPASSERT(ALL(res == dbcsr_distribution_row_dist(dist%dbcsr)))
    1444              : #endif
    1445       339146 :    END FUNCTION dbm_distribution_row_dist
    1446              : 
    1447              : ! **************************************************************************************************
    1448              : !> \brief Returns the columns of the given distribution.
    1449              : !> \param dist ...
    1450              : !> \return ...
    1451              : !> \author Ole Schuett
    1452              : ! **************************************************************************************************
    1453       339146 :    FUNCTION dbm_distribution_col_dist(dist) RESULT(res)
    1454              :       TYPE(dbm_distribution_obj), INTENT(IN)             :: dist
    1455              :       INTEGER, CONTIGUOUS, DIMENSION(:), POINTER         :: res
    1456              : 
    1457              :       INTEGER                                            :: ncols
    1458              :       TYPE(C_PTR)                                        :: col_dist
    1459              :       INTERFACE
    1460              :          SUBROUTINE dbm_distribution_col_dist_c(dist, ncols, col_dist) &
    1461              :             BIND(C, name="dbm_distribution_col_dist")
    1462              :             IMPORT :: C_PTR, C_INT
    1463              :             TYPE(C_PTR), VALUE                        :: dist
    1464              :             INTEGER(C_INT)                            :: ncols
    1465              :             TYPE(C_PTR)                               :: col_dist
    1466              :          END SUBROUTINE dbm_distribution_col_dist_c
    1467              :       END INTERFACE
    1468              : 
    1469       339146 :       CALL dbm_distribution_col_dist_c(dist%c_ptr, ncols, col_dist)
    1470       678292 :       CALL C_F_POINTER(col_dist, res, shape=[ncols])
    1471              : 
    1472              : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
    1473              :       CPASSERT(ALL(res == dbcsr_distribution_col_dist(dist%dbcsr)))
    1474              : #endif
    1475       339146 :    END FUNCTION dbm_distribution_col_dist
    1476              : 
    1477              : ! **************************************************************************************************
    1478              : !> \brief Initialize DBM library
    1479              : !> \author Ole Schuett
    1480              : ! **************************************************************************************************
    1481         9288 :    SUBROUTINE dbm_library_init()
    1482              :       INTERFACE
    1483              :          SUBROUTINE dbm_library_init_c() BIND(C, name="dbm_library_init")
    1484              :          END SUBROUTINE dbm_library_init_c
    1485              :       END INTERFACE
    1486              : 
    1487         9288 :       CALL dbm_library_init_c()
    1488              : 
    1489         9288 :    END SUBROUTINE dbm_library_init
    1490              : 
    1491              : ! **************************************************************************************************
    1492              : !> \brief Finalize DBM library
    1493              : !> \author Ole Schuett
    1494              : ! **************************************************************************************************
    1495         9288 :    SUBROUTINE dbm_library_finalize()
    1496              :       INTERFACE
    1497              :          SUBROUTINE dbm_library_finalize_c() BIND(C, name="dbm_library_finalize")
    1498              :          END SUBROUTINE dbm_library_finalize_c
    1499              :       END INTERFACE
    1500              : 
    1501         9288 :       CALL dbm_library_finalize_c()
    1502              : 
    1503         9288 :    END SUBROUTINE dbm_library_finalize
    1504              : 
    1505              : ! **************************************************************************************************
    1506              : !> \brief Print DBM library statistics
    1507              : !> \param mpi_comm ...
    1508              : !> \param output_unit ...
    1509              : !> \author Ole Schuett
    1510              : ! **************************************************************************************************
    1511         9406 :    SUBROUTINE dbm_library_print_stats(mpi_comm, output_unit)
    1512              :       TYPE(mp_comm_type), INTENT(IN)                     :: mpi_comm
    1513              :       INTEGER, INTENT(IN)                                :: output_unit
    1514              : 
    1515              :       INTERFACE
    1516              :          SUBROUTINE dbm_library_print_stats_c(mpi_comm, print_func, output_unit) &
    1517              :             BIND(C, name="dbm_library_print_stats")
    1518              :             IMPORT :: C_FUNPTR, C_INT
    1519              :             INTEGER(KIND=C_INT), VALUE                :: mpi_comm
    1520              :             TYPE(C_FUNPTR), VALUE                     :: print_func
    1521              :             INTEGER(KIND=C_INT), VALUE                :: output_unit
    1522              :          END SUBROUTINE dbm_library_print_stats_c
    1523              :       END INTERFACE
    1524              : 
    1525              :       ! Since Fortran units groups can't be used from C, we pass a function pointer instead.
    1526              :       CALL dbm_library_print_stats_c(mpi_comm=mpi_comm%get_handle(), &
    1527              :                                      print_func=C_FUNLOC(print_func), &
    1528         9406 :                                      output_unit=output_unit)
    1529              : 
    1530         9406 :    END SUBROUTINE dbm_library_print_stats
    1531              : 
    1532              : ! **************************************************************************************************
    1533              : !> \brief Callback to write to a Fortran output unit (called by C-side).
    1534              : !> \param msg to be printed.
    1535              : !> \param msglen number of characters excluding the terminating character.
    1536              : !> \param output_unit used for output.
    1537              : !> \author Ole Schuett and Hans Pabst
    1538              : ! **************************************************************************************************
    1539         5638 :    SUBROUTINE print_func(msg, msglen, output_unit) BIND(C, name="dbm_api_print_func")
    1540              :       CHARACTER(KIND=C_CHAR), INTENT(IN)                 :: msg(*)
    1541              :       INTEGER(KIND=C_INT), INTENT(IN), VALUE             :: msglen, output_unit
    1542              : 
    1543         5638 :       IF (output_unit <= 0) RETURN ! Omit to print the message.
    1544         2819 :       WRITE (output_unit, FMT="(100A)", ADVANCE="NO") msg(1:msglen)
    1545              :    END SUBROUTINE print_func
    1546            0 : END MODULE dbm_api
        

Generated by: LCOV version 2.0-1