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