52 TYPE(dbcsr_type) :: mat_global, mat_local
55 INTEGER,
DIMENSION(:, :),
OPTIONAL :: atom_ranges
57 CHARACTER(LEN=*),
PARAMETER :: routinen =
'global_matrix_to_local_matrix'
59 INTEGER :: block_counter, block_offset, block_size, col, col_from_buffer, col_offset, &
60 col_size, handle, handle1, i_block, i_entry, i_mepos, igroup, imep, imep_sub, msg_offset, &
61 nblkrows_total, ngroup, nmo, num_blocks, offset, row, row_from_buffer, row_offset, &
62 row_size, total_num_entries
63 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: blk_counter, cols_to_alloc, entry_counter, &
64 num_entries_blocks_rec, num_entries_blocks_send, row_block_from_index, rows_to_alloc, &
66 INTEGER,
DIMENSION(:),
POINTER :: row_blk_offset, row_blk_size
67 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: data_block
68 TYPE(buffer_type),
ALLOCATABLE,
DIMENSION(:) :: buffer_rec, buffer_send
69 TYPE(dbcsr_iterator_type) :: iter
71 CALL timeset(routinen, handle)
73 CALL timeset(
"get_sizes", handle1)
77 ALLOCATE (num_entries_blocks_send(0:2*para_env%num_pe - 1))
78 num_entries_blocks_send(:) = 0
80 ALLOCATE (num_entries_blocks_rec(0:2*para_env%num_pe - 1))
81 num_entries_blocks_rec(:) = 0
83 ngroup = para_env%num_pe/num_pe_sub
85 CALL dbcsr_iterator_start(iter, mat_global)
86 DO WHILE (dbcsr_iterator_blocks_left(iter))
88 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
89 row_size=row_size, col_size=col_size, &
90 row_offset=row_offset, col_offset=col_offset)
92 CALL dbcsr_get_stored_coordinates(mat_local, row, col, imep_sub)
94 DO igroup = 0, ngroup - 1
96 IF (
PRESENT(atom_ranges))
THEN
97 IF (row < atom_ranges(1, igroup + 1) .OR. row > atom_ranges(2, igroup + 1)) cycle
99 imep = imep_sub + igroup*num_pe_sub
101 num_entries_blocks_send(2*imep) = num_entries_blocks_send(2*imep) + row_size*col_size
102 num_entries_blocks_send(2*imep + 1) = num_entries_blocks_send(2*imep + 1) + 1
108 CALL dbcsr_iterator_stop(iter)
110 CALL timestop(handle1)
112 CALL timeset(
"send_sizes_1", handle1)
114 total_num_entries = sum(num_entries_blocks_send)
115 CALL para_env%sum(total_num_entries)
117 CALL timestop(handle1)
119 CALL timeset(
"send_sizes_2", handle1)
121 IF (para_env%num_pe > 1)
THEN
122 CALL para_env%alltoall(num_entries_blocks_send, num_entries_blocks_rec, 2)
124 num_entries_blocks_rec(0:1) = num_entries_blocks_send(0:1)
127 CALL timestop(handle1)
129 CALL timeset(
"get_data", handle1)
131 ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
132 ALLOCATE (buffer_send(0:para_env%num_pe - 1))
135 DO imep = 0, para_env%num_pe - 1
137 ALLOCATE (buffer_rec(imep)%msg(num_entries_blocks_rec(2*imep)))
138 buffer_rec(imep)%msg = 0.0_dp
140 ALLOCATE (buffer_send(imep)%msg(num_entries_blocks_send(2*imep)))
141 buffer_send(imep)%msg = 0.0_dp
143 ALLOCATE (buffer_rec(imep)%indx(num_entries_blocks_rec(2*imep + 1), 3))
144 buffer_rec(imep)%indx = 0
146 ALLOCATE (buffer_send(imep)%indx(num_entries_blocks_send(2*imep + 1), 3))
147 buffer_send(imep)%indx = 0
151 ALLOCATE (entry_counter(0:para_env%num_pe - 1))
154 ALLOCATE (blk_counter(0:para_env%num_pe - 1))
157 CALL dbcsr_iterator_start(iter, mat_global)
158 DO WHILE (dbcsr_iterator_blocks_left(iter))
160 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
161 row_size=row_size, col_size=col_size, &
162 row_offset=row_offset, col_offset=col_offset)
164 CALL dbcsr_get_stored_coordinates(mat_local, row, col, imep_sub)
166 DO igroup = 0, ngroup - 1
168 IF (
PRESENT(atom_ranges))
THEN
169 IF (row < atom_ranges(1, igroup + 1) .OR. row > atom_ranges(2, igroup + 1)) cycle
172 imep = imep_sub + igroup*num_pe_sub
174 msg_offset = entry_counter(imep)
176 block_size = row_size*col_size
178 buffer_send(imep)%msg(msg_offset + 1:msg_offset + block_size) = &
179 reshape(data_block(1:row_size, 1:col_size), (/block_size/))
181 entry_counter(imep) = entry_counter(imep) + block_size
183 blk_counter(imep) = blk_counter(imep) + 1
185 block_offset = blk_counter(imep)
187 buffer_send(imep)%indx(block_offset, 1) = row
188 buffer_send(imep)%indx(block_offset, 2) = col
189 buffer_send(imep)%indx(block_offset, 3) = msg_offset
195 CALL dbcsr_iterator_stop(iter)
197 CALL timestop(handle1)
199 CALL timeset(
"send_data", handle1)
201 ALLOCATE (sizes_rec(0:para_env%num_pe - 1))
202 ALLOCATE (sizes_send(0:para_env%num_pe - 1))
204 DO imep = 0, para_env%num_pe - 1
205 sizes_send(imep) = num_entries_blocks_send(2*imep)
206 sizes_rec(imep) = num_entries_blocks_rec(2*imep)
209 CALL communicate_buffer(para_env, sizes_rec, sizes_send, buffer_rec, buffer_send)
211 CALL timestop(handle1)
213 CALL timeset(
"row_block_from_index", handle1)
215 CALL dbcsr_get_info(mat_local, &
216 nblkrows_total=nblkrows_total, &
217 row_blk_offset=row_blk_offset, &
218 row_blk_size=row_blk_size)
220 ALLOCATE (row_block_from_index(nmo))
221 row_block_from_index = 0
224 DO i_block = 1, nblkrows_total
226 IF (i_entry >= row_blk_offset(i_block) .AND. &
227 i_entry <= row_blk_offset(i_block) + row_blk_size(i_block) - 1)
THEN
229 row_block_from_index(i_entry) = i_block
236 CALL timestop(handle1)
238 CALL timeset(
"reserve_blocks", handle1)
243 DO imep = 0, para_env%num_pe - 1
244 num_blocks = num_blocks + num_entries_blocks_rec(2*imep + 1)
247 ALLOCATE (rows_to_alloc(num_blocks))
250 ALLOCATE (cols_to_alloc(num_blocks))
255 DO i_mepos = 0, para_env%num_pe - 1
257 DO i_block = 1, num_entries_blocks_rec(2*i_mepos + 1)
259 block_counter = block_counter + 1
261 rows_to_alloc(block_counter) = buffer_rec(i_mepos)%indx(i_block, 1)
262 cols_to_alloc(block_counter) = buffer_rec(i_mepos)%indx(i_block, 2)
268 CALL dbcsr_set(mat_local, 0.0_dp)
269 CALL dbcsr_filter(mat_local, 1.0_dp)
270 CALL dbcsr_reserve_blocks(mat_local, rows=rows_to_alloc(:), cols=cols_to_alloc(:))
271 CALL dbcsr_finalize(mat_local)
272 CALL dbcsr_set(mat_local, 0.0_dp)
274 CALL timestop(handle1)
276 CALL timeset(
"fill_mat_local", handle1)
278 CALL dbcsr_iterator_start(iter, mat_local)
280 DO WHILE (dbcsr_iterator_blocks_left(iter))
282 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
283 row_size=row_size, col_size=col_size)
285 DO imep = 0, para_env%num_pe - 1
287 DO i_block = 1, num_entries_blocks_rec(2*imep + 1)
289 row_from_buffer = buffer_rec(imep)%indx(i_block, 1)
290 col_from_buffer = buffer_rec(imep)%indx(i_block, 2)
291 offset = buffer_rec(imep)%indx(i_block, 3)
293 IF (row == row_from_buffer .AND. col == col_from_buffer)
THEN
295 data_block(1:row_size, 1:col_size) = &
296 reshape(buffer_rec(imep)%msg(offset + 1:offset + row_size*col_size), &
297 (/row_size, col_size/))
307 CALL dbcsr_iterator_stop(iter)
309 CALL timestop(handle1)
311 DO imep = 0, para_env%num_pe - 1
312 DEALLOCATE (buffer_rec(imep)%msg)
313 DEALLOCATE (buffer_rec(imep)%indx)
314 DEALLOCATE (buffer_send(imep)%msg)
315 DEALLOCATE (buffer_send(imep)%indx)
318 CALL timestop(handle)
416 TYPE(dbcsr_type) :: mat_local, mat_global
419 CHARACTER(LEN=*),
PARAMETER :: routinen =
'local_matrix_to_global_matrix'
421 INTEGER :: block_size, c, col, col_size, handle, &
422 handle1, i_block, imep, o, offset, r, &
423 rec_counter, row, row_size, &
425 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: block_counter, entry_counter, num_blocks_rec, &
426 num_blocks_send, num_entries_rec, num_entries_send, sizes_rec, sizes_send
427 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: data_block
428 TYPE(buffer_type),
ALLOCATABLE,
DIMENSION(:) :: buffer_rec, buffer_send
429 TYPE(dbcsr_iterator_type) :: iter
430 TYPE(dbcsr_type) :: mat_global_copy
433 CALL timeset(routinen, handle)
435 CALL timeset(
"get_coord", handle1)
437 CALL dbcsr_create(mat_global_copy, template=mat_global)
438 CALL dbcsr_reserve_all_blocks(mat_global_copy)
440 CALL dbcsr_set(mat_global, 0.0_dp)
441 CALL dbcsr_set(mat_global_copy, 0.0_dp)
443 ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
444 ALLOCATE (buffer_send(0:para_env%num_pe - 1))
446 ALLOCATE (num_entries_rec(0:para_env%num_pe - 1))
447 ALLOCATE (num_blocks_rec(0:para_env%num_pe - 1))
448 ALLOCATE (num_entries_send(0:para_env%num_pe - 1))
449 ALLOCATE (num_blocks_send(0:para_env%num_pe - 1))
455 CALL dbcsr_iterator_start(iter, mat_local)
456 DO WHILE (dbcsr_iterator_blocks_left(iter))
458 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
459 row_size=row_size, col_size=col_size)
461 CALL dbcsr_get_stored_coordinates(mat_global, row, col, imep)
463 num_entries_send(imep) = num_entries_send(imep) + row_size*col_size
464 num_blocks_send(imep) = num_blocks_send(imep) + 1
468 CALL dbcsr_iterator_stop(iter)
470 CALL timestop(handle1)
472 CALL timeset(
"comm_size", handle1)
474 IF (para_env%num_pe > 1)
THEN
476 ALLOCATE (sizes_rec(0:2*para_env%num_pe - 1))
477 ALLOCATE (sizes_send(0:2*para_env%num_pe - 1))
479 DO imep = 0, para_env%num_pe - 1
481 sizes_send(2*imep) = num_entries_send(imep)
482 sizes_send(2*imep + 1) = num_blocks_send(imep)
486 CALL para_env%alltoall(sizes_send, sizes_rec, 2)
488 DO imep = 0, para_env%num_pe - 1
489 num_entries_rec(imep) = sizes_rec(2*imep)
490 num_blocks_rec(imep) = sizes_rec(2*imep + 1)
493 DEALLOCATE (sizes_rec, sizes_send)
497 num_entries_rec(0) = num_entries_send(0)
498 num_blocks_rec(0) = num_blocks_send(0)
502 CALL timestop(handle1)
504 CALL timeset(
"fill_buffer", handle1)
507 DO imep = 0, para_env%num_pe - 1
509 ALLOCATE (buffer_rec(imep)%msg(num_entries_rec(imep)))
510 buffer_rec(imep)%msg = 0.0_dp
512 ALLOCATE (buffer_send(imep)%msg(num_entries_send(imep)))
513 buffer_send(imep)%msg = 0.0_dp
515 ALLOCATE (buffer_rec(imep)%indx(num_blocks_rec(imep), 5))
516 buffer_rec(imep)%indx = 0
518 ALLOCATE (buffer_send(imep)%indx(num_blocks_send(imep), 5))
519 buffer_send(imep)%indx = 0
523 ALLOCATE (block_counter(0:para_env%num_pe - 1))
526 ALLOCATE (entry_counter(0:para_env%num_pe - 1))
530 CALL dbcsr_iterator_start(iter, mat_local)
531 DO WHILE (dbcsr_iterator_blocks_left(iter))
533 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
534 row_size=row_size, col_size=col_size)
536 CALL dbcsr_get_stored_coordinates(mat_global, row, col, imep)
538 block_size = row_size*col_size
540 offset = entry_counter(imep)
542 buffer_send(imep)%msg(offset + 1:offset + block_size) = &
543 reshape(data_block(1:row_size, 1:col_size), (/block_size/))
545 i_block = block_counter(imep) + 1
547 buffer_send(imep)%indx(i_block, 1) = row
548 buffer_send(imep)%indx(i_block, 2) = col
549 buffer_send(imep)%indx(i_block, 3) = offset
551 entry_counter(imep) = entry_counter(imep) + block_size
553 block_counter(imep) = block_counter(imep) + 1
557 CALL dbcsr_iterator_stop(iter)
559 CALL timestop(handle1)
561 CALL timeset(
"comm_data", handle1)
564 ALLOCATE (req(1:para_env%num_pe, 4))
566 IF (para_env%num_pe > 1)
THEN
571 DO imep = 0, para_env%num_pe - 1
572 IF (num_entries_rec(imep) > 0)
THEN
573 rec_counter = rec_counter + 1
574 CALL para_env%irecv(buffer_rec(imep)%indx, imep, req(rec_counter, 3), tag=4)
576 IF (num_entries_rec(imep) > 0)
THEN
577 CALL para_env%irecv(buffer_rec(imep)%msg, imep, req(rec_counter, 4), tag=7)
581 DO imep = 0, para_env%num_pe - 1
582 IF (num_entries_send(imep) > 0)
THEN
583 send_counter = send_counter + 1
584 CALL para_env%isend(buffer_send(imep)%indx, imep, req(send_counter, 1), tag=4)
586 IF (num_entries_send(imep) > 0)
THEN
587 CALL para_env%isend(buffer_send(imep)%msg, imep, req(send_counter, 2), tag=7)
596 buffer_rec(0)%indx = buffer_send(0)%indx
597 buffer_rec(0)%msg = buffer_send(0)%msg
601 CALL timestop(handle1)
603 CALL timeset(
"set_blocks", handle1)
606 CALL dbcsr_iterator_start(iter, mat_global_copy)
607 DO WHILE (dbcsr_iterator_blocks_left(iter))
609 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
610 row_size=row_size, col_size=col_size)
612 DO imep = 0, para_env%num_pe - 1
614 DO i_block = 1, num_blocks_rec(imep)
616 IF (row == buffer_rec(imep)%indx(i_block, 1) .AND. &
617 col == buffer_rec(imep)%indx(i_block, 2))
THEN
619 offset = buffer_rec(imep)%indx(i_block, 3)
625 data_block(1:r, 1:c) = data_block(1:r, 1:c) + &
626 reshape(buffer_rec(imep)%msg(o + 1:o + r*c), (/r, c/))
636 CALL dbcsr_iterator_stop(iter)
638 CALL dbcsr_copy(mat_global, mat_global_copy)
640 CALL dbcsr_release(mat_global_copy)
643 CALL dbcsr_filter(mat_global, 1.0e-30_dp)
645 DO imep = 0, para_env%num_pe - 1
646 DEALLOCATE (buffer_rec(imep)%msg)
647 DEALLOCATE (buffer_send(imep)%msg)
648 DEALLOCATE (buffer_rec(imep)%indx)
649 DEALLOCATE (buffer_send(imep)%indx)
652 DEALLOCATE (buffer_rec, buffer_send)
654 DEALLOCATE (block_counter, entry_counter)
658 CALL dbcsr_set(mat_local, 0.0_dp)
659 CALL dbcsr_filter(mat_local, 1.0_dp)
661 CALL timestop(handle1)
663 CALL timestop(handle)