LCOV - code coverage report
Current view: top level - src - gw_communication.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b1f098b) Lines: 282 293 96.2 %
Date: 2024-05-05 06:30:09 Functions: 3 4 75.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief
      10             : !> \author Jan Wilhelm
      11             : !> \date 08.2023
      12             : ! **************************************************************************************************
      13             : MODULE gw_communication
      14             :    USE dbcsr_api,                       ONLY: &
      15             :         dbcsr_copy, dbcsr_create, dbcsr_filter, dbcsr_finalize, dbcsr_get_info, &
      16             :         dbcsr_get_stored_coordinates, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      17             :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_release, &
      18             :         dbcsr_reserve_all_blocks, dbcsr_reserve_blocks, dbcsr_set, dbcsr_type
      19             :    USE kinds,                           ONLY: dp
      20             :    USE message_passing,                 ONLY: mp_para_env_type,&
      21             :                                               mp_request_type,&
      22             :                                               mp_waitall
      23             : #include "./base/base_uses.f90"
      24             : 
      25             :    IMPLICIT NONE
      26             : 
      27             :    PRIVATE
      28             : 
      29             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_communication'
      30             : 
      31             :    PUBLIC :: global_matrix_to_local_matrix, local_matrix_to_global_matrix
      32             : 
      33             :    TYPE buffer_type
      34             :       REAL(KIND=dp), DIMENSION(:), POINTER  :: msg => NULL()
      35             :       INTEGER, DIMENSION(:), POINTER  :: sizes => NULL()
      36             :       INTEGER, DIMENSION(:, :), POINTER  :: indx => NULL()
      37             :       INTEGER :: proc = -1
      38             :       INTEGER :: msg_req = -1
      39             :    END TYPE
      40             : 
      41             : CONTAINS
      42             : 
      43             : ! **************************************************************************************************
      44             : !> \brief ...
      45             : !> \param mat_global ...
      46             : !> \param mat_local ...
      47             : !> \param para_env ...
      48             : !> \param num_pe_sub ...
      49             : !> \param atom_ranges ...
      50             : ! **************************************************************************************************
      51         792 :    SUBROUTINE global_matrix_to_local_matrix(mat_global, mat_local, para_env, num_pe_sub, atom_ranges)
      52             :       TYPE(dbcsr_type)                                   :: mat_global, mat_local
      53             :       TYPE(mp_para_env_type), POINTER                    :: para_env
      54             :       INTEGER                                            :: num_pe_sub
      55             :       INTEGER, DIMENSION(:, :), OPTIONAL                 :: atom_ranges
      56             : 
      57             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'global_matrix_to_local_matrix'
      58             : 
      59             :       INTEGER :: block_counter, block_offset, block_size, col, col_from_buffer, col_offset, &
      60             :          col_size, handle, handle1, i_block, i_entry, i_mepos, igroup, imep, imep_sub, msg_offset, &
      61             :          nblkrows_total, ngroup, nmo, num_blocks, offset, row, row_from_buffer, row_offset, &
      62             :          row_size, total_num_entries
      63         792 :       INTEGER, ALLOCATABLE, DIMENSION(:) :: blk_counter, cols_to_alloc, entry_counter, &
      64         792 :          num_entries_blocks_rec, num_entries_blocks_send, row_block_from_index, rows_to_alloc, &
      65         792 :          sizes_rec, sizes_send
      66         792 :       INTEGER, DIMENSION(:), POINTER                     :: row_blk_offset, row_blk_size
      67         792 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block
      68         792 :       TYPE(buffer_type), ALLOCATABLE, DIMENSION(:)       :: buffer_rec, buffer_send
      69             :       TYPE(dbcsr_iterator_type)                          :: iter
      70             : 
      71         792 :       CALL timeset(routineN, handle)
      72             : 
      73         792 :       CALL timeset("get_sizes", handle1)
      74             : 
      75         792 :       NULLIFY (data_block)
      76             : 
      77        2376 :       ALLOCATE (num_entries_blocks_send(0:2*para_env%num_pe - 1))
      78        3960 :       num_entries_blocks_send(:) = 0
      79             : 
      80        1584 :       ALLOCATE (num_entries_blocks_rec(0:2*para_env%num_pe - 1))
      81        3960 :       num_entries_blocks_rec(:) = 0
      82             : 
      83         792 :       ngroup = para_env%num_pe/num_pe_sub
      84             : 
      85         792 :       CALL dbcsr_iterator_start(iter, mat_global)
      86        8696 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
      87             : 
      88             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
      89             :                                         row_size=row_size, col_size=col_size, &
      90        7904 :                                         row_offset=row_offset, col_offset=col_offset)
      91             : 
      92        7904 :          CALL dbcsr_get_stored_coordinates(mat_local, row, col, imep_sub)
      93             : 
      94       16600 :          DO igroup = 0, ngroup - 1
      95             : 
      96        7904 :             IF (PRESENT(atom_ranges)) THEN
      97        7904 :                IF (row < atom_ranges(1, igroup + 1) .OR. row > atom_ranges(2, igroup + 1)) CYCLE
      98             :             END IF
      99        7904 :             imep = imep_sub + igroup*num_pe_sub
     100             : 
     101        7904 :             num_entries_blocks_send(2*imep) = num_entries_blocks_send(2*imep) + row_size*col_size
     102       15808 :             num_entries_blocks_send(2*imep + 1) = num_entries_blocks_send(2*imep + 1) + 1
     103             : 
     104             :          END DO
     105             : 
     106             :       END DO
     107             : 
     108         792 :       CALL dbcsr_iterator_stop(iter)
     109             : 
     110         792 :       CALL timestop(handle1)
     111             : 
     112         792 :       CALL timeset("send_sizes_1", handle1)
     113             : 
     114        3960 :       total_num_entries = SUM(num_entries_blocks_send)
     115         792 :       CALL para_env%sum(total_num_entries)
     116             : 
     117         792 :       CALL timestop(handle1)
     118             : 
     119         792 :       CALL timeset("send_sizes_2", handle1)
     120             : 
     121         792 :       IF (para_env%num_pe > 1) THEN
     122         792 :          CALL para_env%alltoall(num_entries_blocks_send, num_entries_blocks_rec, 2)
     123             :       ELSE
     124           0 :          num_entries_blocks_rec(0:1) = num_entries_blocks_send(0:1)
     125             :       END IF
     126             : 
     127         792 :       CALL timestop(handle1)
     128             : 
     129         792 :       CALL timeset("get_data", handle1)
     130             : 
     131        3960 :       ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
     132        3960 :       ALLOCATE (buffer_send(0:para_env%num_pe - 1))
     133             : 
     134             :       ! allocate data message and corresponding indices
     135        2376 :       DO imep = 0, para_env%num_pe - 1
     136             : 
     137        3960 :          ALLOCATE (buffer_rec(imep)%msg(num_entries_blocks_rec(2*imep)))
     138      148073 :          buffer_rec(imep)%msg = 0.0_dp
     139             : 
     140        3960 :          ALLOCATE (buffer_send(imep)%msg(num_entries_blocks_send(2*imep)))
     141      148073 :          buffer_send(imep)%msg = 0.0_dp
     142             : 
     143        3960 :          ALLOCATE (buffer_rec(imep)%indx(num_entries_blocks_rec(2*imep + 1), 3))
     144       30048 :          buffer_rec(imep)%indx = 0
     145             : 
     146        3960 :          ALLOCATE (buffer_send(imep)%indx(num_entries_blocks_send(2*imep + 1), 3))
     147       30840 :          buffer_send(imep)%indx = 0
     148             : 
     149             :       END DO
     150             : 
     151        2376 :       ALLOCATE (entry_counter(0:para_env%num_pe - 1))
     152        2376 :       entry_counter(:) = 0
     153             : 
     154        1584 :       ALLOCATE (blk_counter(0:para_env%num_pe - 1))
     155        2376 :       blk_counter = 0
     156             : 
     157         792 :       CALL dbcsr_iterator_start(iter, mat_global)
     158        8696 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     159             : 
     160             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     161             :                                         row_size=row_size, col_size=col_size, &
     162        7904 :                                         row_offset=row_offset, col_offset=col_offset)
     163             : 
     164        7904 :          CALL dbcsr_get_stored_coordinates(mat_local, row, col, imep_sub)
     165             : 
     166       16600 :          DO igroup = 0, ngroup - 1
     167             : 
     168        7904 :             IF (PRESENT(atom_ranges)) THEN
     169        7904 :                IF (row < atom_ranges(1, igroup + 1) .OR. row > atom_ranges(2, igroup + 1)) CYCLE
     170             :             END IF
     171             : 
     172        7904 :             imep = imep_sub + igroup*num_pe_sub
     173             : 
     174        7904 :             msg_offset = entry_counter(imep)
     175             : 
     176        7904 :             block_size = row_size*col_size
     177             : 
     178             :             buffer_send(imep)%msg(msg_offset + 1:msg_offset + block_size) = &
     179      162297 :                RESHAPE(data_block(1:row_size, 1:col_size), (/block_size/))
     180             : 
     181        7904 :             entry_counter(imep) = entry_counter(imep) + block_size
     182             : 
     183        7904 :             blk_counter(imep) = blk_counter(imep) + 1
     184             : 
     185        7904 :             block_offset = blk_counter(imep)
     186             : 
     187        7904 :             buffer_send(imep)%indx(block_offset, 1) = row
     188        7904 :             buffer_send(imep)%indx(block_offset, 2) = col
     189       15808 :             buffer_send(imep)%indx(block_offset, 3) = msg_offset
     190             : 
     191             :          END DO
     192             : 
     193             :       END DO
     194             : 
     195         792 :       CALL dbcsr_iterator_stop(iter)
     196             : 
     197         792 :       CALL timestop(handle1)
     198             : 
     199         792 :       CALL timeset("send_data", handle1)
     200             : 
     201        2376 :       ALLOCATE (sizes_rec(0:para_env%num_pe - 1))
     202        1584 :       ALLOCATE (sizes_send(0:para_env%num_pe - 1))
     203             : 
     204        2376 :       DO imep = 0, para_env%num_pe - 1
     205        1584 :          sizes_send(imep) = num_entries_blocks_send(2*imep)
     206        2376 :          sizes_rec(imep) = num_entries_blocks_rec(2*imep)
     207             :       END DO
     208             : 
     209         792 :       CALL communicate_buffer(para_env, sizes_rec, sizes_send, buffer_rec, buffer_send)
     210             : 
     211         792 :       CALL timestop(handle1)
     212             : 
     213         792 :       CALL timeset("row_block_from_index", handle1)
     214             : 
     215             :       CALL dbcsr_get_info(mat_local, &
     216             :                           nblkrows_total=nblkrows_total, &
     217             :                           row_blk_offset=row_blk_offset, &
     218         792 :                           row_blk_size=row_blk_size)
     219             : 
     220        1584 :       ALLOCATE (row_block_from_index(nmo))
     221         792 :       row_block_from_index = 0
     222             : 
     223         792 :       DO i_entry = 1, nmo
     224         792 :          DO i_block = 1, nblkrows_total
     225             : 
     226           0 :             IF (i_entry >= row_blk_offset(i_block) .AND. &
     227           0 :                 i_entry <= row_blk_offset(i_block) + row_blk_size(i_block) - 1) THEN
     228             : 
     229           0 :                row_block_from_index(i_entry) = i_block
     230             : 
     231             :             END IF
     232             : 
     233             :          END DO
     234             :       END DO
     235             : 
     236         792 :       CALL timestop(handle1)
     237             : 
     238         792 :       CALL timeset("reserve_blocks", handle1)
     239             : 
     240         792 :       num_blocks = 0
     241             : 
     242             :       ! get the number of blocks, which have to be allocated
     243        2376 :       DO imep = 0, para_env%num_pe - 1
     244        2376 :          num_blocks = num_blocks + num_entries_blocks_rec(2*imep + 1)
     245             :       END DO
     246             : 
     247        2376 :       ALLOCATE (rows_to_alloc(num_blocks))
     248        8696 :       rows_to_alloc = 0
     249             : 
     250        1584 :       ALLOCATE (cols_to_alloc(num_blocks))
     251        8696 :       cols_to_alloc = 0
     252             : 
     253             :       block_counter = 0
     254             : 
     255        2376 :       DO i_mepos = 0, para_env%num_pe - 1
     256             : 
     257       10280 :          DO i_block = 1, num_entries_blocks_rec(2*i_mepos + 1)
     258             : 
     259        7904 :             block_counter = block_counter + 1
     260             : 
     261        7904 :             rows_to_alloc(block_counter) = buffer_rec(i_mepos)%indx(i_block, 1)
     262        9488 :             cols_to_alloc(block_counter) = buffer_rec(i_mepos)%indx(i_block, 2)
     263             : 
     264             :          END DO
     265             : 
     266             :       END DO
     267             : 
     268         792 :       CALL dbcsr_set(mat_local, 0.0_dp)
     269         792 :       CALL dbcsr_filter(mat_local, 1.0_dp)
     270         792 :       CALL dbcsr_reserve_blocks(mat_local, rows=rows_to_alloc(:), cols=cols_to_alloc(:))
     271         792 :       CALL dbcsr_finalize(mat_local)
     272         792 :       CALL dbcsr_set(mat_local, 0.0_dp)
     273             : 
     274         792 :       CALL timestop(handle1)
     275             : 
     276         792 :       CALL timeset("fill_mat_local", handle1)
     277             : 
     278         792 :       CALL dbcsr_iterator_start(iter, mat_local)
     279             : 
     280        8696 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     281             : 
     282             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     283        7904 :                                         row_size=row_size, col_size=col_size)
     284             : 
     285       24504 :          DO imep = 0, para_env%num_pe - 1
     286             : 
     287      138686 :             DO i_block = 1, num_entries_blocks_rec(2*imep + 1)
     288             : 
     289      114974 :                row_from_buffer = buffer_rec(imep)%indx(i_block, 1)
     290      114974 :                col_from_buffer = buffer_rec(imep)%indx(i_block, 2)
     291      114974 :                offset = buffer_rec(imep)%indx(i_block, 3)
     292             : 
     293      130782 :                IF (row == row_from_buffer .AND. col == col_from_buffer) THEN
     294             : 
     295             :                   data_block(1:row_size, 1:col_size) = &
     296             :                      RESHAPE(buffer_rec(imep)%msg(offset + 1:offset + row_size*col_size), &
     297      203339 :                              (/row_size, col_size/))
     298             : 
     299             :                END IF
     300             : 
     301             :             END DO
     302             : 
     303             :          END DO
     304             : 
     305             :       END DO ! blocks
     306             : 
     307         792 :       CALL dbcsr_iterator_stop(iter)
     308             : 
     309         792 :       CALL timestop(handle1)
     310             : 
     311        2376 :       DO imep = 0, para_env%num_pe - 1
     312        1584 :          DEALLOCATE (buffer_rec(imep)%msg)
     313        1584 :          DEALLOCATE (buffer_rec(imep)%indx)
     314        1584 :          DEALLOCATE (buffer_send(imep)%msg)
     315        2376 :          DEALLOCATE (buffer_send(imep)%indx)
     316             :       END DO
     317             : 
     318         792 :       CALL timestop(handle)
     319             : 
     320        8712 :    END SUBROUTINE global_matrix_to_local_matrix
     321             : 
     322             : ! **************************************************************************************************
     323             : !> \brief ...
     324             : !> \param para_env ...
     325             : !> \param num_entries_rec ...
     326             : !> \param num_entries_send ...
     327             : !> \param buffer_rec ...
     328             : !> \param buffer_send ...
     329             : !> \param do_indx ...
     330             : !> \param do_msg ...
     331             : ! **************************************************************************************************
     332         792 :    SUBROUTINE communicate_buffer(para_env, num_entries_rec, num_entries_send, &
     333             :                                  buffer_rec, buffer_send, do_indx, do_msg)
     334             : 
     335             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     336             :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: num_entries_rec, num_entries_send
     337             :       TYPE(buffer_type), ALLOCATABLE, DIMENSION(:)       :: buffer_rec, buffer_send
     338             :       LOGICAL, OPTIONAL                                  :: do_indx, do_msg
     339             : 
     340             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'communicate_buffer'
     341             : 
     342             :       INTEGER                                            :: handle, imep, rec_counter, send_counter
     343             :       LOGICAL                                            :: my_do_indx, my_do_msg
     344         792 :       TYPE(mp_request_type), DIMENSION(:, :), POINTER    :: req
     345             : 
     346         792 :       CALL timeset(routineN, handle)
     347             : 
     348         792 :       NULLIFY (req)
     349       12672 :       ALLOCATE (req(1:para_env%num_pe, 4))
     350             : 
     351         792 :       my_do_indx = .TRUE.
     352         792 :       IF (PRESENT(do_indx)) my_do_indx = do_indx
     353         792 :       my_do_msg = .TRUE.
     354         792 :       IF (PRESENT(do_msg)) my_do_msg = do_msg
     355             : 
     356         792 :       IF (para_env%num_pe > 1) THEN
     357             : 
     358         792 :          send_counter = 0
     359         792 :          rec_counter = 0
     360             : 
     361        2376 :          DO imep = 0, para_env%num_pe - 1
     362        2376 :             IF (num_entries_rec(imep) > 0) THEN
     363         792 :                rec_counter = rec_counter + 1
     364         792 :                IF (my_do_indx) THEN
     365         792 :                   CALL para_env%irecv(buffer_rec(imep)%indx, imep, req(rec_counter, 3), tag=4)
     366             :                END IF
     367         792 :                IF (my_do_msg) THEN
     368         792 :                   CALL para_env%irecv(buffer_rec(imep)%msg, imep, req(rec_counter, 4), tag=7)
     369             :                END IF
     370             :             END IF
     371             :          END DO
     372             : 
     373        2376 :          DO imep = 0, para_env%num_pe - 1
     374        2376 :             IF (num_entries_send(imep) > 0) THEN
     375         792 :                send_counter = send_counter + 1
     376         792 :                IF (my_do_indx) THEN
     377         792 :                   CALL para_env%isend(buffer_send(imep)%indx, imep, req(send_counter, 1), tag=4)
     378             :                END IF
     379         792 :                IF (my_do_msg) THEN
     380         792 :                   CALL para_env%isend(buffer_send(imep)%msg, imep, req(send_counter, 2), tag=7)
     381             :                END IF
     382             :             END IF
     383             :          END DO
     384             : 
     385         792 :          IF (my_do_indx) THEN
     386         792 :             CALL mp_waitall(req(1:send_counter, 1))
     387         792 :             CALL mp_waitall(req(1:rec_counter, 3))
     388             :          END IF
     389             : 
     390         792 :          IF (my_do_msg) THEN
     391         792 :             CALL mp_waitall(req(1:send_counter, 2))
     392         792 :             CALL mp_waitall(req(1:rec_counter, 4))
     393             :          END IF
     394             : 
     395             :       ELSE
     396             : 
     397           0 :          buffer_rec(0)%indx = buffer_send(0)%indx
     398           0 :          buffer_rec(0)%msg = buffer_send(0)%msg
     399             : 
     400             :       END IF
     401             : 
     402         792 :       DEALLOCATE (req)
     403             : 
     404         792 :       CALL timestop(handle)
     405             : 
     406         792 :    END SUBROUTINE communicate_buffer
     407             : 
     408             : ! **************************************************************************************************
     409             : !> \brief ...
     410             : !> \param mat_local ...
     411             : !> \param mat_global ...
     412             : !> \param para_env ...
     413             : ! **************************************************************************************************
     414         452 :    SUBROUTINE local_matrix_to_global_matrix(mat_local, mat_global, para_env)
     415             : 
     416             :       TYPE(dbcsr_type)                                   :: mat_local, mat_global
     417             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     418             : 
     419             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'local_matrix_to_global_matrix'
     420             : 
     421             :       INTEGER                                            :: block_size, c, col, col_size, handle, &
     422             :                                                             handle1, i_block, imep, o, offset, r, &
     423             :                                                             rec_counter, row, row_size, &
     424             :                                                             send_counter
     425         452 :       INTEGER, ALLOCATABLE, DIMENSION(:) :: block_counter, entry_counter, num_blocks_rec, &
     426         452 :          num_blocks_send, num_entries_rec, num_entries_send, sizes_rec, sizes_send
     427         452 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block
     428         452 :       TYPE(buffer_type), ALLOCATABLE, DIMENSION(:)       :: buffer_rec, buffer_send
     429             :       TYPE(dbcsr_iterator_type)                          :: iter
     430             :       TYPE(dbcsr_type)                                   :: mat_global_copy
     431         452 :       TYPE(mp_request_type), DIMENSION(:, :), POINTER    :: req
     432             : 
     433         452 :       CALL timeset(routineN, handle)
     434             : 
     435         452 :       CALL timeset("get_coord", handle1)
     436             : 
     437         452 :       CALL dbcsr_create(mat_global_copy, template=mat_global)
     438         452 :       CALL dbcsr_reserve_all_blocks(mat_global_copy)
     439             : 
     440         452 :       CALL dbcsr_set(mat_global, 0.0_dp)
     441         452 :       CALL dbcsr_set(mat_global_copy, 0.0_dp)
     442             : 
     443        2260 :       ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
     444        1808 :       ALLOCATE (buffer_send(0:para_env%num_pe - 1))
     445             : 
     446        1356 :       ALLOCATE (num_entries_rec(0:para_env%num_pe - 1))
     447         904 :       ALLOCATE (num_blocks_rec(0:para_env%num_pe - 1))
     448         904 :       ALLOCATE (num_entries_send(0:para_env%num_pe - 1))
     449         904 :       ALLOCATE (num_blocks_send(0:para_env%num_pe - 1))
     450        1356 :       num_entries_rec = 0
     451        1356 :       num_blocks_rec = 0
     452        1356 :       num_entries_send = 0
     453        1356 :       num_blocks_send = 0
     454             : 
     455         452 :       CALL dbcsr_iterator_start(iter, mat_local)
     456        4550 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     457             : 
     458             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     459        4098 :                                         row_size=row_size, col_size=col_size)
     460             : 
     461        4098 :          CALL dbcsr_get_stored_coordinates(mat_global, row, col, imep)
     462             : 
     463        4098 :          num_entries_send(imep) = num_entries_send(imep) + row_size*col_size
     464        4098 :          num_blocks_send(imep) = num_blocks_send(imep) + 1
     465             : 
     466             :       END DO
     467             : 
     468         452 :       CALL dbcsr_iterator_stop(iter)
     469             : 
     470         452 :       CALL timestop(handle1)
     471             : 
     472         452 :       CALL timeset("comm_size", handle1)
     473             : 
     474         452 :       IF (para_env%num_pe > 1) THEN
     475             : 
     476        1356 :          ALLOCATE (sizes_rec(0:2*para_env%num_pe - 1))
     477         904 :          ALLOCATE (sizes_send(0:2*para_env%num_pe - 1))
     478             : 
     479        1356 :          DO imep = 0, para_env%num_pe - 1
     480             : 
     481         904 :             sizes_send(2*imep) = num_entries_send(imep)
     482        1356 :             sizes_send(2*imep + 1) = num_blocks_send(imep)
     483             : 
     484             :          END DO
     485             : 
     486         452 :          CALL para_env%alltoall(sizes_send, sizes_rec, 2)
     487             : 
     488        1356 :          DO imep = 0, para_env%num_pe - 1
     489         904 :             num_entries_rec(imep) = sizes_rec(2*imep)
     490        1356 :             num_blocks_rec(imep) = sizes_rec(2*imep + 1)
     491             :          END DO
     492             : 
     493         452 :          DEALLOCATE (sizes_rec, sizes_send)
     494             : 
     495             :       ELSE
     496             : 
     497           0 :          num_entries_rec(0) = num_entries_send(0)
     498           0 :          num_blocks_rec(0) = num_blocks_send(0)
     499             : 
     500             :       END IF
     501             : 
     502         452 :       CALL timestop(handle1)
     503             : 
     504         452 :       CALL timeset("fill_buffer", handle1)
     505             : 
     506             :       ! allocate data message and corresponding indices
     507        1356 :       DO imep = 0, para_env%num_pe - 1
     508             : 
     509        2431 :          ALLOCATE (buffer_rec(imep)%msg(num_entries_rec(imep)))
     510       69256 :          buffer_rec(imep)%msg = 0.0_dp
     511             : 
     512        2431 :          ALLOCATE (buffer_send(imep)%msg(num_entries_send(imep)))
     513       69256 :          buffer_send(imep)%msg = 0.0_dp
     514             : 
     515        2431 :          ALLOCATE (buffer_rec(imep)%indx(num_blocks_rec(imep), 5))
     516       25914 :          buffer_rec(imep)%indx = 0
     517             : 
     518        2431 :          ALLOCATE (buffer_send(imep)%indx(num_blocks_send(imep), 5))
     519       26366 :          buffer_send(imep)%indx = 0
     520             : 
     521             :       END DO
     522             : 
     523        1356 :       ALLOCATE (block_counter(0:para_env%num_pe - 1))
     524        1356 :       block_counter(:) = 0
     525             : 
     526         904 :       ALLOCATE (entry_counter(0:para_env%num_pe - 1))
     527        1356 :       entry_counter(:) = 0
     528             : 
     529             :       ! fill buffer_send
     530         452 :       CALL dbcsr_iterator_start(iter, mat_local)
     531        4550 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     532             : 
     533             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     534        4098 :                                         row_size=row_size, col_size=col_size)
     535             : 
     536        4098 :          CALL dbcsr_get_stored_coordinates(mat_global, row, col, imep)
     537             : 
     538        4098 :          block_size = row_size*col_size
     539             : 
     540        4098 :          offset = entry_counter(imep)
     541             : 
     542             :          buffer_send(imep)%msg(offset + 1:offset + block_size) = &
     543       76548 :             RESHAPE(data_block(1:row_size, 1:col_size), (/block_size/))
     544             : 
     545        4098 :          i_block = block_counter(imep) + 1
     546             : 
     547        4098 :          buffer_send(imep)%indx(i_block, 1) = row
     548        4098 :          buffer_send(imep)%indx(i_block, 2) = col
     549        4098 :          buffer_send(imep)%indx(i_block, 3) = offset
     550             : 
     551        4098 :          entry_counter(imep) = entry_counter(imep) + block_size
     552             : 
     553        4098 :          block_counter(imep) = block_counter(imep) + 1
     554             : 
     555             :       END DO
     556             : 
     557         452 :       CALL dbcsr_iterator_stop(iter)
     558             : 
     559         452 :       CALL timestop(handle1)
     560             : 
     561         452 :       CALL timeset("comm_data", handle1)
     562             : 
     563         452 :       NULLIFY (req)
     564        6780 :       ALLOCATE (req(1:para_env%num_pe, 4))
     565             : 
     566         452 :       IF (para_env%num_pe > 1) THEN
     567             : 
     568         452 :          send_counter = 0
     569         452 :          rec_counter = 0
     570             : 
     571        1356 :          DO imep = 0, para_env%num_pe - 1
     572         904 :             IF (num_entries_rec(imep) > 0) THEN
     573         623 :                rec_counter = rec_counter + 1
     574         623 :                CALL para_env%irecv(buffer_rec(imep)%indx, imep, req(rec_counter, 3), tag=4)
     575             :             END IF
     576        1356 :             IF (num_entries_rec(imep) > 0) THEN
     577         623 :                CALL para_env%irecv(buffer_rec(imep)%msg, imep, req(rec_counter, 4), tag=7)
     578             :             END IF
     579             :          END DO
     580             : 
     581        1356 :          DO imep = 0, para_env%num_pe - 1
     582         904 :             IF (num_entries_send(imep) > 0) THEN
     583         623 :                send_counter = send_counter + 1
     584         623 :                CALL para_env%isend(buffer_send(imep)%indx, imep, req(send_counter, 1), tag=4)
     585             :             END IF
     586        1356 :             IF (num_entries_send(imep) > 0) THEN
     587         623 :                CALL para_env%isend(buffer_send(imep)%msg, imep, req(send_counter, 2), tag=7)
     588             :             END IF
     589             :          END DO
     590             : 
     591         452 :          CALL mp_waitall(req(1:send_counter, 1:2))
     592         452 :          CALL mp_waitall(req(1:rec_counter, 3:4))
     593             : 
     594             :       ELSE
     595             : 
     596           0 :          buffer_rec(0)%indx = buffer_send(0)%indx
     597           0 :          buffer_rec(0)%msg = buffer_send(0)%msg
     598             : 
     599             :       END IF
     600             : 
     601         452 :       CALL timestop(handle1)
     602             : 
     603         452 :       CALL timeset("set_blocks", handle1)
     604             : 
     605             :       ! fill mat_global_copy
     606         452 :       CALL dbcsr_iterator_start(iter, mat_global_copy)
     607        5051 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     608             : 
     609             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     610        4599 :                                         row_size=row_size, col_size=col_size)
     611             : 
     612       14249 :          DO imep = 0, para_env%num_pe - 1
     613             : 
     614       74382 :             DO i_block = 1, num_blocks_rec(imep)
     615             : 
     616       60585 :                IF (row == buffer_rec(imep)%indx(i_block, 1) .AND. &
     617        9198 :                    col == buffer_rec(imep)%indx(i_block, 2)) THEN
     618             : 
     619        4098 :                   offset = buffer_rec(imep)%indx(i_block, 3)
     620             : 
     621        4098 :                   r = row_size
     622        4098 :                   c = col_size
     623        4098 :                   o = offset
     624             : 
     625             :                   data_block(1:r, 1:c) = data_block(1:r, 1:c) + &
     626       96723 :                                          RESHAPE(buffer_rec(imep)%msg(o + 1:o + r*c), (/r, c/))
     627             : 
     628             :                END IF
     629             : 
     630             :             END DO
     631             : 
     632             :          END DO
     633             : 
     634             :       END DO
     635             : 
     636         452 :       CALL dbcsr_iterator_stop(iter)
     637             : 
     638         452 :       CALL dbcsr_copy(mat_global, mat_global_copy)
     639             : 
     640         452 :       CALL dbcsr_release(mat_global_copy)
     641             : 
     642             :       ! remove the blocks which are exactly zero from mat_global
     643         452 :       CALL dbcsr_filter(mat_global, 1.0E-30_dp)
     644             : 
     645        1356 :       DO imep = 0, para_env%num_pe - 1
     646         904 :          DEALLOCATE (buffer_rec(imep)%msg)
     647         904 :          DEALLOCATE (buffer_send(imep)%msg)
     648         904 :          DEALLOCATE (buffer_rec(imep)%indx)
     649        1356 :          DEALLOCATE (buffer_send(imep)%indx)
     650             :       END DO
     651             : 
     652         452 :       DEALLOCATE (buffer_rec, buffer_send)
     653             : 
     654         452 :       DEALLOCATE (block_counter, entry_counter)
     655             : 
     656         452 :       DEALLOCATE (req)
     657             : 
     658         452 :       CALL dbcsr_set(mat_local, 0.0_dp)
     659         452 :       CALL dbcsr_filter(mat_local, 1.0_dp)
     660             : 
     661         452 :       CALL timestop(handle1)
     662             : 
     663         452 :       CALL timestop(handle)
     664             : 
     665        3616 :    END SUBROUTINE local_matrix_to_global_matrix
     666             : 
     667           0 : END MODULE gw_communication

Generated by: LCOV version 1.15