LCOV - code coverage report
Current view: top level - src - gw_communication.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b4bd748) Lines: 375 386 97.2 %
Date: 2025-03-09 07:56:22 Functions: 8 9 88.9 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief
      10             : !> \author Jan Wilhelm
      11             : !> \date 08.2023
      12             : ! **************************************************************************************************
      13             : MODULE gw_communication
      14             :    USE cp_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_p_type, &
      18             :         dbcsr_release, dbcsr_reserve_blocks, dbcsr_set, dbcsr_type
      19             :    USE cp_dbcsr_contrib,                ONLY: dbcsr_reserve_all_blocks
      20             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      21             :                                               copy_fm_to_dbcsr
      22             :    USE cp_fm_types,                     ONLY: cp_fm_get_info,&
      23             :                                               cp_fm_type
      24             :    USE dbt_api,                         ONLY: dbt_clear,&
      25             :                                               dbt_copy,&
      26             :                                               dbt_copy_matrix_to_tensor,&
      27             :                                               dbt_copy_tensor_to_matrix,&
      28             :                                               dbt_create,&
      29             :                                               dbt_destroy,&
      30             :                                               dbt_type
      31             :    USE kinds,                           ONLY: dp
      32             :    USE message_passing,                 ONLY: mp_para_env_type,&
      33             :                                               mp_request_type,&
      34             :                                               mp_waitall
      35             :    USE post_scf_bandstructure_types,    ONLY: post_scf_bandstructure_type
      36             : #include "./base/base_uses.f90"
      37             : 
      38             :    IMPLICIT NONE
      39             : 
      40             :    PRIVATE
      41             : 
      42             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_communication'
      43             : 
      44             :    PUBLIC :: local_dbt_to_global_mat, fm_to_local_tensor, fm_to_local_array, local_array_to_fm, &
      45             :              local_dbt_to_global_fm
      46             : 
      47             :    TYPE buffer_type
      48             :       REAL(KIND=dp), DIMENSION(:), POINTER  :: msg => NULL()
      49             :       INTEGER, DIMENSION(:), POINTER  :: sizes => NULL()
      50             :       INTEGER, DIMENSION(:, :), POINTER  :: indx => NULL()
      51             :       INTEGER :: proc = -1
      52             :       INTEGER :: msg_req = -1
      53             :    END TYPE
      54             : 
      55             : CONTAINS
      56             : 
      57             : ! **************************************************************************************************
      58             : !> \brief ...
      59             : !> \param fm_global ...
      60             : !> \param mat_global ...
      61             : !> \param mat_local ...
      62             : !> \param tensor ...
      63             : !> \param bs_env ...
      64             : !> \param atom_ranges ...
      65             : ! **************************************************************************************************
      66        3140 :    SUBROUTINE fm_to_local_tensor(fm_global, mat_global, mat_local, tensor, bs_env, atom_ranges)
      67             : 
      68             :       TYPE(cp_fm_type)                                   :: fm_global
      69             :       TYPE(dbcsr_type)                                   :: mat_global, mat_local
      70             :       TYPE(dbt_type)                                     :: tensor
      71             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
      72             :       INTEGER, DIMENSION(:, :), OPTIONAL                 :: atom_ranges
      73             : 
      74             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'fm_to_local_tensor'
      75             : 
      76             :       INTEGER                                            :: handle
      77       28260 :       TYPE(dbt_type)                                     :: tensor_tmp
      78             : 
      79        3140 :       CALL timeset(routineN, handle)
      80             : 
      81        3140 :       CALL dbt_clear(tensor)
      82        3140 :       CALL copy_fm_to_dbcsr(fm_global, mat_global, keep_sparsity=.FALSE.)
      83        3140 :       CALL dbcsr_filter(mat_global, bs_env%eps_filter)
      84        3140 :       IF (PRESENT(atom_ranges)) THEN
      85             :          CALL global_matrix_to_local_matrix(mat_global, mat_local, bs_env%para_env, &
      86        1052 :                                             bs_env%para_env_tensor%num_pe, atom_ranges)
      87             :       ELSE
      88             :          CALL global_matrix_to_local_matrix(mat_global, mat_local, bs_env%para_env, &
      89        2088 :                                             bs_env%para_env_tensor%num_pe)
      90             :       END IF
      91        3140 :       CALL dbt_create(mat_local, tensor_tmp)
      92        3140 :       CALL dbt_copy_matrix_to_tensor(mat_local, tensor_tmp)
      93        3140 :       CALL dbt_copy(tensor_tmp, tensor, move_data=.TRUE.)
      94        3140 :       CALL dbt_destroy(tensor_tmp)
      95        3140 :       CALL dbcsr_set(mat_local, 0.0_dp)
      96        3140 :       CALL dbcsr_filter(mat_local, 1.0_dp)
      97             : 
      98        3140 :       CALL timestop(handle)
      99             : 
     100        3140 :    END SUBROUTINE fm_to_local_tensor
     101             : 
     102             : ! **************************************************************************************************
     103             : !> \brief ...
     104             : !> \param tensor ...
     105             : !> \param mat_tensor ...
     106             : !> \param mat_global ...
     107             : !> \param para_env ...
     108             : ! **************************************************************************************************
     109        1850 :    SUBROUTINE local_dbt_to_global_mat(tensor, mat_tensor, mat_global, para_env)
     110             : 
     111             :       TYPE(dbt_type)                                     :: tensor
     112             :       TYPE(dbcsr_type)                                   :: mat_tensor, mat_global
     113             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     114             : 
     115             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'local_dbt_to_global_mat'
     116             : 
     117             :       INTEGER                                            :: handle
     118             : 
     119        1850 :       CALL timeset(routineN, handle)
     120             : 
     121        1850 :       CALL dbt_copy_tensor_to_matrix(tensor, mat_tensor)
     122        1850 :       CALL dbt_clear(tensor)
     123             :       ! the next para_env%sync is not mandatory, but it makes the timing output
     124             :       ! of local_matrix_to_global_matrix correct
     125        1850 :       CALL para_env%sync()
     126        1850 :       CALL local_matrix_to_global_matrix(mat_tensor, mat_global, para_env)
     127             : 
     128        1850 :       CALL timestop(handle)
     129             : 
     130        1850 :    END SUBROUTINE local_dbt_to_global_mat
     131             : 
     132             : ! **************************************************************************************************
     133             : !> \brief ...
     134             : !> \param mat_global ...
     135             : !> \param mat_local ...
     136             : !> \param para_env ...
     137             : !> \param num_pe_sub ...
     138             : !> \param atom_ranges ...
     139             : ! **************************************************************************************************
     140        3140 :    SUBROUTINE global_matrix_to_local_matrix(mat_global, mat_local, para_env, num_pe_sub, atom_ranges)
     141             :       TYPE(dbcsr_type)                                   :: mat_global, mat_local
     142             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     143             :       INTEGER                                            :: num_pe_sub
     144             :       INTEGER, DIMENSION(:, :), OPTIONAL                 :: atom_ranges
     145             : 
     146             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'global_matrix_to_local_matrix'
     147             : 
     148             :       INTEGER :: block_counter, block_offset, block_size, col, col_from_buffer, col_offset, &
     149             :          col_size, handle, handle1, i_block, i_entry, i_mepos, igroup, imep, imep_sub, msg_offset, &
     150             :          nblkrows_total, ngroup, nmo, num_blocks, offset, row, row_from_buffer, row_offset, &
     151             :          row_size, total_num_entries
     152        3140 :       INTEGER, ALLOCATABLE, DIMENSION(:) :: blk_counter, cols_to_alloc, entry_counter, &
     153        3140 :          num_entries_blocks_rec, num_entries_blocks_send, row_block_from_index, rows_to_alloc, &
     154        3140 :          sizes_rec, sizes_send
     155        3140 :       INTEGER, DIMENSION(:), POINTER                     :: row_blk_offset, row_blk_size
     156        3140 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block
     157        3140 :       TYPE(buffer_type), ALLOCATABLE, DIMENSION(:)       :: buffer_rec, buffer_send
     158             :       TYPE(dbcsr_iterator_type)                          :: iter
     159             : 
     160        3140 :       CALL timeset(routineN, handle)
     161             : 
     162        3140 :       CALL timeset("get_sizes", handle1)
     163             : 
     164        3140 :       NULLIFY (data_block)
     165             : 
     166        9420 :       ALLOCATE (num_entries_blocks_send(0:2*para_env%num_pe - 1))
     167       15700 :       num_entries_blocks_send(:) = 0
     168             : 
     169        6280 :       ALLOCATE (num_entries_blocks_rec(0:2*para_env%num_pe - 1))
     170       15700 :       num_entries_blocks_rec(:) = 0
     171             : 
     172        3140 :       ngroup = para_env%num_pe/num_pe_sub
     173             : 
     174        3140 :       CALL dbcsr_iterator_start(iter, mat_global)
     175        9019 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     176             : 
     177             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     178             :                                         row_size=row_size, col_size=col_size, &
     179        5879 :                                         row_offset=row_offset, col_offset=col_offset)
     180             : 
     181        5879 :          CALL dbcsr_get_stored_coordinates(mat_local, row, col, imep_sub)
     182             : 
     183       18451 :          DO igroup = 0, ngroup - 1
     184             : 
     185        9432 :             IF (PRESENT(atom_ranges)) THEN
     186        2326 :                IF (row < atom_ranges(1, igroup + 1) .OR. row > atom_ranges(2, igroup + 1)) CYCLE
     187             :             END IF
     188        9432 :             imep = imep_sub + igroup*num_pe_sub
     189             : 
     190        9432 :             num_entries_blocks_send(2*imep) = num_entries_blocks_send(2*imep) + row_size*col_size
     191       15311 :             num_entries_blocks_send(2*imep + 1) = num_entries_blocks_send(2*imep + 1) + 1
     192             : 
     193             :          END DO
     194             : 
     195             :       END DO
     196             : 
     197        3140 :       CALL dbcsr_iterator_stop(iter)
     198             : 
     199        3140 :       CALL timestop(handle1)
     200             : 
     201        3140 :       CALL timeset("send_sizes_1", handle1)
     202             : 
     203       15700 :       total_num_entries = SUM(num_entries_blocks_send)
     204        3140 :       CALL para_env%sum(total_num_entries)
     205             : 
     206        3140 :       CALL timestop(handle1)
     207             : 
     208        3140 :       CALL timeset("send_sizes_2", handle1)
     209             : 
     210        3140 :       IF (para_env%num_pe > 1) THEN
     211        3140 :          CALL para_env%alltoall(num_entries_blocks_send, num_entries_blocks_rec, 2)
     212             :       ELSE
     213           0 :          num_entries_blocks_rec(0:1) = num_entries_blocks_send(0:1)
     214             :       END IF
     215             : 
     216        3140 :       CALL timestop(handle1)
     217             : 
     218        3140 :       CALL timeset("get_data", handle1)
     219             : 
     220       15700 :       ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
     221       15700 :       ALLOCATE (buffer_send(0:para_env%num_pe - 1))
     222             : 
     223             :       ! allocate data message and corresponding indices
     224        9420 :       DO imep = 0, para_env%num_pe - 1
     225             : 
     226       16336 :          ALLOCATE (buffer_rec(imep)%msg(num_entries_blocks_rec(2*imep)))
     227      190134 :          buffer_rec(imep)%msg = 0.0_dp
     228             : 
     229       16336 :          ALLOCATE (buffer_send(imep)%msg(num_entries_blocks_send(2*imep)))
     230      190134 :          buffer_send(imep)%msg = 0.0_dp
     231             : 
     232       16336 :          ALLOCATE (buffer_rec(imep)%indx(num_entries_blocks_rec(2*imep + 1), 3))
     233       53416 :          buffer_rec(imep)%indx = 0
     234             : 
     235       16336 :          ALLOCATE (buffer_send(imep)%indx(num_entries_blocks_send(2*imep + 1), 3))
     236       56556 :          buffer_send(imep)%indx = 0
     237             : 
     238             :       END DO
     239             : 
     240        9420 :       ALLOCATE (entry_counter(0:para_env%num_pe - 1))
     241        9420 :       entry_counter(:) = 0
     242             : 
     243        6280 :       ALLOCATE (blk_counter(0:para_env%num_pe - 1))
     244        9420 :       blk_counter = 0
     245             : 
     246        3140 :       CALL dbcsr_iterator_start(iter, mat_global)
     247        9019 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     248             : 
     249             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     250             :                                         row_size=row_size, col_size=col_size, &
     251        5879 :                                         row_offset=row_offset, col_offset=col_offset)
     252             : 
     253        5879 :          CALL dbcsr_get_stored_coordinates(mat_local, row, col, imep_sub)
     254             : 
     255       18451 :          DO igroup = 0, ngroup - 1
     256             : 
     257        9432 :             IF (PRESENT(atom_ranges)) THEN
     258        2326 :                IF (row < atom_ranges(1, igroup + 1) .OR. row > atom_ranges(2, igroup + 1)) CYCLE
     259             :             END IF
     260             : 
     261        9432 :             imep = imep_sub + igroup*num_pe_sub
     262             : 
     263        9432 :             msg_offset = entry_counter(imep)
     264             : 
     265        9432 :             block_size = row_size*col_size
     266             : 
     267             :             buffer_send(imep)%msg(msg_offset + 1:msg_offset + block_size) = &
     268      202718 :                RESHAPE(data_block(1:row_size, 1:col_size), (/block_size/))
     269             : 
     270        9432 :             entry_counter(imep) = entry_counter(imep) + block_size
     271             : 
     272        9432 :             blk_counter(imep) = blk_counter(imep) + 1
     273             : 
     274        9432 :             block_offset = blk_counter(imep)
     275             : 
     276        9432 :             buffer_send(imep)%indx(block_offset, 1) = row
     277        9432 :             buffer_send(imep)%indx(block_offset, 2) = col
     278       15311 :             buffer_send(imep)%indx(block_offset, 3) = msg_offset
     279             : 
     280             :          END DO
     281             : 
     282             :       END DO
     283             : 
     284        3140 :       CALL dbcsr_iterator_stop(iter)
     285             : 
     286        3140 :       CALL timestop(handle1)
     287             : 
     288        3140 :       CALL timeset("send_data", handle1)
     289             : 
     290        9420 :       ALLOCATE (sizes_rec(0:para_env%num_pe - 1))
     291        6280 :       ALLOCATE (sizes_send(0:para_env%num_pe - 1))
     292             : 
     293        9420 :       DO imep = 0, para_env%num_pe - 1
     294        6280 :          sizes_send(imep) = num_entries_blocks_send(2*imep)
     295        9420 :          sizes_rec(imep) = num_entries_blocks_rec(2*imep)
     296             :       END DO
     297             : 
     298        3140 :       CALL communicate_buffer(para_env, sizes_rec, sizes_send, buffer_rec, buffer_send)
     299             : 
     300        3140 :       CALL timestop(handle1)
     301             : 
     302        3140 :       CALL timeset("row_block_from_index", handle1)
     303             : 
     304             :       CALL dbcsr_get_info(mat_local, &
     305             :                           nblkrows_total=nblkrows_total, &
     306             :                           row_blk_offset=row_blk_offset, &
     307        3140 :                           row_blk_size=row_blk_size)
     308             : 
     309        6280 :       ALLOCATE (row_block_from_index(nmo))
     310        3140 :       row_block_from_index = 0
     311             : 
     312        3140 :       DO i_entry = 1, nmo
     313        3140 :          DO i_block = 1, nblkrows_total
     314             : 
     315           0 :             IF (i_entry >= row_blk_offset(i_block) .AND. &
     316           0 :                 i_entry <= row_blk_offset(i_block) + row_blk_size(i_block) - 1) THEN
     317             : 
     318           0 :                row_block_from_index(i_entry) = i_block
     319             : 
     320             :             END IF
     321             : 
     322             :          END DO
     323             :       END DO
     324             : 
     325        3140 :       CALL timestop(handle1)
     326             : 
     327        3140 :       CALL timeset("reserve_blocks", handle1)
     328             : 
     329        3140 :       num_blocks = 0
     330             : 
     331             :       ! get the number of blocks, which have to be allocated
     332        9420 :       DO imep = 0, para_env%num_pe - 1
     333        9420 :          num_blocks = num_blocks + num_entries_blocks_rec(2*imep + 1)
     334             :       END DO
     335             : 
     336        8786 :       ALLOCATE (rows_to_alloc(num_blocks))
     337       12572 :       rows_to_alloc = 0
     338             : 
     339        5646 :       ALLOCATE (cols_to_alloc(num_blocks))
     340       12572 :       cols_to_alloc = 0
     341             : 
     342             :       block_counter = 0
     343             : 
     344        9420 :       DO i_mepos = 0, para_env%num_pe - 1
     345             : 
     346       18852 :          DO i_block = 1, num_entries_blocks_rec(2*i_mepos + 1)
     347             : 
     348        9432 :             block_counter = block_counter + 1
     349             : 
     350        9432 :             rows_to_alloc(block_counter) = buffer_rec(i_mepos)%indx(i_block, 1)
     351       15712 :             cols_to_alloc(block_counter) = buffer_rec(i_mepos)%indx(i_block, 2)
     352             : 
     353             :          END DO
     354             : 
     355             :       END DO
     356             : 
     357        3140 :       CALL dbcsr_set(mat_local, 0.0_dp)
     358        3140 :       CALL dbcsr_filter(mat_local, 1.0_dp)
     359        3140 :       CALL dbcsr_reserve_blocks(mat_local, rows=rows_to_alloc(:), cols=cols_to_alloc(:))
     360        3140 :       CALL dbcsr_finalize(mat_local)
     361        3140 :       CALL dbcsr_set(mat_local, 0.0_dp)
     362             : 
     363        3140 :       CALL timestop(handle1)
     364             : 
     365        3140 :       CALL timeset("fill_mat_local", handle1)
     366             : 
     367        3140 :       CALL dbcsr_iterator_start(iter, mat_local)
     368             : 
     369       12572 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     370             : 
     371             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     372        9432 :                                         row_size=row_size, col_size=col_size)
     373             : 
     374       31436 :          DO imep = 0, para_env%num_pe - 1
     375             : 
     376       77344 :             DO i_block = 1, num_entries_blocks_rec(2*imep + 1)
     377             : 
     378       49048 :                row_from_buffer = buffer_rec(imep)%indx(i_block, 1)
     379       49048 :                col_from_buffer = buffer_rec(imep)%indx(i_block, 2)
     380       49048 :                offset = buffer_rec(imep)%indx(i_block, 3)
     381             : 
     382       67912 :                IF (row == row_from_buffer .AND. col == col_from_buffer) THEN
     383             : 
     384             :                   data_block(1:row_size, 1:col_size) = &
     385             :                      RESHAPE(buffer_rec(imep)%msg(offset + 1:offset + row_size*col_size), &
     386      249274 :                              (/row_size, col_size/))
     387             : 
     388             :                END IF
     389             : 
     390             :             END DO
     391             : 
     392             :          END DO
     393             : 
     394             :       END DO ! blocks
     395             : 
     396        3140 :       CALL dbcsr_iterator_stop(iter)
     397             : 
     398        3140 :       CALL timestop(handle1)
     399             : 
     400        9420 :       DO imep = 0, para_env%num_pe - 1
     401        6280 :          DEALLOCATE (buffer_rec(imep)%msg)
     402        6280 :          DEALLOCATE (buffer_rec(imep)%indx)
     403        6280 :          DEALLOCATE (buffer_send(imep)%msg)
     404        9420 :          DEALLOCATE (buffer_send(imep)%indx)
     405             :       END DO
     406             : 
     407        3140 :       CALL timestop(handle)
     408             : 
     409       34540 :    END SUBROUTINE global_matrix_to_local_matrix
     410             : 
     411             : ! **************************************************************************************************
     412             : !> \brief ...
     413             : !> \param para_env ...
     414             : !> \param num_entries_rec ...
     415             : !> \param num_entries_send ...
     416             : !> \param buffer_rec ...
     417             : !> \param buffer_send ...
     418             : !> \param do_indx ...
     419             : !> \param do_msg ...
     420             : ! **************************************************************************************************
     421        3140 :    SUBROUTINE communicate_buffer(para_env, num_entries_rec, num_entries_send, &
     422             :                                  buffer_rec, buffer_send, do_indx, do_msg)
     423             : 
     424             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     425             :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: num_entries_rec, num_entries_send
     426             :       TYPE(buffer_type), ALLOCATABLE, DIMENSION(:)       :: buffer_rec, buffer_send
     427             :       LOGICAL, OPTIONAL                                  :: do_indx, do_msg
     428             : 
     429             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'communicate_buffer'
     430             : 
     431             :       INTEGER                                            :: handle, imep, rec_counter, send_counter
     432             :       LOGICAL                                            :: my_do_indx, my_do_msg
     433        3140 :       TYPE(mp_request_type), DIMENSION(:, :), POINTER    :: req
     434             : 
     435        3140 :       CALL timeset(routineN, handle)
     436             : 
     437        3140 :       NULLIFY (req)
     438       50240 :       ALLOCATE (req(1:para_env%num_pe, 4))
     439             : 
     440        3140 :       my_do_indx = .TRUE.
     441        3140 :       IF (PRESENT(do_indx)) my_do_indx = do_indx
     442        3140 :       my_do_msg = .TRUE.
     443        3140 :       IF (PRESENT(do_msg)) my_do_msg = do_msg
     444             : 
     445        3140 :       IF (para_env%num_pe > 1) THEN
     446             : 
     447        3140 :          send_counter = 0
     448        3140 :          rec_counter = 0
     449             : 
     450        9420 :          DO imep = 0, para_env%num_pe - 1
     451        9420 :             IF (num_entries_rec(imep) > 0) THEN
     452        3776 :                rec_counter = rec_counter + 1
     453        3776 :                IF (my_do_indx) THEN
     454        3776 :                   CALL para_env%irecv(buffer_rec(imep)%indx, imep, req(rec_counter, 3), tag=4)
     455             :                END IF
     456        3776 :                IF (my_do_msg) THEN
     457        3776 :                   CALL para_env%irecv(buffer_rec(imep)%msg, imep, req(rec_counter, 4), tag=7)
     458             :                END IF
     459             :             END IF
     460             :          END DO
     461             : 
     462        9420 :          DO imep = 0, para_env%num_pe - 1
     463        9420 :             IF (num_entries_send(imep) > 0) THEN
     464        3776 :                send_counter = send_counter + 1
     465        3776 :                IF (my_do_indx) THEN
     466        3776 :                   CALL para_env%isend(buffer_send(imep)%indx, imep, req(send_counter, 1), tag=4)
     467             :                END IF
     468        3776 :                IF (my_do_msg) THEN
     469        3776 :                   CALL para_env%isend(buffer_send(imep)%msg, imep, req(send_counter, 2), tag=7)
     470             :                END IF
     471             :             END IF
     472             :          END DO
     473             : 
     474        3140 :          IF (my_do_indx) THEN
     475        3140 :             CALL mp_waitall(req(1:send_counter, 1))
     476        3140 :             CALL mp_waitall(req(1:rec_counter, 3))
     477             :          END IF
     478             : 
     479        3140 :          IF (my_do_msg) THEN
     480        3140 :             CALL mp_waitall(req(1:send_counter, 2))
     481        3140 :             CALL mp_waitall(req(1:rec_counter, 4))
     482             :          END IF
     483             : 
     484             :       ELSE
     485             : 
     486           0 :          buffer_rec(0)%indx = buffer_send(0)%indx
     487           0 :          buffer_rec(0)%msg = buffer_send(0)%msg
     488             : 
     489             :       END IF
     490             : 
     491        3140 :       DEALLOCATE (req)
     492             : 
     493        3140 :       CALL timestop(handle)
     494             : 
     495        3140 :    END SUBROUTINE communicate_buffer
     496             : 
     497             : ! **************************************************************************************************
     498             : !> \brief ...
     499             : !> \param mat_local ...
     500             : !> \param mat_global ...
     501             : !> \param para_env ...
     502             : ! **************************************************************************************************
     503        1850 :    SUBROUTINE local_matrix_to_global_matrix(mat_local, mat_global, para_env)
     504             : 
     505             :       TYPE(dbcsr_type)                                   :: mat_local, mat_global
     506             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     507             : 
     508             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'local_matrix_to_global_matrix'
     509             : 
     510             :       INTEGER                                            :: block_size, c, col, col_size, handle, &
     511             :                                                             handle1, i_block, imep, o, offset, r, &
     512             :                                                             rec_counter, row, row_size, &
     513             :                                                             send_counter
     514        1850 :       INTEGER, ALLOCATABLE, DIMENSION(:) :: block_counter, entry_counter, num_blocks_rec, &
     515        1850 :          num_blocks_send, num_entries_rec, num_entries_send, sizes_rec, sizes_send
     516        1850 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block
     517        1850 :       TYPE(buffer_type), ALLOCATABLE, DIMENSION(:)       :: buffer_rec, buffer_send
     518             :       TYPE(dbcsr_iterator_type)                          :: iter
     519             :       TYPE(dbcsr_type)                                   :: mat_global_copy
     520        1850 :       TYPE(mp_request_type), DIMENSION(:, :), POINTER    :: req
     521             : 
     522        1850 :       CALL timeset(routineN, handle)
     523             : 
     524        1850 :       CALL timeset("get_coord", handle1)
     525             : 
     526        1850 :       CALL dbcsr_create(mat_global_copy, template=mat_global)
     527        1850 :       CALL dbcsr_reserve_all_blocks(mat_global_copy)
     528             : 
     529        1850 :       CALL dbcsr_set(mat_global, 0.0_dp)
     530        1850 :       CALL dbcsr_set(mat_global_copy, 0.0_dp)
     531             : 
     532       11100 :       ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
     533        9250 :       ALLOCATE (buffer_send(0:para_env%num_pe - 1))
     534             : 
     535        5550 :       ALLOCATE (num_entries_rec(0:para_env%num_pe - 1))
     536        3700 :       ALLOCATE (num_blocks_rec(0:para_env%num_pe - 1))
     537        3700 :       ALLOCATE (num_entries_send(0:para_env%num_pe - 1))
     538        3700 :       ALLOCATE (num_blocks_send(0:para_env%num_pe - 1))
     539        5550 :       num_entries_rec = 0
     540        5550 :       num_blocks_rec = 0
     541        5550 :       num_entries_send = 0
     542        5550 :       num_blocks_send = 0
     543             : 
     544        1850 :       CALL dbcsr_iterator_start(iter, mat_local)
     545        4724 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     546             : 
     547             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     548        2874 :                                         row_size=row_size, col_size=col_size)
     549             : 
     550        2874 :          CALL dbcsr_get_stored_coordinates(mat_global, row, col, imep)
     551             : 
     552        2874 :          num_entries_send(imep) = num_entries_send(imep) + row_size*col_size
     553        2874 :          num_blocks_send(imep) = num_blocks_send(imep) + 1
     554             : 
     555             :       END DO
     556             : 
     557        1850 :       CALL dbcsr_iterator_stop(iter)
     558             : 
     559        1850 :       CALL timestop(handle1)
     560             : 
     561        1850 :       CALL timeset("comm_size", handle1)
     562             : 
     563        1850 :       IF (para_env%num_pe > 1) THEN
     564             : 
     565        5550 :          ALLOCATE (sizes_rec(0:2*para_env%num_pe - 1))
     566        3700 :          ALLOCATE (sizes_send(0:2*para_env%num_pe - 1))
     567             : 
     568        5550 :          DO imep = 0, para_env%num_pe - 1
     569             : 
     570        3700 :             sizes_send(2*imep) = num_entries_send(imep)
     571        5550 :             sizes_send(2*imep + 1) = num_blocks_send(imep)
     572             : 
     573             :          END DO
     574             : 
     575        1850 :          CALL para_env%alltoall(sizes_send, sizes_rec, 2)
     576             : 
     577        5550 :          DO imep = 0, para_env%num_pe - 1
     578        3700 :             num_entries_rec(imep) = sizes_rec(2*imep)
     579        5550 :             num_blocks_rec(imep) = sizes_rec(2*imep + 1)
     580             :          END DO
     581             : 
     582        1850 :          DEALLOCATE (sizes_rec, sizes_send)
     583             : 
     584             :       ELSE
     585             : 
     586           0 :          num_entries_rec(0) = num_entries_send(0)
     587           0 :          num_blocks_rec(0) = num_blocks_send(0)
     588             : 
     589             :       END IF
     590             : 
     591        1850 :       CALL timestop(handle1)
     592             : 
     593        1850 :       CALL timeset("fill_buffer", handle1)
     594             : 
     595             :       ! allocate data message and corresponding indices
     596        5550 :       DO imep = 0, para_env%num_pe - 1
     597             : 
     598        8838 :          ALLOCATE (buffer_rec(imep)%msg(num_entries_rec(imep)))
     599       72315 :          buffer_rec(imep)%msg = 0.0_dp
     600             : 
     601        8838 :          ALLOCATE (buffer_send(imep)%msg(num_entries_send(imep)))
     602       72315 :          buffer_send(imep)%msg = 0.0_dp
     603             : 
     604        8838 :          ALLOCATE (buffer_rec(imep)%indx(num_blocks_rec(imep), 5))
     605       36570 :          buffer_rec(imep)%indx = 0
     606             : 
     607        8838 :          ALLOCATE (buffer_send(imep)%indx(num_blocks_send(imep), 5))
     608       38420 :          buffer_send(imep)%indx = 0
     609             : 
     610             :       END DO
     611             : 
     612        5550 :       ALLOCATE (block_counter(0:para_env%num_pe - 1))
     613        5550 :       block_counter(:) = 0
     614             : 
     615        3700 :       ALLOCATE (entry_counter(0:para_env%num_pe - 1))
     616        5550 :       entry_counter(:) = 0
     617             : 
     618             :       ! fill buffer_send
     619        1850 :       CALL dbcsr_iterator_start(iter, mat_local)
     620        4724 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     621             : 
     622             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     623        2874 :                                         row_size=row_size, col_size=col_size)
     624             : 
     625        2874 :          CALL dbcsr_get_stored_coordinates(mat_global, row, col, imep)
     626             : 
     627        2874 :          block_size = row_size*col_size
     628             : 
     629        2874 :          offset = entry_counter(imep)
     630             : 
     631             :          buffer_send(imep)%msg(offset + 1:offset + block_size) = &
     632       74363 :             RESHAPE(data_block(1:row_size, 1:col_size), (/block_size/))
     633             : 
     634        2874 :          i_block = block_counter(imep) + 1
     635             : 
     636        2874 :          buffer_send(imep)%indx(i_block, 1) = row
     637        2874 :          buffer_send(imep)%indx(i_block, 2) = col
     638        2874 :          buffer_send(imep)%indx(i_block, 3) = offset
     639             : 
     640        2874 :          entry_counter(imep) = entry_counter(imep) + block_size
     641             : 
     642        2874 :          block_counter(imep) = block_counter(imep) + 1
     643             : 
     644             :       END DO
     645             : 
     646        1850 :       CALL dbcsr_iterator_stop(iter)
     647             : 
     648        1850 :       CALL timestop(handle1)
     649             : 
     650        1850 :       CALL timeset("comm_data", handle1)
     651             : 
     652        1850 :       NULLIFY (req)
     653       29600 :       ALLOCATE (req(1:para_env%num_pe, 4))
     654             : 
     655        1850 :       IF (para_env%num_pe > 1) THEN
     656             : 
     657        1850 :          send_counter = 0
     658        1850 :          rec_counter = 0
     659             : 
     660        5550 :          DO imep = 0, para_env%num_pe - 1
     661        3700 :             IF (num_entries_rec(imep) > 0) THEN
     662        1438 :                rec_counter = rec_counter + 1
     663        1438 :                CALL para_env%irecv(buffer_rec(imep)%indx, imep, req(rec_counter, 3), tag=4)
     664             :             END IF
     665        5550 :             IF (num_entries_rec(imep) > 0) THEN
     666        1438 :                CALL para_env%irecv(buffer_rec(imep)%msg, imep, req(rec_counter, 4), tag=7)
     667             :             END IF
     668             :          END DO
     669             : 
     670        5550 :          DO imep = 0, para_env%num_pe - 1
     671        3700 :             IF (num_entries_send(imep) > 0) THEN
     672        1438 :                send_counter = send_counter + 1
     673        1438 :                CALL para_env%isend(buffer_send(imep)%indx, imep, req(send_counter, 1), tag=4)
     674             :             END IF
     675        5550 :             IF (num_entries_send(imep) > 0) THEN
     676        1438 :                CALL para_env%isend(buffer_send(imep)%msg, imep, req(send_counter, 2), tag=7)
     677             :             END IF
     678             :          END DO
     679             : 
     680        1850 :          CALL mp_waitall(req(1:send_counter, 1:2))
     681        1850 :          CALL mp_waitall(req(1:rec_counter, 3:4))
     682             : 
     683             :       ELSE
     684             : 
     685           0 :          buffer_rec(0)%indx = buffer_send(0)%indx
     686           0 :          buffer_rec(0)%msg = buffer_send(0)%msg
     687             : 
     688             :       END IF
     689             : 
     690        1850 :       CALL timestop(handle1)
     691             : 
     692        1850 :       CALL timeset("set_blocks", handle1)
     693             : 
     694             :       ! fill mat_global_copy
     695        1850 :       CALL dbcsr_iterator_start(iter, mat_global_copy)
     696        7450 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     697             : 
     698             :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
     699        5600 :                                         row_size=row_size, col_size=col_size)
     700             : 
     701       18650 :          DO imep = 0, para_env%num_pe - 1
     702             : 
     703       27826 :             DO i_block = 1, num_blocks_rec(imep)
     704             : 
     705       11026 :                IF (row == buffer_rec(imep)%indx(i_block, 1) .AND. &
     706       11200 :                    col == buffer_rec(imep)%indx(i_block, 2)) THEN
     707             : 
     708        2874 :                   offset = buffer_rec(imep)%indx(i_block, 3)
     709             : 
     710        2874 :                   r = row_size
     711        2874 :                   c = col_size
     712        2874 :                   o = offset
     713             : 
     714             :                   data_block(1:r, 1:c) = data_block(1:r, 1:c) + &
     715       88681 :                                          RESHAPE(buffer_rec(imep)%msg(o + 1:o + r*c), (/r, c/))
     716             : 
     717             :                END IF
     718             : 
     719             :             END DO
     720             : 
     721             :          END DO
     722             : 
     723             :       END DO
     724             : 
     725        1850 :       CALL dbcsr_iterator_stop(iter)
     726             : 
     727        1850 :       CALL dbcsr_copy(mat_global, mat_global_copy)
     728             : 
     729        1850 :       CALL dbcsr_release(mat_global_copy)
     730             : 
     731             :       ! remove the blocks which are exactly zero from mat_global
     732        1850 :       CALL dbcsr_filter(mat_global, 1.0E-30_dp)
     733             : 
     734        5550 :       DO imep = 0, para_env%num_pe - 1
     735        3700 :          DEALLOCATE (buffer_rec(imep)%msg)
     736        3700 :          DEALLOCATE (buffer_send(imep)%msg)
     737        3700 :          DEALLOCATE (buffer_rec(imep)%indx)
     738        5550 :          DEALLOCATE (buffer_send(imep)%indx)
     739             :       END DO
     740             : 
     741        1850 :       DEALLOCATE (buffer_rec, buffer_send)
     742             : 
     743        1850 :       DEALLOCATE (block_counter, entry_counter)
     744             : 
     745        1850 :       DEALLOCATE (req)
     746             : 
     747        1850 :       CALL dbcsr_set(mat_local, 0.0_dp)
     748        1850 :       CALL dbcsr_filter(mat_local, 1.0_dp)
     749             : 
     750        1850 :       CALL timestop(handle1)
     751             : 
     752        1850 :       CALL timestop(handle)
     753             : 
     754       14800 :    END SUBROUTINE local_matrix_to_global_matrix
     755             : 
     756             : ! **************************************************************************************************
     757             : !> \brief ...
     758             : !> \param fm_S ...
     759             : !> \param array_S ...
     760             : !> \param weight ...
     761             : !> \param add ...
     762             : ! **************************************************************************************************
     763         412 :    SUBROUTINE fm_to_local_array(fm_S, array_S, weight, add)
     764             : 
     765             :       TYPE(cp_fm_type), DIMENSION(:)                     :: fm_S
     766             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: array_S
     767             :       REAL(KIND=dp), OPTIONAL                            :: weight
     768             :       LOGICAL, OPTIONAL                                  :: add
     769             : 
     770             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'fm_to_local_array'
     771             : 
     772             :       INTEGER                                            :: handle, i, i_row_local, img, j, &
     773             :                                                             j_col_local, n_basis, ncol_local, &
     774             :                                                             nimages, nrow_local
     775         412 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     776             :       LOGICAL                                            :: my_add
     777             :       REAL(KIND=dp)                                      :: my_weight
     778         412 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: array_tmp
     779             : 
     780         412 :       CALL timeset(routineN, handle)
     781             : 
     782         412 :       my_weight = 1.0_dp
     783         412 :       IF (PRESENT(weight)) my_weight = weight
     784             : 
     785         412 :       my_add = .FALSE.
     786         412 :       IF (PRESENT(add)) my_add = add
     787             : 
     788         412 :       n_basis = SIZE(array_S, 1)
     789         412 :       nimages = SIZE(array_S, 3)
     790             : 
     791             :       ! checks
     792         412 :       CPASSERT(SIZE(array_S, 2) == n_basis)
     793         412 :       CPASSERT(SIZE(fm_S) == nimages)
     794         412 :       CPASSERT(LBOUND(array_S, 1) == 1)
     795         412 :       CPASSERT(LBOUND(array_S, 2) == 1)
     796         412 :       CPASSERT(LBOUND(array_S, 3) == 1)
     797             : 
     798             :       CALL cp_fm_get_info(matrix=fm_S(1), &
     799             :                           nrow_local=nrow_local, &
     800             :                           ncol_local=ncol_local, &
     801             :                           row_indices=row_indices, &
     802         412 :                           col_indices=col_indices)
     803             : 
     804       23704 :       IF (.NOT. my_add) array_S(:, :, :) = 0.0_dp
     805        2060 :       ALLOCATE (array_tmp(SIZE(array_S, 1), SIZE(array_S, 2), SIZE(array_S, 3)))
     806      135232 :       array_tmp(:, :, :) = 0.0_dp
     807             : 
     808        4120 :       DO img = 1, nimages
     809       14218 :          DO i_row_local = 1, nrow_local
     810             : 
     811       10098 :             i = row_indices(i_row_local)
     812             : 
     813       69264 :             DO j_col_local = 1, ncol_local
     814             : 
     815       55458 :                j = col_indices(j_col_local)
     816             : 
     817       65556 :                array_tmp(i, j, img) = fm_S(img)%local_data(i_row_local, j_col_local)
     818             : 
     819             :             END DO ! j_col_local
     820             :          END DO ! i_row_local
     821             :       END DO ! img
     822             : 
     823         412 :       CALL fm_S(1)%matrix_struct%para_env%sync()
     824         412 :       CALL fm_S(1)%matrix_struct%para_env%sum(array_tmp)
     825         412 :       CALL fm_S(1)%matrix_struct%para_env%sync()
     826             : 
     827      135232 :       array_S(:, :, :) = array_S(:, :, :) + my_weight*array_tmp(:, :, :)
     828             : 
     829         412 :       CALL timestop(handle)
     830             : 
     831        1236 :    END SUBROUTINE fm_to_local_array
     832             : 
     833             : ! **************************************************************************************************
     834             : !> \brief ...
     835             : !> \param array_S ...
     836             : !> \param fm_S ...
     837             : !> \param weight ...
     838             : !> \param add ...
     839             : ! **************************************************************************************************
     840         350 :    SUBROUTINE local_array_to_fm(array_S, fm_S, weight, add)
     841             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: array_S
     842             :       TYPE(cp_fm_type), DIMENSION(:)                     :: fm_S
     843             :       REAL(KIND=dp), OPTIONAL                            :: weight
     844             :       LOGICAL, OPTIONAL                                  :: add
     845             : 
     846             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'local_array_to_fm'
     847             : 
     848             :       INTEGER                                            :: handle, i, i_row_local, img, j, &
     849             :                                                             j_col_local, n_basis, ncol_local, &
     850             :                                                             nimages, nrow_local
     851         350 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     852             :       LOGICAL                                            :: my_add
     853             :       REAL(KIND=dp)                                      :: my_weight, S_ij
     854             : 
     855         350 :       CALL timeset(routineN, handle)
     856             : 
     857         350 :       my_weight = 1.0_dp
     858         350 :       IF (PRESENT(weight)) my_weight = weight
     859             : 
     860         350 :       my_add = .FALSE.
     861         350 :       IF (PRESENT(add)) my_add = add
     862             : 
     863         350 :       n_basis = SIZE(array_S, 1)
     864         350 :       nimages = SIZE(array_S, 3)
     865             : 
     866             :       ! checks
     867         350 :       CPASSERT(SIZE(array_S, 2) == n_basis)
     868         350 :       CPASSERT(SIZE(fm_S) == nimages)
     869         350 :       CPASSERT(LBOUND(array_S, 1) == 1)
     870         350 :       CPASSERT(LBOUND(array_S, 2) == 1)
     871         350 :       CPASSERT(LBOUND(array_S, 3) == 1)
     872             : 
     873             :       CALL cp_fm_get_info(matrix=fm_S(1), &
     874             :                           nrow_local=nrow_local, &
     875             :                           ncol_local=ncol_local, &
     876             :                           row_indices=row_indices, &
     877         350 :                           col_indices=col_indices)
     878             : 
     879        3500 :       DO img = 1, nimages
     880             : 
     881       12041 :          DO i_row_local = 1, nrow_local
     882             : 
     883        8541 :             i = row_indices(i_row_local)
     884             : 
     885       58392 :             DO j_col_local = 1, ncol_local
     886             : 
     887       46701 :                j = col_indices(j_col_local)
     888             : 
     889       46701 :                IF (my_add) THEN
     890             :                   S_ij = fm_S(img)%local_data(i_row_local, j_col_local) + &
     891       45828 :                          array_S(i, j, img)*my_weight
     892             :                ELSE
     893         873 :                   S_ij = array_S(i, j, img)*my_weight
     894             :                END IF
     895       55242 :                fm_S(img)%local_data(i_row_local, j_col_local) = S_ij
     896             : 
     897             :             END DO ! j_col_local
     898             : 
     899             :          END DO ! i_row_local
     900             : 
     901             :       END DO ! img
     902             : 
     903         350 :       CALL timestop(handle)
     904             : 
     905         350 :    END SUBROUTINE local_array_to_fm
     906             : 
     907             : ! **************************************************************************************************
     908             : !> \brief ...
     909             : !> \param t_R ...
     910             : !> \param fm_R ...
     911             : !> \param mat_global ...
     912             : !> \param mat_local ...
     913             : !> \param bs_env ...
     914             : ! **************************************************************************************************
     915         138 :    SUBROUTINE local_dbt_to_global_fm(t_R, fm_R, mat_global, mat_local, bs_env)
     916             :       TYPE(dbt_type), DIMENSION(:)                       :: t_R
     917             :       TYPE(cp_fm_type), DIMENSION(:)                     :: fm_R
     918             :       TYPE(dbcsr_p_type)                                 :: mat_global, mat_local
     919             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     920             : 
     921             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'local_dbt_to_global_fm'
     922             : 
     923             :       INTEGER                                            :: handle, i_cell, n_images
     924             : 
     925         138 :       CALL timeset(routineN, handle)
     926             : 
     927         138 :       n_images = SIZE(t_R)
     928             : 
     929         138 :       CPASSERT(n_images == SIZE(fm_R))
     930             : 
     931        1380 :       DO i_cell = 1, n_images
     932        1242 :          CALL dbcsr_set(mat_global%matrix, 0.0_dp)
     933        1242 :          CALL dbcsr_set(mat_local%matrix, 0.0_dp)
     934             :          CALL local_dbt_to_global_mat(t_R(i_cell), mat_local%matrix, mat_global%matrix, &
     935        1242 :                                       bs_env%para_env)
     936        1380 :          CALL copy_dbcsr_to_fm(mat_global%matrix, fm_R(i_cell))
     937             :       END DO
     938             : 
     939         138 :       CALL timestop(handle)
     940             : 
     941         138 :    END SUBROUTINE local_dbt_to_global_fm
     942             : 
     943           0 : END MODULE gw_communication

Generated by: LCOV version 1.15