(git:ed6f26b)
Loading...
Searching...
No Matches
rpa_exchange.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Auxiliary routines needed for RPA-exchange
10!> given blacs_env to another
11!> \par History
12!> 09.2016 created [Vladimir Rybkin]
13!> 03.2019 Renamed [Frederick Stein]
14!> 03.2019 Moved Functions from rpa_ri_gpw.F [Frederick Stein]
15!> 04.2024 Added open-shell calculations, SOSEX [Frederick Stein]
16!> \author Vladimir Rybkin
17! **************************************************************************************************
20 USE cell_types, ONLY: cell_type
23 USE cp_dbcsr_api, ONLY: &
25 dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
33 USE cp_fm_types, ONLY: cp_fm_create,&
44 maxsize,&
47 USE hfx_types, ONLY: hfx_create,&
55 USE kinds, ONLY: dp,&
56 int_8
58 USE mathconstants, ONLY: sqrthalf
61 USE mp2_types, ONLY: mp2_type
70 USE rpa_util, ONLY: calc_fm_mat_s_rpa,&
73#include "./base/base_uses.f90"
74
75 IMPLICIT NONE
76
77 PRIVATE
78
79 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rpa_exchange'
80
82
83 TYPE rpa_exchange_env_type
84 PRIVATE
85 TYPE(qs_environment_type), POINTER :: qs_env => null()
86 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_hfx => null()
87 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: dbcsr_Gamma_munu_P => null()
88 TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: dbcsr_Gamma_inu_P
89 ! Workaround GCC 8
90 TYPE(dbcsr_type), DIMENSION(:), POINTER :: mo_coeff_o => null()
91 TYPE(dbcsr_type), DIMENSION(:), POINTER :: mo_coeff_v => null()
92 TYPE(dbcsr_type) :: work_ao
93 TYPE(hfx_type), DIMENSION(:, :), POINTER :: x_data => null()
94 TYPE(mp_para_env_type), POINTER :: para_env => null()
95 TYPE(section_vals_type), POINTER :: hfx_sections => null()
96 LOGICAL :: my_recalc_hfx_integrals = .false.
97 REAL(KIND=dp) :: eps_filter = 0.0_dp
98 TYPE(cp_fm_struct_p_type), DIMENSION(:), ALLOCATABLE :: struct_Gamma
99 CONTAINS
100 PROCEDURE, PASS(exchange_env), NON_OVERRIDABLE :: create => hfx_create_subgroup
101 !PROCEDURE, PASS(exchange_env), NON_OVERRIDABLE :: integrate => integrate_exchange
102 PROCEDURE, PASS(exchange_env), NON_OVERRIDABLE :: release => hfx_release_subgroup
103 END TYPE
104
105 TYPE dbcsr_matrix_p_set
106 TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: matrix_set
107 END TYPE
108
110 PRIVATE
111 INTEGER :: exchange_correction = rpa_exchange_none
112 TYPE(rpa_exchange_env_type) :: exchange_env
113 INTEGER, DIMENSION(:), ALLOCATABLE :: homo, virtual, dimen_ia
114 TYPE(group_dist_d1_type) :: aux_func_dist = group_dist_d1_type()
115 INTEGER, DIMENSION(:), ALLOCATABLE :: aux2send
116 INTEGER :: dimen_ri = 0
117 INTEGER :: block_size = 0
118 INTEGER :: color_sub = 0
119 INTEGER :: ngroup = 0
120 TYPE(cp_fm_type) :: fm_mat_q_tmp = cp_fm_type()
121 TYPE(cp_fm_type) :: fm_mat_r_half_gemm = cp_fm_type()
122 TYPE(cp_fm_type) :: fm_mat_u = cp_fm_type()
123 TYPE(mp_para_env_type), POINTER :: para_env_sub => null()
124 CONTAINS
125 PROCEDURE, PUBLIC, pass(exchange_work), non_overridable :: create => rpa_exchange_work_create
126 PROCEDURE, PUBLIC, pass(exchange_work), non_overridable :: compute => rpa_exchange_work_compute
127 PROCEDURE, PUBLIC, pass(exchange_work), non_overridable :: release => rpa_exchange_work_release
128 PROCEDURE, PRIVATE, pass(exchange_work), non_overridable :: redistribute_into_subgroups
129 PROCEDURE, PRIVATE, pass(exchange_work), non_overridable :: compute_fm => rpa_exchange_work_compute_fm
130 PROCEDURE, PRIVATE, pass(exchange_work), non_overridable :: compute_hfx => rpa_exchange_work_compute_hfx
131 END TYPE
132
133CONTAINS
134
135! **************************************************************************************************
136!> \brief ...
137!> \param mp2_env ...
138!> \param homo ...
139!> \param virtual ...
140!> \param dimen_RI ...
141!> \param para_env ...
142!> \param mem_per_rank ...
143!> \param mem_per_repl ...
144! **************************************************************************************************
145 SUBROUTINE rpa_exchange_needed_mem(mp2_env, homo, virtual, dimen_RI, para_env, mem_per_rank, mem_per_repl)
146 TYPE(mp2_type), INTENT(IN) :: mp2_env
147 INTEGER, DIMENSION(:), INTENT(IN) :: homo, virtual
148 INTEGER, INTENT(IN) :: dimen_ri
149 TYPE(mp_para_env_type), INTENT(IN) :: para_env
150 REAL(kind=dp), INTENT(INOUT) :: mem_per_rank, mem_per_repl
151
152 INTEGER :: block_size
153
154 ! We need the block size and if it is unknown, an upper bound
155 block_size = mp2_env%ri_rpa%exchange_block_size
156 IF (block_size <= 0) block_size = max(1, (dimen_ri + para_env%num_pe - 1)/para_env%num_pe)
157
158 ! storage of product matrix (upper bound only as it depends on the square of the potential still unknown block size)
159 mem_per_rank = mem_per_rank + real(maxval(homo), kind=dp)**2*block_size**2*8.0_dp/(1024_dp**2)
160
161 ! work arrays R (2x) and U, copies of Gamma (2x), communication buffer (as expensive as Gamma)
162 mem_per_repl = mem_per_repl + 3.0_dp*dimen_ri*dimen_ri*8.0_dp/(1024_dp**2) &
163 + 3.0_dp*maxval(homo*virtual)*dimen_ri*8.0_dp/(1024_dp**2)
164 END SUBROUTINE rpa_exchange_needed_mem
165
166! **************************************************************************************************
167!> \brief ...
168!> \param exchange_work ...
169!> \param qs_env ...
170!> \param para_env_sub ...
171!> \param mat_munu ...
172!> \param dimen_RI ...
173!> \param fm_mat_S ...
174!> \param fm_mat_Q ...
175!> \param fm_mat_Q_gemm ...
176!> \param homo ...
177!> \param virtual ...
178! **************************************************************************************************
179 SUBROUTINE rpa_exchange_work_create(exchange_work, qs_env, para_env_sub, mat_munu, dimen_RI, &
180 fm_mat_S, fm_mat_Q, fm_mat_Q_gemm, homo, virtual)
181 CLASS(rpa_exchange_work_type), INTENT(INOUT) :: exchange_work
182 TYPE(qs_environment_type), POINTER :: qs_env
183 TYPE(mp_para_env_type), POINTER, INTENT(IN) :: para_env_sub
184 TYPE(dbcsr_p_type), INTENT(IN) :: mat_munu
185 INTEGER, INTENT(IN) :: dimen_ri
186 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: fm_mat_s
187 TYPE(cp_fm_type), INTENT(IN) :: fm_mat_q, fm_mat_q_gemm
188 INTEGER, DIMENSION(SIZE(fm_mat_S)), INTENT(IN) :: homo, virtual
189
190 INTEGER :: nspins, aux_global, aux_local, my_process_row, proc, ispin
191 INTEGER, DIMENSION(:), POINTER :: row_indices, aux_distribution_fm
192 TYPE(cp_blacs_env_type), POINTER :: context
193
194 exchange_work%exchange_correction = qs_env%mp2_env%ri_rpa%exchange_correction
195
196 IF (exchange_work%exchange_correction == rpa_exchange_none) RETURN
197
198 associate(para_env => fm_mat_s(1)%matrix_struct%para_env)
199 exchange_work%para_env_sub => para_env_sub
200 exchange_work%ngroup = para_env%num_pe/para_env_sub%num_pe
201 exchange_work%color_sub = para_env%mepos/para_env_sub%num_pe
202 END associate
203
204 CALL cp_fm_get_info(fm_mat_s(1), row_indices=row_indices, nrow_locals=aux_distribution_fm, context=context)
205 CALL context%get(my_process_row=my_process_row)
206
207 CALL create_group_dist(exchange_work%aux_func_dist, exchange_work%ngroup, dimen_ri)
208 ALLOCATE (exchange_work%aux2send(0:exchange_work%ngroup - 1))
209 exchange_work%aux2send = 0
210 DO aux_local = 1, aux_distribution_fm(my_process_row)
211 aux_global = row_indices(aux_local)
212 proc = group_dist_proc(exchange_work%aux_func_dist, aux_global)
213 exchange_work%aux2send(proc) = exchange_work%aux2send(proc) + 1
214 END DO
215
216 nspins = SIZE(fm_mat_s)
217
218 ALLOCATE (exchange_work%homo(nspins), exchange_work%virtual(nspins), exchange_work%dimen_ia(nspins))
219 exchange_work%homo(:) = homo
220 exchange_work%virtual(:) = virtual
221 exchange_work%dimen_ia(:) = homo*virtual
222 exchange_work%dimen_RI = dimen_ri
223
224 exchange_work%block_size = qs_env%mp2_env%ri_rpa%exchange_block_size
225 IF (exchange_work%block_size <= 0) exchange_work%block_size = dimen_ri
226
227 CALL cp_fm_create(exchange_work%fm_mat_U, fm_mat_q%matrix_struct, name="fm_mat_U")
228 CALL cp_fm_create(exchange_work%fm_mat_Q_tmp, fm_mat_q%matrix_struct, name="fm_mat_Q_tmp")
229 CALL cp_fm_create(exchange_work%fm_mat_R_half_gemm, fm_mat_q_gemm%matrix_struct)
230
231 IF (qs_env%mp2_env%ri_rpa%use_hfx_implementation) THEN
232 CALL exchange_work%exchange_env%create(qs_env, mat_munu%matrix, para_env_sub, fm_mat_s)
233 END IF
234
235 IF (ASSOCIATED(qs_env%mp2_env%ri_rpa%mo_coeff_o)) THEN
236 DO ispin = 1, SIZE(qs_env%mp2_env%ri_rpa%mo_coeff_o)
237 CALL dbcsr_release(qs_env%mp2_env%ri_rpa%mo_coeff_o(ispin))
238 END DO
239 DEALLOCATE (qs_env%mp2_env%ri_rpa%mo_coeff_o)
240 END IF
241
242 IF (ASSOCIATED(qs_env%mp2_env%ri_rpa%mo_coeff_v)) THEN
243 DO ispin = 1, SIZE(qs_env%mp2_env%ri_rpa%mo_coeff_v)
244 CALL dbcsr_release(qs_env%mp2_env%ri_rpa%mo_coeff_v(ispin))
245 END DO
246 DEALLOCATE (qs_env%mp2_env%ri_rpa%mo_coeff_v)
247 END IF
248 END SUBROUTINE
249
250! **************************************************************************************************
251!> \brief ... Initializes x_data on a subgroup
252!> \param exchange_env ...
253!> \param qs_env ...
254!> \param mat_munu ...
255!> \param para_env_sub ...
256!> \param fm_mat_S ...
257!> \author Vladimir Rybkin
258! **************************************************************************************************
259 SUBROUTINE hfx_create_subgroup(exchange_env, qs_env, mat_munu, para_env_sub, fm_mat_S)
260 CLASS(rpa_exchange_env_type), INTENT(INOUT) :: exchange_env
261 TYPE(dbcsr_type), INTENT(IN) :: mat_munu
262 TYPE(qs_environment_type), POINTER :: qs_env
263 TYPE(mp_para_env_type), POINTER, INTENT(IN) :: para_env_sub
264 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: fm_mat_s
265
266 CHARACTER(LEN=*), PARAMETER :: routinen = 'hfx_create_subgroup'
267
268 INTEGER :: handle, nelectron_total, ispin, &
269 number_of_aos, nspins, dimen_ri, dimen_ia
270 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
271 TYPE(cell_type), POINTER :: my_cell
272 TYPE(dft_control_type), POINTER :: dft_control
273 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
274 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
275 TYPE(qs_subsys_type), POINTER :: subsys
276 TYPE(scf_control_type), POINTER :: scf_control
277 TYPE(section_vals_type), POINTER :: input
278
279 CALL timeset(routinen, handle)
280
281 exchange_env%mo_coeff_o => qs_env%mp2_env%ri_rpa%mo_coeff_o
282 exchange_env%mo_coeff_v => qs_env%mp2_env%ri_rpa%mo_coeff_v
283 NULLIFY (qs_env%mp2_env%ri_rpa%mo_coeff_o, qs_env%mp2_env%ri_rpa%mo_coeff_v)
284
285 nspins = SIZE(exchange_env%mo_coeff_o)
286
287 exchange_env%qs_env => qs_env
288 exchange_env%para_env => para_env_sub
289 exchange_env%eps_filter = qs_env%mp2_env%mp2_gpw%eps_filter
290
291 NULLIFY (my_cell, atomic_kind_set, particle_set, dft_control, qs_kind_set, scf_control)
292
293 CALL get_qs_env(qs_env, &
294 subsys=subsys, &
295 input=input, &
296 scf_control=scf_control, &
297 nelectron_total=nelectron_total)
298
299 CALL qs_subsys_get(subsys, &
300 cell=my_cell, &
301 atomic_kind_set=atomic_kind_set, &
302 qs_kind_set=qs_kind_set, &
303 particle_set=particle_set)
304
305 exchange_env%hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%WF_CORRELATION%RI_RPA%HF")
306 CALL get_qs_env(qs_env, dft_control=dft_control)
307
308 ! Retrieve particle_set and atomic_kind_set
309 CALL hfx_create(exchange_env%x_data, para_env_sub, exchange_env%hfx_sections, atomic_kind_set, &
310 qs_kind_set, particle_set, dft_control, my_cell, orb_basis='ORB', &
311 nelectron_total=nelectron_total)
312
313 exchange_env%my_recalc_hfx_integrals = .true.
314
315 CALL dbcsr_allocate_matrix_set(exchange_env%mat_hfx, nspins)
316 DO ispin = 1, nspins
317 ALLOCATE (exchange_env%mat_hfx(ispin)%matrix)
318 CALL dbcsr_init_p(exchange_env%mat_hfx(ispin)%matrix)
319 CALL dbcsr_create(exchange_env%mat_hfx(ispin)%matrix, template=mat_munu, &
320 matrix_type=dbcsr_type_no_symmetry)
321 CALL dbcsr_copy(exchange_env%mat_hfx(ispin)%matrix, mat_munu)
322 END DO
323
324 CALL dbcsr_get_info(mat_munu, nfullcols_total=number_of_aos)
325
326 CALL dbcsr_create(exchange_env%work_ao, template=mat_munu, &
327 matrix_type=dbcsr_type_no_symmetry)
328
329 ALLOCATE (exchange_env%dbcsr_Gamma_inu_P(nspins))
330 CALL dbcsr_allocate_matrix_set(exchange_env%dbcsr_Gamma_munu_P, nspins)
331 DO ispin = 1, nspins
332 ALLOCATE (exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix)
333 CALL dbcsr_create(exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix, template=mat_munu, &
334 matrix_type=dbcsr_type_no_symmetry)
335 CALL dbcsr_copy(exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix, mat_munu)
336 CALL dbcsr_set(exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix, 0.0_dp)
337
338 CALL dbcsr_create(exchange_env%dbcsr_Gamma_inu_P(ispin), template=exchange_env%mo_coeff_o(ispin))
339 CALL dbcsr_copy(exchange_env%dbcsr_Gamma_inu_P(ispin), exchange_env%mo_coeff_o(ispin))
340 CALL dbcsr_set(exchange_env%dbcsr_Gamma_inu_P(ispin), 0.0_dp)
341 END DO
342
343 ALLOCATE (exchange_env%struct_Gamma(nspins))
344 DO ispin = 1, nspins
345 CALL cp_fm_get_info(fm_mat_s(ispin), nrow_global=dimen_ri, ncol_global=dimen_ia)
346 CALL cp_fm_struct_create(exchange_env%struct_Gamma(ispin)%struct, template_fmstruct=fm_mat_s(ispin)%matrix_struct, &
347 nrow_global=dimen_ia, ncol_global=dimen_ri)
348 END DO
349
350 CALL timestop(handle)
351
352 END SUBROUTINE hfx_create_subgroup
353
354! **************************************************************************************************
355!> \brief ...
356!> \param exchange_work ...
357! **************************************************************************************************
358 SUBROUTINE rpa_exchange_work_release(exchange_work)
359 CLASS(rpa_exchange_work_type), INTENT(INOUT) :: exchange_work
360
361 IF (ALLOCATED(exchange_work%homo)) DEALLOCATE (exchange_work%homo)
362 IF (ALLOCATED(exchange_work%virtual)) DEALLOCATE (exchange_work%virtual)
363 IF (ALLOCATED(exchange_work%dimen_ia)) DEALLOCATE (exchange_work%dimen_ia)
364 NULLIFY (exchange_work%para_env_sub)
365 CALL release_group_dist(exchange_work%aux_func_dist)
366 IF (ALLOCATED(exchange_work%aux2send)) DEALLOCATE (exchange_work%aux2send)
367 CALL cp_fm_release(exchange_work%fm_mat_Q_tmp)
368 CALL cp_fm_release(exchange_work%fm_mat_U)
369 CALL cp_fm_release(exchange_work%fm_mat_R_half_gemm)
370
371 CALL exchange_work%exchange_env%release()
372 END SUBROUTINE
373
374! **************************************************************************************************
375!> \brief ...
376!> \param exchange_env ...
377! **************************************************************************************************
378 SUBROUTINE hfx_release_subgroup(exchange_env)
379 CLASS(rpa_exchange_env_type), INTENT(INOUT) :: exchange_env
380
381 INTEGER :: ispin
382
383 NULLIFY (exchange_env%para_env, exchange_env%hfx_sections)
384
385 IF (ASSOCIATED(exchange_env%x_data)) THEN
386 CALL hfx_release(exchange_env%x_data)
387 NULLIFY (exchange_env%x_data)
388 END IF
389
390 CALL dbcsr_release(exchange_env%work_ao)
391
392 IF (ASSOCIATED(exchange_env%dbcsr_Gamma_munu_P)) THEN
393 DO ispin = 1, SIZE(exchange_env%mat_hfx, 1)
394 CALL dbcsr_release(exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix)
395 CALL dbcsr_release(exchange_env%mat_hfx(ispin)%matrix)
396 CALL dbcsr_release(exchange_env%dbcsr_Gamma_inu_P(ispin))
397 CALL dbcsr_release(exchange_env%mo_coeff_o(ispin))
398 CALL dbcsr_release(exchange_env%mo_coeff_v(ispin))
399 DEALLOCATE (exchange_env%mat_hfx(ispin)%matrix)
400 DEALLOCATE (exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix)
401 END DO
402 DEALLOCATE (exchange_env%mat_hfx, exchange_env%dbcsr_Gamma_munu_P)
403 DEALLOCATE (exchange_env%dbcsr_Gamma_inu_P, exchange_env%mo_coeff_o, exchange_env%mo_coeff_v)
404 NULLIFY (exchange_env%mat_hfx, exchange_env%dbcsr_Gamma_munu_P)
405 END IF
406 IF (ALLOCATED(exchange_env%struct_Gamma)) THEN
407 DO ispin = 1, SIZE(exchange_env%struct_Gamma)
408 CALL cp_fm_struct_release(exchange_env%struct_Gamma(ispin)%struct)
409 END DO
410 DEALLOCATE (exchange_env%struct_Gamma)
411 END IF
412 END SUBROUTINE hfx_release_subgroup
413
414! **************************************************************************************************
415!> \brief Main driver for RPA-exchange energies
416!> \param exchange_work ...
417!> \param fm_mat_Q ...
418!> \param eig ...
419!> \param fm_mat_S ...
420!> \param omega ...
421!> \param e_exchange_corr exchange energy correction for a quadrature point
422!> \param mp2_env ...
423!> \author Vladimir Rybkin, 07/2016
424! **************************************************************************************************
425 SUBROUTINE rpa_exchange_work_compute(exchange_work, fm_mat_Q, eig, fm_mat_S, omega, &
426 e_exchange_corr, mp2_env)
427 CLASS(rpa_exchange_work_type), INTENT(INOUT) :: exchange_work
428 TYPE(cp_fm_type), INTENT(IN) :: fm_mat_q
429 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: eig
430 TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: fm_mat_s
431 REAL(kind=dp), INTENT(IN) :: omega
432 REAL(kind=dp), INTENT(INOUT) :: e_exchange_corr
433 TYPE(mp2_type), INTENT(INOUT) :: mp2_env
434
435 CHARACTER(LEN=*), PARAMETER :: routinen = 'rpa_exchange_work_compute'
436 REAL(kind=dp), PARAMETER :: thresh = 0.0000001_dp
437
438 INTEGER :: handle, nspins, dimen_ri, iib
439 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenval
440
441 IF (exchange_work%exchange_correction == rpa_exchange_none) RETURN
442
443 CALL timeset(routinen, handle)
444
445 CALL cp_fm_get_info(fm_mat_q, ncol_global=dimen_ri)
446
447 nspins = SIZE(fm_mat_s)
448
449 ! Eigenvalues
450 ALLOCATE (eigenval(dimen_ri))
451 eigenval = 0.0_dp
452
453 CALL cp_fm_set_all(matrix=exchange_work%fm_mat_Q_tmp, alpha=0.0_dp)
454 CALL cp_fm_set_all(matrix=exchange_work%fm_mat_U, alpha=0.0_dp)
455
456 ! Copy Q to Q_tmp
457 CALL cp_fm_to_fm(fm_mat_q, exchange_work%fm_mat_Q_tmp)
458 ! Diagonalize Q
459 CALL choose_eigv_solver(exchange_work%fm_mat_Q_tmp, exchange_work%fm_mat_U, eigenval)
460
461 ! Calculate diagonal matrix for R_half
462
463 ! Manipulate eigenvalues to get diagonal matrix
464 IF (exchange_work%exchange_correction == rpa_exchange_axk) THEN
465 DO iib = 1, dimen_ri
466 IF (abs(eigenval(iib)) .GE. thresh) THEN
467 eigenval(iib) = &
468 sqrt((1.0_dp/(eigenval(iib)**2))*log(1.0_dp + eigenval(iib)) &
469 - 1.0_dp/(eigenval(iib)*(eigenval(iib) + 1.0_dp)))
470 ELSE
471 eigenval(iib) = sqrthalf
472 END IF
473 END DO
474 ELSE IF (exchange_work%exchange_correction == rpa_exchange_sosex) THEN
475 DO iib = 1, dimen_ri
476 IF (abs(eigenval(iib)) .GE. thresh) THEN
477 eigenval(iib) = &
478 sqrt(-(1.0_dp/(eigenval(iib)**2))*log(1.0_dp + eigenval(iib)) &
479 + 1.0_dp/eigenval(iib))
480 ELSE
481 eigenval(iib) = sqrthalf
482 END IF
483 END DO
484 ELSE
485 cpabort("Unknown RPA exchange correction")
486 END IF
487
488 ! fm_mat_U now contains some sqrt of the required matrix-valued function
489 CALL cp_fm_column_scale(exchange_work%fm_mat_U, eigenval)
490
491 ! Release memory
492 DEALLOCATE (eigenval)
493
494 ! Redistribute fm_mat_U for "rectangular" multiplication: ia*P P*P
495 CALL cp_fm_set_all(matrix=exchange_work%fm_mat_R_half_gemm, alpha=0.0_dp)
496
497 CALL cp_fm_to_fm_submat_general(exchange_work%fm_mat_U, exchange_work%fm_mat_R_half_gemm, dimen_ri, &
498 dimen_ri, 1, 1, 1, 1, exchange_work%fm_mat_U%matrix_struct%context)
499
500 IF (mp2_env%ri_rpa%use_hfx_implementation) THEN
501 CALL exchange_work%compute_hfx(fm_mat_s, eig, omega, e_exchange_corr)
502 ELSE
503 CALL exchange_work%compute_fm(fm_mat_s, eig, omega, e_exchange_corr, mp2_env)
504 END IF
505
506 CALL timestop(handle)
507
508 END SUBROUTINE rpa_exchange_work_compute
509
510! **************************************************************************************************
511!> \brief Main driver for RPA-exchange energies
512!> \param exchange_work ...
513!> \param fm_mat_S ...
514!> \param eig ...
515!> \param omega ...
516!> \param e_exchange_corr exchange energy correction for a quadrature point
517!> \param mp2_env ...
518!> \author Frederick Stein, May-June 2024
519! **************************************************************************************************
520 SUBROUTINE rpa_exchange_work_compute_fm(exchange_work, fm_mat_S, eig, omega, &
521 e_exchange_corr, mp2_env)
522 CLASS(rpa_exchange_work_type), INTENT(INOUT) :: exchange_work
523 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: fm_mat_s
524 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: eig
525 REAL(kind=dp), INTENT(IN) :: omega
526 REAL(kind=dp), INTENT(INOUT) :: e_exchange_corr
527 TYPE(mp2_type), INTENT(INOUT) :: mp2_env
528
529 CHARACTER(LEN=*), PARAMETER :: routinen = 'rpa_exchange_work_compute_fm'
530
531 INTEGER :: handle, ispin, nspins, p, q, l_size_gamma, hom, virt, i, &
532 send_proc, recv_proc, recv_size, max_aux_size, proc_shift, dimen_ia, &
533 block_size, p_start, p_end, p_size, q_start, q_size, q_end, handle2, my_aux_size, my_virt
534 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), TARGET :: mat_gamma_3_3d
535 REAL(kind=dp), POINTER, DIMENSION(:), CONTIGUOUS :: mat_gamma_3_1d
536 REAL(kind=dp), POINTER, DIMENSION(:, :), CONTIGUOUS :: mat_gamma_3_2d
537 REAL(kind=dp), ALLOCATABLE, TARGET, DIMENSION(:) :: recv_buffer_1d
538 REAL(kind=dp), POINTER, DIMENSION(:, :), CONTIGUOUS :: recv_buffer_2d
539 REAL(kind=dp), POINTER, DIMENSION(:, :, :), CONTIGUOUS :: recv_buffer_3d
540 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: mat_b_iap
541 REAL(kind=dp), ALLOCATABLE, DIMENSION(:), TARGET :: product_matrix_1d
542 REAL(kind=dp), POINTER, DIMENSION(:, :), CONTIGUOUS :: product_matrix_2d
543 REAL(kind=dp), POINTER, DIMENSION(:, :, :, :), CONTIGUOUS :: product_matrix_4d
544 TYPE(cp_fm_type) :: fm_mat_gamma_3
545 TYPE(mp_para_env_type), POINTER :: para_env
546 TYPE(group_dist_d1_type) :: virt_dist
547
548 CALL timeset(routinen, handle)
549
550 nspins = SIZE(fm_mat_s)
551
552 CALL get_group_dist(exchange_work%aux_func_dist, exchange_work%color_sub, sizes=my_aux_size)
553
554 e_exchange_corr = 0.0_dp
555 max_aux_size = maxsize(exchange_work%aux_func_dist)
556
557 ! local_gemm_ctx has a very large footprint the first time this routine is
558 ! called.
559 CALL mp2_env%local_gemm_ctx%create(local_gemm_pu_gpu)
560 CALL mp2_env%local_gemm_ctx%set_op_threshold_gpu(128*128*128*2)
561
562 DO ispin = 1, nspins
563 hom = exchange_work%homo(ispin)
564 virt = exchange_work%virtual(ispin)
565 dimen_ia = hom*virt
566 IF (hom < 1 .OR. virt < 1) cycle
567
568 CALL cp_fm_get_info(fm_mat_s(ispin), para_env=para_env)
569
570 CALL cp_fm_create(fm_mat_gamma_3, fm_mat_s(ispin)%matrix_struct)
571 CALL cp_fm_set_all(matrix=fm_mat_gamma_3, alpha=0.0_dp)
572
573 ! Update G with a new value of Omega: in practice, it is G*S
574
575 ! Scale fm_work_iaP
576 CALL calc_fm_mat_s_rpa(fm_mat_s(ispin), .true., virt, eig(:, ispin), &
577 hom, omega, 0.0_dp)
578
579 ! Calculate Gamma_3: Gamma_3 = G*S*R^(1/2) = G*S*R^(1/2)
580 CALL parallel_gemm(transa="T", transb="N", m=exchange_work%dimen_RI, n=dimen_ia, k=exchange_work%dimen_RI, alpha=1.0_dp, &
581 matrix_a=exchange_work%fm_mat_R_half_gemm, matrix_b=fm_mat_s(ispin), beta=0.0_dp, &
582 matrix_c=fm_mat_gamma_3)
583
584 CALL create_group_dist(virt_dist, exchange_work%para_env_sub%num_pe, virt)
585
586 ! Remove extra factor from S after the multiplication (to return to the original matrix)
587 CALL remove_scaling_factor_rpa(fm_mat_s(ispin), virt, eig(:, ispin), hom, omega)
588
589 CALL exchange_work%redistribute_into_subgroups(fm_mat_gamma_3, mat_gamma_3_3d, ispin, virt_dist)
590 CALL cp_fm_release(fm_mat_gamma_3)
591
592 ! We need only the pure matrix
593 CALL remove_scaling_factor_rpa(fm_mat_s(ispin), virt, eig(:, ispin), hom, omega)
594
595 ! Reorder matrix from (P, i*a) -> (a, i, P) with P being distributed within subgroups
596 CALL exchange_work%redistribute_into_subgroups(fm_mat_s(ispin), mat_b_iap, ispin, virt_dist)
597
598 ! Return to the original tensor
599 CALL calc_fm_mat_s_rpa(fm_mat_s(ispin), .true., virt, eig(:, ispin), hom, omega, 0.0_dp)
600
601 l_size_gamma = SIZE(mat_gamma_3_3d, 3)
602 my_virt = SIZE(mat_gamma_3_3d, 1)
603 block_size = exchange_work%block_size
604
605 mat_gamma_3_1d(1:int(my_virt, kind=int_8)*hom*my_aux_size) => mat_gamma_3_3d(:, :, 1:my_aux_size)
606 mat_gamma_3_2d(1:my_virt, 1:hom*my_aux_size) => mat_gamma_3_1d(1:int(my_virt, kind=int_8)*hom*my_aux_size)
607
608 ALLOCATE (product_matrix_1d(int(hom*min(block_size, l_size_gamma), kind=int_8)* &
609 int(hom*min(block_size, max_aux_size), kind=int_8)))
610 ALLOCATE (recv_buffer_1d(int(virt, kind=int_8)*hom*max_aux_size))
611 recv_buffer_2d(1:my_virt, 1:hom*max_aux_size) => recv_buffer_1d(1:int(virt, kind=int_8)*hom*max_aux_size)
612 recv_buffer_3d(1:my_virt, 1:hom, 1:max_aux_size) => recv_buffer_1d(1:int(virt, kind=int_8)*hom*max_aux_size)
613 DO proc_shift = 0, para_env%num_pe - 1, exchange_work%para_env_sub%num_pe
614 send_proc = modulo(para_env%mepos + proc_shift, para_env%num_pe)
615 recv_proc = modulo(para_env%mepos - proc_shift, para_env%num_pe)
616
617 CALL get_group_dist(exchange_work%aux_func_dist, recv_proc/exchange_work%para_env_sub%num_pe, sizes=recv_size)
618
619 IF (recv_size == 0) recv_proc = mp_proc_null
620
621 CALL para_env%sendrecv(mat_b_iap, send_proc, recv_buffer_3d(:, :, 1:recv_size), recv_proc)
622
623 IF (recv_size == 0) cycle
624
625 DO p_start = 1, l_size_gamma, block_size
626 p_end = min(l_size_gamma, p_start + block_size - 1)
627 p_size = p_end - p_start + 1
628 DO q_start = 1, recv_size, block_size
629 q_end = min(recv_size, q_start + block_size - 1)
630 q_size = q_end - q_start + 1
631
632 ! Reassign product_matrix pointers to enforce contiguity of target array
633 product_matrix_2d(1:hom*p_size, 1:hom*q_size) => &
634 product_matrix_1d(1:int(hom*p_size, kind=int_8)*int(hom*q_size, kind=int_8))
635 product_matrix_4d(1:hom, 1:p_size, 1:hom, 1:q_size) => &
636 product_matrix_1d(1:int(hom*p_size, kind=int_8)*int(hom*q_size, kind=int_8))
637
638 CALL timeset(routinen//"_gemm", handle2)
639 CALL mp2_env%local_gemm_ctx%gemm("T", "N", hom*p_size, hom*q_size, my_virt, 1.0_dp, &
640 mat_gamma_3_2d(:, hom*(p_start - 1) + 1:hom*p_end), my_virt, &
641 recv_buffer_2d(:, hom*(q_start - 1) + 1:hom*q_end), my_virt, &
642 0.0_dp, product_matrix_2d, hom*p_size)
643 CALL timestop(handle2)
644
645 CALL timeset(routinen//"_energy", handle2)
646!$OMP PARALLEL DO DEFAULT(NONE) SHARED(P_size, Q_size, hom, product_matrix_4D) &
647!$OMP COLLAPSE(3) REDUCTION(+: e_exchange_corr) PRIVATE(P, Q, i)
648 DO p = 1, p_size
649 DO q = 1, q_size
650 DO i = 1, hom
651 e_exchange_corr = e_exchange_corr + dot_product(product_matrix_4d(i, p, :, q), product_matrix_4d(:, p, i, q))
652 END DO
653 END DO
654 END DO
655 CALL timestop(handle2)
656 END DO
657 END DO
658 END DO
659
660 CALL release_group_dist(virt_dist)
661 IF (ALLOCATED(mat_b_iap)) DEALLOCATE (mat_b_iap)
662 IF (ALLOCATED(mat_gamma_3_3d)) DEALLOCATE (mat_gamma_3_3d)
663 IF (ALLOCATED(product_matrix_1d)) DEALLOCATE (product_matrix_1d)
664 IF (ALLOCATED(recv_buffer_1d)) DEALLOCATE (recv_buffer_1d)
665 END DO
666
667 CALL mp2_env%local_gemm_ctx%destroy()
668
669 IF (nspins == 2) e_exchange_corr = e_exchange_corr*2.0_dp
670 IF (nspins == 1) e_exchange_corr = e_exchange_corr*4.0_dp
671
672 CALL timestop(handle)
673
674 END SUBROUTINE rpa_exchange_work_compute_fm
675
676! **************************************************************************************************
677!> \brief Contract RPA-exchange density matrix with HF exchange integrals and evaluate the correction
678!> \param exchange_work ...
679!> \param fm_mat_S ...
680!> \param eig ...
681!> \param omega ...
682!> \param e_exchange_corr ...
683!> \author Vladimir Rybkin, 08/2016
684! **************************************************************************************************
685 SUBROUTINE rpa_exchange_work_compute_hfx(exchange_work, fm_mat_S, eig, omega, e_exchange_corr)
686 CLASS(rpa_exchange_work_type), INTENT(INOUT) :: exchange_work
687 TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: fm_mat_s
688 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: eig
689 REAL(kind=dp), INTENT(IN) :: omega
690 REAL(kind=dp), INTENT(OUT) :: e_exchange_corr
691
692 CHARACTER(LEN=*), PARAMETER :: routinen = 'rpa_exchange_work_compute_hfx'
693
694 INTEGER :: handle, ispin, my_aux_start, my_aux_end, &
695 my_aux_size, nspins, l_counter, dimen_ia, hom, virt
696 REAL(kind=dp) :: e_exchange_p
697 TYPE(dbcsr_matrix_p_set), DIMENSION(:), ALLOCATABLE :: dbcsr_gamma_3
698 TYPE(cp_fm_type) :: fm_mat_gamma_3
699 TYPE(mp_para_env_type), POINTER :: para_env
700
701 CALL timeset(routinen, handle)
702
703 e_exchange_corr = 0.0_dp
704
705 nspins = SIZE(fm_mat_s)
706
707 CALL get_group_dist(exchange_work%aux_func_dist, exchange_work%color_sub, my_aux_start, my_aux_end, my_aux_size)
708
709 ALLOCATE (dbcsr_gamma_3(nspins))
710 DO ispin = 1, nspins
711 hom = exchange_work%homo(ispin)
712 virt = exchange_work%virtual(ispin)
713 dimen_ia = hom*virt
714 IF (hom < 1 .OR. virt < 1) cycle
715
716 CALL cp_fm_get_info(fm_mat_s(ispin), para_env=para_env)
717
718 CALL cp_fm_create(fm_mat_gamma_3, exchange_work%exchange_env%struct_Gamma(ispin)%struct)
719 CALL cp_fm_set_all(matrix=fm_mat_gamma_3, alpha=0.0_dp)
720
721 ! Update G with a new value of Omega: in practice, it is G*S
722
723 ! Scale fm_work_iaP
724 CALL calc_fm_mat_s_rpa(fm_mat_s(ispin), .true., virt, eig(:, ispin), &
725 hom, omega, 0.0_dp)
726
727 ! Calculate Gamma_3: Gamma_3 = G*S*R^(1/2) = G*S*R^(1/2)
728 CALL parallel_gemm(transa="T", transb="N", m=dimen_ia, n=exchange_work%dimen_RI, &
729 k=exchange_work%dimen_RI, alpha=1.0_dp, &
730 matrix_a=fm_mat_s(ispin), matrix_b=exchange_work%fm_mat_R_half_gemm, beta=0.0_dp, &
731 matrix_c=fm_mat_gamma_3)
732
733 ! Remove extra factor from S after the multiplication (to return to the original matrix)
734 CALL remove_scaling_factor_rpa(fm_mat_s(ispin), virt, eig(:, ispin), hom, omega)
735
736 ! Copy Gamma_ia_P^3 to dbcsr matrix set
737 CALL gamma_fm_to_dbcsr(fm_mat_gamma_3, dbcsr_gamma_3(ispin)%matrix_set, &
738 para_env, exchange_work%para_env_sub, hom, virt, &
739 exchange_work%exchange_env%mo_coeff_o(ispin), &
740 exchange_work%ngroup, my_aux_start, my_aux_end, my_aux_size)
741 END DO
742
743 DO l_counter = 1, my_aux_size
744 DO ispin = 1, nspins
745 ! Do dbcsr multiplication: transform the virtual index
746 CALL dbcsr_multiply("N", "T", 1.0_dp, exchange_work%exchange_env%mo_coeff_v(ispin), &
747 dbcsr_gamma_3(ispin)%matrix_set(l_counter), &
748 0.0_dp, exchange_work%exchange_env%dbcsr_Gamma_inu_P(ispin), &
749 filter_eps=exchange_work%exchange_env%eps_filter)
750
751 CALL dbcsr_release(dbcsr_gamma_3(ispin)%matrix_set(l_counter))
752
753 ! Do dbcsr multiplication: transform the occupied index
754 CALL dbcsr_multiply("N", "T", 0.5_dp, exchange_work%exchange_env%dbcsr_Gamma_inu_P(ispin), &
755 exchange_work%exchange_env%mo_coeff_o(ispin), &
756 0.0_dp, exchange_work%exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix, &
757 filter_eps=exchange_work%exchange_env%eps_filter)
758 CALL dbcsr_multiply("N", "T", 0.5_dp, exchange_work%exchange_env%mo_coeff_o(ispin), &
759 exchange_work%exchange_env%dbcsr_Gamma_inu_P(ispin), &
760 1.0_dp, exchange_work%exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix, &
761 filter_eps=exchange_work%exchange_env%eps_filter)
762
763 CALL dbcsr_set(exchange_work%exchange_env%mat_hfx(ispin)%matrix, 0.0_dp)
764 END DO
765
766 CALL tddft_hfx_matrix(exchange_work%exchange_env%mat_hfx, exchange_work%exchange_env%dbcsr_Gamma_munu_P, &
767 exchange_work%exchange_env%qs_env, .false., &
768 exchange_work%exchange_env%my_recalc_hfx_integrals, &
769 exchange_work%exchange_env%hfx_sections, exchange_work%exchange_env%x_data, &
770 exchange_work%exchange_env%para_env)
771
772 exchange_work%exchange_env%my_recalc_hfx_integrals = .false.
773 DO ispin = 1, nspins
774 CALL dbcsr_multiply("N", "T", 1.0_dp, exchange_work%exchange_env%mat_hfx(ispin)%matrix, &
775 exchange_work%exchange_env%dbcsr_Gamma_munu_P(ispin)%matrix, &
776 0.0_dp, exchange_work%exchange_env%work_ao, filter_eps=exchange_work%exchange_env%eps_filter)
777 CALL dbcsr_trace(exchange_work%exchange_env%work_ao, e_exchange_p)
778 e_exchange_corr = e_exchange_corr - e_exchange_p
779 END DO
780 END DO
781
782 IF (nspins == 2) e_exchange_corr = e_exchange_corr
783 IF (nspins == 1) e_exchange_corr = e_exchange_corr*4.0_dp
784
785 CALL timestop(handle)
786
787 END SUBROUTINE rpa_exchange_work_compute_hfx
788
789! **************************************************************************************************
790!> \brief ...
791!> \param exchange_work ...
792!> \param fm_mat ...
793!> \param mat ...
794!> \param ispin ...
795!> \param virt_dist ...
796! **************************************************************************************************
797 SUBROUTINE redistribute_into_subgroups(exchange_work, fm_mat, mat, ispin, virt_dist)
798 CLASS(rpa_exchange_work_type), INTENT(IN) :: exchange_work
799 TYPE(cp_fm_type), INTENT(IN) :: fm_mat
800 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
801 INTENT(OUT) :: mat
802 INTEGER, INTENT(IN) :: ispin
803 TYPE(group_dist_d1_type), INTENT(IN) :: virt_dist
804
805 CHARACTER(LEN=*), PARAMETER :: routinen = 'redistribute_into_subgroups'
806
807 INTEGER :: aux_counter, aux_global, aux_local, aux_proc, avirt, dimen_ri, handle, handle2, &
808 ia_global, ia_local, iocc, max_number_recv, max_number_send, my_aux_end, my_aux_size, &
809 my_aux_start, my_process_column, my_process_row, my_virt_end, my_virt_size, &
810 my_virt_start, proc, proc_shift, recv_proc, send_proc, virt_counter, virt_proc, group_size
811 INTEGER, ALLOCATABLE, DIMENSION(:) :: data2send, recv_col_indices, &
812 recv_row_indices, send_aux_indices, send_virt_indices, virt2send
813 INTEGER, DIMENSION(2) :: recv_shape
814 INTEGER, DIMENSION(:), POINTER :: aux_distribution_fm, col_indices, &
815 ia_distribution_fm, row_indices
816 INTEGER, DIMENSION(:, :), POINTER :: mpi2blacs
817 REAL(kind=dp), ALLOCATABLE, DIMENSION(:), TARGET :: recv_buffer, send_buffer
818 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
819 POINTER :: recv_ptr, send_ptr
820 TYPE(cp_blacs_env_type), POINTER :: context
821 TYPE(mp_para_env_type), POINTER :: para_env
822
823 CALL timeset(routinen, handle)
824
825 CALL cp_fm_get_info(matrix=fm_mat, &
826 nrow_locals=aux_distribution_fm, &
827 col_indices=col_indices, &
828 row_indices=row_indices, &
829 ncol_locals=ia_distribution_fm, &
830 context=context, &
831 nrow_global=dimen_ri, &
832 para_env=para_env)
833
834 IF (exchange_work%homo(ispin) <= 0 .OR. exchange_work%virtual(ispin) <= 0) THEN
835 CALL get_group_dist(virt_dist, exchange_work%para_env_sub%mepos, my_virt_start, my_virt_end, my_virt_size)
836 ALLOCATE (mat(exchange_work%homo(ispin), my_virt_size, dimen_ri))
837 CALL timestop(handle)
838 RETURN
839 END IF
840
841 group_size = exchange_work%para_env_sub%num_pe
842
843 CALL timeset(routinen//"_prep", handle2)
844 CALL get_group_dist(exchange_work%aux_func_dist, exchange_work%color_sub, my_aux_start, my_aux_end, my_aux_size)
845 CALL get_group_dist(virt_dist, exchange_work%para_env_sub%mepos, my_virt_start, my_virt_end, my_virt_size)
846 CALL context%get(my_process_column=my_process_column, my_process_row=my_process_row, mpi2blacs=mpi2blacs)
847
848 ! Determine the number of columns to send
849 ALLOCATE (send_aux_indices(maxval(exchange_work%aux2send)))
850 ALLOCATE (virt2send(0:group_size - 1))
851 virt2send = 0
852 DO ia_local = 1, ia_distribution_fm(my_process_column)
853 ia_global = col_indices(ia_local)
854 avirt = mod(ia_global - 1, exchange_work%virtual(ispin)) + 1
855 proc = group_dist_proc(virt_dist, avirt)
856 virt2send(proc) = virt2send(proc) + 1
857 END DO
858
859 ALLOCATE (data2send(0:para_env%num_pe - 1))
860 DO aux_proc = 0, exchange_work%ngroup - 1
861 DO virt_proc = 0, group_size - 1
862 data2send(aux_proc*group_size + virt_proc) = exchange_work%aux2send(aux_proc)*virt2send(virt_proc)
863 END DO
864 END DO
865
866 ALLOCATE (send_virt_indices(maxval(virt2send)))
867 max_number_send = maxval(data2send)
868
869 ALLOCATE (send_buffer(int(max_number_send, kind=int_8)*exchange_work%homo(ispin)))
870 max_number_recv = max_number_send
871 CALL para_env%max(max_number_recv)
872 ALLOCATE (recv_buffer(max_number_recv))
873
874 ALLOCATE (mat(my_virt_size, exchange_work%homo(ispin), my_aux_size))
875
876 CALL timestop(handle2)
877
878 CALL timeset(routinen//"_own", handle2)
879 ! Start with own data
880 DO aux_local = 1, aux_distribution_fm(my_process_row)
881 aux_global = row_indices(aux_local)
882 IF (aux_global < my_aux_start .OR. aux_global > my_aux_end) cycle
883 DO ia_local = 1, ia_distribution_fm(my_process_column)
884 ia_global = fm_mat%matrix_struct%col_indices(ia_local)
885
886 iocc = (ia_global - 1)/exchange_work%virtual(ispin) + 1
887 avirt = mod(ia_global - 1, exchange_work%virtual(ispin)) + 1
888
889 IF (my_virt_start > avirt .OR. my_virt_end < avirt) cycle
890
891 mat(avirt - my_virt_start + 1, iocc, aux_global - my_aux_start + 1) = fm_mat%local_data(aux_local, ia_local)
892 END DO
893 END DO
894 CALL timestop(handle2)
895
896 DO proc_shift = 1, para_env%num_pe - 1
897 send_proc = modulo(para_env%mepos + proc_shift, para_env%num_pe)
898 recv_proc = modulo(para_env%mepos - proc_shift, para_env%num_pe)
899
900 CALL timeset(routinen//"_pack_buffer", handle2)
901 send_ptr(1:virt2send(mod(send_proc, group_size)), &
902 1:exchange_work%aux2send(send_proc/group_size)) => &
903 send_buffer(1:int(virt2send(mod(send_proc, group_size)), kind=int_8)* &
904 exchange_work%aux2send(send_proc/group_size))
905! Pack send buffer
906 aux_counter = 0
907 DO aux_local = 1, aux_distribution_fm(my_process_row)
908 aux_global = row_indices(aux_local)
909 proc = group_dist_proc(exchange_work%aux_func_dist, aux_global)
910 IF (proc /= send_proc/group_size) cycle
911 aux_counter = aux_counter + 1
912 virt_counter = 0
913 DO ia_local = 1, ia_distribution_fm(my_process_column)
914 ia_global = col_indices(ia_local)
915 avirt = mod(ia_global - 1, exchange_work%virtual(ispin)) + 1
916
917 proc = group_dist_proc(virt_dist, avirt)
918 IF (proc /= mod(send_proc, group_size)) cycle
919 virt_counter = virt_counter + 1
920 send_ptr(virt_counter, aux_counter) = fm_mat%local_data(aux_local, ia_local)
921 send_virt_indices(virt_counter) = ia_global
922 END DO
923 send_aux_indices(aux_counter) = aux_global
924 END DO
925 CALL timestop(handle2)
926
927 CALL timeset(routinen//"_ex_size", handle2)
928 recv_shape = [1, 1]
929 CALL para_env%sendrecv(shape(send_ptr), send_proc, recv_shape, recv_proc)
930 CALL timestop(handle2)
931
932 IF (SIZE(send_ptr) == 0) send_proc = mp_proc_null
933 IF (product(recv_shape) == 0) recv_proc = mp_proc_null
934
935 CALL timeset(routinen//"_ex_idx", handle2)
936 ALLOCATE (recv_row_indices(recv_shape(1)), recv_col_indices(recv_shape(2)))
937 CALL para_env%sendrecv(send_virt_indices(1:virt_counter), send_proc, recv_row_indices, recv_proc)
938 CALL para_env%sendrecv(send_aux_indices(1:aux_counter), send_proc, recv_col_indices, recv_proc)
939 CALL timestop(handle2)
940
941 ! Prepare pointer to recv buffer (consider transposition while packing the send buffer)
942 recv_ptr(1:recv_shape(1), 1:max(1, recv_shape(2))) => recv_buffer(1:recv_shape(1)*max(1, recv_shape(2)))
943
944 CALL timeset(routinen//"_sendrecv", handle2)
945! Perform communication
946 CALL para_env%sendrecv(send_ptr, send_proc, recv_ptr, recv_proc)
947 CALL timestop(handle2)
948
949 IF (recv_proc == mp_proc_null) THEN
950 DEALLOCATE (recv_row_indices, recv_col_indices)
951 cycle
952 END IF
953
954 CALL timeset(routinen//"_unpack", handle2)
955! Unpack receive buffer
956 DO aux_local = 1, SIZE(recv_col_indices)
957 aux_global = recv_col_indices(aux_local)
958
959 DO ia_local = 1, SIZE(recv_row_indices)
960 ia_global = recv_row_indices(ia_local)
961
962 iocc = (ia_global - 1)/exchange_work%virtual(ispin) + 1
963 avirt = mod(ia_global - 1, exchange_work%virtual(ispin)) + 1
964
965 mat(avirt - my_virt_start + 1, iocc, aux_global - my_aux_start + 1) = recv_ptr(ia_local, aux_local)
966 END DO
967 END DO
968 CALL timestop(handle2)
969
970 IF (ALLOCATED(recv_row_indices)) DEALLOCATE (recv_row_indices)
971 IF (ALLOCATED(recv_col_indices)) DEALLOCATE (recv_col_indices)
972 END DO
973
974 DEALLOCATE (send_aux_indices, send_virt_indices)
975
976 CALL timestop(handle)
977
978 END SUBROUTINE redistribute_into_subgroups
979
980END MODULE rpa_exchange
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Define the atomic kind types and their sub types.
Handles all functions related to the CELL.
Definition cell_types.F:15
methods related to the blacs parallel environment
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_multiply(transa, transb, alpha, matrix_a, matrix_b, beta, matrix_c, first_row, last_row, first_column, last_column, first_k, last_k, retain_sparsity, filter_eps, flop)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_init_p(matrix)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_trace(matrix, trace)
Computes the trace of the given matrix, also known as the sum of its diagonal elements.
DBCSR operations in CP2K.
basic linear algebra operations for full matrices
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
Definition cp_fm_diag.F:17
subroutine, public choose_eigv_solver(matrix, eigenvectors, eigenvalues, info)
Choose the Eigensolver depending on which library is available ELPA seems to be unstable for small sy...
Definition cp_fm_diag.F:229
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
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
subroutine, public cp_fm_to_fm_submat_general(source, destination, nrows, ncols, s_firstrow, s_firstcol, d_firstrow, d_firstcol, global_context)
General copy of a submatrix of fm matrix to a submatrix of another fm matrix. The two matrices can ha...
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp)
creates a new full matrix with the given structure
Types to describe group distributions.
elemental integer function, public maxsize(this)
...
elemental integer function, public group_dist_proc(this, pos)
...
Utilities for hfx and admm methods.
subroutine, public tddft_hfx_matrix(matrix_ks, rho_ao, qs_env, update_energy, recalc_integrals, external_hfx_sections, external_x_data, external_para_env)
Add the hfx contributions to the Hamiltonian.
Types and set/get functions for HFX.
Definition hfx_types.F:15
subroutine, public hfx_create(x_data, para_env, hfx_section, atomic_kind_set, qs_kind_set, particle_set, dft_control, cell, orb_basis, ri_basis, nelectron_total, nkp_grid)
This routine allocates and initializes all types in hfx_data
Definition hfx_types.F:594
subroutine, public hfx_release(x_data)
This routine deallocates all data structures
Definition hfx_types.F:1905
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public rpa_exchange_none
integer, parameter, public rpa_exchange_sosex
integer, parameter, public rpa_exchange_axk
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public local_gemm_pu_gpu
Definition of mathematical constants and functions.
real(kind=dp), parameter, public sqrthalf
Interface to the message passing library MPI.
integer, parameter, public mp_proc_null
Types needed for MP2 calculations.
Definition mp2_types.F:14
basic linear algebra operations for full matrixes
Define the data structure for the particle information.
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, ecoul_1c, rho0_s_rs, rho0_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs)
Get the QUICKSTEP environment.
Define the quickstep kind type and their sub types.
types that represent a quickstep subsys
subroutine, public qs_subsys_get(subsys, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell, cell_ref, use_ref_cell, energy, force, qs_kind_set, cp_subsys, nelectron_total, nelectron_spin)
...
Auxiliary routines necessary to redistribute an fm_matrix from a given blacs_env to another.
subroutine, public gamma_fm_to_dbcsr(fm_mat_gamma_3, dbcsr_gamma_3, para_env_rpa, para_env_sub, homo, virtual, mo_coeff_o, ngroup, my_group_l_start, my_group_l_end, my_group_l_size)
Redistribute RPA-AXK Gamma_3 density matrices: from fm to dbcsr.
Auxiliary routines needed for RPA-exchange given blacs_env to another.
subroutine, public rpa_exchange_needed_mem(mp2_env, homo, virtual, dimen_ri, para_env, mem_per_rank, mem_per_repl)
...
Utility functions for RPA calculations.
Definition rpa_util.F:13
subroutine, public remove_scaling_factor_rpa(fm_mat_s, virtual, eigenval_last, homo, omega_old)
...
Definition rpa_util.F:711
subroutine, public calc_fm_mat_s_rpa(fm_mat_s, first_cycle, virtual, eigenval, homo, omega, omega_old)
...
Definition rpa_util.F:761
parameters that control an scf iteration
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:55
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
represent a full matrix
stores some data used in construction of Kohn-Sham matrix
Definition hfx_types.F:509
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.