(git:ed6f26b)
Loading...
Searching...
No Matches
mp2_gpw_method.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 Routines to calculate MP2 energy using GPW method
10!> \par History
11!> 10.2011 created [Joost VandeVondele and Mauro Del Ben]
12! **************************************************************************************************
15 USE cell_types, ONLY: cell_type
18 USE cp_dbcsr_api, ONLY: &
21 dbcsr_p_type, dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
27 USE cp_fm_types, ONLY: cp_fm_create,&
35 USE kinds, ONLY: dp,&
36 int_8
37 USE machine, ONLY: m_memory
38 USE message_passing, ONLY: mp_comm_type,&
44 USE pw_env_types, ONLY: pw_env_type
45 USE pw_methods, ONLY: pw_multiply,&
50 USE pw_types, ONLY: pw_c1d_gs_type,&
54 USE qs_integrate_potential, ONLY: integrate_v_rspace
58#include "./base/base_uses.f90"
59
60 IMPLICIT NONE
61
62 PRIVATE
63
64 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mp2_gpw_method'
65
66 PUBLIC :: mp2_gpw_compute
67
68CONTAINS
69
70! **************************************************************************************************
71!> \brief ...
72!> \param Emp2 ...
73!> \param Emp2_Cou ...
74!> \param Emp2_EX ...
75!> \param qs_env ...
76!> \param para_env ...
77!> \param para_env_sub ...
78!> \param color_sub ...
79!> \param cell ...
80!> \param particle_set ...
81!> \param atomic_kind_set ...
82!> \param qs_kind_set ...
83!> \param Eigenval ...
84!> \param nmo ...
85!> \param homo ...
86!> \param mat_munu ...
87!> \param sab_orb_sub ...
88!> \param mo_coeff_o ...
89!> \param mo_coeff_v ...
90!> \param eps_filter ...
91!> \param unit_nr ...
92!> \param mp2_memory ...
93!> \param calc_ex ...
94!> \param blacs_env_sub ...
95!> \param Emp2_AB ...
96! **************************************************************************************************
97 SUBROUTINE mp2_gpw_compute(Emp2, Emp2_Cou, Emp2_EX, qs_env, para_env, para_env_sub, color_sub, &
98 cell, particle_set, atomic_kind_set, qs_kind_set, Eigenval, nmo, homo, &
99 mat_munu, sab_orb_sub, mo_coeff_o, mo_coeff_v, eps_filter, unit_nr, &
100 mp2_memory, calc_ex, blacs_env_sub, Emp2_AB)
101
102 REAL(kind=dp), INTENT(OUT) :: emp2, emp2_cou, emp2_ex
103 TYPE(qs_environment_type), POINTER :: qs_env
104 TYPE(mp_para_env_type), POINTER :: para_env, para_env_sub
105 INTEGER, INTENT(IN) :: color_sub
106 TYPE(cell_type), POINTER :: cell
107 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
108 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
109 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
110 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: eigenval
111 INTEGER, INTENT(IN) :: nmo
112 INTEGER, DIMENSION(:), INTENT(IN) :: homo
113 TYPE(dbcsr_p_type), INTENT(INOUT) :: mat_munu
114 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
115 POINTER :: sab_orb_sub
116 TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN) :: mo_coeff_o, mo_coeff_v
117 REAL(kind=dp), INTENT(IN) :: eps_filter
118 INTEGER, INTENT(IN) :: unit_nr
119 REAL(kind=dp), INTENT(IN) :: mp2_memory
120 LOGICAL, INTENT(IN) :: calc_ex
121 TYPE(cp_blacs_env_type), POINTER :: blacs_env_sub
122 REAL(kind=dp), INTENT(OUT), OPTIONAL :: emp2_ab
123
124 CHARACTER(LEN=*), PARAMETER :: routinen = 'mp2_gpw_compute'
125
126 INTEGER :: a, a_group_counter, b, b_global, b_group_counter, col, col_offset, col_size, &
127 color_counter, ex_end, ex_end_send, ex_start, ex_start_send, group_counter, handle, &
128 handle2, handle3, i, i_counter, i_group_counter, index_proc_shift, ispin, j, max_b_size, &
129 max_batch_size_a, max_batch_size_i, max_row_col_local, my_a_batch_size, my_a_virtual_end, &
130 my_a_virtual_start, my_b_size, my_b_virtual_end, my_b_virtual_start, my_i_batch_size, &
131 my_i_occupied_end, my_i_occupied_start, my_q_position, ncol_local, nfullcols_total, &
132 nfullrows_total, ngroup, nrow_local, nspins, p, p_best, proc_receive
133 INTEGER :: proc_send, q, q_best, row, row_offset, row_size, size_ex, size_ex_send, &
134 sub_sub_color, wfn_calc, wfn_calc_best
135 INTEGER(KIND=int_8) :: mem
136 INTEGER, ALLOCATABLE, DIMENSION(:) :: vector_b_sizes, &
137 vector_batch_a_size_group, &
138 vector_batch_i_size_group
139 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: color_array, local_col_row_info
140 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
141 INTEGER, DIMENSION(SIZE(homo)) :: virtual
142 LOGICAL :: do_alpha_beta
143 REAL(kind=dp) :: cutoff_old, mem_min, mem_real, mem_try, &
144 relative_cutoff_old, wfn_size
145 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: e_cutoff_old
146 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: my_cocc, my_cvirt
147 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: bib_c, bib_ex, bib_send
148 REAL(kind=dp), DIMENSION(:, :), POINTER :: data_block
149 TYPE(cp_fm_struct_type), POINTER :: fm_struct
150 TYPE(cp_fm_type) :: fm_bib_jb
151 TYPE(dbcsr_iterator_type) :: iter
152 TYPE(dbcsr_type), DIMENSION(SIZE(homo)) :: matrix_ia_jb, matrix_ia_jnu
153 TYPE(dft_control_type), POINTER :: dft_control
154 TYPE(group_dist_d1_type) :: gd_exchange
155 TYPE(mp_comm_type) :: comm_exchange
156 TYPE(pw_c1d_gs_type) :: pot_g, rho_g
157 TYPE(pw_env_type), POINTER :: pw_env_sub
158 TYPE(pw_poisson_type), POINTER :: poisson_env
159 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
160 TYPE(pw_r3d_rs_type) :: psi_a, rho_r
161 TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:) :: psi_i
162 TYPE(task_list_type), POINTER :: task_list_sub
163
164 CALL timeset(routinen, handle)
165
166 do_alpha_beta = .false.
167 IF (PRESENT(emp2_ab)) do_alpha_beta = .true.
168
169 nspins = SIZE(homo)
170 virtual = nmo - homo
171
172 DO ispin = 1, nspins
173 ! initialize and create the matrix (ia|jnu)
174 CALL dbcsr_create(matrix_ia_jnu(ispin), template=mo_coeff_o(ispin)%matrix)
175
176 ! Allocate Sparse matrices: (ia|jb)
177 CALL cp_dbcsr_m_by_n_from_template(matrix_ia_jb(ispin), template=mo_coeff_o(ispin)%matrix, m=homo(ispin), n=nmo - homo(ispin), &
178 sym=dbcsr_type_no_symmetry)
179
180 ! set all to zero in such a way that the memory is actually allocated
181 CALL dbcsr_set(matrix_ia_jnu(ispin), 0.0_dp)
182 CALL dbcsr_set(matrix_ia_jb(ispin), 0.0_dp)
183 END DO
184 CALL dbcsr_set(mat_munu%matrix, 0.0_dp)
185
186 IF (calc_ex) THEN
187 ! create the analogous of matrix_ia_jb in fm type
188 NULLIFY (fm_struct)
189 CALL dbcsr_get_info(matrix_ia_jb(1), nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
190 CALL cp_fm_struct_create(fm_struct, context=blacs_env_sub, nrow_global=nfullrows_total, &
191 ncol_global=nfullcols_total, para_env=para_env_sub)
192 CALL cp_fm_create(fm_bib_jb, fm_struct, name="fm_BIb_jb")
193
194 CALL copy_dbcsr_to_fm(matrix_ia_jb(1), fm_bib_jb)
195 CALL cp_fm_struct_release(fm_struct)
196
197 CALL cp_fm_get_info(matrix=fm_bib_jb, &
198 nrow_local=nrow_local, &
199 ncol_local=ncol_local, &
200 row_indices=row_indices, &
201 col_indices=col_indices)
202
203 max_row_col_local = max(nrow_local, ncol_local)
204 CALL para_env_sub%max(max_row_col_local)
205
206 ALLOCATE (local_col_row_info(0:max_row_col_local, 2))
207 local_col_row_info = 0
208 ! 0,1 nrows
209 local_col_row_info(0, 1) = nrow_local
210 local_col_row_info(1:nrow_local, 1) = row_indices(1:nrow_local)
211 ! 0,2 ncols
212 local_col_row_info(0, 2) = ncol_local
213 local_col_row_info(1:ncol_local, 2) = col_indices(1:ncol_local)
214 END IF
215
216 ! Get everything for GPW calculations
217 CALL prepare_gpw(qs_env, dft_control, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
218 auxbas_pw_pool, poisson_env, task_list_sub, rho_r, rho_g, pot_g, psi_a, sab_orb_sub)
219
220 wfn_size = real(SIZE(rho_r%array), kind=dp)
221 CALL para_env%max(wfn_size)
222
223 ngroup = para_env%num_pe/para_env_sub%num_pe
224
225 ! calculate the minimal memory required per MPI task (p=occupied division,q=virtual division)
226 p_best = ngroup
227 q_best = 1
228 mem_min = huge(0)
229 DO p = 1, ngroup
230 q = ngroup/p
231 IF (p*q .NE. ngroup) cycle
232
233 CALL estimate_memory_usage(wfn_size, p, q, para_env_sub%num_pe, nmo, virtual(1), homo(1), calc_ex, mem_try)
234
235 IF (mem_try <= mem_min) THEN
236 mem_min = mem_try
237 p_best = p
238 q_best = q
239 END IF
240 END DO
241 IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T69,F9.2,A3)') 'Minimum required memory per MPI process for MP2:', &
242 mem_min, ' MB'
243
244 CALL m_memory(mem)
245 mem_real = (mem + 1024*1024 - 1)/(1024*1024)
246 CALL para_env%min(mem_real)
247
248 mem_real = mp2_memory - mem_real
249 mem_real = max(mem_real, mem_min)
250 IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T69,F9.2,A3)') 'Available memory per MPI process for MP2:', &
251 mem_real, ' MB'
252
253 wfn_calc_best = huge(wfn_calc_best)
254 DO p = 1, ngroup
255 q = ngroup/p
256 IF (p*q .NE. ngroup) cycle
257
258 CALL estimate_memory_usage(wfn_size, p, q, para_env_sub%num_pe, nmo, virtual(1), homo(1), calc_ex, mem_try)
259
260 IF (mem_try > mem_real) cycle
261 wfn_calc = ((homo(1) + p - 1)/p) + ((virtual(1) + q - 1)/q)
262 IF (wfn_calc < wfn_calc_best) THEN
263 wfn_calc_best = wfn_calc
264 p_best = p
265 q_best = q
266 END IF
267 END DO
268
269 max_batch_size_i = (homo(1) + p_best - 1)/p_best
270 max_batch_size_a = (virtual(1) + q_best - 1)/q_best
271
272 IF (unit_nr > 0) THEN
273 WRITE (unit=unit_nr, fmt="(T3,A,T77,i4)") &
274 "MP2_GPW| max. batch size for the occupied states:", max_batch_size_i
275 WRITE (unit=unit_nr, fmt="(T3,A,T77,i4)") &
276 "MP2_GPW| max. batch size for the virtual states:", max_batch_size_a
277 END IF
278
279 CALL get_vector_batch(vector_batch_i_size_group, p_best, max_batch_size_i, homo(1))
280 CALL get_vector_batch(vector_batch_a_size_group, q_best, max_batch_size_a, virtual(1))
281
282 !XXXXXXXXXXXXX inverse group distribution
283 group_counter = 0
284 a_group_counter = 0
285 my_a_virtual_start = 1
286 DO j = 0, q_best - 1
287 my_i_occupied_start = 1
288 i_group_counter = 0
289 DO i = 0, p_best - 1
290 group_counter = group_counter + 1
291 IF (color_sub == group_counter - 1) EXIT
292 my_i_occupied_start = my_i_occupied_start + vector_batch_i_size_group(i)
293 i_group_counter = i_group_counter + 1
294 END DO
295 my_q_position = j
296 IF (color_sub == group_counter - 1) EXIT
297 my_a_virtual_start = my_a_virtual_start + vector_batch_a_size_group(j)
298 a_group_counter = a_group_counter + 1
299 END DO
300 !XXXXXXXXXXXXX inverse group distribution
301
302 my_i_occupied_end = my_i_occupied_start + vector_batch_i_size_group(i_group_counter) - 1
303 my_i_batch_size = vector_batch_i_size_group(i_group_counter)
304 my_a_virtual_end = my_a_virtual_start + vector_batch_a_size_group(a_group_counter) - 1
305 my_a_batch_size = vector_batch_a_size_group(a_group_counter)
306
307 DEALLOCATE (vector_batch_i_size_group)
308 DEALLOCATE (vector_batch_a_size_group)
309
310 ! replicate on a local array on proc 0 the occupied and virtual wavevectior
311 ! needed for the calculation of the WF's by calculate_wavefunction
312 ! (external vector)
313 CALL grep_occ_virt_wavefunc(para_env_sub, nmo, &
314 my_i_occupied_start, my_i_occupied_end, my_i_batch_size, &
315 my_a_virtual_start, my_a_virtual_end, my_a_batch_size, &
316 mo_coeff_o(1)%matrix, mo_coeff_v(1)%matrix, my_cocc, my_cvirt)
317
318 ! divide the b states in the sub_group in such a way to create
319 ! b_start and b_end for each proc inside the sub_group
320 max_b_size = (virtual(1) + para_env_sub%num_pe - 1)/para_env_sub%num_pe
321 CALL get_vector_batch(vector_b_sizes, para_env_sub%num_pe, max_b_size, virtual(1))
322
323 ! now give to each proc its b_start and b_end
324 b_group_counter = 0
325 my_b_virtual_start = 1
326 DO j = 0, para_env_sub%num_pe - 1
327 b_group_counter = b_group_counter + 1
328 IF (b_group_counter - 1 == para_env_sub%mepos) EXIT
329 my_b_virtual_start = my_b_virtual_start + vector_b_sizes(j)
330 END DO
331 my_b_virtual_end = my_b_virtual_start + vector_b_sizes(para_env_sub%mepos) - 1
332 my_b_size = vector_b_sizes(para_env_sub%mepos)
333
334 DEALLOCATE (vector_b_sizes)
335
336 ! create an array containing a different "color" for each pair of
337 ! A_start and B_start, communication will take place only among
338 ! those proc that have the same A_start and B_start
339 ALLOCATE (color_array(0:para_env_sub%num_pe - 1, 0:q_best - 1))
340 color_array = 0
341 color_counter = 0
342 DO j = 0, q_best - 1
343 DO i = 0, para_env_sub%num_pe - 1
344 color_counter = color_counter + 1
345 color_array(i, j) = color_counter
346 END DO
347 END DO
348 sub_sub_color = color_array(para_env_sub%mepos, my_q_position)
349
350 DEALLOCATE (color_array)
351
352 ! now create a group that contains all the proc that have the same 2 virtual starting points
353 ! in this way it is possible to sum the common integrals needed for the full MP2 energy
354 CALL comm_exchange%from_split(para_env, sub_sub_color)
355
356 ! create an array containing the information for communication
357 CALL create_group_dist(gd_exchange, my_i_occupied_start, my_i_occupied_end, my_i_batch_size, comm_exchange)
358
359 ALLOCATE (psi_i(my_i_occupied_start:my_i_occupied_end))
360 DO i = my_i_occupied_start, my_i_occupied_end
361 CALL auxbas_pw_pool%create_pw(psi_i(i))
362 CALL collocate_function(my_cocc(:, i - my_i_occupied_start + 1), &
363 psi_i(i), rho_g, atomic_kind_set, qs_kind_set, cell, particle_set, &
364 pw_env_sub, dft_control%qs_control%eps_rho_rspace)
365 END DO
366
367 emp2 = 0.0_dp
368 emp2_cou = 0.0_dp
369 emp2_ex = 0.0_dp
370 IF (do_alpha_beta) emp2_ab = 0.0_dp
371 IF (calc_ex) THEN
372 ALLOCATE (bib_c(my_b_size, homo(1), my_i_batch_size))
373 END IF
374
375 CALL timeset(routinen//"_loop", handle2)
376 DO a = homo(1) + my_a_virtual_start, homo(1) + my_a_virtual_end
377
378 IF (calc_ex) bib_c = 0.0_dp
379
380 ! psi_a
381 CALL collocate_function(my_cvirt(:, a - (homo(1) + my_a_virtual_start) + 1), &
382 psi_a, rho_g, atomic_kind_set, qs_kind_set, cell, particle_set, &
383 pw_env_sub, dft_control%qs_control%eps_rho_rspace)
384 i_counter = 0
385 DO i = my_i_occupied_start, my_i_occupied_end
386 i_counter = i_counter + 1
387
388 ! potential
389 CALL pw_zero(rho_r)
390 CALL pw_multiply(rho_r, psi_i(i), psi_a)
391 CALL pw_transfer(rho_r, rho_g)
392 CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, qs_env%mp2_env%potential_parameter)
393
394 ! and finally (ia|munu)
395 CALL timeset(routinen//"_int", handle3)
396 CALL dbcsr_set(mat_munu%matrix, 0.0_dp)
397 CALL integrate_v_rspace(rho_r, hmat=mat_munu, qs_env=qs_env, &
398 calculate_forces=.false., compute_tau=.false., gapw=.false., &
399 pw_env_external=pw_env_sub, task_list_external=task_list_sub)
400 CALL timestop(handle3)
401
402 ! multiply and goooooooo ...
403 CALL timeset(routinen//"_mult_o", handle3)
404 DO ispin = 1, nspins
405 CALL dbcsr_multiply("N", "N", 1.0_dp, mat_munu%matrix, mo_coeff_o(ispin)%matrix, &
406 0.0_dp, matrix_ia_jnu(ispin), filter_eps=eps_filter)
407 END DO
408 CALL timestop(handle3)
409 CALL timeset(routinen//"_mult_v", handle3)
410 DO ispin = 1, nspins
411 CALL dbcsr_multiply("T", "N", 1.0_dp, matrix_ia_jnu(ispin), mo_coeff_v(ispin)%matrix, &
412 0.0_dp, matrix_ia_jb(ispin), filter_eps=eps_filter)
413 END DO
414 CALL timestop(handle3)
415
416 CALL timeset(routinen//"_E_Cou", handle3)
417 CALL dbcsr_iterator_start(iter, matrix_ia_jb(1))
418 DO WHILE (dbcsr_iterator_blocks_left(iter))
419 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
420 row_size=row_size, col_size=col_size, &
421 row_offset=row_offset, col_offset=col_offset)
422 DO b = 1, col_size
423 DO j = 1, row_size
424 ! Compute the coulomb MP2 energy
425 emp2_cou = emp2_cou - 2.0_dp*data_block(j, b)**2/ &
426 (eigenval(a, 1) + eigenval(homo(1) + col_offset + b - 1, 1) - eigenval(i, 1) - eigenval(row_offset + j - 1, 1))
427 END DO
428 END DO
429 END DO
430 CALL dbcsr_iterator_stop(iter)
431 IF (do_alpha_beta) THEN
432 ! Compute the coulomb only= SO = MP2 alpha-beta MP2 energy component
433 CALL dbcsr_iterator_start(iter, matrix_ia_jb(2))
434 DO WHILE (dbcsr_iterator_blocks_left(iter))
435 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
436 row_size=row_size, col_size=col_size, &
437 row_offset=row_offset, col_offset=col_offset)
438 DO b = 1, col_size
439 DO j = 1, row_size
440 ! Compute the coulomb MP2 energy alpha beta case
441 emp2_ab = emp2_ab - data_block(j, b)**2/ &
442 (eigenval(a, 1) + eigenval(homo(2) + col_offset + b - 1, 2) - eigenval(i, 1) - eigenval(row_offset + j - 1, 2))
443 END DO
444 END DO
445 END DO
446 CALL dbcsr_iterator_stop(iter)
447 END IF
448 CALL timestop(handle3)
449
450 ! now collect my local data from all the other members of the group
451 ! b_start, b_end
452 IF (calc_ex) THEN
453 CALL timeset(routinen//"_E_Ex_1", handle3)
454 CALL copy_dbcsr_to_fm(matrix_ia_jb(1), fm_bib_jb)
455 CALL grep_my_integrals(para_env_sub, fm_bib_jb, bib_c(1:my_b_size, 1:homo(1), i_counter), max_row_col_local, &
456 local_col_row_info, my_b_virtual_end, my_b_virtual_start)
457 CALL timestop(handle3)
458 END IF
459
460 END DO
461
462 IF (calc_ex) THEN
463
464 associate(mepos_in_ex_group => comm_exchange%mepos, size_of_exchange_group => comm_exchange%num_pe)
465 CALL timeset(routinen//"_E_Ex_2", handle3)
466 ! calculate the contribution to MP2 energy for my local data
467 DO i = 1, my_i_batch_size
468 DO j = my_i_occupied_start, my_i_occupied_end
469 DO b = 1, my_b_size
470 b_global = b - 1 + my_b_virtual_start
471 emp2_ex = emp2_ex + bib_c(b, j, i)*bib_c(b, i + my_i_occupied_start - 1, j - my_i_occupied_start + 1) &
472 /(eigenval(a, 1) + eigenval(homo(1) + b_global, 1) - eigenval(i + my_i_occupied_start - 1, 1) - eigenval(j, 1))
473 END DO
474 END DO
475 END DO
476
477 ! start communicating and collecting exchange contributions from
478 ! other processes in my exchange group
479 DO index_proc_shift = 1, size_of_exchange_group - 1
480 proc_send = modulo(mepos_in_ex_group + index_proc_shift, size_of_exchange_group)
481 proc_receive = modulo(mepos_in_ex_group - index_proc_shift, size_of_exchange_group)
482
483 CALL get_group_dist(gd_exchange, proc_receive, ex_start, ex_end, size_ex)
484
485 ALLOCATE (bib_ex(my_b_size, my_i_batch_size, size_ex))
486 bib_ex = 0.0_dp
487
488 CALL get_group_dist(gd_exchange, proc_send, ex_start_send, ex_end_send, size_ex_send)
489
490 ALLOCATE (bib_send(my_b_size, size_ex_send, my_i_batch_size))
491 bib_send(1:my_b_size, 1:size_ex_send, 1:my_i_batch_size) = &
492 bib_c(1:my_b_size, ex_start_send:ex_end_send, 1:my_i_batch_size)
493
494 ! send and receive the exchange array
495 CALL comm_exchange%sendrecv(bib_send, proc_send, bib_ex, proc_receive)
496
497 DO i = 1, my_i_batch_size
498 DO j = 1, size_ex
499 DO b = 1, my_b_size
500 b_global = b - 1 + my_b_virtual_start
501 emp2_ex = emp2_ex + bib_c(b, j + ex_start - 1, i)*bib_ex(b, i, j) &
502 /(eigenval(a, 1) + eigenval(homo(1) + b_global, 1) - eigenval(i + my_i_occupied_start - 1, 1) &
503 - eigenval(j + ex_start - 1, 1))
504 END DO
505 END DO
506 END DO
507
508 DEALLOCATE (bib_ex)
509 DEALLOCATE (bib_send)
510
511 END DO
512 CALL timestop(handle3)
513 END associate
514 END IF
515
516 END DO
517 CALL timestop(handle2)
518
519 CALL para_env%sum(emp2_cou)
520 CALL para_env%sum(emp2_ex)
521 emp2 = emp2_cou + emp2_ex
522 IF (do_alpha_beta) CALL para_env%sum(emp2_ab)
523
524 DEALLOCATE (my_cocc)
525 DEALLOCATE (my_cvirt)
526
527 IF (calc_ex) THEN
528 CALL cp_fm_release(fm_bib_jb)
529 DEALLOCATE (local_col_row_info)
530 DEALLOCATE (bib_c)
531 END IF
532 CALL release_group_dist(gd_exchange)
533
534 CALL comm_exchange%free()
535
536 DO ispin = 1, nspins
537 CALL dbcsr_release(matrix_ia_jnu(ispin))
538 CALL dbcsr_release(matrix_ia_jb(ispin))
539 END DO
540
541 DO i = my_i_occupied_start, my_i_occupied_end
542 CALL psi_i(i)%release()
543 END DO
544 DEALLOCATE (psi_i)
545
546 CALL cleanup_gpw(qs_env, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
547 task_list_sub, auxbas_pw_pool, rho_r, rho_g, pot_g, psi_a)
548
549 CALL timestop(handle)
550
551 END SUBROUTINE mp2_gpw_compute
552
553! **************************************************************************************************
554!> \brief ...
555!> \param wfn_size ...
556!> \param p ...
557!> \param q ...
558!> \param num_w ...
559!> \param nmo ...
560!> \param virtual ...
561!> \param homo ...
562!> \param calc_ex ...
563!> \param mem_try ...
564! **************************************************************************************************
565 ELEMENTAL SUBROUTINE estimate_memory_usage(wfn_size, p, q, num_w, nmo, virtual, homo, calc_ex, mem_try)
566 REAL(kind=dp), INTENT(IN) :: wfn_size
567 INTEGER, INTENT(IN) :: p, q, num_w, nmo, virtual, homo
568 LOGICAL, INTENT(IN) :: calc_ex
569 REAL(kind=dp), INTENT(OUT) :: mem_try
570
571 mem_try = 0.0_dp
572 ! integrals
573 mem_try = mem_try + virtual*real(homo, kind=dp)**2/(p*num_w)
574 ! array for the coefficient matrix and wave vectors
575 mem_try = mem_try + real(homo, kind=dp)*nmo/p + &
576 REAL(virtual, kind=dp)*nmo/q + &
577 2.0_dp*max(real(homo, kind=dp)*nmo/p, real(virtual, kind=dp)*nmo/q)
578 ! temporary array for MO integrals and MO integrals to be exchanged
579 IF (calc_ex) THEN
580 mem_try = mem_try + 2.0_dp*max(virtual*real(homo, kind=dp)*min(1, num_w - 1)/num_w, &
581 virtual*real(homo, kind=dp)**2/(p*p*num_w))
582 ELSE
583 mem_try = mem_try + 2.0_dp*virtual*real(homo, kind=dp)
584 END IF
585 ! wfn
586 mem_try = mem_try + ((homo + p - 1)/p)*wfn_size
587 ! Mb
588 mem_try = mem_try*8.0d+00/1024.0d+00**2
589
590 END SUBROUTINE
591
592! **************************************************************************************************
593!> \brief ...
594!> \param vector_batch_I_size_group ...
595!> \param p_best ...
596!> \param max_batch_size_I ...
597!> \param homo ...
598! **************************************************************************************************
599 PURE SUBROUTINE get_vector_batch(vector_batch_I_size_group, p_best, max_batch_size_I, homo)
600 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: vector_batch_i_size_group
601 INTEGER, INTENT(IN) :: p_best, max_batch_size_i, homo
602
603 INTEGER :: i, one
604
605 ALLOCATE (vector_batch_i_size_group(0:p_best - 1))
606
607 vector_batch_i_size_group = max_batch_size_i
608 IF (sum(vector_batch_i_size_group) /= homo) THEN
609 one = 1
610 IF (sum(vector_batch_i_size_group) > homo) one = -1
611 i = -1
612 DO
613 i = i + 1
614 vector_batch_i_size_group(i) = vector_batch_i_size_group(i) + one
615 IF (sum(vector_batch_i_size_group) == homo) EXIT
616 IF (i == p_best - 1) i = -1
617 END DO
618 END IF
619
620 END SUBROUTINE get_vector_batch
621
622! **************************************************************************************************
623!> \brief ...
624!> \param para_env_sub ...
625!> \param fm_BIb_jb ...
626!> \param BIb_jb ...
627!> \param max_row_col_local ...
628!> \param local_col_row_info ...
629!> \param my_B_virtual_end ...
630!> \param my_B_virtual_start ...
631! **************************************************************************************************
632 SUBROUTINE grep_my_integrals(para_env_sub, fm_BIb_jb, BIb_jb, max_row_col_local, &
633 local_col_row_info, &
634 my_B_virtual_end, my_B_virtual_start)
635 TYPE(mp_para_env_type), INTENT(IN) :: para_env_sub
636 TYPE(cp_fm_type), INTENT(IN) :: fm_bib_jb
637 REAL(kind=dp), DIMENSION(:, :), INTENT(OUT) :: bib_jb
638 INTEGER, INTENT(IN) :: max_row_col_local
639 INTEGER, ALLOCATABLE, DIMENSION(:, :), INTENT(IN) :: local_col_row_info
640 INTEGER, INTENT(IN) :: my_b_virtual_end, my_b_virtual_start
641
642 INTEGER :: i_global, iib, j_global, jjb, ncol_rec, &
643 nrow_rec, proc_receive, proc_send, &
644 proc_shift
645 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: rec_col_row_info
646 INTEGER, DIMENSION(:), POINTER :: col_indices_rec, row_indices_rec
647 REAL(kind=dp), DIMENSION(:, :), POINTER :: local_bi, rec_bi
648
649 ALLOCATE (rec_col_row_info(0:max_row_col_local, 2))
650
651 rec_col_row_info(:, :) = local_col_row_info
652
653 nrow_rec = rec_col_row_info(0, 1)
654 ncol_rec = rec_col_row_info(0, 2)
655
656 ALLOCATE (row_indices_rec(nrow_rec))
657 row_indices_rec = rec_col_row_info(1:nrow_rec, 1)
658
659 ALLOCATE (col_indices_rec(ncol_rec))
660 col_indices_rec = rec_col_row_info(1:ncol_rec, 2)
661
662 ! accumulate data on BIb_jb buffer starting from myself
663 DO jjb = 1, ncol_rec
664 j_global = col_indices_rec(jjb)
665 IF (j_global >= my_b_virtual_start .AND. j_global <= my_b_virtual_end) THEN
666 DO iib = 1, nrow_rec
667 i_global = row_indices_rec(iib)
668 bib_jb(j_global - my_b_virtual_start + 1, i_global) = fm_bib_jb%local_data(iib, jjb)
669 END DO
670 END IF
671 END DO
672
673 DEALLOCATE (row_indices_rec)
674 DEALLOCATE (col_indices_rec)
675
676 IF (para_env_sub%num_pe > 1) THEN
677 ALLOCATE (local_bi(nrow_rec, ncol_rec))
678 local_bi(1:nrow_rec, 1:ncol_rec) = fm_bib_jb%local_data(1:nrow_rec, 1:ncol_rec)
679
680 DO proc_shift = 1, para_env_sub%num_pe - 1
681 proc_send = modulo(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
682 proc_receive = modulo(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
683
684 ! first exchange information on the local data
685 rec_col_row_info = 0
686 CALL para_env_sub%sendrecv(local_col_row_info, proc_send, rec_col_row_info, proc_receive)
687 nrow_rec = rec_col_row_info(0, 1)
688 ncol_rec = rec_col_row_info(0, 2)
689
690 ALLOCATE (row_indices_rec(nrow_rec))
691 row_indices_rec = rec_col_row_info(1:nrow_rec, 1)
692
693 ALLOCATE (col_indices_rec(ncol_rec))
694 col_indices_rec = rec_col_row_info(1:ncol_rec, 2)
695
696 ALLOCATE (rec_bi(nrow_rec, ncol_rec))
697 rec_bi = 0.0_dp
698
699 ! then send and receive the real data
700 CALL para_env_sub%sendrecv(local_bi, proc_send, rec_bi, proc_receive)
701
702 ! accumulate the received data on BIb_jb buffer
703 DO jjb = 1, ncol_rec
704 j_global = col_indices_rec(jjb)
705 IF (j_global >= my_b_virtual_start .AND. j_global <= my_b_virtual_end) THEN
706 DO iib = 1, nrow_rec
707 i_global = row_indices_rec(iib)
708 bib_jb(j_global - my_b_virtual_start + 1, i_global) = rec_bi(iib, jjb)
709 END DO
710 END IF
711 END DO
712
713 DEALLOCATE (col_indices_rec)
714 DEALLOCATE (row_indices_rec)
715 DEALLOCATE (rec_bi)
716 END DO
717
718 DEALLOCATE (local_bi)
719 END IF
720
721 DEALLOCATE (rec_col_row_info)
722
723 END SUBROUTINE grep_my_integrals
724
725! **************************************************************************************************
726!> \brief ...
727!> \param para_env_sub ...
728!> \param dimen ...
729!> \param my_I_occupied_start ...
730!> \param my_I_occupied_end ...
731!> \param my_I_batch_size ...
732!> \param my_A_virtual_start ...
733!> \param my_A_virtual_end ...
734!> \param my_A_batch_size ...
735!> \param mo_coeff_o ...
736!> \param mo_coeff_v ...
737!> \param my_Cocc ...
738!> \param my_Cvirt ...
739! **************************************************************************************************
740 SUBROUTINE grep_occ_virt_wavefunc(para_env_sub, dimen, &
741 my_I_occupied_start, my_I_occupied_end, my_I_batch_size, &
742 my_A_virtual_start, my_A_virtual_end, my_A_batch_size, &
743 mo_coeff_o, mo_coeff_v, my_Cocc, my_Cvirt)
744
745 TYPE(mp_para_env_type), INTENT(IN) :: para_env_sub
746 INTEGER, INTENT(IN) :: dimen, my_i_occupied_start, my_i_occupied_end, my_i_batch_size, &
747 my_a_virtual_start, my_a_virtual_end, my_a_batch_size
748 TYPE(dbcsr_type), POINTER :: mo_coeff_o, mo_coeff_v
749 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :), &
750 INTENT(OUT) :: my_cocc, my_cvirt
751
752 CHARACTER(LEN=*), PARAMETER :: routinen = 'grep_occ_virt_wavefunc'
753
754 INTEGER :: col, col_offset, col_size, handle, i, &
755 i_global, j, j_global, row, &
756 row_offset, row_size
757 REAL(kind=dp), DIMENSION(:, :), POINTER :: data_block
758 TYPE(dbcsr_iterator_type) :: iter
759
760 CALL timeset(routinen, handle)
761
762 ALLOCATE (my_cocc(dimen, my_i_batch_size))
763 my_cocc = 0.0_dp
764
765 ALLOCATE (my_cvirt(dimen, my_a_batch_size))
766 my_cvirt = 0.0_dp
767
768 ! accumulate data from mo_coeff_o into Cocc
769 CALL dbcsr_iterator_start(iter, mo_coeff_o)
770 DO WHILE (dbcsr_iterator_blocks_left(iter))
771 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
772 row_size=row_size, col_size=col_size, &
773 row_offset=row_offset, col_offset=col_offset)
774 DO j = 1, col_size
775 j_global = col_offset + j - 1
776 IF (j_global >= my_i_occupied_start .AND. j_global <= my_i_occupied_end) THEN
777 DO i = 1, row_size
778 i_global = row_offset + i - 1
779 my_cocc(i_global, j_global - my_i_occupied_start + 1) = data_block(i, j)
780 END DO
781 END IF
782 END DO
783 END DO
784 CALL dbcsr_iterator_stop(iter)
785
786 CALL para_env_sub%sum(my_cocc)
787
788 ! accumulate data from mo_coeff_o into Cocc
789 CALL dbcsr_iterator_start(iter, mo_coeff_v)
790 DO WHILE (dbcsr_iterator_blocks_left(iter))
791 CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
792 row_size=row_size, col_size=col_size, &
793 row_offset=row_offset, col_offset=col_offset)
794 DO j = 1, col_size
795 j_global = col_offset + j - 1
796 IF (j_global >= my_a_virtual_start .AND. j_global <= my_a_virtual_end) THEN
797 DO i = 1, row_size
798 i_global = row_offset + i - 1
799 my_cvirt(i_global, j_global - my_a_virtual_start + 1) = data_block(i, j)
800 END DO
801 END IF
802 END DO
803 END DO
804 CALL dbcsr_iterator_stop(iter)
805
806 CALL para_env_sub%sum(my_cvirt)
807
808 CALL timestop(handle)
809
810 END SUBROUTINE grep_occ_virt_wavefunc
811
812END MODULE mp2_gpw_method
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_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
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_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
DBCSR operations in CP2K.
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public cp_dbcsr_m_by_n_from_template(matrix, template, m, n, sym)
Utility function to create an arbitrary shaped dbcsr matrix with the same processor grid as the templ...
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_create(matrix, matrix_struct, name, use_sp)
creates a new full matrix with the given structure
Types to describe group distributions.
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
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_memory(mem)
Returns the total amount of memory [bytes] in use, if known, zero otherwise.
Definition machine.F:440
Interface to the message passing library MPI.
Routines to calculate 2c- and 3c-integrals for RI with GPW.
Definition mp2_eri_gpw.F:13
subroutine, public prepare_gpw(qs_env, dft_control, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, auxbas_pw_pool, poisson_env, task_list_sub, rho_r, rho_g, pot_g, psi_l, sab_orb_sub)
Prepares GPW calculation for RI-MP2/RI-RPA.
subroutine, public calc_potential_gpw(pot_r, rho_g, poisson_env, pot_g, potential_parameter, dvg, no_transfer)
Calculates potential from a given density in g-space.
subroutine, public cleanup_gpw(qs_env, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, task_list_sub, auxbas_pw_pool, rho_r, rho_g, pot_g, psi_l)
Cleanup GPW integration for RI-MP2/RI-RPA.
Routines to calculate MP2 energy using GPW method.
subroutine, public mp2_gpw_compute(emp2, emp2_cou, emp2_ex, qs_env, para_env, para_env_sub, color_sub, cell, particle_set, atomic_kind_set, qs_kind_set, eigenval, nmo, homo, mat_munu, sab_orb_sub, mo_coeff_o, mo_coeff_v, eps_filter, unit_nr, mp2_memory, calc_ex, blacs_env_sub, emp2_ab)
...
Define the data structure for the particle information.
container for various plainwaves related things
functions related to the poisson solver on regular grids
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Calculate the plane wave density by collocating the primitive Gaussian functions (pgf).
subroutine, public collocate_function(vector, rho, rho_gspace, atomic_kind_set, qs_kind_set, cell, particle_set, pw_env, eps_rho_rspace, basis_type)
maps a given function on the grid
Integrate single or product functions over a potential on a RS grid.
Define the quickstep kind type and their sub types.
Define the neighbor list data types and the corresponding functionality.
types for task lists
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...
keeps the information about the structure of a full matrix
represent a full matrix
stores all the informations relevant to an mpi environment
contained for different pw related things
environment for the poisson solver
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Provides all information about a quickstep kind.