LCOV - code coverage report
Current view: top level - src - gw_communication.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 375 386 97.2 %
Date: 2024-12-21 06:28:57 Functions: 8 9 88.9 %

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

Generated by: LCOV version 1.15