39#include "./base/base_uses.f90"
45 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mp2_ri_gpw'
72 SUBROUTINE mp2_ri_gpw_compute_en(Emp2_Cou, Emp2_EX, Emp2_S, Emp2_T, BIb_C, mp2_env, para_env, para_env_sub, color_sub, &
73 gd_array, gd_B_virtual, &
74 Eigenval, nmo, homo, dimen_RI, unit_nr, calc_forces, calc_ex)
75 REAL(kind=
dp),
INTENT(INOUT) :: emp2_cou, emp2_ex, emp2_s, emp2_t
77 INTENT(INOUT) :: bib_c
80 INTEGER,
INTENT(IN) :: color_sub
82 INTEGER,
DIMENSION(:),
INTENT(IN) :: homo
83 INTEGER,
INTENT(IN) :: nmo
84 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: eigenval
86 INTENT(INOUT) :: gd_b_virtual
87 INTEGER,
INTENT(IN) :: dimen_ri, unit_nr
88 LOGICAL,
INTENT(IN) :: calc_forces, calc_ex
90 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_ri_gpw_compute_en'
92 INTEGER :: a, a_global, b, b_global, block_size, decil, end_point, handle, handle2, handle3, &
93 iib, ij_counter, ij_counter_send, ij_index, integ_group_size, ispin, jjb, jspin, &
94 max_ij_pairs, my_block_size, my_group_l_end, my_group_l_size, my_group_l_size_orig, &
95 my_group_l_start, my_i, my_ij_pairs, my_j, my_new_group_l_size, ngroup, nspins, &
96 num_integ_group, proc_receive, proc_send, proc_shift, rec_b_size, rec_b_virtual_end, &
97 rec_b_virtual_start, rec_l_size, send_b_size, send_b_virtual_end, send_b_virtual_start, &
98 send_i, send_ij_index, send_j, start_point, tag, total_ij_pairs
99 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: integ_group_pos2color_sub, my_b_size, &
100 my_b_virtual_end, my_b_virtual_start, num_ij_pairs, sizes_array_orig, virtual
101 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: ij_map
102 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: ranges_info_array
103 LOGICAL :: my_alpha_beta_case, my_beta_beta_case, &
105 REAL(kind=
dp) :: amp_fac, my_emp2_cou, my_emp2_ex, &
106 sym_fac, t_new, t_start
107 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:),
TARGET :: buffer_1d
108 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
109 TARGET :: local_ab, local_ba, t_ab
110 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
111 TARGET :: local_i_al, local_j_al, y_i_ap, y_j_ap
112 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
113 POINTER :: external_ab, external_i_al
114 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :, :), &
119 DIMENSION(:) :: b_ia_q
121 CALL timeset(routinen, handle)
125 ALLOCATE (virtual(nspins))
126 virtual(:) = nmo - homo(:)
128 ALLOCATE (my_b_size(nspins), my_b_virtual_start(nspins), my_b_virtual_end(nspins))
131 my_b_virtual_start(ispin), my_b_virtual_end(ispin), my_b_size(ispin))
134 CALL get_group_dist(gd_array, color_sub, my_group_l_start, my_group_l_end, my_group_l_size)
141 CALL mp2_env%local_gemm_ctx%set_op_threshold_gpu(128*128*128*2)
143 CALL mp2_ri_get_integ_group_size( &
144 mp2_env, para_env, para_env_sub, gd_array, gd_b_virtual, &
145 homo, dimen_ri, unit_nr, &
146 integ_group_size, ngroup, &
147 num_integ_group, virtual, calc_forces)
151 CALL mp2_ri_create_group( &
152 para_env, para_env_sub, color_sub, &
153 gd_array%sizes, calc_forces, &
154 integ_group_size, my_group_l_end, &
155 my_group_l_size, my_group_l_size_orig, my_group_l_start, my_new_group_l_size, &
156 integ_group_pos2color_sub, sizes_array_orig, &
157 ranges_info_array, comm_exchange, comm_rep, num_integ_group)
164 CALL replicate_iak_2intgroup(bib_c(jspin)%array, comm_exchange, comm_rep, &
165 homo(jspin), gd_array%sizes, my_b_size(jspin), &
166 my_group_l_size, ranges_info_array)
170 IF (unit_nr > 0)
THEN
171 IF (nspins == 1)
THEN
172 WRITE (unit_nr, *)
"Start loop run"
173 ELSE IF (ispin == 1 .AND. jspin == 1)
THEN
174 WRITE (unit_nr, *)
"Start loop run alpha-alpha"
175 ELSE IF (ispin == 1 .AND. jspin == 2)
THEN
176 WRITE (unit_nr, *)
"Start loop run alpha-beta"
177 ELSE IF (ispin == 2 .AND. jspin == 2)
THEN
178 WRITE (unit_nr, *)
"Start loop run beta-beta"
183 my_open_shell_ss = (nspins == 2) .AND. (ispin == jspin)
189 my_beta_beta_case = .false.
190 my_alpha_beta_case = .false.
191 IF (ispin /= jspin)
THEN
192 my_alpha_beta_case = .true.
193 ELSE IF (my_open_shell_ss)
THEN
194 IF (ispin == 2) my_beta_beta_case = .true.
197 amp_fac = mp2_env%scale_S + mp2_env%scale_T
198 IF (my_alpha_beta_case .OR. my_open_shell_ss) amp_fac = mp2_env%scale_T
200 CALL mp2_ri_allocate_no_blk(local_ab, t_ab, mp2_env, homo, virtual, my_b_size, &
201 my_group_l_size, calc_forces, ispin, jspin, local_ba)
203 CALL mp2_ri_get_block_size( &
204 mp2_env, para_env, para_env_sub, gd_array, gd_b_virtual(ispin:jspin), &
205 homo(ispin:jspin), virtual(ispin:jspin), dimen_ri, unit_nr, block_size, &
206 ngroup, num_integ_group, my_open_shell_ss, calc_forces, buffer_1d)
216 CALL mp2_ri_communication(my_alpha_beta_case, total_ij_pairs, homo(ispin), homo(jspin), &
217 block_size, ngroup, ij_map, color_sub, my_ij_pairs, my_open_shell_ss, unit_nr)
219 ALLOCATE (num_ij_pairs(0:comm_exchange%num_pe - 1))
220 CALL comm_exchange%allgather(my_ij_pairs, num_ij_pairs)
222 max_ij_pairs = maxval(num_ij_pairs)
225 CALL mp2_ri_allocate_blk(dimen_ri, my_b_size, block_size, local_i_al, &
226 local_j_al, calc_forces, y_i_ap, y_j_ap, ispin, jspin)
228 CALL timeset(routinen//
"_RI_loop", handle2)
232 DO ij_index = 1, max_ij_pairs
235 IF (unit_nr > 0 .AND. ij_index > 1)
THEN
236 decil = ij_index*10/max_ij_pairs
237 IF (decil /= (ij_index - 1)*10/max_ij_pairs)
THEN
239 t_new = (t_new - t_start)/60.0_dp*(max_ij_pairs - ij_index + 1)/(ij_index - 1)
240 WRITE (unit_nr, fmt=
"(T3,A)")
"Percentage of finished loop: "// &
246 IF (calc_forces)
THEN
251 IF (ij_index <= my_ij_pairs)
THEN
253 ij_counter = (ij_index - min(1, color_sub))*ngroup + color_sub
254 my_i = ij_map(1, ij_counter)
255 my_j = ij_map(2, ij_counter)
256 my_block_size = ij_map(3, ij_counter)
259 CALL fill_local_i_al(local_i_al(:, :, 1:my_block_size), ranges_info_array(:, :, comm_exchange%mepos), &
260 bib_c(ispin)%array(:, :, my_i:my_i + my_block_size - 1))
263 CALL fill_local_i_al(local_j_al(:, :, 1:my_block_size), ranges_info_array(:, :, comm_exchange%mepos), &
264 bib_c(jspin)%array(:, :, my_j:my_j + my_block_size - 1))
267 CALL timeset(routinen//
"_comm", handle3)
268 DO proc_shift = 1, comm_exchange%num_pe - 1
269 proc_send =
modulo(comm_exchange%mepos + proc_shift, comm_exchange%num_pe)
270 proc_receive =
modulo(comm_exchange%mepos - proc_shift, comm_exchange%num_pe)
272 send_ij_index = num_ij_pairs(proc_send)
276 IF (ij_index <= send_ij_index)
THEN
277 ij_counter_send = (ij_index - min(1, integ_group_pos2color_sub(proc_send)))*ngroup + &
278 integ_group_pos2color_sub(proc_send)
279 send_i = ij_map(1, ij_counter_send)
280 send_j = ij_map(2, ij_counter_send)
283 bi_c_rec(1:rec_l_size, 1:my_b_size(ispin), 1:my_block_size) => &
284 buffer_1d(1:rec_l_size*my_b_size(ispin)*my_block_size)
286 CALL comm_exchange%sendrecv(bib_c(ispin)%array(:, :, send_i:send_i + my_block_size - 1), &
287 proc_send, bi_c_rec, proc_receive, tag)
289 CALL fill_local_i_al(local_i_al(:, :, 1:my_block_size), ranges_info_array(:, :, proc_receive), &
290 bi_c_rec(:, 1:my_b_size(ispin), :))
293 bi_c_rec(1:rec_l_size, 1:my_b_size(jspin), 1:my_block_size) => &
294 buffer_1d(1:int(rec_l_size,
int_8)*my_b_size(jspin)*my_block_size)
296 CALL comm_exchange%sendrecv(bib_c(jspin)%array(:, :, send_j:send_j + my_block_size - 1), &
297 proc_send, bi_c_rec, proc_receive, tag)
299 CALL fill_local_i_al(local_j_al(:, :, 1:my_block_size), ranges_info_array(:, :, proc_receive), &
300 bi_c_rec(:, 1:my_b_size(jspin), :))
306 bi_c_rec(1:rec_l_size, 1:my_b_size(ispin), 1:my_block_size) => &
307 buffer_1d(1:int(rec_l_size,
int_8)*my_b_size(ispin)*my_block_size)
309 CALL comm_exchange%recv(bi_c_rec, proc_receive, tag)
311 CALL fill_local_i_al(local_i_al(:, :, 1:my_block_size), ranges_info_array(:, :, proc_receive), &
312 bi_c_rec(:, 1:my_b_size(ispin), 1:my_block_size))
315 bi_c_rec(1:rec_l_size, 1:my_b_size(jspin), 1:my_block_size) => &
316 buffer_1d(1:int(rec_l_size,
int_8)*my_b_size(jspin)*my_block_size)
318 CALL comm_exchange%recv(bi_c_rec, proc_receive, tag)
320 CALL fill_local_i_al(local_j_al(:, :, 1:my_block_size), ranges_info_array(:, :, proc_receive), &
321 bi_c_rec(:, 1:my_b_size(jspin), 1:my_block_size))
327 CALL timestop(handle3)
330 DO iib = 1, my_block_size
331 DO jjb = 1, my_block_size
332 CALL timeset(routinen//
"_expansion", handle3)
333 associate(my_local_i_al => local_i_al(:, :, iib), my_local_j_al => local_j_al(:, :, jjb))
337 IF ((my_alpha_beta_case) .AND. (calc_forces))
THEN
341 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', my_b_size(ispin), my_b_size(jspin), dimen_ri, 1.0_dp, &
342 my_local_i_al, dimen_ri, my_local_j_al, dimen_ri, &
343 0.0_dp, local_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), :), &
346 IF (my_alpha_beta_case .AND. calc_forces)
THEN
347 local_ba(my_b_virtual_start(jspin):my_b_virtual_end(jspin), :) = &
348 transpose(local_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), :))
351 DO proc_shift = 1, para_env_sub%num_pe - 1
352 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
353 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
355 CALL get_group_dist(gd_b_virtual(ispin), proc_receive, rec_b_virtual_start, &
356 rec_b_virtual_end, rec_b_size)
358 external_i_al(1:dimen_ri, 1:rec_b_size) => buffer_1d(1:int(dimen_ri,
int_8)*rec_b_size)
359 external_i_al = 0.0_dp
361 CALL para_env_sub%sendrecv(my_local_i_al, proc_send, &
362 external_i_al, proc_receive, tag)
364 CALL mp2_env%local_gemm_ctx%gemm( &
365 'T',
'N', rec_b_size, my_b_size(jspin), dimen_ri, 1.0_dp, &
366 external_i_al, dimen_ri, my_local_j_al, dimen_ri, &
367 0.0_dp, local_ab(rec_b_virtual_start:rec_b_virtual_end, 1:my_b_size(jspin)), rec_b_size)
370 IF (my_alpha_beta_case .AND. calc_forces)
THEN
372 CALL get_group_dist(gd_b_virtual(jspin), proc_receive, rec_b_virtual_start, &
373 rec_b_virtual_end, rec_b_size)
375 external_i_al(1:dimen_ri, 1:rec_b_size) => buffer_1d(1:int(dimen_ri,
int_8)*rec_b_size)
376 external_i_al = 0.0_dp
378 CALL para_env_sub%sendrecv(my_local_j_al, proc_send, &
379 external_i_al, proc_receive, tag)
381 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', rec_b_size, my_b_size(ispin), dimen_ri, 1.0_dp, &
382 external_i_al, dimen_ri, my_local_i_al, dimen_ri, &
383 0.0_dp, local_ba(rec_b_virtual_start:rec_b_virtual_end, 1:my_b_size(ispin)), rec_b_size)
386 IF (my_alpha_beta_case .AND. calc_forces)
THEN
389 CALL dgemm_counter_stop(dgemm_counter, virtual(ispin), my_b_size(ispin) + my_b_size(jspin), dimen_ri)
393 CALL timestop(handle3)
398 CALL timeset(routinen//
"_ener", handle3)
401 IF (my_i == my_j) sym_fac = 1.0_dp
402 IF (my_alpha_beta_case) sym_fac = 0.5_dp
403 DO b = 1, my_b_size(jspin)
404 b_global = b + my_b_virtual_start(jspin) - 1
405 DO a = 1, virtual(ispin)
406 my_emp2_cou = my_emp2_cou - sym_fac*2.0_dp*local_ab(a, b)**2/ &
407 (eigenval(homo(ispin) + a, ispin) + eigenval(homo(jspin) + b_global, jspin) - &
408 eigenval(my_i + iib - 1, ispin) - eigenval(my_j + jjb - 1, jspin))
415 IF (calc_forces .AND. (.NOT. my_alpha_beta_case)) t_ab = 0.0_dp
416 DO b = 1, my_b_size(ispin)
417 b_global = b + my_b_virtual_start(ispin) - 1
418 DO a = 1, my_b_size(ispin)
419 a_global = a + my_b_virtual_start(ispin) - 1
420 my_emp2_ex = my_emp2_ex + sym_fac*local_ab(a_global, b)*local_ab(b_global, a)/ &
421 (eigenval(homo(ispin) + a_global, ispin) + eigenval(homo(ispin) + b_global, ispin) - &
422 eigenval(my_i + iib - 1, ispin) - eigenval(my_j + jjb - 1, ispin))
423 IF (calc_forces .AND. (.NOT. my_alpha_beta_case))
THEN
424 t_ab(a_global, b) = -(amp_fac*local_ab(a_global, b) - mp2_env%scale_T*local_ab(b_global, a))/ &
425 (eigenval(homo(ispin) + a_global, ispin) + &
426 eigenval(homo(ispin) + b_global, ispin) - &
427 eigenval(my_i + iib - 1, ispin) - eigenval(my_j + jjb - 1, ispin))
432 DO proc_shift = 1, para_env_sub%num_pe - 1
433 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
434 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
437 rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
439 send_b_virtual_start, send_b_virtual_end, send_b_size)
441 external_ab(1:my_b_size(ispin), 1:rec_b_size) => &
442 buffer_1d(1:int(rec_b_size,
int_8)*my_b_size(ispin))
445 CALL para_env_sub%sendrecv(local_ab(send_b_virtual_start:send_b_virtual_end, 1:my_b_size(ispin)), proc_send, &
446 external_ab(1:my_b_size(ispin), 1:rec_b_size), proc_receive, tag)
448 DO b = 1, my_b_size(ispin)
449 b_global = b + my_b_virtual_start(ispin) - 1
451 a_global = a + rec_b_virtual_start - 1
452 my_emp2_ex = my_emp2_ex + sym_fac*local_ab(a_global, b)*external_ab(b, a)/ &
453 (eigenval(homo(ispin) + a_global, ispin) + eigenval(homo(ispin) + b_global, ispin) - &
454 eigenval(my_i + iib - 1, ispin) - eigenval(my_j + jjb - 1, ispin))
455 IF (calc_forces .AND. (.NOT. my_alpha_beta_case))
THEN
456 t_ab(a_global, b) = -(amp_fac*local_ab(a_global, b) - mp2_env%scale_T*external_ab(b, a))/ &
457 (eigenval(homo(ispin) + a_global, ispin) + &
458 eigenval(homo(ispin) + b_global, ispin) - &
459 eigenval(my_i + iib - 1, ispin) - eigenval(my_j + jjb - 1, ispin))
465 CALL timestop(handle3)
467 IF (calc_forces)
THEN
469 CALL mp2_update_p_gamma(mp2_env, para_env_sub, gd_b_virtual, &
470 eigenval, homo, dimen_ri, iib, jjb, my_b_size, &
471 my_b_virtual_end, my_b_virtual_start, my_i, my_j, virtual, &
472 local_ab, t_ab, my_local_i_al, my_local_j_al, &
473 my_open_shell_ss, y_i_ap(:, :, iib), y_j_ap(:, :, jjb), local_ba, &
474 ispin, jspin, dgemm_counter, buffer_1d)
487 CALL timeset(routinen//
"_comm", handle3)
490 DO proc_shift = 1, comm_exchange%num_pe - 1
491 proc_send =
modulo(comm_exchange%mepos + proc_shift, comm_exchange%num_pe)
492 proc_receive =
modulo(comm_exchange%mepos - proc_shift, comm_exchange%num_pe)
494 send_ij_index = num_ij_pairs(proc_send)
496 IF (ij_index <= send_ij_index)
THEN
498 ij_counter_send = (ij_index - min(1, integ_group_pos2color_sub(proc_send)))*ngroup + &
499 integ_group_pos2color_sub(proc_send)
500 send_i = ij_map(1, ij_counter_send)
501 send_j = ij_map(2, ij_counter_send)
504 CALL comm_exchange%send(bib_c(ispin)%array(:, :, send_i:send_i + my_block_size - 1), &
507 CALL comm_exchange%send(bib_c(jspin)%array(:, :, send_j:send_j + my_block_size - 1), &
511 CALL timestop(handle3)
515 IF (calc_forces)
THEN
516 CALL mp2_redistribute_gamma(mp2_env%ri_grad%Gamma_P_ia(ispin)%array, ij_index, my_b_size(ispin), &
517 my_block_size, my_group_l_size, my_i, my_ij_pairs, ngroup, &
518 num_integ_group, integ_group_pos2color_sub, num_ij_pairs, &
519 ij_map, ranges_info_array, y_i_ap(:, :, 1:my_block_size), comm_exchange, &
520 gd_array%sizes, 1, buffer_1d)
521 CALL mp2_redistribute_gamma(mp2_env%ri_grad%Gamma_P_ia(jspin)%array, ij_index, my_b_size(jspin), &
522 my_block_size, my_group_l_size, my_j, my_ij_pairs, ngroup, &
523 num_integ_group, integ_group_pos2color_sub, num_ij_pairs, &
524 ij_map, ranges_info_array, y_j_ap(:, :, 1:my_block_size), comm_exchange, &
525 gd_array%sizes, 2, buffer_1d)
529 CALL timestop(handle2)
531 DEALLOCATE (local_i_al)
532 DEALLOCATE (local_j_al)
534 DEALLOCATE (num_ij_pairs)
535 DEALLOCATE (local_ab)
537 IF (calc_forces)
THEN
540 IF (
ALLOCATED(t_ab))
THEN
543 DEALLOCATE (local_ba)
552 CALL quasi_degenerate_p_ij( &
553 mp2_env, eigenval(:, ispin:jspin), homo(ispin:jspin), virtual(ispin:jspin), my_open_shell_ss, &
554 my_beta_beta_case, bib_c(ispin:jspin), unit_nr, dimen_ri, &
555 my_b_size(ispin:jspin), ngroup, my_group_l_size, &
556 color_sub, ranges_info_array, comm_exchange, para_env_sub, para_env, &
557 my_b_virtual_start(ispin:jspin), my_b_virtual_end(ispin:jspin), gd_array%sizes, gd_b_virtual(ispin:jspin), &
558 integ_group_pos2color_sub, dgemm_counter, buffer_1d)
562 DEALLOCATE (buffer_1d)
567 IF (calc_forces .AND. jspin == nspins)
THEN
568 IF (.NOT.
ALLOCATED(b_ia_q))
ALLOCATE (b_ia_q(nspins))
569 ALLOCATE (b_ia_q(ispin)%array(homo(ispin), my_b_size(ispin), my_group_l_size_orig))
570 b_ia_q(ispin)%array = 0.0_dp
571 DO jjb = 1, homo(ispin)
572 DO iib = 1, my_b_size(ispin)
573 b_ia_q(ispin)%array(jjb, iib, 1:my_group_l_size_orig) = &
574 bib_c(ispin)%array(1:my_group_l_size_orig, iib, jjb)
577 DEALLOCATE (bib_c(ispin)%array)
580 ALLOCATE (bib_c(ispin)%array(my_b_size(ispin), homo(ispin), my_group_l_size_orig))
581 DO proc_shift = 1, comm_rep%num_pe - 1
583 proc_send =
modulo(comm_rep%mepos - proc_shift, comm_rep%num_pe)
584 proc_receive =
modulo(comm_rep%mepos + proc_shift, comm_rep%num_pe)
586 start_point = ranges_info_array(3, proc_shift, comm_exchange%mepos)
587 end_point = ranges_info_array(4, proc_shift, comm_exchange%mepos)
589 CALL comm_rep%sendrecv(mp2_env%ri_grad%Gamma_P_ia(ispin)%array(:, :, start_point:end_point), &
590 proc_send, bib_c(ispin)%array, proc_receive, tag)
593 mp2_env%ri_grad%Gamma_P_ia(ispin)%array(:, :, 1:my_group_l_size_orig) = &
594 mp2_env%ri_grad%Gamma_P_ia(ispin)%array(:, :, 1:my_group_l_size_orig) &
595 + bib_c(ispin)%array(:, :, :)
599 bib_c(ispin)%array(:, :, :) = mp2_env%ri_grad%Gamma_P_ia(ispin)%array(:, :, 1:my_group_l_size_orig)
600 DEALLOCATE (mp2_env%ri_grad%Gamma_P_ia(ispin)%array)
601 CALL move_alloc(bib_c(ispin)%array, mp2_env%ri_grad%Gamma_P_ia(ispin)%array)
602 ELSE IF (jspin == nspins)
THEN
603 DEALLOCATE (bib_c(ispin)%array)
606 CALL para_env%sum(my_emp2_cou)
607 CALL para_env%sum(my_emp2_ex)
609 IF (my_open_shell_ss .OR. my_alpha_beta_case)
THEN
610 IF (my_alpha_beta_case)
THEN
611 emp2_s = emp2_s + my_emp2_cou
612 emp2_cou = emp2_cou + my_emp2_cou
614 my_emp2_cou = my_emp2_cou*0.25_dp
615 my_emp2_ex = my_emp2_ex*0.5_dp
616 emp2_t = emp2_t + my_emp2_cou + my_emp2_ex
617 emp2_cou = emp2_cou + my_emp2_cou
618 emp2_ex = emp2_ex + my_emp2_ex
621 emp2_cou = emp2_cou + my_emp2_cou
622 emp2_ex = emp2_ex + my_emp2_ex
628 DEALLOCATE (integ_group_pos2color_sub)
629 DEALLOCATE (ranges_info_array)
631 CALL comm_exchange%free()
634 IF (calc_forces)
THEN
636 DEALLOCATE (gd_array%sizes)
637 iib =
SIZE(sizes_array_orig)
638 ALLOCATE (gd_array%sizes(0:iib - 1))
639 gd_array%sizes(:) = sizes_array_orig
640 DEALLOCATE (sizes_array_orig)
643 my_group_l_size = my_group_l_size_orig
647 CALL complete_gamma(mp2_env, b_ia_q(ispin)%array, dimen_ri, homo(ispin), &
648 virtual(ispin), para_env, para_env_sub, ngroup, &
649 my_group_l_size, my_group_l_start, my_group_l_end, &
650 my_b_size(ispin), my_b_virtual_start(ispin), &
651 gd_array, gd_b_virtual(ispin), &
656 IF (nspins == 1) mp2_env%ri_grad%P_ab(1)%array(:, :) = mp2_env%ri_grad%P_ab(1)%array(:, :)*2.0_dp
659 CALL comm%from_split(para_env, para_env_sub%mepos)
662 CALL comm%sum(mp2_env%ri_grad%P_ab(ispin)%array)
664 CALL para_env%sum(mp2_env%ri_grad%P_ij(ispin)%array)
670 CALL release_group_dist(gd_array)
672 IF (
ALLOCATED(bib_c(ispin)%array))
DEALLOCATE (bib_c(ispin)%array)
673 CALL release_group_dist(gd_b_virtual(ispin))
677 IF (calc_forces)
DEALLOCATE (mp2_env%ri_grad%PQ_half)
678 IF (calc_forces .AND. .NOT. compare_potential_types(mp2_env%ri_metric, mp2_env%potential_parameter))
THEN
679 DEALLOCATE (mp2_env%ri_grad%operator_half)
682 CALL dgemm_counter_write(dgemm_counter, para_env)
685 CALL mp2_env%local_gemm_ctx%destroy()
686 CALL timestop(handle)
696 SUBROUTINE fill_local_i_al(local_i_aL, ranges_info_array, BIb_C_rec)
697 REAL(kind=dp),
DIMENSION(:, :, :),
INTENT(INOUT) :: local_i_al
698 INTEGER,
DIMENSION(:, :),
INTENT(IN) :: ranges_info_array
699 REAL(kind=dp),
DIMENSION(:, :, :),
INTENT(IN) :: bib_c_rec
701 CHARACTER(LEN=*),
PARAMETER :: routinen =
'fill_local_i_aL'
703 INTEGER :: end_point, handle, irep, lend_pos, &
704 lstart_pos, start_point
706 CALL timeset(routinen, handle)
708 DO irep = 1,
SIZE(ranges_info_array, 2)
709 lstart_pos = ranges_info_array(1, irep)
710 lend_pos = ranges_info_array(2, irep)
711 start_point = ranges_info_array(3, irep)
712 end_point = ranges_info_array(4, irep)
716 local_i_al(lstart_pos:lend_pos, :, :) = bib_c_rec(start_point:end_point, :, :)
720 CALL timestop(handle)
722 END SUBROUTINE fill_local_i_al
730 SUBROUTINE fill_local_i_al_2d(local_i_aL, ranges_info_array, BIb_C_rec)
731 REAL(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: local_i_al
732 INTEGER,
DIMENSION(:, :),
INTENT(IN) :: ranges_info_array
733 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: bib_c_rec
735 CHARACTER(LEN=*),
PARAMETER :: routinen =
'fill_local_i_aL_2D'
737 INTEGER :: end_point, handle, irep, lend_pos, &
738 lstart_pos, start_point
740 CALL timeset(routinen, handle)
742 DO irep = 1,
SIZE(ranges_info_array, 2)
743 lstart_pos = ranges_info_array(1, irep)
744 lend_pos = ranges_info_array(2, irep)
745 start_point = ranges_info_array(3, irep)
746 end_point = ranges_info_array(4, irep)
750 local_i_al(lstart_pos:lend_pos, :) = bib_c_rec(start_point:end_point, :)
754 CALL timestop(handle)
756 END SUBROUTINE fill_local_i_al_2d
769 SUBROUTINE replicate_iak_2intgroup(BIb_C, comm_exchange, comm_rep, homo, sizes_array, my_B_size, &
770 my_group_L_size, ranges_info_array)
771 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
772 INTENT(INOUT) :: bib_c
773 TYPE(mp_comm_type),
INTENT(IN) :: comm_exchange, comm_rep
774 INTEGER,
INTENT(IN) :: homo
775 INTEGER,
DIMENSION(:),
INTENT(IN) :: sizes_array
776 INTEGER,
INTENT(IN) :: my_b_size, my_group_l_size
777 INTEGER,
DIMENSION(:, 0:, 0:),
INTENT(IN) :: ranges_info_array
779 CHARACTER(LEN=*),
PARAMETER :: routinen =
'replicate_iaK_2intgroup'
781 INTEGER :: end_point, handle, max_l_size, &
782 proc_receive, proc_shift, start_point
783 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: bib_c_copy
784 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: bib_c_gather
786 CALL timeset(routinen, handle)
790 max_l_size = maxval(sizes_array)
792 ALLOCATE (bib_c_copy(max_l_size, my_b_size, homo))
794 bib_c_copy(1:
SIZE(bib_c, 1), 1:my_b_size, 1:homo) = bib_c
798 ALLOCATE (bib_c_gather(max_l_size, my_b_size, homo, 0:comm_rep%num_pe - 1))
799 bib_c_gather = 0.0_dp
801 CALL comm_rep%allgather(bib_c_copy, bib_c_gather)
803 DEALLOCATE (bib_c_copy)
805 ALLOCATE (bib_c(my_group_l_size, my_b_size, homo))
809 DO proc_shift = 0, comm_rep%num_pe - 1
810 proc_receive =
modulo(comm_rep%mepos - proc_shift, comm_rep%num_pe)
812 start_point = ranges_info_array(3, proc_shift, comm_exchange%mepos)
813 end_point = ranges_info_array(4, proc_shift, comm_exchange%mepos)
815 bib_c(start_point:end_point, 1:my_b_size, 1:homo) = &
816 bib_c_gather(1:end_point - start_point + 1, 1:my_b_size, 1:homo, proc_receive)
820 DEALLOCATE (bib_c_gather)
822 CALL timestop(handle)
824 END SUBROUTINE replicate_iak_2intgroup
840 SUBROUTINE mp2_ri_allocate_no_blk(local_ab, t_ab, mp2_env, homo, virtual, my_B_size, &
841 my_group_L_size, calc_forces, ispin, jspin, local_ba)
842 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :), &
843 INTENT(OUT) :: local_ab, t_ab
844 TYPE(mp2_type) :: mp2_env
845 INTEGER,
INTENT(IN) :: homo(2), virtual(2), my_b_size(2), &
847 LOGICAL,
INTENT(IN) :: calc_forces
848 INTEGER,
INTENT(IN) :: ispin, jspin
849 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :), &
850 INTENT(OUT) :: local_ba
852 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_ri_allocate_no_blk'
856 CALL timeset(routinen, handle)
858 ALLOCATE (local_ab(virtual(ispin), my_b_size(jspin)))
861 IF (calc_forces)
THEN
862 IF (.NOT.
ALLOCATED(mp2_env%ri_grad%P_ij(jspin)%array))
THEN
863 ALLOCATE (mp2_env%ri_grad%P_ij(jspin)%array(homo(ispin), homo(ispin)))
864 mp2_env%ri_grad%P_ij(jspin)%array = 0.0_dp
866 IF (.NOT.
ALLOCATED(mp2_env%ri_grad%P_ab(jspin)%array))
THEN
867 ALLOCATE (mp2_env%ri_grad%P_ab(jspin)%array(my_b_size(jspin), virtual(jspin)))
868 mp2_env%ri_grad%P_ab(jspin)%array = 0.0_dp
870 IF (.NOT.
ALLOCATED(mp2_env%ri_grad%Gamma_P_ia(jspin)%array))
THEN
871 ALLOCATE (mp2_env%ri_grad%Gamma_P_ia(jspin)%array(my_b_size(jspin), homo(jspin), my_group_l_size))
872 mp2_env%ri_grad%Gamma_P_ia(jspin)%array = 0.0_dp
875 IF (ispin == jspin)
THEN
877 ALLOCATE (t_ab(virtual(ispin), my_b_size(jspin)))
880 ALLOCATE (local_ba(1, 1))
883 ALLOCATE (local_ba(virtual(jspin), my_b_size(ispin)))
888 CALL timestop(handle)
890 END SUBROUTINE mp2_ri_allocate_no_blk
905 SUBROUTINE mp2_ri_allocate_blk(dimen_RI, my_B_size, block_size, &
906 local_i_aL, local_j_aL, calc_forces, &
907 Y_i_aP, Y_j_aP, ispin, jspin)
908 INTEGER,
INTENT(IN) :: dimen_ri, my_b_size(2), block_size
909 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
910 INTENT(OUT) :: local_i_al, local_j_al
911 LOGICAL,
INTENT(IN) :: calc_forces
912 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
913 INTENT(OUT) :: y_i_ap, y_j_ap
914 INTEGER,
INTENT(IN) :: ispin, jspin
916 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_ri_allocate_blk'
920 CALL timeset(routinen, handle)
922 ALLOCATE (local_i_al(dimen_ri, my_b_size(ispin), block_size))
924 ALLOCATE (local_j_al(dimen_ri, my_b_size(jspin), block_size))
927 IF (calc_forces)
THEN
928 ALLOCATE (y_i_ap(my_b_size(ispin), dimen_ri, block_size))
932 ALLOCATE (y_j_ap(my_b_size(jspin), dimen_ri, block_size))
937 CALL timestop(handle)
939 END SUBROUTINE mp2_ri_allocate_blk
955 SUBROUTINE mp2_ri_communication(my_alpha_beta_case, total_ij_pairs, homo, homo_beta, &
956 block_size, ngroup, ij_map, color_sub, my_ij_pairs, my_open_shell_SS, unit_nr)
957 LOGICAL,
INTENT(IN) :: my_alpha_beta_case
958 INTEGER,
INTENT(OUT) :: total_ij_pairs
959 INTEGER,
INTENT(IN) :: homo, homo_beta, block_size, ngroup
960 INTEGER,
ALLOCATABLE,
DIMENSION(:, :),
INTENT(OUT) :: ij_map
961 INTEGER,
INTENT(IN) :: color_sub
962 INTEGER,
INTENT(OUT) :: my_ij_pairs
963 LOGICAL,
INTENT(IN) :: my_open_shell_ss
964 INTEGER,
INTENT(IN) :: unit_nr
966 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_ri_communication'
968 INTEGER :: assigned_blocks, first_i_block, first_j_block, handle, iib, ij_block_counter, &
969 ij_counter, jjb, last_i_block, last_j_block, num_block_per_group, num_ij_blocks, &
970 num_ij_blocks_beta, total_ij_block, total_ij_pairs_blocks
971 LOGICAL,
ALLOCATABLE,
DIMENSION(:, :) :: ij_marker
976 CALL timeset(routinen, handle)
978 IF (.NOT. my_open_shell_ss .AND. .NOT. my_alpha_beta_case)
THEN
979 total_ij_pairs = homo*(1 + homo)/2
980 num_ij_blocks = homo/block_size - 1
983 last_i_block = block_size*(num_ij_blocks - 1)
985 first_j_block = block_size + 1
986 last_j_block = block_size*(num_ij_blocks + 1)
989 DO iib = first_i_block, last_i_block, block_size
990 DO jjb = iib + block_size, last_j_block, block_size
991 ij_block_counter = ij_block_counter + 1
995 total_ij_block = ij_block_counter
996 num_block_per_group = total_ij_block/ngroup
997 assigned_blocks = num_block_per_group*ngroup
999 total_ij_pairs_blocks = assigned_blocks + (total_ij_pairs - assigned_blocks*(block_size**2))
1001 ALLOCATE (ij_marker(homo, homo))
1003 ALLOCATE (ij_map(3, total_ij_pairs_blocks))
1007 DO iib = first_i_block, last_i_block, block_size
1008 DO jjb = iib + block_size, last_j_block, block_size
1009 IF (ij_counter + 1 > assigned_blocks)
EXIT
1010 ij_counter = ij_counter + 1
1011 ij_marker(iib:iib + block_size - 1, jjb:jjb + block_size - 1) = .false.
1012 ij_map(1, ij_counter) = iib
1013 ij_map(2, ij_counter) = jjb
1014 ij_map(3, ij_counter) = block_size
1015 IF (mod(ij_counter, ngroup) == color_sub) my_ij_pairs = my_ij_pairs + 1
1020 IF (ij_marker(iib, jjb))
THEN
1021 ij_counter = ij_counter + 1
1022 ij_map(1, ij_counter) = iib
1023 ij_map(2, ij_counter) = jjb
1024 ij_map(3, ij_counter) = 1
1025 IF (mod(ij_counter, ngroup) == color_sub) my_ij_pairs = my_ij_pairs + 1
1029 DEALLOCATE (ij_marker)
1031 ELSE IF (.NOT. my_alpha_beta_case)
THEN
1034 total_ij_pairs = homo*(homo - 1)/2
1035 num_ij_blocks = (homo - 1)/block_size - 1
1038 last_i_block = block_size*(num_ij_blocks - 1)
1041 first_j_block = block_size + 2
1042 last_j_block = block_size*(num_ij_blocks + 1) + 1
1044 ij_block_counter = 0
1045 DO iib = first_i_block, last_i_block, block_size
1046 DO jjb = iib + block_size + 1, last_j_block, block_size
1047 ij_block_counter = ij_block_counter + 1
1051 total_ij_block = ij_block_counter
1052 num_block_per_group = total_ij_block/ngroup
1053 assigned_blocks = num_block_per_group*ngroup
1055 total_ij_pairs_blocks = assigned_blocks + (total_ij_pairs - assigned_blocks*(block_size**2))
1057 ALLOCATE (ij_marker(homo, homo))
1059 ALLOCATE (ij_map(3, total_ij_pairs_blocks))
1063 DO iib = first_i_block, last_i_block, block_size
1064 DO jjb = iib + block_size + 1, last_j_block, block_size
1065 IF (ij_counter + 1 > assigned_blocks)
EXIT
1066 ij_counter = ij_counter + 1
1067 ij_marker(iib:iib + block_size - 1, jjb:jjb + block_size - 1) = .false.
1068 ij_map(1, ij_counter) = iib
1069 ij_map(2, ij_counter) = jjb
1070 ij_map(3, ij_counter) = block_size
1071 IF (mod(ij_counter, ngroup) == color_sub) my_ij_pairs = my_ij_pairs + 1
1075 DO jjb = iib + 1, homo
1076 IF (ij_marker(iib, jjb))
THEN
1077 ij_counter = ij_counter + 1
1078 ij_map(1, ij_counter) = iib
1079 ij_map(2, ij_counter) = jjb
1080 ij_map(3, ij_counter) = 1
1081 IF (mod(ij_counter, ngroup) == color_sub) my_ij_pairs = my_ij_pairs + 1
1085 DEALLOCATE (ij_marker)
1088 total_ij_pairs = homo*homo_beta
1089 num_ij_blocks = homo/block_size
1090 num_ij_blocks_beta = homo_beta/block_size
1093 last_i_block = block_size*(num_ij_blocks - 1)
1096 last_j_block = block_size*(num_ij_blocks_beta - 1)
1098 ij_block_counter = 0
1099 DO iib = first_i_block, last_i_block, block_size
1100 DO jjb = first_j_block, last_j_block, block_size
1101 ij_block_counter = ij_block_counter + 1
1105 total_ij_block = ij_block_counter
1106 num_block_per_group = total_ij_block/ngroup
1107 assigned_blocks = num_block_per_group*ngroup
1109 total_ij_pairs_blocks = assigned_blocks + (total_ij_pairs - assigned_blocks*(block_size**2))
1111 ALLOCATE (ij_marker(homo, homo_beta))
1113 ALLOCATE (ij_map(3, total_ij_pairs_blocks))
1117 DO iib = first_i_block, last_i_block, block_size
1118 DO jjb = first_j_block, last_j_block, block_size
1119 IF (ij_counter + 1 > assigned_blocks)
EXIT
1120 ij_counter = ij_counter + 1
1121 ij_marker(iib:iib + block_size - 1, jjb:jjb + block_size - 1) = .false.
1122 ij_map(1, ij_counter) = iib
1123 ij_map(2, ij_counter) = jjb
1124 ij_map(3, ij_counter) = block_size
1125 IF (mod(ij_counter, ngroup) == color_sub) my_ij_pairs = my_ij_pairs + 1
1129 DO jjb = 1, homo_beta
1130 IF (ij_marker(iib, jjb))
THEN
1131 ij_counter = ij_counter + 1
1132 ij_map(1, ij_counter) = iib
1133 ij_map(2, ij_counter) = jjb
1134 ij_map(3, ij_counter) = 1
1135 IF (mod(ij_counter, ngroup) == color_sub) my_ij_pairs = my_ij_pairs + 1
1139 DEALLOCATE (ij_marker)
1142 IF (unit_nr > 0)
THEN
1143 IF (block_size == 1)
THEN
1144 WRITE (unit=unit_nr, fmt=
"(T3,A,T66,F15.1)") &
1145 "RI_INFO| Percentage of ij pairs communicated with block size 1:", 100.0_dp
1147 WRITE (unit=unit_nr, fmt=
"(T3,A,T66,F15.1)") &
1148 "RI_INFO| Percentage of ij pairs communicated with block size 1:", &
1149 100.0_dp*real((total_ij_pairs - assigned_blocks*(block_size**2)), kind=dp)/real(total_ij_pairs, kind=dp)
1151 CALL m_flush(unit_nr)
1154 CALL timestop(handle)
1156 END SUBROUTINE mp2_ri_communication
1178 SUBROUTINE mp2_ri_create_group(para_env, para_env_sub, color_sub, &
1179 sizes_array, calc_forces, &
1180 integ_group_size, my_group_L_end, &
1181 my_group_L_size, my_group_L_size_orig, my_group_L_start, my_new_group_L_size, &
1182 integ_group_pos2color_sub, &
1183 sizes_array_orig, ranges_info_array, comm_exchange, comm_rep, num_integ_group)
1184 TYPE(mp_para_env_type),
INTENT(IN) :: para_env, para_env_sub
1185 INTEGER,
INTENT(IN) :: color_sub
1186 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(INOUT) :: sizes_array
1187 LOGICAL,
INTENT(IN) :: calc_forces
1188 INTEGER,
INTENT(IN) :: integ_group_size, my_group_l_end
1189 INTEGER,
INTENT(INOUT) :: my_group_l_size
1190 INTEGER,
INTENT(OUT) :: my_group_l_size_orig
1191 INTEGER,
INTENT(IN) :: my_group_l_start
1192 INTEGER,
INTENT(INOUT) :: my_new_group_l_size
1193 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: integ_group_pos2color_sub, &
1195 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :), &
1196 INTENT(OUT) :: ranges_info_array
1197 TYPE(mp_comm_type),
INTENT(OUT) :: comm_exchange, comm_rep
1198 INTEGER,
INTENT(IN) :: num_integ_group
1200 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_ri_create_group'
1202 INTEGER :: handle, iib, proc_receive, proc_shift, &
1204 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: new_sizes_array, rep_ends_array, &
1205 rep_sizes_array, rep_starts_array
1206 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: my_info
1208 CALL timeset(routinen, handle)
1210 sub_sub_color = para_env_sub%mepos*num_integ_group + color_sub/integ_group_size
1211 CALL comm_exchange%from_split(para_env, sub_sub_color)
1214 sub_sub_color = para_env_sub%mepos*comm_exchange%num_pe + comm_exchange%mepos
1215 CALL comm_rep%from_split(para_env, sub_sub_color)
1221 ALLOCATE (rep_ends_array(0:comm_rep%num_pe - 1))
1222 ALLOCATE (rep_starts_array(0:comm_rep%num_pe - 1))
1223 ALLOCATE (rep_sizes_array(0:comm_rep%num_pe - 1))
1225 CALL comm_rep%allgather(my_group_l_size, rep_sizes_array)
1226 CALL comm_rep%allgather(my_group_l_start, rep_starts_array)
1227 CALL comm_rep%allgather(my_group_l_end, rep_ends_array)
1230 my_new_group_l_size = my_group_l_size
1233 ALLOCATE (my_info(4, 0:comm_rep%num_pe - 1))
1234 my_info(1, 0) = my_group_l_start
1235 my_info(2, 0) = my_group_l_end
1237 my_info(4, 0) = my_group_l_size
1239 DO proc_shift = 1, comm_rep%num_pe - 1
1240 proc_receive =
modulo(comm_rep%mepos - proc_shift, comm_rep%num_pe)
1242 my_new_group_l_size = my_new_group_l_size + rep_sizes_array(proc_receive)
1244 my_info(1, proc_shift) = rep_starts_array(proc_receive)
1245 my_info(2, proc_shift) = rep_ends_array(proc_receive)
1246 my_info(3, proc_shift) = my_info(4, proc_shift - 1) + 1
1247 my_info(4, proc_shift) = my_new_group_l_size
1251 ALLOCATE (new_sizes_array(0:comm_exchange%num_pe - 1))
1252 ALLOCATE (ranges_info_array(4, 0:comm_rep%num_pe - 1, 0:comm_exchange%num_pe - 1))
1253 CALL comm_exchange%allgather(my_new_group_l_size, new_sizes_array)
1254 CALL comm_exchange%allgather(my_info, ranges_info_array)
1256 DEALLOCATE (rep_sizes_array)
1257 DEALLOCATE (rep_starts_array)
1258 DEALLOCATE (rep_ends_array)
1260 ALLOCATE (integ_group_pos2color_sub(0:comm_exchange%num_pe - 1))
1261 CALL comm_exchange%allgather(color_sub, integ_group_pos2color_sub)
1263 IF (calc_forces)
THEN
1264 iib =
SIZE(sizes_array)
1265 ALLOCATE (sizes_array_orig(0:iib - 1))
1266 sizes_array_orig(:) = sizes_array
1269 my_group_l_size_orig = my_group_l_size
1270 my_group_l_size = my_new_group_l_size
1271 DEALLOCATE (sizes_array)
1273 ALLOCATE (sizes_array(0:integ_group_size - 1))
1274 sizes_array(:) = new_sizes_array
1276 DEALLOCATE (new_sizes_array)
1278 CALL timestop(handle)
1280 END SUBROUTINE mp2_ri_create_group
1298 SUBROUTINE mp2_ri_get_integ_group_size(mp2_env, para_env, para_env_sub, gd_array, gd_B_virtual, &
1299 homo, dimen_RI, unit_nr, &
1301 ngroup, num_integ_group, &
1302 virtual, calc_forces)
1303 TYPE(mp2_type) :: mp2_env
1304 TYPE(mp_para_env_type),
INTENT(IN) :: para_env, para_env_sub
1305 TYPE(group_dist_d1_type),
INTENT(IN) :: gd_array
1306 TYPE(group_dist_d1_type),
DIMENSION(:),
INTENT(IN) :: gd_b_virtual
1307 INTEGER,
DIMENSION(:),
INTENT(IN) :: homo
1308 INTEGER,
INTENT(IN) :: dimen_ri, unit_nr
1309 INTEGER,
INTENT(OUT) :: integ_group_size, ngroup, num_integ_group
1310 INTEGER,
DIMENSION(:),
INTENT(IN) :: virtual
1311 LOGICAL,
INTENT(IN) :: calc_forces
1313 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_ri_get_integ_group_size'
1315 INTEGER :: block_size, handle, iib, &
1316 max_repl_group_size, &
1317 min_integ_group_size
1318 INTEGER(KIND=int_8) :: mem
1319 LOGICAL :: calc_group_size
1320 REAL(kind=dp) :: factor, mem_base, mem_min, mem_per_blk, &
1321 mem_per_repl, mem_per_repl_blk, &
1324 CALL timeset(routinen, handle)
1326 ngroup = para_env%num_pe/para_env_sub%num_pe
1328 calc_group_size = mp2_env%ri_mp2%number_integration_groups <= 0
1329 IF (.NOT. calc_group_size)
THEN
1330 IF (mod(ngroup, mp2_env%ri_mp2%number_integration_groups) /= 0) calc_group_size = .true.
1333 IF (calc_group_size)
THEN
1335 mem_real = (mem + 1024*1024 - 1)/(1024*1024)
1336 CALL para_env%min(mem_real)
1337 mem_real = min(mem_real, mp2_env%mp2_memory)
1340 mem_per_blk = 0.0_dp
1341 mem_per_repl = 0.0_dp
1342 mem_per_repl_blk = 0.0_dp
1345 mem_per_repl = mem_per_repl + maxval(max(real(homo, kind=dp)*maxsize(gd_array), real(dimen_ri, kind=dp))* &
1346 maxsize(gd_b_virtual))*8.0_dp/(1024**2)
1348 mem_per_repl = mem_per_repl + sum(real(homo, kind=dp)*maxsize(gd_b_virtual))*maxsize(gd_array)*8.0_dp/(1024**2)
1350 mem_per_repl_blk = mem_per_repl_blk + real(maxval(maxsize(gd_b_virtual)), kind=dp)*maxsize(gd_array)*8.0_dp/(1024**2)
1352 mem_per_blk = mem_per_blk + 2.0_dp*maxval(maxsize(gd_b_virtual))*real(dimen_ri, kind=dp)*8.0_dp/(1024**2)
1354 mem_base = mem_base + maxval(real(virtual, kind=dp)*maxsize(gd_b_virtual))*8.0_dp/(1024**2)
1356 mem_base = mem_base + real(max(dimen_ri, maxval(virtual)), kind=dp)*maxval(maxsize(gd_b_virtual))*8.0_dp/(1024**2)
1358 IF (calc_forces)
THEN
1360 mem_per_repl = mem_per_repl + sum(real(homo, kind=dp)*maxsize(gd_array)* &
1361 maxsize(gd_b_virtual))*8.0_dp/(1024**2)
1363 mem_per_blk = mem_per_blk + 2.0_dp*maxval(maxsize(gd_b_virtual))*dimen_ri*8.0_dp/(1024**2)
1365 mem_base = mem_base + real(maxval(maxsize(gd_b_virtual)), kind=dp)*max(dimen_ri, maxval(virtual))*8.0_dp/(1024**2)
1367 mem_base = mem_base + sum(real(homo, kind=dp)*homo)*8.0_dp/(1024**2)
1369 mem_base = mem_base + sum(real(virtual, kind=dp)*maxsize(gd_b_virtual))*8.0_dp/(1024**2)
1371 mem_base = mem_base + real(max(dimen_ri, maxval(virtual)), kind=dp)*maxval(maxsize(gd_b_virtual))*8.0_dp/(1024**2)
1375 block_size = max(1, min(floor(sqrt(real(minval(homo), kind=dp))), floor(minval(homo)/sqrt(2.0_dp*ngroup))))
1376 IF (mp2_env%ri_mp2%block_size > 0) block_size = mp2_env%ri_mp2%block_size
1378 mem_min = mem_base + mem_per_repl + (mem_per_blk + mem_per_repl_blk)*block_size
1380 IF (unit_nr > 0)
WRITE (unit_nr,
'(T3,A,T68,F9.2,A4)')
'RI_INFO| Minimum available memory per MPI process:', &
1382 IF (unit_nr > 0)
WRITE (unit_nr,
'(T3,A,T68,F9.2,A4)')
'RI_INFO| Minimum required memory per MPI process:', &
1404 integ_group_size = ngroup
1407 factor = real(sum(homo*virtual), kind=dp) &
1408 - sum((real(maxval(homo), kind=dp)/block_size + block_size - 2.0_dp)*homo*virtual)/ngroup
1409 IF (
SIZE(homo) == 2) factor = factor - 2.0_dp*product(homo)/block_size/ngroup*sum(homo*virtual)
1411 IF (factor <= 0.0_dp)
THEN
1413 max_repl_group_size = min(max(floor((mem_real - mem_base - mem_per_blk*block_size)/ &
1414 (mem_per_repl + mem_per_repl_blk*block_size)), 1), ngroup)
1416 min_integ_group_size = ngroup/max_repl_group_size
1419 DO iib = max(min(min_integ_group_size, ngroup), 1), ngroup
1421 IF (mod(ngroup, iib) == 0)
THEN
1422 integ_group_size = iib
1425 integ_group_size = integ_group_size + 1
1429 integ_group_size = ngroup/mp2_env%ri_mp2%number_integration_groups
1432 IF (unit_nr > 0)
THEN
1433 WRITE (unit=unit_nr, fmt=
"(T3,A,T75,i6)") &
1434 "RI_INFO| Group size for integral replication:", integ_group_size*para_env_sub%num_pe
1435 CALL m_flush(unit_nr)
1438 num_integ_group = ngroup/integ_group_size
1440 CALL timestop(handle)
1442 END SUBROUTINE mp2_ri_get_integ_group_size
1462 SUBROUTINE mp2_ri_get_block_size(mp2_env, para_env, para_env_sub, gd_array, gd_B_virtual, &
1463 homo, virtual, dimen_RI, unit_nr, &
1464 block_size, ngroup, num_integ_group, &
1465 my_open_shell_ss, calc_forces, buffer_1D)
1466 TYPE(mp2_type) :: mp2_env
1467 TYPE(mp_para_env_type),
INTENT(IN) :: para_env, para_env_sub
1468 TYPE(group_dist_d1_type),
INTENT(IN) :: gd_array
1469 TYPE(group_dist_d1_type),
DIMENSION(:),
INTENT(IN) :: gd_b_virtual
1470 INTEGER,
DIMENSION(:),
INTENT(IN) :: homo, virtual
1471 INTEGER,
INTENT(IN) :: dimen_ri, unit_nr
1472 INTEGER,
INTENT(OUT) :: block_size, ngroup
1473 INTEGER,
INTENT(IN) :: num_integ_group
1474 LOGICAL,
INTENT(IN) :: my_open_shell_ss, calc_forces
1475 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:), &
1476 INTENT(OUT) :: buffer_1d
1478 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_ri_get_block_size'
1480 INTEGER :: best_block_size, handle, num_ij_blocks
1481 INTEGER(KIND=int_8) :: buffer_size, mem
1482 REAL(kind=dp) :: mem_base, mem_per_blk, mem_per_repl_blk, &
1485 CALL timeset(routinen, handle)
1487 ngroup = para_env%num_pe/para_env_sub%num_pe
1490 mem_real = (mem + 1024*1024 - 1)/(1024*1024)
1491 CALL para_env%min(mem_real)
1494 mem_per_blk = 0.0_dp
1495 mem_per_repl_blk = 0.0_dp
1498 mem_base = mem_base + maxval(maxsize(gd_b_virtual))*max(dimen_ri, maxval(virtual))*8.0_dp/(1024**2)
1500 mem_per_repl_blk = mem_per_repl_blk + real(maxval(maxsize(gd_b_virtual)), kind=dp)*maxsize(gd_array)*8.0_dp/(1024**2)
1502 mem_per_blk = mem_per_blk + 2.0_dp*maxval(maxsize(gd_b_virtual))*real(dimen_ri, kind=dp)*8.0_dp/(1024**2)
1504 mem_base = mem_base + maxval(maxsize(gd_b_virtual))*max(dimen_ri, maxval(virtual))*8.0_dp/(1024**2)
1506 IF (calc_forces)
THEN
1508 mem_per_blk = mem_per_blk + 3.0_dp*maxval(maxsize(gd_b_virtual))*dimen_ri*8.0_dp/(1024**2)
1510 mem_base = mem_base + maxval(maxsize(gd_b_virtual))*max(dimen_ri, maxval(virtual))*8.0_dp/(1024**2)
1516 IF (mp2_env%ri_mp2%block_size > 0)
THEN
1517 best_block_size = mp2_env%ri_mp2%block_size
1519 best_block_size = max(floor((mem_real - mem_base)/(mem_per_blk + mem_per_repl_blk*ngroup/num_integ_group)), 1)
1522 IF (
SIZE(homo) == 1)
THEN
1523 IF (.NOT. my_open_shell_ss)
THEN
1524 num_ij_blocks = (homo(1)/best_block_size)
1525 num_ij_blocks = (num_ij_blocks*num_ij_blocks - num_ij_blocks)/2
1527 num_ij_blocks = ((homo(1) - 1)/best_block_size)
1528 num_ij_blocks = (num_ij_blocks*num_ij_blocks - num_ij_blocks)/2
1531 num_ij_blocks = product(homo/best_block_size)
1534 IF ((num_ij_blocks >= ngroup .AND. num_ij_blocks > 0) .OR. best_block_size == 1)
THEN
1537 best_block_size = best_block_size - 1
1541 IF (
SIZE(homo) == 1)
THEN
1542 IF (my_open_shell_ss)
THEN
1545 best_block_size = min(floor(sqrt(real(homo(1) - 1, kind=dp))), best_block_size)
1548 best_block_size = min(floor(sqrt(real(homo(1), kind=dp))), best_block_size)
1552 block_size = max(1, best_block_size)
1554 IF (unit_nr > 0)
THEN
1555 WRITE (unit=unit_nr, fmt=
"(T3,A,T75,i6)") &
1556 "RI_INFO| Block size:", block_size
1557 CALL m_flush(unit_nr)
1561 buffer_size = max(int(maxsize(gd_array), kind=int_8)*block_size, int(max(dimen_ri, maxval(virtual)), kind=int_8)) &
1562 *maxval(maxsize(gd_b_virtual))
1564 IF (calc_forces) buffer_size = buffer_size*2
1565 ALLOCATE (buffer_1d(buffer_size))
1567 CALL timestop(handle)
1569 END SUBROUTINE mp2_ri_get_block_size
1600 SUBROUTINE mp2_update_p_gamma(mp2_env, para_env_sub, gd_B_virtual, &
1601 Eigenval, homo, dimen_RI, iiB, jjB, my_B_size, &
1602 my_B_virtual_end, my_B_virtual_start, my_i, my_j, virtual, local_ab, &
1603 t_ab, my_local_i_aL, my_local_j_aL, open_ss, Y_i_aP, Y_j_aP, &
1604 local_ba, ispin, jspin, dgemm_counter, buffer_1D)
1605 TYPE(mp2_type) :: mp2_env
1606 TYPE(mp_para_env_type),
INTENT(IN) :: para_env_sub
1607 TYPE(group_dist_d1_type),
DIMENSION(:),
INTENT(IN) :: gd_b_virtual
1608 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: eigenval
1609 INTEGER,
DIMENSION(:),
INTENT(IN) :: homo
1610 INTEGER,
INTENT(IN) :: dimen_ri, iib, jjb
1611 INTEGER,
DIMENSION(:),
INTENT(IN) :: my_b_size, my_b_virtual_end, &
1613 INTEGER,
INTENT(IN) :: my_i, my_j
1614 INTEGER,
DIMENSION(:),
INTENT(IN) :: virtual
1615 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:, :), &
1616 INTENT(INOUT),
TARGET :: local_ab
1617 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:, :), &
1618 INTENT(IN),
TARGET :: t_ab, my_local_i_al, my_local_j_al
1619 LOGICAL,
INTENT(IN) :: open_ss
1620 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:, :), &
1621 INTENT(INOUT),
TARGET :: y_i_ap, y_j_ap, local_ba
1622 INTEGER,
INTENT(IN) :: ispin, jspin
1623 TYPE(dgemm_counter_type),
INTENT(INOUT) :: dgemm_counter
1624 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:),
TARGET :: buffer_1d
1626 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_update_P_gamma'
1628 INTEGER :: a, b, b_global, handle, proc_receive, proc_send, proc_shift, rec_b_size, &
1629 rec_b_virtual_end, rec_b_virtual_start, send_b_size, send_b_virtual_end, &
1630 send_b_virtual_start
1631 INTEGER(KIND=int_8) :: offset
1632 LOGICAL :: alpha_beta
1633 REAL(kind=dp) :: factor, p_ij_diag
1634 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:, :), &
1635 POINTER :: external_ab, send_ab
1637 CALL timeset(routinen//
"_Pia", handle)
1639 alpha_beta = .NOT. (ispin == jspin)
1646 DO b = 1, my_b_size(jspin)
1647 b_global = b + my_b_virtual_start(jspin) - 1
1648 DO a = 1, virtual(ispin)
1649 local_ab(a, b) = -local_ab(a, b)/ &
1650 (eigenval(homo(ispin) + a, ispin) + eigenval(homo(jspin) + b_global, jspin) - &
1651 eigenval(my_i + iib - 1, ispin) - eigenval(my_j + jjb - 1, jspin))
1654 IF (.NOT. (alpha_beta))
THEN
1655 p_ij_diag = -sum(local_ab*t_ab)*factor
1658 p_ij_diag = -sum(local_ab*local_ab)*mp2_env%scale_S
1660 DO b = 1, my_b_size(ispin)
1661 b_global = b + my_b_virtual_start(ispin) - 1
1662 DO a = 1, virtual(jspin)
1663 local_ba(a, b) = -local_ba(a, b)/ &
1664 (eigenval(homo(jspin) + a, jspin) + eigenval(homo(ispin) + b_global, ispin) - &
1665 eigenval(my_i + iib - 1, ispin) - eigenval(my_j + jjb - 1, jspin))
1672 CALL dgemm_counter_start(dgemm_counter)
1673 IF (.NOT. (alpha_beta))
THEN
1674 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', my_b_size(ispin), my_b_size(ispin), virtual(ispin), 1.0_dp, &
1675 t_ab, virtual(ispin), local_ab, virtual(ispin), &
1676 1.0_dp, mp2_env%ri_grad%P_ab(ispin)%array(:, &
1677 my_b_virtual_start(ispin):my_b_virtual_end(ispin)), my_b_size(ispin))
1678 mp2_env%ri_grad%P_ij(ispin)%array(my_i + iib - 1, my_i + iib - 1) = &
1679 mp2_env%ri_grad%P_ij(ispin)%array(my_i + iib - 1, my_i + iib - 1) + p_ij_diag
1681 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', my_b_size(ispin), my_b_size(ispin), virtual(jspin), mp2_env%scale_S, &
1682 local_ba, virtual(jspin), local_ba, virtual(jspin), 1.0_dp, &
1683 mp2_env%ri_grad%P_ab(ispin)%array(:, my_b_virtual_start(ispin):my_b_virtual_end(ispin)), my_b_size(ispin))
1685 mp2_env%ri_grad%P_ij(ispin)%array(my_i + iib - 1, my_i + iib - 1) = &
1686 mp2_env%ri_grad%P_ij(ispin)%array(my_i + iib - 1, my_i + iib - 1) + p_ij_diag
1688 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', my_b_size(jspin), my_b_size(jspin), virtual(ispin), mp2_env%scale_S, &
1689 local_ab, virtual(ispin), local_ab, virtual(ispin), 1.0_dp, &
1690 mp2_env%ri_grad%P_ab(jspin)%array(:, my_b_virtual_start(jspin):my_b_virtual_end(jspin)), my_b_size(jspin))
1692 mp2_env%ri_grad%P_ij(jspin)%array(my_j + jjb - 1, my_j + jjb - 1) = &
1693 mp2_env%ri_grad%P_ij(jspin)%array(my_j + jjb - 1, my_j + jjb - 1) + p_ij_diag
1698 IF ((my_i /= my_j) .AND. (.NOT. alpha_beta))
THEN
1700 CALL mp2_env%local_gemm_ctx%gemm(
'N',
'T', my_b_size(ispin), virtual(ispin), my_b_size(ispin), 1.0_dp, &
1701 t_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), :), my_b_size(ispin), &
1702 local_ab, virtual(ispin), &
1703 1.0_dp, mp2_env%ri_grad%P_ab(ispin)%array, my_b_size(ispin))
1705 mp2_env%ri_grad%P_ij(ispin)%array(my_j + jjb - 1, my_j + jjb - 1) = &
1706 mp2_env%ri_grad%P_ij(ispin)%array(my_j + jjb - 1, my_j + jjb - 1) + p_ij_diag
1708 DO proc_shift = 1, para_env_sub%num_pe - 1
1709 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
1710 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
1712 CALL get_group_dist(gd_b_virtual(jspin), proc_receive, rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
1713 CALL get_group_dist(gd_b_virtual(jspin), proc_send, send_b_virtual_start, send_b_virtual_end, send_b_size)
1715 external_ab(1:virtual(ispin), 1:rec_b_size) => buffer_1d(1:int(virtual(ispin), int_8)*rec_b_size)
1716 external_ab = 0.0_dp
1718 CALL para_env_sub%sendrecv(local_ab, proc_send, &
1719 external_ab, proc_receive)
1721 IF (.NOT. (alpha_beta))
THEN
1722 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', my_b_size(ispin), rec_b_size, virtual(ispin), 1.0_dp, &
1723 t_ab, virtual(ispin), external_ab, virtual(ispin), &
1724 1.0_dp, mp2_env%ri_grad%P_ab(ispin)%array(:, rec_b_virtual_start:rec_b_virtual_end), my_b_size(ispin))
1726 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', my_b_size(jspin), rec_b_size, virtual(ispin), mp2_env%scale_S, &
1727 local_ab, virtual(ispin), external_ab, virtual(ispin), &
1728 1.0_dp, mp2_env%ri_grad%P_ab(jspin)%array(:, rec_b_virtual_start:rec_b_virtual_end), &
1733 CALL get_group_dist(gd_b_virtual(ispin), proc_receive, rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
1734 CALL get_group_dist(gd_b_virtual(ispin), proc_send, send_b_virtual_start, send_b_virtual_end, send_b_size)
1735 external_ab(1:virtual(jspin), 1:rec_b_size) => buffer_1d(1:int(virtual(jspin), int_8)*rec_b_size)
1736 external_ab = 0.0_dp
1737 CALL para_env_sub%sendrecv(local_ba, proc_send, &
1738 external_ab, proc_receive)
1739 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', my_b_size(ispin), rec_b_size, virtual(jspin), mp2_env%scale_S, &
1740 local_ba, virtual(jspin), external_ab, virtual(jspin), &
1741 1.0_dp, mp2_env%ri_grad%P_ab(ispin)%array(:, rec_b_virtual_start:rec_b_virtual_end), my_b_size(ispin))
1744 IF ((my_i /= my_j) .AND. (.NOT. alpha_beta))
THEN
1745 external_ab(1:my_b_size(ispin), 1:virtual(ispin)) => &
1746 buffer_1d(1:int(virtual(ispin), int_8)*my_b_size(ispin))
1747 external_ab = 0.0_dp
1749 offset = int(virtual(ispin), int_8)*my_b_size(ispin)
1751 send_ab(1:send_b_size, 1:virtual(ispin)) => buffer_1d(offset + 1:offset + int(send_b_size, int_8)*virtual(ispin))
1754 CALL mp2_env%local_gemm_ctx%gemm(
'N',
'T', send_b_size, virtual(ispin), my_b_size(ispin), 1.0_dp, &
1755 t_ab(send_b_virtual_start:send_b_virtual_end, :), send_b_size, &
1756 local_ab, virtual(ispin), 0.0_dp, send_ab, send_b_size)
1757 CALL para_env_sub%sendrecv(send_ab, proc_send, &
1758 external_ab, proc_receive)
1760 mp2_env%ri_grad%P_ab(ispin)%array(:, :) = mp2_env%ri_grad%P_ab(ispin)%array + external_ab
1764 IF (.NOT. alpha_beta)
THEN
1765 IF (my_i /= my_j)
THEN
1766 CALL dgemm_counter_stop(dgemm_counter, 2*my_b_size(ispin), virtual(ispin), virtual(ispin))
1768 CALL dgemm_counter_stop(dgemm_counter, my_b_size(ispin), virtual(ispin), virtual(ispin))
1771 CALL dgemm_counter_stop(dgemm_counter, sum(my_b_size), virtual(ispin), virtual(jspin))
1773 CALL timestop(handle)
1777 CALL timeset(routinen//
"_Gamma", handle)
1778 CALL dgemm_counter_start(dgemm_counter)
1779 IF (.NOT. alpha_beta)
THEN
1781 CALL mp2_env%local_gemm_ctx%gemm(
'N',
'T', my_b_size(ispin), dimen_ri, my_b_size(ispin), 1.0_dp, &
1782 t_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), :), my_b_size(ispin), &
1783 my_local_j_al, dimen_ri, 1.0_dp, y_i_ap, my_b_size(ispin))
1785 CALL mp2_env%local_gemm_ctx%gemm(
'N',
'T', my_b_size(ispin), dimen_ri, my_b_size(jspin), mp2_env%scale_S, &
1786 local_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), :), my_b_size(ispin), &
1787 my_local_j_al, dimen_ri, 1.0_dp, y_i_ap, my_b_size(ispin))
1788 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'T', my_b_size(jspin), dimen_ri, my_b_size(ispin), mp2_env%scale_S, &
1789 local_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), :), my_b_size(ispin), &
1790 my_local_i_al, dimen_ri, 1.0_dp, y_j_ap, my_b_size(jspin))
1793 IF (para_env_sub%num_pe > 1)
THEN
1794 external_ab(1:my_b_size(ispin), 1:dimen_ri) => buffer_1d(1:int(my_b_size(ispin), int_8)*dimen_ri)
1795 external_ab = 0.0_dp
1797 offset = int(my_b_size(ispin), int_8)*dimen_ri
1800 DO proc_shift = 1, para_env_sub%num_pe - 1
1801 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
1802 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
1804 CALL get_group_dist(gd_b_virtual(ispin), proc_receive, rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
1805 CALL get_group_dist(gd_b_virtual(ispin), proc_send, send_b_virtual_start, send_b_virtual_end, send_b_size)
1807 send_ab(1:send_b_size, 1:dimen_ri) => buffer_1d(offset + 1:offset + int(dimen_ri, int_8)*send_b_size)
1809 IF (.NOT. alpha_beta)
THEN
1810 CALL mp2_env%local_gemm_ctx%gemm(
'N',
'T', send_b_size, dimen_ri, my_b_size(ispin), 1.0_dp, &
1811 t_ab(send_b_virtual_start:send_b_virtual_end, :), send_b_size, &
1812 my_local_j_al, dimen_ri, 0.0_dp, send_ab, send_b_size)
1813 CALL para_env_sub%sendrecv(send_ab, proc_send, external_ab, proc_receive)
1815 y_i_ap(:, :) = y_i_ap + external_ab
1819 CALL mp2_env%local_gemm_ctx%gemm(
'N',
'T', send_b_size, dimen_ri, my_b_size(jspin), mp2_env%scale_S, &
1820 local_ab(send_b_virtual_start:send_b_virtual_end, :), send_b_size, &
1821 my_local_j_al, dimen_ri, 0.0_dp, send_ab, send_b_size)
1822 CALL para_env_sub%sendrecv(send_ab, proc_send, external_ab, proc_receive)
1823 y_i_ap(:, :) = y_i_ap + external_ab
1827 IF (alpha_beta)
THEN
1829 IF (para_env_sub%num_pe > 1)
THEN
1830 external_ab(1:my_b_size(jspin), 1:dimen_ri) => buffer_1d(1:int(my_b_size(jspin), int_8)*dimen_ri)
1831 external_ab = 0.0_dp
1833 offset = int(my_b_size(jspin), int_8)*dimen_ri
1835 DO proc_shift = 1, para_env_sub%num_pe - 1
1836 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
1837 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
1839 CALL get_group_dist(gd_b_virtual(jspin), proc_send, send_b_virtual_start, send_b_virtual_end, send_b_size)
1840 send_ab(1:send_b_size, 1:dimen_ri) => buffer_1d(offset + 1:offset + int(dimen_ri, int_8)*send_b_size)
1842 CALL mp2_env%local_gemm_ctx%gemm(
'N',
'T', send_b_size, dimen_ri, my_b_size(ispin), mp2_env%scale_S, &
1843 local_ba(send_b_virtual_start:send_b_virtual_end, :), send_b_size, &
1844 my_local_i_al, dimen_ri, 0.0_dp, send_ab, send_b_size)
1845 CALL para_env_sub%sendrecv(send_ab, proc_send, external_ab, proc_receive)
1846 y_j_ap(:, :) = y_j_ap + external_ab
1851 CALL dgemm_counter_stop(dgemm_counter, 3*virtual(ispin), dimen_ri, my_b_size(jspin))
1853 CALL dgemm_counter_stop(dgemm_counter, virtual(ispin), dimen_ri, my_b_size(ispin))
1856 IF ((my_i /= my_j) .AND. (.NOT. alpha_beta))
THEN
1858 CALL dgemm_counter_start(dgemm_counter)
1859 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'T', my_b_size(ispin), dimen_ri, my_b_size(ispin), 1.0_dp, &
1860 t_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), :), my_b_size(ispin), &
1861 my_local_i_al, dimen_ri, 1.0_dp, y_j_ap, my_b_size(ispin))
1862 DO proc_shift = 1, para_env_sub%num_pe - 1
1863 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
1864 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
1866 CALL get_group_dist(gd_b_virtual(ispin), proc_receive, rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
1868 external_ab(1:dimen_ri, 1:rec_b_size) => buffer_1d(1:int(dimen_ri, int_8)*rec_b_size)
1869 external_ab = 0.0_dp
1871 CALL para_env_sub%sendrecv(my_local_i_al, proc_send, &
1872 external_ab, proc_receive)
1875 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'T', my_b_size(ispin), dimen_ri, rec_b_size, 1.0_dp, &
1876 t_ab(rec_b_virtual_start:rec_b_virtual_end, :), rec_b_size, &
1877 external_ab, dimen_ri, 1.0_dp, y_j_ap, my_b_size(ispin))
1880 CALL dgemm_counter_stop(dgemm_counter, my_b_size(ispin), dimen_ri, virtual(ispin))
1883 CALL timestop(handle)
1884 END SUBROUTINE mp2_update_p_gamma
1907 SUBROUTINE mp2_redistribute_gamma(Gamma_P_ia, ij_index, my_B_size, &
1908 my_block_size, my_group_L_size, my_i, my_ij_pairs, ngroup, &
1909 num_integ_group, integ_group_pos2color_sub, num_ij_pairs, &
1910 ij_map, ranges_info_array, Y_i_aP, comm_exchange, &
1911 sizes_array, spin, buffer_1D)
1913 REAL(kind=dp),
DIMENSION(:, :, :),
INTENT(INOUT) :: gamma_p_ia
1914 INTEGER,
INTENT(IN) :: ij_index, my_b_size, my_block_size, &
1915 my_group_l_size, my_i, my_ij_pairs, &
1916 ngroup, num_integ_group
1917 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(IN) :: integ_group_pos2color_sub, num_ij_pairs
1918 INTEGER,
ALLOCATABLE,
DIMENSION(:, :),
INTENT(IN) :: ij_map
1919 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :), &
1920 INTENT(IN) :: ranges_info_array
1921 REAL(kind=dp),
DIMENSION(:, :, :),
INTENT(IN) :: y_i_ap
1922 TYPE(mp_comm_type),
INTENT(IN) :: comm_exchange
1923 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(IN) :: sizes_array
1924 INTEGER,
INTENT(IN) :: spin
1925 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:),
TARGET :: buffer_1d
1927 CHARACTER(LEN=*),
PARAMETER :: routinen =
'mp2_redistribute_gamma'
1929 INTEGER :: end_point, handle, handle2, iib, ij_counter_rec, irep, kkk, lll, lstart_pos, &
1930 proc_receive, proc_send, proc_shift, rec_i, rec_ij_index, send_l_size, start_point, tag
1931 INTEGER(KIND=int_8) :: offset
1932 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:, :, :), &
1933 POINTER :: bi_c_rec, bi_c_send
1937 CALL timeset(routinen//
"_comm2", handle)
1941 IF (ij_index <= my_ij_pairs)
THEN
1944 CALL timeset(routinen//
"_comm2_w", handle2)
1945 DO irep = 0, num_integ_group - 1
1946 lstart_pos = ranges_info_array(1, irep, comm_exchange%mepos)
1947 start_point = ranges_info_array(3, irep, comm_exchange%mepos)
1948 end_point = ranges_info_array(4, irep, comm_exchange%mepos)
1953 DO kkk = start_point, end_point
1954 lll = kkk - start_point + lstart_pos
1955 DO iib = 1, my_block_size
1956 gamma_p_ia(1:my_b_size, my_i + iib - 1, kkk) = &
1957 gamma_p_ia(1:my_b_size, my_i + iib - 1, kkk) + &
1958 y_i_ap(1:my_b_size, lll, iib)
1963 CALL timestop(handle2)
1967 DO proc_shift = 1, comm_exchange%num_pe - 1
1968 proc_send =
modulo(comm_exchange%mepos + proc_shift, comm_exchange%num_pe)
1969 proc_receive =
modulo(comm_exchange%mepos - proc_shift, comm_exchange%num_pe)
1971 send_l_size = sizes_array(proc_send)
1972 bi_c_send(1:my_b_size, 1:my_block_size, 1:send_l_size) => &
1973 buffer_1d(1:int(my_b_size, int_8)*my_block_size*send_l_size)
1975 offset = int(my_b_size, int_8)*my_block_size*send_l_size
1977 CALL timeset(routinen//
"_comm2_w", handle2)
1979 DO irep = 0, num_integ_group - 1
1980 lstart_pos = ranges_info_array(1, irep, proc_send)
1981 start_point = ranges_info_array(3, irep, proc_send)
1982 end_point = ranges_info_array(4, irep, proc_send)
1987 DO kkk = start_point, end_point
1988 lll = kkk - start_point + lstart_pos
1989 DO iib = 1, my_block_size
1990 bi_c_send(1:my_b_size, iib, kkk) = y_i_ap(1:my_b_size, lll, iib)
1995 CALL timestop(handle2)
1997 rec_ij_index = num_ij_pairs(proc_receive)
1999 IF (ij_index <= rec_ij_index)
THEN
2002 (ij_index - min(1, integ_group_pos2color_sub(proc_receive)))*ngroup + integ_group_pos2color_sub(proc_receive)
2004 rec_i = ij_map(spin, ij_counter_rec)
2006 bi_c_rec(1:my_b_size, 1:my_block_size, 1:my_group_l_size) => &
2007 buffer_1d(offset + 1:offset + int(my_b_size, int_8)*my_block_size*my_group_l_size)
2010 CALL comm_exchange%sendrecv(bi_c_send, proc_send, &
2011 bi_c_rec, proc_receive, tag)
2013 CALL timeset(routinen//
"_comm2_w", handle2)
2014 DO irep = 0, num_integ_group - 1
2015 start_point = ranges_info_array(3, irep, comm_exchange%mepos)
2016 end_point = ranges_info_array(4, irep, comm_exchange%mepos)
2020 gamma_p_ia(:, rec_i:rec_i + my_block_size - 1, start_point:end_point) = &
2021 gamma_p_ia(:, rec_i:rec_i + my_block_size - 1, start_point:end_point) + &
2022 bi_c_rec(1:my_b_size, :, start_point:end_point)
2025 CALL timestop(handle2)
2029 CALL comm_exchange%send(bi_c_send, proc_send, tag)
2037 DO proc_shift = 1, comm_exchange%num_pe - 1
2038 proc_send =
modulo(comm_exchange%mepos + proc_shift, comm_exchange%num_pe)
2039 proc_receive =
modulo(comm_exchange%mepos - proc_shift, comm_exchange%num_pe)
2040 rec_ij_index = num_ij_pairs(proc_receive)
2042 IF (ij_index <= rec_ij_index)
THEN
2045 (ij_index - min(1, integ_group_pos2color_sub(proc_receive)))*ngroup + integ_group_pos2color_sub(proc_receive)
2047 rec_i = ij_map(spin, ij_counter_rec)
2049 bi_c_rec(1:my_b_size, 1:my_block_size, 1:my_group_l_size) => &
2050 buffer_1d(1:int(my_b_size, int_8)*my_block_size*my_group_l_size)
2054 CALL comm_exchange%recv(bi_c_rec, proc_receive, tag)
2056 CALL timeset(routinen//
"_comm2_w", handle2)
2057 DO irep = 0, num_integ_group - 1
2058 start_point = ranges_info_array(3, irep, comm_exchange%mepos)
2059 end_point = ranges_info_array(4, irep, comm_exchange%mepos)
2060#if !defined(__INTEL_LLVM_COMPILER) || (20250000 <= __INTEL_LLVM_COMPILER)
2065 gamma_p_ia(:, rec_i:rec_i + my_block_size - 1, start_point:end_point) = &
2066 gamma_p_ia(:, rec_i:rec_i + my_block_size - 1, start_point:end_point) + &
2067 bi_c_rec(1:my_b_size, :, start_point:end_point)
2068#if !defined(__INTEL_LLVM_COMPILER) || (20250000 <= __INTEL_LLVM_COMPILER)
2072 CALL timestop(handle2)
2078 CALL timestop(handle)
2080 END SUBROUTINE mp2_redistribute_gamma
2109 SUBROUTINE quasi_degenerate_p_ij(mp2_env, Eigenval, homo, virtual, open_shell, &
2110 beta_beta, Bib_C, unit_nr, dimen_RI, &
2111 my_B_size, ngroup, my_group_L_size, &
2112 color_sub, ranges_info_array, comm_exchange, para_env_sub, para_env, &
2113 my_B_virtual_start, my_B_virtual_end, sizes_array, gd_B_virtual, &
2114 integ_group_pos2color_sub, dgemm_counter, buffer_1D)
2115 TYPE(mp2_type) :: mp2_env
2116 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: eigenval
2117 INTEGER,
DIMENSION(:),
INTENT(IN) :: homo, virtual
2118 LOGICAL,
INTENT(IN) :: open_shell, beta_beta
2119 TYPE(three_dim_real_array),
DIMENSION(:), &
2121 INTEGER,
INTENT(IN) :: unit_nr, dimen_ri
2122 INTEGER,
DIMENSION(:),
INTENT(IN) :: my_b_size
2123 INTEGER,
INTENT(IN) :: ngroup, my_group_l_size, color_sub
2124 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :), &
2125 INTENT(IN) :: ranges_info_array
2126 TYPE(mp_comm_type),
INTENT(IN) :: comm_exchange
2127 TYPE(mp_para_env_type),
INTENT(IN) :: para_env_sub, para_env
2128 INTEGER,
DIMENSION(:),
INTENT(IN) :: my_b_virtual_start, my_b_virtual_end
2129 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(IN) :: sizes_array
2130 TYPE(group_dist_d1_type),
DIMENSION(:),
INTENT(IN) :: gd_b_virtual
2131 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(IN) :: integ_group_pos2color_sub
2132 TYPE(dgemm_counter_type),
INTENT(INOUT) :: dgemm_counter
2133 REAL(kind=dp),
CONTIGUOUS,
DIMENSION(:),
TARGET :: buffer_1d
2135 CHARACTER(LEN=*),
PARAMETER :: routinen =
'quasi_degenerate_P_ij'
2137 INTEGER :: a, a_global, b, b_global, block_size, decil, handle, handle2, ijk_counter, &
2138 ijk_counter_send, ijk_index, ispin, kkb, kspin, max_block_size, max_ijk, my_i, my_ijk, &
2139 my_j, my_k, my_last_k(2), my_virtual, nspins, proc_receive, proc_send, proc_shift, &
2140 rec_b_size, rec_b_virtual_end, rec_b_virtual_start, rec_l_size, send_b_size, &
2141 send_b_virtual_end, send_b_virtual_start, send_i, send_ijk_index, send_j, send_k, &
2142 size_b_i, size_b_k, tag, tag2
2143 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: num_ijk
2144 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: ijk_map, send_last_k
2145 LOGICAL :: alpha_beta, do_recv_i, do_recv_j, &
2146 do_recv_k, do_send_i, do_send_j, &
2148 REAL(kind=dp) :: amp_fac, p_ij_elem, t_new, t_start
2149 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :), &
2150 TARGET :: local_ab, local_al_i, local_al_j, t_ab
2151 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: local_al_k
2152 REAL(kind=dp),
DIMENSION(:, :),
POINTER :: bi_c_rec, external_ab, external_al
2153 REAL(kind=dp),
DIMENSION(:, :, :),
POINTER :: bi_c_rec_3d
2155 CALL timeset(routinen//
"_ij_sing", handle)
2160 nspins =
SIZE(bib_c)
2161 alpha_beta = (nspins == 2)
2164 amp_fac = mp2_env%scale_S + mp2_env%scale_T
2165 IF (open_shell) amp_fac = mp2_env%scale_T
2167 ALLOCATE (send_last_k(2, comm_exchange%num_pe - 1))
2170 DO ispin = 1, nspins
2171 size_b_i = my_b_size(ispin)
2172 IF (ispin == 1 .AND. alpha_beta)
THEN
2177 size_b_k = my_b_size(kspin)
2181 CALL find_quasi_degenerate_ij(my_ijk, homo(ispin), homo(kspin), eigenval(:, ispin), mp2_env, ijk_map, unit_nr, ngroup, &
2182 .NOT. beta_beta .AND. ispin /= 2, comm_exchange, num_ijk, max_ijk, color_sub, &
2183 SIZE(buffer_1d), my_group_l_size, size_b_k, para_env, virtual(ispin), size_b_i)
2185 my_virtual = virtual(ispin)
2186 IF (
SIZE(ijk_map, 2) > 0)
THEN
2187 max_block_size = ijk_map(4, 1)
2192 ALLOCATE (local_al_i(dimen_ri, size_b_i))
2193 ALLOCATE (local_al_j(dimen_ri, size_b_i))
2194 ALLOCATE (local_al_k(dimen_ri, size_b_k, max_block_size))
2195 ALLOCATE (t_ab(my_virtual, size_b_k))
2200 t_start = m_walltime()
2201 DO ijk_index = 1, max_ijk
2204 IF (unit_nr > 0 .AND. ijk_index > 1)
THEN
2205 decil = ijk_index*10/max_ijk
2206 IF (decil /= (ijk_index - 1)*10/max_ijk)
THEN
2207 t_new = m_walltime()
2208 t_new = (t_new - t_start)/60.0_dp*(max_ijk - ijk_index + 1)/(ijk_index - 1)
2209 WRITE (unit_nr, fmt=
"(T3,A)")
"Percentage of finished loop: "// &
2210 cp_to_string(decil*10)//
". Minutes left: "//cp_to_string(t_new)
2211 CALL m_flush(unit_nr)
2215 IF (ijk_index <= my_ijk)
THEN
2217 ijk_counter = (ijk_index - min(1, color_sub))*ngroup + color_sub
2218 my_i = ijk_map(1, ijk_counter)
2219 my_j = ijk_map(2, ijk_counter)
2220 my_k = ijk_map(3, ijk_counter)
2221 block_size = ijk_map(4, ijk_counter)
2223 do_recv_i = (ispin /= kspin) .OR. my_i < my_k .OR. my_i > my_k + block_size - 1
2224 do_recv_j = (ispin /= kspin) .OR. my_j < my_k .OR. my_j > my_k + block_size - 1
2225 do_recv_k = my_k /= my_last_k(1) .OR. my_k + block_size - 1 /= my_last_k(2)
2227 my_last_k(2) = my_k + block_size - 1
2231 CALL fill_local_i_al_2d(local_al_i, ranges_info_array(:, :, comm_exchange%mepos), &
2232 bib_c(ispin)%array(:, :, my_i))
2237 CALL fill_local_i_al_2d(local_al_j, ranges_info_array(:, :, comm_exchange%mepos), &
2238 bib_c(ispin)%array(:, :, my_j))
2243 CALL fill_local_i_al(local_al_k(:, :, 1:block_size), ranges_info_array(:, :, comm_exchange%mepos), &
2244 bib_c(kspin)%array(:, :, my_k:my_k + block_size - 1))
2247 CALL timeset(routinen//
"_comm", handle2)
2248 DO proc_shift = 1, comm_exchange%num_pe - 1
2249 proc_send =
modulo(comm_exchange%mepos + proc_shift, comm_exchange%num_pe)
2250 proc_receive =
modulo(comm_exchange%mepos - proc_shift, comm_exchange%num_pe)
2252 send_ijk_index = num_ijk(proc_send)
2254 rec_l_size = sizes_array(proc_receive)
2255 bi_c_rec(1:rec_l_size, 1:size_b_i) => buffer_1d(1:int(rec_l_size, kind=int_8)*size_b_i)
2260 IF (ijk_index <= send_ijk_index)
THEN
2262 ijk_counter_send = (ijk_index - min(1, integ_group_pos2color_sub(proc_send)))* &
2263 ngroup + integ_group_pos2color_sub(proc_send)
2264 send_i = ijk_map(1, ijk_counter_send)
2265 send_j = ijk_map(2, ijk_counter_send)
2266 send_k = ijk_map(3, ijk_counter_send)
2268 do_send_i = (ispin /= kspin) .OR. send_i < send_k .OR. send_i > send_k + block_size - 1
2269 do_send_j = (ispin /= kspin) .OR. send_j < send_k .OR. send_j > send_k + block_size - 1
2270 do_send_k = send_k /= send_last_k(1, proc_shift) .OR. send_k + block_size - 1 /= send_last_k(2, proc_shift)
2271 send_last_k(1, proc_shift) = send_k
2272 send_last_k(2, proc_shift) = send_k + block_size - 1
2279 CALL comm_exchange%sendrecv(bib_c(ispin)%array(:, :, send_i), proc_send, &
2280 bi_c_rec, proc_receive, tag)
2282 CALL comm_exchange%send(bib_c(ispin)%array(:, :, send_i), proc_send, tag)
2284 ELSE IF (do_recv_i)
THEN
2285 CALL comm_exchange%recv(bi_c_rec, proc_receive, tag)
2288 CALL fill_local_i_al_2d(local_al_i, ranges_info_array(:, :, proc_receive), bi_c_rec)
2295 CALL comm_exchange%sendrecv(bib_c(ispin)%array(:, :, send_j), proc_send, &
2296 bi_c_rec, proc_receive, tag)
2298 CALL comm_exchange%send(bib_c(ispin)%array(:, :, send_j), proc_send, tag)
2300 ELSE IF (do_recv_j)
THEN
2301 CALL comm_exchange%recv(bi_c_rec, proc_receive, tag)
2304 CALL fill_local_i_al_2d(local_al_j, ranges_info_array(:, :, proc_receive), bi_c_rec)
2308 bi_c_rec_3d(1:rec_l_size, 1:size_b_k, 1:block_size) => &
2309 buffer_1d(1:int(rec_l_size, kind=int_8)*size_b_k*block_size)
2312 CALL comm_exchange%sendrecv(bib_c(kspin)%array(:, :, send_k:send_k + block_size - 1), proc_send, &
2313 bi_c_rec_3d, proc_receive, tag)
2315 CALL comm_exchange%send(bi_c_rec, proc_receive, tag)
2317 ELSE IF (do_recv_k)
THEN
2318 CALL comm_exchange%recv(bi_c_rec_3d, proc_receive, tag)
2321 CALL fill_local_i_al(local_al_k(:, :, 1:block_size), ranges_info_array(:, :, proc_receive), bi_c_rec_3d)
2325 IF (.NOT. do_recv_i) local_al_i(:, :) = local_al_k(:, :, my_i - my_k + 1)
2326 IF (.NOT. do_recv_j) local_al_j(:, :) = local_al_k(:, :, my_j - my_k + 1)
2327 CALL timestop(handle2)
2330 DO kkb = 1, block_size
2331 CALL timeset(routinen//
"_exp_ik", handle2)
2332 CALL dgemm_counter_start(dgemm_counter)
2333 ALLOCATE (local_ab(my_virtual, size_b_k))
2335 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', size_b_i, size_b_k, dimen_ri, 1.0_dp, &
2336 local_al_i, dimen_ri, local_al_k(:, :, kkb), dimen_ri, &
2337 0.0_dp, local_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), 1:size_b_k), size_b_i)
2338 DO proc_shift = 1, para_env_sub%num_pe - 1
2339 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
2340 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
2342 CALL get_group_dist(gd_b_virtual(ispin), proc_receive, rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
2344 external_al(1:dimen_ri, 1:rec_b_size) => buffer_1d(1:int(dimen_ri, kind=int_8)*rec_b_size)
2346 CALL comm_exchange%sendrecv(local_al_i, proc_send, &
2347 external_al, proc_receive, tag)
2349 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', rec_b_size, size_b_k, dimen_ri, 1.0_dp, &
2350 external_al, dimen_ri, local_al_k(:, :, kkb), dimen_ri, &
2351 0.0_dp, local_ab(rec_b_virtual_start:rec_b_virtual_end, 1:size_b_k), rec_b_size)
2353 CALL dgemm_counter_stop(dgemm_counter, my_virtual, size_b_k, dimen_ri)
2354 CALL timestop(handle2)
2357 CALL timeset(routinen//
"_tab", handle2)
2360 IF (.NOT. alpha_beta)
THEN
2362 b_global = b + my_b_virtual_start(1) - 1
2363 DO a = 1, my_b_size(1)
2364 a_global = a + my_b_virtual_start(1) - 1
2365 t_ab(a_global, b) = (amp_fac*local_ab(a_global, b) - mp2_env%scale_T*local_ab(b_global, a))/ &
2366 (eigenval(my_i, 1) + eigenval(my_k + kkb - 1, 1) &
2367 - eigenval(homo(1) + a_global, 1) - eigenval(homo(1) + b_global, 1))
2372 b_global = b + my_b_virtual_start(kspin) - 1
2373 DO a = 1, my_b_size(ispin)
2374 a_global = a + my_b_virtual_start(ispin) - 1
2375 t_ab(a_global, b) = mp2_env%scale_S*local_ab(a_global, b)/ &
2376 (eigenval(my_i, ispin) + eigenval(my_k + kkb - 1, kspin) &
2377 - eigenval(homo(ispin) + a_global, ispin) - eigenval(homo(kspin) + b_global, kspin))
2382 IF (.NOT. alpha_beta)
THEN
2383 DO proc_shift = 1, para_env_sub%num_pe - 1
2384 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
2385 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
2386 CALL get_group_dist(gd_b_virtual(1), proc_receive, rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
2387 CALL get_group_dist(gd_b_virtual(1), proc_send, send_b_virtual_start, send_b_virtual_end, send_b_size)
2389 external_ab(1:size_b_i, 1:rec_b_size) => buffer_1d(1:int(size_b_i, kind=int_8)*rec_b_size)
2390 CALL para_env_sub%sendrecv(local_ab(send_b_virtual_start:send_b_virtual_end, 1:size_b_k), proc_send, &
2391 external_ab(1:size_b_i, 1:rec_b_size), proc_receive, tag)
2393 DO b = 1, my_b_size(1)
2394 b_global = b + my_b_virtual_start(1) - 1
2395 DO a = 1, rec_b_size
2396 a_global = a + rec_b_virtual_start - 1
2397 t_ab(a_global, b) = (amp_fac*local_ab(a_global, b) - mp2_env%scale_T*external_ab(b, a))/ &
2398 (eigenval(my_i, 1) + eigenval(my_k + kkb - 1, 1) &
2399 - eigenval(homo(1) + a_global, 1) - eigenval(homo(1) + b_global, 1))
2404 CALL timestop(handle2)
2407 CALL timeset(routinen//
"_exp_jk", handle2)
2409 CALL dgemm_counter_start(dgemm_counter)
2410 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', size_b_i, size_b_k, dimen_ri, 1.0_dp, &
2411 local_al_j, dimen_ri, local_al_k(:, :, kkb), dimen_ri, &
2412 0.0_dp, local_ab(my_b_virtual_start(ispin):my_b_virtual_end(ispin), 1:size_b_k), size_b_i)
2413 DO proc_shift = 1, para_env_sub%num_pe - 1
2414 proc_send =
modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
2415 proc_receive =
modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
2417 CALL get_group_dist(gd_b_virtual(ispin), proc_receive, rec_b_virtual_start, rec_b_virtual_end, rec_b_size)
2419 external_al(1:dimen_ri, 1:rec_b_size) => buffer_1d(1:int(dimen_ri, kind=int_8)*rec_b_size)
2421 CALL comm_exchange%sendrecv(local_al_j, proc_send, &
2422 external_al, proc_receive, tag)
2423 CALL mp2_env%local_gemm_ctx%gemm(
'T',
'N', rec_b_size, size_b_k, dimen_ri, 1.0_dp, &
2424 external_al, dimen_ri, local_al_k(:, :, kkb), dimen_ri, &
2425 0.0_dp, local_ab(rec_b_virtual_start:rec_b_virtual_end, 1:size_b_k), rec_b_size)
2427 CALL dgemm_counter_stop(dgemm_counter, my_virtual, size_b_k, dimen_ri)
2428 CALL timestop(handle2)
2430 CALL timeset(routinen//
"_Pij", handle2)
2432 b_global = b + my_b_virtual_start(kspin) - 1
2433 DO a = 1, my_b_size(ispin)
2434 a_global = a + my_b_virtual_start(ispin) - 1
2435 local_ab(a_global, b) = &
2436 local_ab(a_global, b)/(eigenval(my_j, ispin) + eigenval(my_k + kkb - 1, kspin) &
2437 - eigenval(homo(ispin) + a_global, ispin) - eigenval(homo(kspin) + b_global, kspin))
2441 p_ij_elem = sum(local_ab*t_ab)
2442 DEALLOCATE (local_ab)
2443 IF ((.NOT. open_shell) .AND. (.NOT. alpha_beta))
THEN
2444 p_ij_elem = p_ij_elem*2.0_dp
2447 mp2_env%ri_grad%P_ij(2)%array(my_i, my_j) = mp2_env%ri_grad%P_ij(2)%array(my_i, my_j) - p_ij_elem
2448 mp2_env%ri_grad%P_ij(2)%array(my_j, my_i) = mp2_env%ri_grad%P_ij(2)%array(my_j, my_i) - p_ij_elem
2450 mp2_env%ri_grad%P_ij(ispin)%array(my_i, my_j) = mp2_env%ri_grad%P_ij(ispin)%array(my_i, my_j) - p_ij_elem
2451 mp2_env%ri_grad%P_ij(ispin)%array(my_j, my_i) = mp2_env%ri_grad%P_ij(ispin)%array(my_j, my_i) - p_ij_elem
2453 CALL timestop(handle2)
2456 CALL timeset(routinen//
"_comm", handle2)
2458 DO proc_shift = 1, comm_exchange%num_pe - 1
2459 proc_send =
modulo(comm_exchange%mepos + proc_shift, comm_exchange%num_pe)
2460 proc_receive =
modulo(comm_exchange%mepos - proc_shift, comm_exchange%num_pe)
2462 send_ijk_index = num_ijk(proc_send)
2464 IF (ijk_index <= send_ijk_index)
THEN
2466 ijk_counter_send = (ijk_index - min(1, integ_group_pos2color_sub(proc_send)))*ngroup + &
2467 integ_group_pos2color_sub(proc_send)
2468 send_i = ijk_map(1, ijk_counter_send)
2469 send_j = ijk_map(2, ijk_counter_send)
2470 send_k = ijk_map(3, ijk_counter_send)
2471 block_size = ijk_map(4, ijk_counter_send)
2473 do_send_i = (ispin /= kspin) .OR. send_i < send_k .OR. send_i > send_k + block_size - 1
2474 do_send_j = (ispin /= kspin) .OR. send_j < send_k .OR. send_j > send_k + block_size - 1
2477 CALL comm_exchange%send(bib_c(ispin)%array(:, :, send_i), proc_send, tag)
2481 CALL comm_exchange%send(bib_c(ispin)%array(:, :, send_j), proc_send, tag)
2484 CALL comm_exchange%send(bib_c(kspin)%array(:, :, send_k:send_k + block_size - 1), proc_send, tag)
2488 CALL timestop(handle2)
2491 DEALLOCATE (local_al_i)
2492 DEALLOCATE (local_al_j)
2493 DEALLOCATE (local_al_k)
2495 DEALLOCATE (ijk_map)
2497 CALL timestop(handle)
2499 END SUBROUTINE quasi_degenerate_p_ij
2523 SUBROUTINE find_quasi_degenerate_ij(my_ijk, homo, homo_beta, Eigenval, mp2_env, ijk_map, unit_nr, ngroup, &
2524 do_print_alpha, comm_exchange, num_ijk, max_ijk, color_sub, &
2525 buffer_size, my_group_L_size, B_size_k, para_env, virtual, B_size_i)
2527 INTEGER,
INTENT(OUT) :: my_ijk
2528 INTEGER,
INTENT(IN) :: homo, homo_beta
2529 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: eigenval
2530 TYPE(mp2_type),
INTENT(IN) :: mp2_env
2531 INTEGER,
ALLOCATABLE,
DIMENSION(:, :),
INTENT(OUT) :: ijk_map
2532 INTEGER,
INTENT(IN) :: unit_nr, ngroup
2533 LOGICAL,
INTENT(IN) :: do_print_alpha
2534 TYPE(mp_comm_type),
INTENT(IN) :: comm_exchange
2535 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: num_ijk
2536 INTEGER,
INTENT(OUT) :: max_ijk
2537 INTEGER,
INTENT(IN) :: color_sub, buffer_size, my_group_l_size, &
2539 TYPE(mp_para_env_type),
INTENT(IN) :: para_env
2540 INTEGER,
INTENT(IN) :: virtual, b_size_i
2542 INTEGER :: block_size, communication_steps, communication_volume, iib, ij_counter, &
2543 ijk_counter, jjb, kkb, max_block_size, max_num_k_blocks, min_communication_volume, &
2544 my_steps, num_k_blocks, num_sing_ij, total_ijk
2545 INTEGER(KIND=int_8) :: mem
2546 LOGICAL,
ALLOCATABLE,
DIMENSION(:, :) :: ijk_marker
2548 ALLOCATE (num_ijk(0:comm_exchange%num_pe - 1))
2553 DO jjb = iib + 1, homo
2554 IF (abs(eigenval(jjb) - eigenval(iib)) < mp2_env%ri_grad%eps_canonical)
THEN
2555 num_sing_ij = num_sing_ij + 1
2560 IF (unit_nr > 0)
THEN
2561 IF (do_print_alpha)
THEN
2562 WRITE (unit=unit_nr, fmt=
"(T3,A,T75,i6)") &
2563 "MO_INFO| Number of ij pairs below EPS_CANONICAL:", num_sing_ij
2565 WRITE (unit=unit_nr, fmt=
"(T3,A,T75,i6)") &
2566 "MO_INFO| Number of ij pairs (spin beta) below EPS_CANONICAL:", num_sing_ij
2571 max_block_size = buffer_size/(my_group_l_size*b_size_k)
2578 mem = mem - 2_int_8*(virtual*b_size_k + b_size_i*my_group_l_size)
2579 max_block_size = min(max_block_size, max(1, int(mem/(my_group_l_size*b_size_k), kind(max_block_size))))
2582 CALL para_env%min(max_block_size)
2586 min_communication_volume = 3*homo_beta*num_sing_ij
2587 communication_steps = 3*homo_beta*num_sing_ij
2588 DO iib = max_block_size, 2, -1
2589 max_num_k_blocks = homo_beta/iib*num_sing_ij
2590 num_k_blocks = max_num_k_blocks - mod(max_num_k_blocks, ngroup)
2591 communication_volume = num_k_blocks*(2 + iib) + 3*(homo_beta*num_sing_ij - iib*num_k_blocks)
2592 my_steps = num_k_blocks + homo_beta*num_sing_ij - iib*num_k_blocks
2593 IF (communication_volume < min_communication_volume)
THEN
2595 min_communication_volume = communication_volume
2596 communication_steps = my_steps
2597 ELSE IF (communication_volume == min_communication_volume .AND. my_steps < communication_steps)
THEN
2599 communication_steps = my_steps
2603 IF (unit_nr > 0)
THEN
2604 WRITE (unit=unit_nr, fmt=
"(T3,A,T75,i6)") &
2605 "MO_INFO| Block size:", block_size
2606 CALL m_flush(unit_nr)
2610 max_num_k_blocks = homo_beta/block_size*num_sing_ij
2611 num_k_blocks = max_num_k_blocks - mod(max_num_k_blocks, ngroup)
2613 total_ijk = num_k_blocks + homo_beta*num_sing_ij - num_k_blocks*block_size
2614 ALLOCATE (ijk_map(4, total_ijk))
2616 ALLOCATE (ijk_marker(homo_beta, num_sing_ij))
2624 DO jjb = iib + 1, homo
2625 IF (abs(eigenval(jjb) - eigenval(iib)) >= mp2_env%ri_grad%eps_canonical) cycle
2626 ij_counter = ij_counter + 1
2627 DO kkb = 1, homo_beta - mod(homo_beta, block_size), block_size
2628 IF (ijk_counter + 1 > num_k_blocks)
EXIT
2629 ijk_counter = ijk_counter + 1
2630 ijk_marker(kkb:kkb + block_size - 1, ij_counter) = .false.
2631 ijk_map(1, ijk_counter) = iib
2632 ijk_map(2, ijk_counter) = jjb
2633 ijk_map(3, ijk_counter) = kkb
2634 ijk_map(4, ijk_counter) = block_size
2635 IF (mod(ijk_counter, ngroup) == color_sub) my_ijk = my_ijk + 1
2642 DO jjb = iib + 1, homo
2643 IF (abs(eigenval(jjb) - eigenval(iib)) >= mp2_env%ri_grad%eps_canonical) cycle
2644 ij_counter = ij_counter + 1
2645 DO kkb = 1, homo_beta
2646 IF (ijk_marker(kkb, ij_counter))
THEN
2647 ijk_counter = ijk_counter + 1
2648 ijk_map(1, ijk_counter) = iib
2649 ijk_map(2, ijk_counter) = jjb
2650 ijk_map(3, ijk_counter) = kkb
2651 ijk_map(4, ijk_counter) = 1
2652 IF (mod(ijk_counter, ngroup) == color_sub) my_ijk = my_ijk + 1
2658 DEALLOCATE (ijk_marker)
2660 CALL comm_exchange%allgather(my_ijk, num_ijk)
2661 max_ijk = maxval(num_ijk)
2663 END SUBROUTINE find_quasi_degenerate_ij
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
various routines to log and control the output. The idea is that decisions about where to log should ...
Counters to determine the performance of parallel DGEMMs.
elemental subroutine, public dgemm_counter_init(dgemm_counter, unit_nr, print_info)
Initialize a dgemm_counter.
subroutine, public dgemm_counter_write(dgemm_counter, para_env)
calculate and print flop rates
subroutine, public dgemm_counter_start(dgemm_counter)
start timer of the counter
subroutine, public dgemm_counter_stop(dgemm_counter, size1, size2, size3)
stop timer of the counter and provide matrix sizes
Types to describe group distributions.
elemental integer function, public maxsize(this)
...
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
2- and 3-center electron repulsion integral routines based on libint2 Currently available operators: ...
pure logical function, public compare_potential_types(potential1, potential2)
Helper function to compare libint_potential_types.
integer, parameter, public local_gemm_pu_gpu
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_memory(mem)
Returns the total amount of memory [bytes] in use, if known, zero otherwise.
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Interface to the message passing library MPI.
Routines to calculate RI-GPW-MP2 energy using pw.
subroutine, public mp2_ri_gpw_compute_en(emp2_cou, emp2_ex, emp2_s, emp2_t, bib_c, mp2_env, para_env, para_env_sub, color_sub, gd_array, gd_b_virtual, eigenval, nmo, homo, dimen_ri, unit_nr, calc_forces, calc_ex)
...
Routines for calculating RI-MP2 gradients.
subroutine, public complete_gamma(mp2_env, b_ia_q, dimen_ri, homo, virtual, para_env, para_env_sub, ngroup, my_group_l_size, my_group_l_start, my_group_l_end, my_b_size, my_b_virtual_start, gd_array, gd_b_virtual, kspin)
complete the calculation of the Gamma matrices
Types needed for MP2 calculations.
stores all the informations relevant to an mpi environment