48 SUBROUTINE cp_fm_permute(fm_out, fm_in, beta, nrow_secidx_in, ncol_secidx_in, &
49 nrow_secidx_out, ncol_secidx_out, reordering, row_offset, col_offset, &
50 first_index, last_index)
53 REAL(kind=
dp),
INTENT(IN) :: beta
54 INTEGER,
INTENT(IN) :: nrow_secidx_in, ncol_secidx_in, &
55 nrow_secidx_out, ncol_secidx_out
56 INTEGER,
DIMENSION(4),
INTENT(IN) :: reordering
57 INTEGER,
INTENT(IN),
OPTIONAL :: row_offset, col_offset
58 INTEGER,
DIMENSION(4),
INTENT(IN),
OPTIONAL :: first_index, last_index
60 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_permute'
62 INTEGER :: handle, i, idx_col, idx_row, ientry, ii, &
63 iproc, j, jj, my_col_offset, &
64 my_row_offset, ncol_local, nprocs, &
66 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: entry_counter, num_entries_rec, &
68 INTEGER,
DIMENSION(4) :: first, indices, last, mapped
69 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
73 CALL timeset(routinen, handle)
74 para_env => fm_out%matrix_struct%para_env
75 nprocs = para_env%num_pe
78 IF (
PRESENT(row_offset)) my_row_offset = row_offset
79 IF (
PRESENT(col_offset)) my_col_offset = col_offset
81 last = [fm_in%matrix_struct%nrow_global/nrow_secidx_in, nrow_secidx_in, &
82 fm_in%matrix_struct%ncol_global/ncol_secidx_in, ncol_secidx_in]
83 IF (
PRESENT(first_index)) first = first_index
84 IF (
PRESENT(last_index)) last = last_index
86 CALL cp_fm_get_info(fm_in, nrow_local=nrow_local, ncol_local=ncol_local, &
87 row_indices=row_indices, col_indices=col_indices)
88 ALLOCATE (num_entries_send(0:nprocs - 1), num_entries_rec(0:nprocs - 1), &
89 entry_counter(0:nprocs - 1))
95 CALL para_env%alltoall(num_entries_send, num_entries_rec, 1)
97 entry_counter(:) = buffer_send%msg_offset(:nprocs - 1)
101 indices(1) = (row_indices(i) - 1)/nrow_secidx_in + 1
102 indices(2) = mod(row_indices(i) - 1, nrow_secidx_in) + 1
104 indices(3) = (col_indices(j) - 1)/ncol_secidx_in + 1
105 indices(4) = mod(col_indices(j) - 1, ncol_secidx_in) + 1
106 IF (any(indices < first) .OR. any(indices > last)) cycle
107 mapped = indices - first + 1
108 idx_row = my_row_offset + mapped(reordering(2)) + &
109 (mapped(reordering(1)) - 1)*nrow_secidx_out
110 idx_col = my_col_offset + mapped(reordering(4)) + &
111 (mapped(reordering(3)) - 1)*ncol_secidx_out
112 iproc = fm_out%matrix_struct%context%blacs2mpi( &
113 fm_out%matrix_struct%g2p_row(idx_row), fm_out%matrix_struct%g2p_col(idx_col))
115 num_entries_send(iproc) = num_entries_send(iproc) + 1
117 entry_counter(iproc) = entry_counter(iproc) + 1
118 ientry = entry_counter(iproc)
119 buffer_send%msg(ientry) = fm_in%local_data(i, j)
120 buffer_send%indx(:, ientry) = [idx_row, idx_col]
131 DO ientry = 1,
SIZE(buffer_rec%msg)
132 ii = fm_out%matrix_struct%g2l_row(buffer_rec%indx(1, ientry))
133 jj = fm_out%matrix_struct%g2l_col(buffer_rec%indx(2, ientry))
134 fm_out%local_data(ii, jj) = fm_out%local_data(ii, jj) + beta*buffer_rec%msg(ientry)
137 CALL timestop(handle)
152 my_start_col, my_end_col, fm_mat, do_release_mat)
153 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
154 INTENT(INOUT) :: mat2d
156 INTEGER,
INTENT(IN) :: my_start_row, my_end_row, my_start_col, &
159 LOGICAL,
INTENT(IN),
OPTIONAL :: do_release_mat
161 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_array_to_fm'
163 INTEGER :: handle, i, ientry, j, pass, peer
164 INTEGER,
ALLOCATABLE :: cursor(:), recv_count(:), send_count(:)
165 LOGICAL :: release_mat
169 CALL timeset(routinen, handle)
170 para_env => fm_struct%para_env
172 IF (
PRESENT(do_release_mat)) release_mat = do_release_mat
173 CALL cp_fm_create(fm_mat, fm_struct, name=
"fm_mat", set_zero=.true.)
174 ALLOCATE (send_count(0:para_env%num_pe - 1), recv_count(0:para_env%num_pe - 1), &
175 cursor(0:para_env%num_pe - 1))
180 CALL para_env%alltoall(send_count, recv_count, 1)
182 cursor(:) = buffer_send%msg_offset(:para_env%num_pe - 1)
184 DO j = my_start_col, my_end_col
185 DO i = my_start_row, my_end_row
186 peer = fm_struct%context%blacs2mpi(fm_struct%g2p_row(i), fm_struct%g2p_col(j))
188 send_count(peer) = send_count(peer) + 1
190 cursor(peer) = cursor(peer) + 1
191 ientry = cursor(peer)
192 buffer_send%indx(:, ientry) = [i, j]
193 buffer_send%msg(ientry) = mat2d(i - my_start_row + 1, j - my_start_col + 1)
198 IF (release_mat)
DEALLOCATE (mat2d)
200 DO ientry = 1,
SIZE(buffer_rec%msg)
201 i = fm_struct%g2l_row(buffer_rec%indx(1, ientry))
202 j = fm_struct%g2l_col(buffer_rec%indx(2, ientry))
203 fm_mat%local_data(i, j) = buffer_rec%msg(ientry)
205 CALL timestop(handle)
217 SUBROUTINE cp_fm_to_array(mat2D, my_start_row, my_end_row, my_start_col, my_end_col, fm_mat)
218 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
220 INTEGER,
INTENT(IN) :: my_start_row, my_end_row, my_start_col, &
224 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_to_array'
226 INTEGER :: handle, i, ientry, j, ncols, nrows, peer
227 INTEGER,
ALLOCATABLE :: bounds(:, :), recv_count(:), &
229 INTEGER,
POINTER :: col_indices(:), row_indices(:)
233 CALL timeset(routinen, handle)
234 CALL cp_fm_get_info(fm_mat, nrow_local=nrows, ncol_local=ncols, row_indices=row_indices, &
235 col_indices=col_indices, para_env=para_env)
236 ALLOCATE (mat2d(my_end_row - my_start_row + 1, my_end_col - my_start_col + 1))
238 ALLOCATE (bounds(4, 0:para_env%num_pe - 1), send_count(0:para_env%num_pe - 1), &
239 recv_count(0:para_env%num_pe - 1))
240 CALL para_env%allgather([my_start_row, my_end_row, my_start_col, my_end_col], bounds)
243 DO peer = 0, para_env%num_pe - 1
244 bounds(:, peer) = [count(row_indices(:nrows) < bounds(1, peer)) + 1, &
245 count(row_indices(:nrows) <= bounds(2, peer)), &
246 count(col_indices(:ncols) < bounds(3, peer)) + 1, &
247 count(col_indices(:ncols) <= bounds(4, peer))]
248 send_count(peer) = max(0, bounds(2, peer) - bounds(1, peer) + 1)* &
249 max(0, bounds(4, peer) - bounds(3, peer) + 1)
251 CALL para_env%alltoall(send_count, recv_count, 1)
253 DO peer = 0, para_env%num_pe - 1
254 IF (send_count(peer) == 0) cycle
255 ientry = buffer_send%msg_offset(peer)
256 DO j = bounds(3, peer), bounds(4, peer)
257 DO i = bounds(1, peer), bounds(2, peer)
259 buffer_send%indx(:, ientry) = [row_indices(i), col_indices(j)]
260 buffer_send%msg(ientry) = fm_mat%local_data(i, j)
265 DO ientry = 1,
SIZE(buffer_rec%msg)
266 i = buffer_rec%indx(1, ientry) - my_start_row + 1
267 j = buffer_rec%indx(2, ientry) - my_start_col + 1
268 mat2d(i, j) = buffer_rec%msg(ientry)
271 CALL timestop(handle)
284 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: array_s
285 REAL(kind=
dp),
OPTIONAL :: weight
286 LOGICAL,
OPTIONAL :: add
288 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_fm_to_replicated_array'
290 INTEGER :: handle, i, i_row_local, img, j, &
291 j_col_local, n_basis, ncol_local, &
293 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
295 REAL(kind=
dp) :: my_weight
296 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: array_tmp
298 CALL timeset(routinen, handle)
301 IF (
PRESENT(weight)) my_weight = weight
304 IF (
PRESENT(add)) my_add = add
306 n_basis =
SIZE(array_s, 1)
307 nimages =
SIZE(array_s, 3)
310 cpassert(
SIZE(array_s, 2) == n_basis)
311 cpassert(
SIZE(fm_s) == nimages)
312 cpassert(lbound(array_s, 1) == 1)
313 cpassert(lbound(array_s, 2) == 1)
314 cpassert(lbound(array_s, 3) == 1)
317 nrow_local=nrow_local, &
318 ncol_local=ncol_local, &
319 row_indices=row_indices, &
320 col_indices=col_indices)
322 IF (.NOT. my_add) array_s(:, :, :) = 0.0_dp
323 ALLOCATE (array_tmp(
SIZE(array_s, 1),
SIZE(array_s, 2),
SIZE(array_s, 3)))
324 array_tmp(:, :, :) = 0.0_dp
327 DO i_row_local = 1, nrow_local
328 i = row_indices(i_row_local)
329 DO j_col_local = 1, ncol_local
330 j = col_indices(j_col_local)
331 array_tmp(i, j, img) = fm_s(img)%local_data(i_row_local, j_col_local)
336 CALL fm_s(1)%matrix_struct%para_env%sum(array_tmp)
338 array_s(:, :, :) = array_s(:, :, :) + my_weight*array_tmp(:, :, :)
340 CALL timestop(handle)
355 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
358 INTEGER,
INTENT(IN) :: first_col, last_col, nrows
360 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cp_array_columns_to_fm'
362 INTEGER :: handle, i, ientry, j, nprocs, pass, peer
363 INTEGER,
ALLOCATABLE :: counter(:), recv_count(:), send_count(:)
366 CALL timeset(routinen, handle)
367 nprocs = para_env%num_pe
368 ALLOCATE (send_count(0:nprocs - 1), recv_count(0:nprocs - 1), counter(0:nprocs - 1))
372 CALL para_env%alltoall(send_count, recv_count, 1)
374 counter(:) = buffer_send%msg_offset(:nprocs - 1)
376 DO j = first_col, last_col
378 peer = matrix%matrix_struct%context%blacs2mpi( &
379 matrix%matrix_struct%g2p_row(i), matrix%matrix_struct%g2p_col(j))
381 send_count(peer) = send_count(peer) + 1
383 counter(peer) = counter(peer) + 1
384 ientry = counter(peer)
385 buffer_send%msg(ientry) = array(i, j - first_col + 1)
386 buffer_send%indx(:, ientry) = [i, j]
393 matrix%local_data = 0.0_dp
394 DO ientry = 1,
SIZE(buffer_rec%msg)
395 i = matrix%matrix_struct%g2l_row(buffer_rec%indx(1, ientry))
396 j = matrix%matrix_struct%g2l_col(buffer_rec%indx(2, ientry))
397 matrix%local_data(i, j) = buffer_rec%msg(ientry)
399 CALL timestop(handle)
subroutine, public cp_fm_permute(fm_out, fm_in, beta, nrow_secidx_in, ncol_secidx_in, nrow_secidx_out, ncol_secidx_out, reordering, row_offset, col_offset, first_index, last_index)
Add a permuted or restricted four-index tensor stored as a full matrix.
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix