(git:f2099e5)
Loading...
Searching...
No Matches
gw_ri_rs_large_cell_gamma.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief GW using RI-RS Approximation for molecules
10!> \par History
11!> 04.2026 created [Ritaj Tyagi]
12! **************************************************************************************************
16 USE cell_types, ONLY: cell_type,&
17 get_cell,&
18 pbc
22 USE cp_dbcsr_api, ONLY: &
26 dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
32 USE cp_fm_types, ONLY: cp_fm_create,&
37 USE cp_output_handling, ONLY: cp_p_file,&
51 USE gw_utils, ONLY: de_init_bs_env
63 USE kinds, ONLY: dp
64 USE machine, ONLY: m_walltime
67 USE orbital_pointers, ONLY: indco,&
68 ncoset
73#include "./base/base_uses.f90"
74
75 IMPLICIT NONE
76
77 PRIVATE
78
79 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_ri_rs_large_cell_Gamma'
80
84
85CONTAINS
86
87! **************************************************************************************************
88!> \brief GW calculation using RI-RS formalism for molecules
89!> \param qs_env ...
90!> \param bs_env Band-structure environment containing GW parameters.
91! **************************************************************************************************
92
93 SUBROUTINE gw_calc_ri_rs_large_cell_gamma(qs_env, bs_env)
94
95 TYPE(qs_environment_type), POINTER :: qs_env
96 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
97
98 CHARACTER(LEN=*), PARAMETER :: routinen = 'gw_calc_ri_rs_large_cell_Gamma'
99
100 INTEGER :: handle
101 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_sigma_x_gamma, fm_w_time
102 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: fm_sigma_c_gamma_time
103
104 CALL timeset(routinen, handle)
105
106 !!========================================================================
107 !! 0. Precompute AO and RI Radii
108 !! Per-atom cutoff radii from the most diffuse Gaussian primitives in
109 !! the AO and RI auxiliary basis sets. Stored in bs_env%ri_rs%
110 !! radius_ao_per_atom and radius_ri_per_atom, used for sphere-cutoff
111 !! and phi_local screening.
112 !!========================================================================
113 CALL precompute_ri_rs_radii(bs_env)
114
115 !!========================================================================
116 !! 1. Grid Generation for RI-RS
117 !! (Modified Lebedev grids from Ivan Duchemin and Xavier Blase)
118 !! Generate flattened 1D array of grid points for RI-RS.
119 !! Equation: r_g(k) = R_A + r_g(A)
120 !!========================================================================
121 CALL setup_ri_rs_grid(bs_env, bs_env%ri_rs%grid_points)
122
123 !!========================================================================
124 !! 2. Atomic Basis Evaluation
125 !! Compute values of spherical atomic basis functions at grid points.
126 !! Expression: ϕ_μl = ϕ_μ(r_l) (mat_phi_mu_l)
127 !!========================================================================
128 CALL atomic_basis_at_grid_point(bs_env, bs_env%ri_rs%grid_points, &
129 bs_env%ri_rs%mat_phi_mu_l)
130
131 !!========================================================================
132 !! 3. Compute RI-RS Coefficients (Z_lp)
133 !! Solve the regularized system for each atom P, where the grid domain
134 !! is restricted to r_l within a cutoff distance of atom P:
135 !! a. D_ll' = [ Σ_μ ϕ_μ(r_l) ϕ_μ(r_l') ]^2 (Equation 13)
136 !! b. D_lP = Σ_{μν} ϕ_μ(r_l) ϕ_ν(r_l) (μν|P) (Equation 15)
137 !! c. Conditioning:
138 !! Dvec_l = 1 / sqrt(D_ll) (Diagonal scaling vector)
139 !! D'_ll' = Dvec_l * D_ll' * Dvec_l' + λδ_ll'
140 !! D'_lP = Dvec_l * D_lP
141 !! d. Solve: Σ_l' D'_ll' * Z'_l'P = D'_lP (Equation 14)
142 !! e. Rescale: Z_lP = Z'_lP * Dvec_l (Z_lP stored in mat_Z_lP)
143 !!========================================================================
144 CALL compute_z_lp(qs_env, bs_env, bs_env%ri_rs%grid_points, &
145 bs_env%ri_rs%mat_phi_mu_l, bs_env%ri_rs%mat_Z_lP)
146 bs_env%ri_rs%grid_built = .true.
147
148 !!========================================================================
149 !! 4. Compute Independent-Particle Polarizability (χ)
150 !! G^occ_µλ(i|τ|) = sum_n^occ C_µn e^(-|(ϵ_n-ϵ_F)τ|) C_λn
151 !! G^vir_µλ(i|τ|) = sum_n^vir C_µn e^(-|(ϵ_n-ϵ_F)τ|) C_λn
152 !! G^occ_ll'(i|τ|) = sum_µν ϕ_µ(r_l) G^occ_µν ϕ_ν(r_l')
153 !! G^vir_ll'(i|τ|) = sum_µν ϕ_µ(r_l) G^vir_µν ϕ_ν(r_l')
154 !! χ_ll'(iτ) = G^occ_ll'(i|τ|) * G^vir_ll'(i|τ|)
155 !! χ_PQ(iτ) = sum_ll' Z_lP χ_ll'(iτ) Z_l'Q
156 !!========================================================================
157 CALL get_mat_chi_gamma_tau(bs_env, bs_env%mat_chi_Gamma_tau, &
158 bs_env%ri_rs%mat_phi_mu_l, bs_env%ri_rs%mat_Z_lP)
159
160 !!========================================================================
161 !! 5. Compute Screened Interaction (W^MIC)
162 !! χ_PQ(iτ) -> χ_PQ(iω) -> ε_PQ(iω) -> W_PQ(iω) -> W^MIC_PQ(iτ)
163 !!========================================================================
164 CALL get_w_mic(bs_env, qs_env, bs_env%mat_chi_Gamma_tau, fm_w_time)
165
166 !!========================================================================
167 !! 6. Compute Exact Exchange Self-Energy (Σ^x)
168 !! D_µν = sum_n^occ C_µn C_νn
169 !! D_ll' = sum_µν ϕ_µ(r_l) D_µν ϕ_ν(r_l')
170 !! V^trunc_ll' = sum_PQ Z_lP V^trunc_PQ Z_l'Q
171 !! Σ^x_ll' = D_ll' * V^trunc_ll'
172 !! Σ^x_λσ(k=0) = -sum_ll' ϕ_λ(r_l) Σ^x_ll' ϕ_σ(r_l')
173 !!========================================================================
174 CALL compute_sigma_x(bs_env, qs_env, bs_env%ri_rs%mat_phi_mu_l, &
175 bs_env%ri_rs%mat_Z_lP, fm_sigma_x_gamma)
176
177 !!========================================================================
178 !! 7. Compute Correlation Self-Energy (Σ^c)
179 !! W^MIC_ll'(iτ) = sum_PQ Z_lP W^MIC_PQ(iτ) Z_l'Q
180 !! Σ^c_ll'(iτ) = -G^occ_ll'(i|τ|) * W^MIC_ll'(iτ), for τ < 0
181 !! Σ^c_ll'(iτ) = G^vir_ll'(i|τ|) * W^MIC_ll'(iτ), for τ > 0
182 !! Σ^c_λσ(iτ) = sum_ll' ϕ_λ(r_l) Σ^c_ll'(iτ) ϕ_σ(r_l')
183 !!========================================================================
184 CALL compute_sigma_c(bs_env, fm_w_time, bs_env%ri_rs%mat_phi_mu_l, &
185 bs_env%ri_rs%mat_Z_lP, fm_sigma_c_gamma_time)
186
187 !!========================================================================
188 !! 8. Compute Quasiparticle Energies
189 !! Σ^c_λσ(iτ) -> Σ^c_nn(ϵ)
190 !! ϵ_nk^GW = ϵ_nk^DFT + Σ^c_nn(ϵ) + Σ^x_nn - v^xc_nn
191 !!========================================================================
192 CALL compute_qp_energies(bs_env, qs_env, fm_sigma_x_gamma, fm_sigma_c_gamma_time)
193
194 CALL de_init_bs_env(qs_env, bs_env)
195
196 CALL timestop(handle)
197
198 END SUBROUTINE gw_calc_ri_rs_large_cell_gamma
199
200! **************************************************************************************************
201!> \brief Evaluates atomic basis functions on a real-space grid and builds a sparse DBCSR matrix.
202!> \param bs_env ...
203!> \param ri_rs_grid_points ...
204!> \param mat_phi_mu_l ...
205! **************************************************************************************************
206
207 SUBROUTINE atomic_basis_at_grid_point(bs_env, ri_rs_grid_points, mat_phi_mu_l)
208
209 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
210 REAL(kind=dp), ALLOCATABLE, INTENT(INOUT) :: ri_rs_grid_points(:, :)
211 TYPE(dbcsr_type), INTENT(OUT) :: mat_phi_mu_l
212
213 CHARACTER(LEN=*), PARAMETER :: routinen = 'atomic_basis_at_grid_point'
214
215 INTEGER :: c_size, chunk_size, handle, i, i_blk, &
216 iatom, natom, npcol, nprow, &
217 num_grid_chunks, r_end, r_start
218 INTEGER, DIMENSION(:), POINTER :: col_dist, r_blk_sizes, row_dist, sizes_ao
219 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: atom_col_buffer
220 TYPE(cell_type), POINTER :: cell
221 TYPE(dbcsr_distribution_type) :: dbcsr_dist_ks, dist
222 TYPE(mp_para_env_type), POINTER :: para_env
223 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
224
225 CALL timeset(routinen, handle)
226
227 ! Setup Grid Blocking
228 chunk_size = max_elements_per_block
229
230 natom = bs_env%n_atom
231 cell => bs_env%ri_rs%cell
232 para_env => bs_env%para_env
233 particle_set => bs_env%ri_rs%particle_set
234 sizes_ao => bs_env%sizes_AO
235 cpassert(ASSOCIATED(cell))
236 cpassert(ASSOCIATED(para_env))
237 cpassert(ASSOCIATED(particle_set))
238 cpassert(SIZE(sizes_ao) == natom)
239 cpassert(SIZE(ri_rs_grid_points, 2) == bs_env%ri_rs%n_grid_points)
240
241 ! =========================================================================
242 ! 1. SETUP DBCSR MATRIX TOPOLOGY
243 ! =========================================================================
244
245 ! B. Define Row Block Sizes (Grid chunks of max size 256)
246 num_grid_chunks = ceiling(real(bs_env%ri_rs%n_grid_points, kind=dp)/real(chunk_size, kind=dp))
247 ALLOCATE (r_blk_sizes(num_grid_chunks))
248 r_blk_sizes = chunk_size
249 IF (mod(bs_env%ri_rs%n_grid_points, chunk_size) /= 0) THEN
250 r_blk_sizes(num_grid_chunks) = mod(bs_env%ri_rs%n_grid_points, chunk_size)
251 END IF
252
253 ! C. Fetch CP2K's Default Process Grid Configuration
254 CALL dbcsr_get_info(bs_env%mat_ao_ao%matrix, distribution=dbcsr_dist_ks)
255 CALL dbcsr_distribution_get(dbcsr_dist_ks, nprows=nprow, npcols=npcol)
256
257 ! D. Build Custom Mappings using Round-Robin across the 2D process grid
258
259 ALLOCATE (row_dist(num_grid_chunks))
260 DO i = 1, num_grid_chunks
261 row_dist(i) = mod(i - 1, nprow)
262 END DO
263
264 ALLOCATE (col_dist(natom))
265 DO i = 1, natom
266 col_dist(i) = mod(i - 1, npcol)
267 END DO
268
269 ! E. Create the DBCSR Distribution and Initialize the Matrix
270 CALL dbcsr_distribution_new(dist, template=dbcsr_dist_ks, &
271 row_dist=row_dist, col_dist=col_dist)
272
273 CALL dbcsr_create(mat_phi_mu_l, name="phi_val_sparse", dist=dist, &
274 matrix_type=dbcsr_type_no_symmetry, &
275 row_blk_size=r_blk_sizes, col_blk_size=sizes_ao)
276
277 ! =========================================================================
278 ! 2. STREAM DATA DIRECTLY INTO SPARSE MATRIX
279 ! =========================================================================
280 ! Iterate over the atoms assigned to this specific MPI rank
281 DO iatom = para_env%mepos + 1, natom, para_env%num_pe
282
283 c_size = sizes_ao(iatom)
284
285 ! Allocate a temporary dense buffer just for this specific atom
286 ALLOCATE (atom_col_buffer(bs_env%ri_rs%n_grid_points, c_size))
287 atom_col_buffer = 0.0_dp
288
289 ! Evaluate the basis functions on the grid. Skip grid points outside the spatial
290 ! extent of the most diffuse AO Gaussian on iatom; beyond that radius the contribution
291 ! is guaranteed below eps_filter.
292 CALL fill_phi_for_atom(atom_col_buffer, ri_rs_grid_points, bs_env%ri_rs%n_grid_points, &
293 iatom, bs_env, &
294 r2_threshold=bs_env%ri_rs%radius_ao_per_atom(iatom)**2)
295
296 ! Slice the dense column into chunks and insert into DBCSR
297 DO i_blk = 1, num_grid_chunks
298 r_start = (i_blk - 1)*chunk_size + 1
299 r_end = min(i_blk*chunk_size, bs_env%ri_rs%n_grid_points)
300
301 ! Apply dynamic sparsity filtering: Only store blocks with physical significance
302 IF (maxval(abs(atom_col_buffer(r_start:r_end, 1:c_size))) > bs_env%eps_filter) THEN
303 CALL dbcsr_put_block(mat_phi_mu_l, row=i_blk, col=iatom, &
304 block=atom_col_buffer(r_start:r_end, 1:c_size))
305 END IF
306 END DO
307
308 DEALLOCATE (atom_col_buffer)
309
310 END DO
311
312 ! Finalize triggers internal MPI communication to route blocks to their correct 2D process owners
313 CALL dbcsr_finalize(mat_phi_mu_l)
314
315 IF (bs_env%unit_nr > 0) THEN
316 WRITE (bs_env%unit_nr, *) "Done with evaluation of phi"
317 END IF
318
319 ! -------------------------------------------------------------------------
320 ! CLEANUP
321 ! -------------------------------------------------------------------------
322 DEALLOCATE (r_blk_sizes, row_dist, col_dist)
324
325 CALL timestop(handle)
326
327 END SUBROUTINE atomic_basis_at_grid_point
328
329! **************************************************************************************************
330!> \brief Compute value of all basis functions for a single atom across all grid points.
331!> Sums contributions from periodic images of `iatom` (loop over (ix, iy, iz) cells gated
332!> by `cell%perd`). Each per-image squared distance is compared against `r2_threshold`
333!> (per-atom AO Gaussian extent²); images beyond that radius contribute below eps_filter
334!> and are skipped.
335!> \param phi_val ...
336!> \param ri_rs_grid ...
337!> \param npts ...
338!> \param iatom ...
339!> \param bs_env ...
340!> \param r2_threshold per-image squared-distance threshold; CYCLE if r² > r2_threshold. Pass
341!> HUGE(1.0_dp) to disable.
342! **************************************************************************************************
343
344 SUBROUTINE fill_phi_for_atom(phi_val, ri_rs_grid, npts, iatom, bs_env, r2_threshold)
345
346 REAL(kind=dp), INTENT(INOUT) :: phi_val(:, :)
347 INTEGER, INTENT(IN) :: npts
348 REAL(kind=dp), INTENT(IN) :: ri_rs_grid(3, npts)
349 INTEGER, INTENT(IN) :: iatom
350 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
351 REAL(kind=dp), INTENT(IN) :: r2_threshold
352
353 CHARACTER(LEN=*), PARAMETER :: routinen = 'fill_phi_for_atom'
354
355 INTEGER :: first_sgf, handle, i_pt, ico, iend_co, ikind, ipgf, iset, isgf, ishell, &
356 istart_co, ix, ix_max, ix_min, iy, iy_max, iy_min, iz, iz_max, iz_min, l, last_sgf, lx, &
357 ly, lz, n_cart_total, row_idx
358 REAL(kind=dp) :: alpha, cell_vector(3), dist_vec(3), &
359 dist_vec_raw(3), exp_val, poly, r2, &
360 r_atom(3), weight
361 REAL(kind=dp), DIMENSION(3, 3) :: hmat
362 TYPE(cell_type), POINTER :: cell
363 TYPE(gto_basis_set_type), POINTER :: orb_basis_set
364 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
365
366 CALL timeset(routinen, handle)
367
368 ! Get Atom Info
369 cell => bs_env%ri_rs%cell
370 particle_set => bs_env%ri_rs%particle_set
371 ikind = particle_set(iatom)%atomic_kind%kind_number
372 orb_basis_set => bs_env%basis_set_AO(ikind)%gto_basis_set
373 CALL get_cell(cell=cell, h=hmat)
374 cpassert(ASSOCIATED(orb_basis_set))
375
376 IF (cell%perd(1) == 1) then; ix_min = -1; ix_max = 1; else; ix_min = 0; ix_max = 0
377 END IF
378 IF (cell%perd(2) == 1) then; iy_min = -1; iy_max = 1; else; iy_min = 0; iy_max = 0
379 END IF
380 IF (cell%perd(3) == 1) then; iz_min = -1; iz_max = 1; else; iz_min = 0; iz_max = 0
381 END IF
382
383 r_atom = particle_set(iatom)%r
384
385 !$OMP PARALLEL DO DEFAULT(NONE) &
386 !$OMP SHARED(phi_val, ri_rs_grid, npts, orb_basis_set, r_atom, hmat, &
387 !$OMP ncoset, indco, cell, ix_min, ix_max, &
388 !$OMP iy_min, iy_max, iz_min, iz_max, r2_threshold) &
389 !$OMP PRIVATE(i_pt, dist_vec_raw, ix, iy, iz, cell_vector, dist_vec, r2, iset, &
390 !$OMP n_cart_total, ishell, l, istart_co, iend_co, first_sgf, last_sgf, &
391 !$OMP ipgf, alpha, exp_val, isgf, ico, row_idx, weight, lx, ly, lz, poly) &
392 !$OMP SCHEDULE(DYNAMIC)
393
394 DO i_pt = 1, npts
395
396 dist_vec_raw = ri_rs_grid(:, i_pt) - r_atom
397
398 DO ix = ix_min, ix_max
399 DO iy = iy_min, iy_max
400 DO iz = iz_min, iz_max
401
402 cell_vector(1:3) = matmul(hmat, real([ix, iy, iz], dp))
403
404 dist_vec = dist_vec_raw - cell_vector
405
406 r2 = dot_product(dist_vec, dist_vec)
407
408 IF (r2 > r2_threshold) cycle
409
410 DO iset = 1, orb_basis_set%nset
411 n_cart_total = ncoset(orb_basis_set%lmax(iset))
412
413 DO ishell = 1, orb_basis_set%nshell(iset)
414 l = orb_basis_set%l(ishell, iset)
415 istart_co = ncoset(l - 1) + 1
416 iend_co = ncoset(l)
417
418 first_sgf = orb_basis_set%first_sgf(ishell, iset)
419 last_sgf = orb_basis_set%last_sgf(ishell, iset)
420
421 DO ipgf = 1, orb_basis_set%npgf(iset)
422 alpha = orb_basis_set%zet(ipgf, iset)
423 exp_val = exp(-alpha*r2)
424
425 DO isgf = first_sgf, last_sgf
426 DO ico = istart_co, iend_co
427 row_idx = (ipgf - 1)*n_cart_total + ico
428 weight = orb_basis_set%sphi(row_idx, isgf)
429 lx = indco(1, ico)
430 ly = indco(2, ico)
431 lz = indco(3, ico)
432 poly = (dist_vec(1)**lx)*(dist_vec(2)**ly)*(dist_vec(3)**lz)
433
434 phi_val(i_pt, isgf) = phi_val(i_pt, isgf) + (weight*poly*exp_val)
435
436 END DO
437 END DO
438 END DO
439 END DO
440 END DO
441 END DO
442 END DO
443 END DO
444 END DO
445 !$OMP END PARALLEL DO
446
447 CALL timestop(handle)
448
449 END SUBROUTINE fill_phi_for_atom
450
451! **************************************************************************************************
452!> \brief Compute RI-RS Coefficients (Z_lP)
453!> \param qs_env ...
454!> \param bs_env ...
455!> \param ri_rs_grid_points ...
456!> \param mat_phi_mu_l ...
457!> \param mat_Z_lP ...
458! **************************************************************************************************
459
460 SUBROUTINE compute_z_lp(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_Z_lP)
461
462 ! Arguments
463 TYPE(qs_environment_type), POINTER :: qs_env
464 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
465 REAL(kind=dp), ALLOCATABLE, INTENT(INOUT) :: ri_rs_grid_points(:, :)
466 TYPE(dbcsr_type), INTENT(INOUT) :: mat_phi_mu_l
467 TYPE(dbcsr_type), INTENT(OUT) :: mat_z_lp
468
469 CHARACTER(LEN=*), PARAMETER :: key = 'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
470 routinen = 'compute_Z_lP'
471
472 INTEGER :: atom_j_mepos, atom_j_stride, atom_p, atom_p_start, atom_p_stride, col_end, &
473 col_start, group_handle, handle, handle_dpotrf, handle_dpotrs, i_blk, ikind, info, j, l, &
474 loc_idx, max_ao_size, max_loc_ri, my_group, n_ao_total, n_grid_total, n_groups, n_loc_ri, &
475 n_local_grid, n_procs_per_atom, natom, nkind, npcol_phi, num_grid_chunks, p_loop_atom, &
476 ri_atom
477 INTEGER, ALLOCATABLE, DIMENSION(:) :: local_grid_idx, row_offset
478 INTEGER, DIMENSION(:), POINTER :: col_dist_ri, r_blk_sizes, ri_blk_sizes, &
479 row_dist_grid
480 REAL(kind=dp) :: cutoff_ri, cutoff_ri_2, d_sp, dist2_min, &
481 r2_threshold, r_c, t1, t2, t3
482 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: cutoff_ri_per_atom, cutoff_ri_per_kind, &
483 d_vec_local
484 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: d_local, d_lp_local, phi_local, &
485 sphere_grid
486 REAL(kind=dp), DIMENSION(3) :: dist_vec_raw, pos_p
487 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
488 TYPE(cell_type), POINTER :: cell
489 TYPE(cp_blacs_env_type), POINTER :: blacs_env_sub
490 TYPE(cp_fm_struct_type), POINTER :: fm_struct_b, fm_struct_d
491 TYPE(cp_fm_type) :: fm_b, fm_d
492 TYPE(cp_logger_type), POINTER :: logger
493 TYPE(dbcsr_distribution_type) :: dist_phi, dist_z
494 TYPE(gw_3c_ctx_type) :: ctx_3c
495 TYPE(mp_para_env_type), POINTER :: para_env, para_env_sub
496 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
497 TYPE(section_vals_type), POINTER :: input
498
499 CALL timeset(routinen, handle)
500
501 t1 = m_walltime()
502
503 CALL get_qs_env(qs_env, para_env=para_env, particle_set=particle_set, input=input, cell=cell)
504 atomic_kind_set => bs_env%ri_rs%atomic_kind_set
505
506 ! ---------------------------------------------------------------------
507 ! Subgroup setup. Default G=1 keeps the single-rank BLAS path; G>1 splits
508 ! ranks into atom-groups so the Cholesky on D_local distributes across G
509 ! ranks (memory ~1/G) and the compute_d_lp build also splits across the
510 ! subgroup. G=1 leaves para_env_sub / blacs_env_sub NULL — no subgroup
511 ! comms created, atom_P loop uses per-rank round-robin, compute_d_lp runs
512 ! its full atom_j range on each rank, no allreduce.
513 ! ---------------------------------------------------------------------
514 n_procs_per_atom = min(bs_env%ri_rs%n_procs_per_atom_z_lp, para_env%num_pe)
515 IF (n_procs_per_atom < 1) n_procs_per_atom = 1
516
517 NULLIFY (para_env_sub, blacs_env_sub)
518 IF (n_procs_per_atom > 1) THEN
519 n_groups = para_env%num_pe/n_procs_per_atom
520 my_group = min(para_env%mepos/n_procs_per_atom, n_groups - 1)
521 ALLOCATE (para_env_sub)
522 CALL para_env_sub%from_split(para_env, my_group)
523 CALL cp_blacs_env_create(blacs_env=blacs_env_sub, para_env=para_env_sub)
524 atom_p_start = my_group + 1
525 atom_p_stride = n_groups
526 atom_j_mepos = para_env_sub%mepos
527 atom_j_stride = para_env_sub%num_pe
528 ELSE
529 atom_p_start = para_env%mepos + 1
530 atom_p_stride = para_env%num_pe
531 atom_j_mepos = 0
532 atom_j_stride = 1
533 END IF
534
535 natom = bs_env%n_atom
536 n_ao_total = bs_env%i_ao_end_from_atom(natom)
537 n_grid_total = bs_env%ri_rs%n_grid_points
538 cpassert(SIZE(ri_rs_grid_points, 2) == n_grid_total)
539
540 ! =========================================================================
541 ! 1. SETUP DBCSR TOPOLOGY & EXACT OFFSETS
542 ! =========================================================================
543 CALL dbcsr_get_info(mat_phi_mu_l, row_blk_size=r_blk_sizes, distribution=dist_phi)
544 CALL dbcsr_distribution_get(dist_phi, row_dist=row_dist_grid, &
545 group=group_handle, npcols=npcol_phi)
546
547 num_grid_chunks = SIZE(r_blk_sizes)
548
549 ALLOCATE (row_offset(num_grid_chunks))
550 row_offset(1) = 0
551 DO i_blk = 2, num_grid_chunks
552 row_offset(i_blk) = row_offset(i_blk - 1) + r_blk_sizes(i_blk - 1)
553 END DO
554
555 ALLOCATE (ri_blk_sizes(natom), col_dist_ri(natom))
556 DO atom_p = 1, natom
557 ri_blk_sizes(atom_p) = bs_env%i_RI_end_from_atom(atom_p) - bs_env%i_RI_start_from_atom(atom_p) + 1
558 col_dist_ri(atom_p) = mod(atom_p - 1, npcol_phi)
559 END DO
560
561 CALL dbcsr_distribution_new(dist_z, template=dist_phi, row_dist=row_dist_grid, col_dist=col_dist_ri)
562
563 IF (bs_env%ri_rs%Z_lP_exists) THEN
564 CALL dbcsr_binary_read(filepath=trim(bs_env%prefix)//"Z_lP.matrix", &
565 distribution=dist_z, &
566 matrix_new=mat_z_lp)
567 IF (bs_env%unit_nr > 0) THEN
568 WRITE (bs_env%unit_nr, '(T2,A,T57,A,F7.1,A)') &
569 'Read Z_lP from file ', ' Execution time', m_walltime() - t1, ' s'
570 WRITE (bs_env%unit_nr, '(A)') ' '
571 END IF
572 ELSE
573
574 CALL dbcsr_create(mat_z_lp, name="mat_Z_lP", dist=dist_z, &
575 matrix_type=dbcsr_type_no_symmetry, &
576 row_blk_size=r_blk_sizes, col_blk_size=ri_blk_sizes)
577
578 max_ao_size = 0
579 DO j = 1, natom
580 max_ao_size = max(max_ao_size, bs_env%i_ao_end_from_atom(j) - bs_env%i_ao_start_from_atom(j) + 1)
581 END DO
582 max_loc_ri = maxval(ri_blk_sizes)
583
584 ! Per-atom RI-RS integration sphere:
585 ! cutoff_ri(P) = r_c + r_AO(P)
586 ! where r_c is the truncated-Coulomb cutoff of the RI metric. The
587 ! CUTOFF_RADIUS_RI_RS keyword (when > 0) overrides the entire cutoff calculation.
588 nkind = SIZE(atomic_kind_set)
589 ALLOCATE (cutoff_ri_per_atom(natom))
590
591 IF (bs_env%ri_rs%cutoff_radius_ri_rs > 0.0_dp) THEN
592 cutoff_ri_per_atom(:) = bs_env%ri_rs%cutoff_radius_ri_rs
593 ELSE
594 r_c = bs_env%ri_metric%cutoff_radius
595 DO p_loop_atom = 1, natom
596 cutoff_ri_per_atom(p_loop_atom) = &
597 r_c + bs_env%ri_rs%radius_ao_per_atom(p_loop_atom)
598 END DO
599 END IF
600
601 ALLOCATE (cutoff_ri_per_kind(nkind))
602 cutoff_ri_per_kind(:) = 0.0_dp
603 IF (bs_env%unit_nr > 0) THEN
604 DO p_loop_atom = 1, natom
605 ikind = particle_set(p_loop_atom)%atomic_kind%kind_number
606 cutoff_ri_per_kind(ikind) = max(cutoff_ri_per_kind(ikind), &
607 cutoff_ri_per_atom(p_loop_atom))
608 END DO
609 WRITE (bs_env%unit_nr, '(T2,A)') 'Per-kind maximum RI-RS sphere cutoff (Bohr):'
610 WRITE (bs_env%unit_nr, '(T4,A4,A14)') 'Kind', 'max cutoff_ri'
611 DO ikind = 1, nkind
612 WRITE (bs_env%unit_nr, '(T4,A4,F14.4)') &
613 atomic_kind_set(ikind)%element_symbol, &
614 cutoff_ri_per_kind(ikind)
615 END DO
616 WRITE (bs_env%unit_nr, '(A)') ' '
617 DEALLOCATE (cutoff_ri_per_kind)
618 END IF
619
620 ! Shared 3c-integral context: hoists libint / t_c_g0 / md_ftable / contracted
621 ! sphi tables out of the per-triple call so compute_d_lp threads only allocate
622 ! a lightweight per-thread workspace. MPI-collective; must be outside any
623 ! OMP region.
624 CALL gw_3c_ctx_create(ctx_3c, bs_env, bs_env%ri_metric, &
625 basis_j=bs_env%basis_set_AO, basis_k=bs_env%basis_set_AO, &
626 basis_i=bs_env%basis_set_RI)
627
628 ! =========================================================================
629 ! 2. MPI LOOP OVER ATOMS (Fully independent, no MPI barriers inside)
630 ! phi_local for each atom_P's cutoff sphere is built on the fly via
631 ! fill_phi_for_atom — no dense replicated phi_global, no allreduce.
632 ! =========================================================================
633 DO atom_p = atom_p_start, natom, atom_p_stride
634
635 n_loc_ri = ri_blk_sizes(atom_p)
636 pos_p(:) = particle_set(atom_p)%r(:)
637
638 cutoff_ri = cutoff_ri_per_atom(atom_p)
639 cutoff_ri_2 = cutoff_ri**2
640
641 ! ---------------------------------------------------------------------
642 ! A. Determine Local Grid Domain based on cutoff_ri (PBC distance)
643 ! ---------------------------------------------------------------------
644 n_local_grid = 0
645 DO l = 1, n_grid_total
646 dist_vec_raw = pbc(ri_rs_grid_points(1:3, l), pos_p(1:3), cell)
647 dist2_min = dot_product(dist_vec_raw, dist_vec_raw)
648 IF (dist2_min <= cutoff_ri_2) n_local_grid = n_local_grid + 1
649 END DO
650
651 ALLOCATE (local_grid_idx(n_local_grid))
652
653 n_local_grid = 0
654 DO l = 1, n_grid_total
655 dist_vec_raw = pbc(ri_rs_grid_points(1:3, l), pos_p(1:3), cell)
656 dist2_min = dot_product(dist_vec_raw, dist_vec_raw)
657 IF (dist2_min <= cutoff_ri_2) THEN
658 n_local_grid = n_local_grid + 1
659 local_grid_idx(n_local_grid) = l
660 END IF
661 END DO
662
663 ! ---------------------------------------------------------------------
664 ! B. Build phi_local on the fly via fill_phi_for_atom.
665 ! Only source atoms whose AO basis can reach the cutoff sphere of
666 ! atom_P (MIC distance) contribute; the rest are pruned. The
667 ! periodic fill_phi_for_atom sums over (ix, iy, iz) images of
668 ! ri_atom internally.
669 ! ---------------------------------------------------------------------
670 ALLOCATE (sphere_grid(3, n_local_grid))
671 DO loc_idx = 1, n_local_grid
672 sphere_grid(:, loc_idx) = ri_rs_grid_points(:, local_grid_idx(loc_idx))
673 END DO
674
675 ALLOCATE (phi_local(n_local_grid, n_ao_total))
676 phi_local = 0.0_dp
677
678 DO ri_atom = 1, natom
679 dist_vec_raw = pbc(particle_set(ri_atom)%r(:), pos_p(:), cell)
680 d_sp = norm2(dist_vec_raw)
681 IF (d_sp > bs_env%ri_rs%radius_ao_per_atom(ri_atom) + cutoff_ri) cycle
682
683 col_start = bs_env%i_ao_start_from_atom(ri_atom)
684 col_end = bs_env%i_ao_end_from_atom(ri_atom)
685 r2_threshold = bs_env%ri_rs%radius_ao_per_atom(ri_atom)**2
686
687 CALL fill_phi_for_atom(phi_local(:, col_start:col_end), sphere_grid, &
688 n_local_grid, ri_atom, bs_env, r2_threshold)
689 END DO
690
691 DEALLOCATE (sphere_grid)
692
693 ! ---------------------------------------------------------------------
694 ! C. Build Local RHS Matrix (d_lp_local) first so the subgroup-
695 ! distributed compute_d_lp + allreduce is not entangled with the LHS
696 ! build. compute_d_lp does not depend on D_local or d_vec_local.
697 ! ---------------------------------------------------------------------
698 ALLOCATE (d_lp_local(n_local_grid, n_loc_ri))
699 d_lp_local = 0.0_dp
700
701 t2 = m_walltime()
702
703 CALL compute_d_lp(bs_env, ctx_3c, phi_local, d_lp_local, n_local_grid, &
704 n_loc_ri, atom_p, max_ao_size, atom_j_mepos, atom_j_stride)
705
706 ! Reduce per-subgroup-rank partials into the replicated d_lp_local.
707 ! Skipped for G=1 (BLAS path): each rank has the full sum locally.
708 IF (n_procs_per_atom > 1) THEN
709 CALL para_env_sub%sum(d_lp_local)
710 END IF
711
712 t3 = m_walltime()
713
714 ! ---------------------------------------------------------------------
715 ! D. Build d_vec_local (Jacobi diagonal) + LHS — BLAS or ScaLAPACK
716 ! ---------------------------------------------------------------------
717 ALLOCATE (d_vec_local(n_local_grid))
718
719 IF (n_procs_per_atom == 1) THEN
720 CALL build_gram_jacobi_blas(phi_local, n_local_grid, n_ao_total, &
721 bs_env%ri_rs%tikhonov, d_local, d_vec_local)
722 ELSE
723 ! ScaLAPACK path: d_vec computed directly from phi (= 1/||phi_i||^2);
724 ! solve_D_lp_distributed builds D block-cyclic internally with
725 ! the squared+scaled values, so no dense D_local on this rank.
726 CALL build_jacobi_diag_from_phi(phi_local, n_local_grid, n_ao_total, &
727 d_vec_local)
728 END IF
729
730 ! ---------------------------------------------------------------------
731 ! E. Pre-scale d_lp by d_vec
732 ! ---------------------------------------------------------------------
733 CALL scale_rows_by_diag(d_lp_local, d_vec_local, n_local_grid, n_loc_ri)
734
735 ! ---------------------------------------------------------------------
736 ! F. Solve — BLAS dpotrf/dpotrs or ScaLAPACK pdpotrf/pdpotrs
737 ! ---------------------------------------------------------------------
738 IF (n_procs_per_atom == 1) THEN
739 CALL timeset(routinen//"_dpotrf", handle_dpotrf)
740 CALL dpotrf('L', n_local_grid, d_local, n_local_grid, info)
741 CALL timestop(handle_dpotrf)
742 IF (info /= 0) cpabort("RI-RS Cholesky factorization failed")
743 CALL timeset(routinen//"_dpotrs", handle_dpotrs)
744 CALL dpotrs('L', n_local_grid, n_loc_ri, d_local, n_local_grid, &
745 d_lp_local, n_local_grid, info)
746 CALL timestop(handle_dpotrs)
747 IF (info /= 0) cpabort("RI-RS Cholesky solve failed")
748 DEALLOCATE (d_local)
749 ELSE
750 CALL solve_d_lp_distributed(phi_local, d_vec_local, d_lp_local, &
751 n_local_grid, n_ao_total, n_loc_ri, &
752 bs_env%ri_rs%tikhonov, &
753 para_env_sub, blacs_env_sub, &
754 fm_struct_d, fm_struct_b, fm_d, fm_b, info)
755 IF (info /= 0) cpabort("Distributed RI-RS Cholesky solve failed")
756 END IF
757
758 ! ---------------------------------------------------------------------
759 ! G. Post-scale solution by d_vec (common to both paths)
760 ! ---------------------------------------------------------------------
761 CALL scale_rows_by_diag(d_lp_local, d_vec_local, n_local_grid, n_loc_ri)
762
763 ! ---------------------------------------------------------------------
764 ! H. Scatter Local Solution Back to Global DBCSR Matrix.
765 ! Under ScaLAPACK (G>1) the d_lp_local solution is identical on all
766 ! G subgroup ranks (gathered via cp_fm_get_submatrix); only the
767 ! subgroup root writes to mat_Z_lP so each atom column is emitted
768 ! exactly once. DBCSR routes blocks to their global owner on finalize.
769 ! local_grid_idx is ascending (built by the ordered scan above), so
770 ! a single walking pointer over chunks works.
771 ! ---------------------------------------------------------------------
772 IF (n_procs_per_atom == 1 .OR. para_env_sub%mepos == 0) THEN
773 CALL store_z_lp_columns(mat_z_lp, d_lp_local, local_grid_idx, n_local_grid, &
774 n_loc_ri, atom_p, r_blk_sizes, row_offset, &
775 bs_env%eps_filter)
776 END IF
777
778 DEALLOCATE (d_vec_local, d_lp_local)
779 DEALLOCATE (local_grid_idx, phi_local)
780
781 END DO
782
783 DEALLOCATE (cutoff_ri_per_atom)
784 CALL gw_3c_ctx_release(ctx_3c)
785
786 CALL dbcsr_finalize(mat_z_lp)
787
788 IF (bs_env%unit_nr > 0) THEN
789 WRITE (bs_env%unit_nr, '(T2,A,T57,A,F7.1,A)') &
790 'Computed Z_lP ', ' Execution time', m_walltime() - t1, ' s'
791 WRITE (bs_env%unit_nr, '(A)') ' '
792 END IF
793
794 logger => cp_get_default_logger()
795
796 IF (btest(cp_print_key_should_output(logger%iter_info, input, key), cp_p_file)) THEN
797 CALL dbcsr_binary_write(matrix=mat_z_lp, filepath=trim(bs_env%prefix)//"Z_lP.matrix")
798 END IF
799
800 END IF
801
802 DEALLOCATE (row_offset, ri_blk_sizes, col_dist_ri)
803 CALL dbcsr_distribution_release(dist_z)
804
805 IF (n_procs_per_atom > 1) THEN
806 CALL cp_blacs_env_release(blacs_env_sub)
807 CALL para_env_sub%free()
808 DEALLOCATE (para_env_sub)
809 END IF
810
811 DEALLOCATE (ri_rs_grid_points)
812
813 CALL timestop(handle)
814
815 END SUBROUTINE compute_z_lp
816
817! **************************************************************************************************
818!> \brief Computes the dense localized RHS d_lp(l,P) = Σ_{μν,R,S} ϕ_μ(r_l)·ϕ_ν(r_l)·(μν|P) for one
819!> RI atom P. OMP-threaded over (atom_j, atom_k) AO-pair blocks: per thread, sweep all
820!> (cell_R, cell_S) periodic images of (atom_j, atom_k) about atom_P at cell (0,0,0); each
821!> 3c block is built by build_3c_integral_block_ctx (cached libint / sphi tables in ctx,
822!> kind-radius triangle screen → `screened` short-circuits negligible image triples), and
823!> grid-chunked pair densities are contracted into a private d_lp partial that is reduced
824!> into d_lp at the end of the parallel region.
825!> \param bs_env ...
826!> \param ctx shared 3c-integral context (gw_3c_ctx_create)
827!> \param phi_val ϕ_μ(r_l) on the local-sphere grid (n_grid_total × n_ao)
828!> \param d_lp output (n_grid_total × n_loc_ri), zeroed by the caller, accumulated here
829!> \param n_grid_total number of local-sphere grid rows
830!> \param n_loc_ri number of RI functions of atom_P
831!> \param atom_P RI atom (pinned to cell (0,0,0))
832!> \param max_ao_size ...
833!> \param atom_j_mepos ...
834!> \param atom_j_stride ...
835! **************************************************************************************************
836
837 SUBROUTINE compute_d_lp(bs_env, ctx, phi_val, d_lp, n_grid_total, n_loc_ri, atom_P, &
838 max_ao_size, atom_j_mepos, atom_j_stride)
839
840 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
841 TYPE(gw_3c_ctx_type), INTENT(IN) :: ctx
842 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: phi_val
843 INTEGER, INTENT(IN) :: n_grid_total, n_loc_ri
844 REAL(kind=dp), INTENT(INOUT) :: d_lp(n_grid_total, n_loc_ri)
845 INTEGER, INTENT(IN) :: atom_p, max_ao_size, atom_j_mepos, &
846 atom_j_stride
847
848 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_d_lp'
849 INTEGER, PARAMETER :: grid_chunk = 1024
850
851 INTEGER :: atom_j, atom_k, c, handle, handle_dgemm, ix_max, ix_min, ix_r, ix_s, iy_max, &
852 iy_min, iy_r, iy_s, iz_max, iz_min, iz_r, iz_s, j, jk_idx, jsize, jstart, k, ksize, &
853 kstart, l, l0, natom, ri
854 INTEGER, DIMENSION(3) :: cell_r_vec, cell_s_vec
855 LOGICAL :: any_kept, screened
856 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: d_lp_prv, int_2d_prv, rho_chunk
857 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: int_3c_prv, int_3c_sum
858 TYPE(gw_3c_ws_type) :: ws
859
860 CALL timeset(routinen, handle)
861
862 natom = bs_env%n_atom
863
864 IF (bs_env%ri_rs%cell%perd(1) == 1) then; ix_min = -1; ix_max = 1; else; ix_min = 0; ix_max = 0
865 END IF
866 IF (bs_env%ri_rs%cell%perd(2) == 1) then; iy_min = -1; iy_max = 1; else; iy_min = 0; iy_max = 0
867 END IF
868 IF (bs_env%ri_rs%cell%perd(3) == 1) then; iz_min = -1; iz_max = 1; else; iz_min = 0; iz_max = 0
869 END IF
870
871 !$OMP PARALLEL DEFAULT(NONE) &
872 !$OMP SHARED(bs_env, ctx, phi_val, d_lp, n_grid_total, n_loc_ri, atom_P, max_ao_size, &
873 !$OMP natom, ix_min, ix_max, iy_min, iy_max, iz_min, iz_max, &
874 !$OMP atom_j_mepos, atom_j_stride) &
875 !$OMP PRIVATE(any_kept, atom_j, atom_k, c, handle_dgemm, j, jk_idx, jsize, jstart, k, &
876 !$OMP ksize, kstart, l, l0, ri, ix_R, iy_R, iz_R, ix_S, iy_S, iz_S, cell_R_vec, &
877 !$OMP cell_S_vec, screened, d_lp_prv, int_2d_prv, rho_chunk, int_3c_prv, int_3c_sum, ws)
878
879 CALL gw_3c_ws_create(ws, ctx)
880 ALLOCATE (int_3c_prv(max_ao_size, max_ao_size, n_loc_ri))
881 ALLOCATE (int_3c_sum(max_ao_size, max_ao_size, n_loc_ri))
882 ALLOCATE (int_2d_prv(max_ao_size*max_ao_size, n_loc_ri))
883 ALLOCATE (rho_chunk(grid_chunk, max_ao_size*max_ao_size))
884 ALLOCATE (d_lp_prv(n_grid_total, n_loc_ri))
885 d_lp_prv(:, :) = 0.0_dp
886
887 ! atom_P pinned at cell (0,0,0); enumerate (atom_j, cell_R) × (atom_k, cell_S). The ctx
888 ! integral builder's kind_radius triangle screen sets screened=.TRUE. for the bulk of
889 ! image triples (one or both AO atoms beyond the truncated-Coulomb reach of atom_P),
890 ! so the 27 × 27 = 729 candidate cells collapse to "adjacent cells" in practice.
891 ! MPI-stride atom_j over the subgroup (atom_j_stride = 1 for the BLAS path, > 1 for the
892 ! ScaLAPACK path). COLLAPSE(2) dropped because the outer stride is non-unit under
893 ! ScaLAPACK; the inner atom_k loop carries enough work for DYNAMIC.
894 !$OMP DO SCHEDULE(DYNAMIC)
895 DO atom_j = atom_j_mepos + 1, natom, atom_j_stride
896 DO atom_k = 1, natom
897 jstart = bs_env%i_ao_start_from_atom(atom_j)
898 jsize = bs_env%i_ao_end_from_atom(atom_j) - jstart + 1
899 kstart = bs_env%i_ao_start_from_atom(atom_k)
900 ksize = bs_env%i_ao_end_from_atom(atom_k) - kstart + 1
901
902 int_3c_sum(1:jsize, 1:ksize, 1:n_loc_ri) = 0.0_dp
903 any_kept = .false.
904
905 DO ix_r = ix_min, ix_max
906 DO iy_r = iy_min, iy_max
907 DO iz_r = iz_min, iz_max
908 cell_r_vec = [ix_r, iy_r, iz_r]
909 DO ix_s = ix_min, ix_max
910 DO iy_s = iy_min, iy_max
911 DO iz_s = iz_min, iz_max
912 cell_s_vec = [ix_s, iy_s, iz_s]
913
914 int_3c_prv(1:jsize, 1:ksize, 1:n_loc_ri) = 0.0_dp
915
916 CALL build_3c_integral_block_ctx(int_3c_prv( &
917 1:jsize, 1:ksize, 1:n_loc_ri), ctx, ws, &
918 atom_j=atom_j, atom_k=atom_k, atom_i=atom_p, &
919 cell_j=cell_r_vec, cell_k=cell_s_vec, cell_i=[0, 0, 0], &
920 screened=screened)
921 IF (screened) cycle
922
923 any_kept = .true.
924 int_3c_sum(1:jsize, 1:ksize, 1:n_loc_ri) = &
925 int_3c_sum(1:jsize, 1:ksize, 1:n_loc_ri) + &
926 int_3c_prv(1:jsize, 1:ksize, 1:n_loc_ri)
927 END DO
928 END DO
929 END DO
930 END DO
931 END DO
932 END DO
933
934 IF (.NOT. any_kept) cycle
935
936 ! Flatten 3D B_{μν,P} → 2D B_{(μν),P}
937 DO ri = 1, n_loc_ri
938 DO k = 1, ksize
939 DO j = 1, jsize
940 jk_idx = (k - 1)*jsize + j
941 int_2d_prv(jk_idx, ri) = int_3c_sum(j, k, ri)
942 END DO
943 END DO
944 END DO
945
946 ! Pair density ρ(l,μν) = ϕ_μ(r_l)ϕ_ν(r_l) in grid chunks, contracted on the fly:
947 ! d_{l,P} += ρ(l,μν) B_{(μν),P} (dgemm runs serially inside the parallel region)
948 DO l0 = 1, n_grid_total, grid_chunk
949 c = min(grid_chunk, n_grid_total - l0 + 1)
950 DO k = 1, ksize
951 DO j = 1, jsize
952 jk_idx = (k - 1)*jsize + j
953 DO l = 1, c
954 rho_chunk(l, jk_idx) = phi_val(l0 + l - 1, jstart + j - 1)* &
955 phi_val(l0 + l - 1, kstart + k - 1)
956 END DO
957 END DO
958 END DO
959 CALL timeset(routinen//"_dgemm", handle_dgemm)
960 CALL dgemm("N", "N", c, n_loc_ri, jsize*ksize, &
961 1.0_dp, rho_chunk, grid_chunk, &
962 int_2d_prv, max_ao_size*max_ao_size, &
963 1.0_dp, d_lp_prv(l0, 1), n_grid_total)
964 CALL timestop(handle_dgemm)
965 END DO
966 END DO
967 END DO
968 !$OMP END DO
969
970 !$OMP CRITICAL (compute_d_lp_reduce)
971 d_lp(1:n_grid_total, 1:n_loc_ri) = d_lp(1:n_grid_total, 1:n_loc_ri) + &
972 d_lp_prv(1:n_grid_total, 1:n_loc_ri)
973 !$OMP END CRITICAL (compute_d_lp_reduce)
974
975 DEALLOCATE (int_3c_prv, int_3c_sum, int_2d_prv, rho_chunk, d_lp_prv)
976 CALL gw_3c_ws_release(ws)
977
978 !$OMP END PARALLEL
979
980 CALL timestop(handle)
981
982 END SUBROUTINE compute_d_lp
983
984! **************************************************************************************************
985!> \brief Computes the χ(iτ, k=0) matrix
986!> \param bs_env ...
987!> \param mat_chi_Gamma_tau ...
988!> \param mat_phi_mu_l ...
989!> \param mat_Z_lP ...
990! **************************************************************************************************
991
992 SUBROUTINE get_mat_chi_gamma_tau(bs_env, mat_chi_Gamma_tau, mat_phi_mu_l, mat_Z_lP)
993
994 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
995 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_gamma_tau
996 TYPE(dbcsr_type), INTENT(INOUT) :: mat_phi_mu_l, mat_z_lp
997
998 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_mat_chi_Gamma_tau'
999
1000 INTEGER :: handle, i, i_t, ispin, npcol
1001 INTEGER, DIMENSION(:), POINTER :: blk_ao, blk_grid, dist_col_grid, &
1002 dist_row_grid
1003 REAL(kind=dp) :: t1, tau
1004 TYPE(dbcsr_distribution_type) :: dist_grid_grid, dist_phi
1005 TYPE(dbcsr_type) :: matrix_chi_grid, matrix_chi_grid_spin, &
1006 matrix_g_occ_grid, matrix_g_vir_grid
1007
1008 CALL timeset(routinen, handle)
1009
1010 ! =========================================================================
1011 ! 1. SETUP CORE TOPOLOGIES
1012 ! =========================================================================
1013 CALL dbcsr_get_info(mat_phi_mu_l, distribution=dist_phi, row_blk_size=blk_grid, col_blk_size=blk_ao)
1014 CALL dbcsr_distribution_get(dist_phi, row_dist=dist_row_grid, npcols=npcol)
1015
1016 ! Build a perfectly safe column distribution for the Grid dimension
1017 ALLOCATE (dist_col_grid(SIZE(blk_grid)))
1018 DO i = 1, SIZE(blk_grid)
1019 dist_col_grid(i) = mod(i - 1, npcol)
1020 END DO
1021
1022 CALL dbcsr_distribution_new(dist_grid_grid, template=dist_phi, &
1023 row_dist=dist_row_grid, col_dist=dist_col_grid)
1024
1025 CALL dbcsr_create(matrix_g_occ_grid, "G_occ_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1026 CALL dbcsr_create(matrix_g_vir_grid, "G_vir_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1027 CALL dbcsr_create(matrix_chi_grid, "chi_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1028 CALL dbcsr_create(matrix_chi_grid_spin, "chi_grid_spin", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1029
1030 ! =========================================================================
1031 ! 2. MAIN IMAGINARY TIME LOOP
1032 ! =========================================================================
1033 DO i_t = 1, bs_env%num_time_freq_points
1034 t1 = m_walltime()
1035
1036 tau = bs_env%time_frequency_grid%imaginary_time(i_t)
1037 CALL dbcsr_set(matrix_chi_grid, 0.0_dp)
1038
1039 ! ----------------------------------------------------------------------
1040 ! A. SPIN LOOP (Allocations safely encapsulated in wrappers)
1041 ! ----------------------------------------------------------------------
1042 DO ispin = 1, bs_env%n_spin
1043
1044 ! G^occ_µλ(i|τ|,k=0) = sum_n^occ C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
1045 ! G^occ_ll'(i|τ|,k=0) = sum_µν ϕ_µ(r_l) G^occ_µν ϕ_ν(r_l')
1046 CALL build_g_grid(bs_env, tau, ispin, .true., .false., mat_phi_mu_l, &
1047 matrix_g_occ_grid, bs_env%eps_filter)
1048
1049 ! G^vir_µλ(i|τ|,k=0) = sum_n^vir C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
1050 ! G^vir_ll'(i|τ|,k=0) = sum_µν ϕ_µ(r_l) G^vir_µν ϕ_ν(r_l')
1051 CALL build_g_grid(bs_env, tau, ispin, .false., .true., mat_phi_mu_l, &
1052 matrix_g_vir_grid, bs_env%eps_filter)
1053
1054 ! -------------------------------------------------------------------
1055 ! B. ELEMENT-WISE HADAMARD PRODUCT
1056 ! -------------------------------------------------------------------
1057 ! χ_ll'(iτ,k=0) = G^occ_ll'(i|τ|,k=0) * G^vir_ll'(i|τ|,k=0)
1058 CALL hadamard_product(matrix_g_occ_grid, matrix_g_vir_grid, matrix_chi_grid_spin, bs_env%spin_degeneracy)
1059
1060 ! Accumulate spin contributions
1061 CALL dbcsr_add(matrix_chi_grid, matrix_chi_grid_spin, 1.0_dp, 1.0_dp)
1062
1063 END DO ! ispin
1064
1065 ! ----------------------------------------------------------------------
1066 ! C. TRANSFORM TO AUXILIARY BASIS & EXPORT DIRECTLY
1067 ! χ_aux = Z^T * χ_grid * Z
1068 ! χ_PQ(iτ,k=0) = sum_ll' Z_lP χ_ll'(iτ,k=0) Z_l'Q
1069 ! Result is dumped directly into the final array mat_chi_Gamma_tau!
1070 ! ----------------------------------------------------------------------
1071 CALL dbcsr_contract_aba("T", "N", mat_z_lp, matrix_chi_grid, &
1072 mat_chi_gamma_tau(i_t)%matrix, bs_env%eps_filter)
1073
1074 IF (bs_env%unit_nr > 0) THEN
1075 WRITE (bs_env%unit_nr, '(T2,A,I13,A,I3,A,F7.1,A)') &
1076 'Computed χ(iτ,k=0) for time point', i_t, ' /', bs_env%num_time_freq_points, &
1077 ', Execution time', m_walltime() - t1, ' s'
1078 END IF
1079
1080 END DO ! i_t
1081
1082 ! =========================================================================
1083 ! 3. FINAL CLEANUP
1084 ! =========================================================================
1085 CALL dbcsr_release(matrix_g_occ_grid)
1086 CALL dbcsr_release(matrix_g_vir_grid)
1087 CALL dbcsr_release(matrix_chi_grid)
1088 CALL dbcsr_release(matrix_chi_grid_spin)
1089 CALL dbcsr_distribution_release(dist_grid_grid)
1090 DEALLOCATE (dist_col_grid)
1091
1092 IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
1093
1094 CALL timestop(handle)
1095
1096 END SUBROUTINE get_mat_chi_gamma_tau
1097
1098! **************************************************************************************************
1099!> \brief Computes Green's Function in grid basis
1100!> \param bs_env ...
1101!> \param tau ...
1102!> \param ispin ...
1103!> \param occ ...
1104!> \param vir ...
1105!> \param mat_phi_mu_l ...
1106!> \param matrix_G_grid ...
1107!> \param eps_filter ...
1108! **************************************************************************************************
1109
1110 SUBROUTINE build_g_grid(bs_env, tau, ispin, occ, vir, mat_phi_mu_l, matrix_G_grid, eps_filter)
1111
1112 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1113 REAL(kind=dp), INTENT(IN) :: tau
1114 INTEGER, INTENT(IN) :: ispin
1115 LOGICAL, INTENT(IN) :: occ, vir
1116 TYPE(dbcsr_type), INTENT(INOUT) :: mat_phi_mu_l, matrix_g_grid
1117 REAL(kind=dp), INTENT(IN) :: eps_filter
1118
1119 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_G_grid'
1120
1121 INTEGER :: handle
1122 INTEGER, DIMENSION(:), POINTER :: blk_ao, dist_row_ao
1123 TYPE(cp_fm_type), POINTER :: fm_g
1124 TYPE(dbcsr_distribution_type) :: dist_ao_ao
1125 TYPE(dbcsr_type) :: matrix_g_ao
1126
1127 CALL timeset(routinen, handle)
1128
1129 ! 1. Select the correct FM matrix based on occ/vir flags
1130 IF (occ) THEN
1131 fm_g => bs_env%fm_Gocc
1132 ELSE
1133 fm_g => bs_env%fm_Gvir
1134 END IF
1135
1136 ! 2. Compute Dense FM Green's Function
1137 ! G^occ/vir_µλ(i|τ|,k=0) = sum_G^occ/vir_µλn^occ/vir C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
1138 CALL g_occ_vir(bs_env, tau, fm_g, ispin, occ=occ, vir=vir)
1139
1140 ! 3. Setup AO DBCSR Topology and Create Matrix dynamically
1141 CALL setup_square_topology(mat_phi_mu_l, 'COL', dist_ao_ao, blk_ao, dist_row_ao)
1142
1143 CALL dbcsr_create(matrix_g_ao, name="G_ao", dist=dist_ao_ao, &
1144 matrix_type=dbcsr_type_no_symmetry, &
1145 row_blk_size=blk_ao, col_blk_size=blk_ao)
1146
1147 ! 4. Convert FM to Sparse DBCSR
1148 CALL copy_fm_to_dbcsr(fm_g, matrix_g_ao, keep_sparsity=.false.)
1149
1150 ! 5. Transform to Grid Basis: G_grid = phi * G_ao * phi^T
1151 ! G^occ/vir_ll'(i|τ|,k=0) = sum_µν ϕ_µ(r_l) G^occ/vir_µν ϕ_ν(r_l')
1152 CALL dbcsr_contract_aba("N", "T", mat_phi_mu_l, matrix_g_ao, matrix_g_grid, &
1153 eps_filter)
1154
1155 ! 6. Release AO matrix and topology
1156 CALL release_dbcsr_topology_and_matrices(dist=dist_ao_ao, mapped_dist=dist_row_ao, m1=matrix_g_ao)
1157
1158 CALL timestop(handle)
1159
1160 END SUBROUTINE build_g_grid
1161
1162! **************************************************************************************************
1163!> \brief Computes the exact exchange part of the GW self-energy
1164!> \param bs_env ...
1165!> \param qs_env ...
1166!> \param mat_phi_mu_l ...
1167!> \param mat_Z_lP ...
1168!> \param fm_Sigma_x_Gamma ...
1169! **************************************************************************************************
1170
1171 SUBROUTINE compute_sigma_x(bs_env, qs_env, mat_phi_mu_l, mat_Z_lP, fm_Sigma_x_Gamma)
1172
1173 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1174 TYPE(qs_environment_type), POINTER :: qs_env
1175 TYPE(dbcsr_type), INTENT(INOUT) :: mat_phi_mu_l, mat_z_lp
1176 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_sigma_x_gamma
1177
1178 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_Sigma_x'
1179
1180 INTEGER :: handle, ispin
1181 INTEGER, DIMENSION(:), POINTER :: blk_aux, blk_grid, dist_col_grid, &
1182 dist_row_aux
1183 REAL(kind=dp) :: t1
1184 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: fm_vtr_gamma
1185 TYPE(dbcsr_distribution_type) :: dist_aux_aux, dist_grid_grid
1186 TYPE(dbcsr_type) :: mat_sigma_x_gamma, matrix_d_grid, &
1187 matrix_sigma_x_grid, matrix_v_aux, &
1188 matrix_v_grid
1189
1190 CALL timeset(routinen, handle)
1191
1192 t1 = m_walltime()
1193
1194 ALLOCATE (fm_sigma_x_gamma(bs_env%n_spin))
1195 DO ispin = 1, bs_env%n_spin
1196 CALL cp_fm_create(fm_sigma_x_gamma(ispin), bs_env%fm_s_Gamma%matrix_struct)
1197 END DO
1198
1199 CALL dbcsr_create(mat_sigma_x_gamma, template=bs_env%mat_ao_ao%matrix)
1200
1201 ! =========================================================================
1202 ! 1. SETUP CORE TOPOLOGIES
1203 ! =========================================================================
1204 CALL setup_square_topology(mat_phi_mu_l, 'ROW', dist_grid_grid, blk_grid, dist_col_grid)
1205 CALL setup_square_topology(mat_z_lp, 'COL', dist_aux_aux, blk_aux, dist_row_aux)
1206
1207 ! =========================================================================
1208 ! 2. COMPUTE V^tr_ll'
1209 ! =========================================================================
1210 CALL ri_2c_integral_mat(qs_env, fm_vtr_gamma, bs_env%fm_RI_RI%matrix_struct, bs_env%n_RI, &
1211 bs_env%trunc_coulomb)
1212
1213 ! M^-1(k=0) V^tr(τ) M^-1(k=0) -> fm_Vtr_Gamma
1214 CALL fm_contract_aba(bs_env%fm_Minv_Gamma, fm_vtr_gamma(:, 1))
1215
1216 CALL dbcsr_create(matrix_v_aux, "V_aux", dist_aux_aux, dbcsr_type_no_symmetry, blk_aux, blk_aux)
1217 CALL dbcsr_create(matrix_v_grid, "V_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1218
1219 CALL copy_fm_to_dbcsr(fm_vtr_gamma(1, 1), matrix_v_aux, keep_sparsity=.false.)
1220
1221 ! V^tr_ll' = sum_PQ Z_lP V^trunc_PQ Z_l'Q
1222 CALL dbcsr_contract_aba("N", "T", mat_z_lp, matrix_v_aux, matrix_v_grid, &
1223 bs_env%eps_filter)
1224 CALL dbcsr_release(matrix_v_aux)
1225
1226 ! =========================================================================
1227 ! 3. SPIN LOOP FOR EXACT EXCHANGE
1228 ! =========================================================================
1229 DO ispin = 1, bs_env%n_spin
1230
1231 ! Density matrix on grid is essentially G_occ at tau = 0.0
1232 ! D_µν = sum_n^occ C_µn(k=0) C_νn(k=0)
1233 ! D_ll' = sum_µν ϕ_µ(r_l) D_µν ϕ_ν(r_l')
1234 CALL dbcsr_create(matrix_d_grid, "D_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1235 CALL build_g_grid(bs_env, 0.0_dp, ispin, .true., .false., mat_phi_mu_l, matrix_d_grid, bs_env%eps_filter)
1236
1237 ! Element-wise Hadamard product: Σ^x_grid = D_grid ◦ V_grid
1238 ! Σ^x_ll' = D_ll' * V^tr_ll'
1239 CALL dbcsr_create(matrix_sigma_x_grid, template=matrix_v_grid)
1240 CALL hadamard_product(matrix_d_grid, matrix_v_grid, matrix_sigma_x_grid, 1.0_dp)
1241
1242 CALL dbcsr_release(matrix_d_grid)
1243
1244 ! Transform back to AO basis: Σ^x_ao = -1.0 * phi^T * Σ^x_grid * phi
1245 ! Σ^x_λσ(k=0) = -sum_ll' ϕ_λ(r_l) Σ^x_ll' ϕ_σ(r_l')
1246 CALL dbcsr_contract_aba("T", "N", mat_phi_mu_l, matrix_sigma_x_grid, &
1247 mat_sigma_x_gamma, bs_env%eps_filter)
1248 CALL dbcsr_scale(mat_sigma_x_gamma, -1.0_dp)
1249
1250 CALL dbcsr_release(matrix_sigma_x_grid)
1251
1252 ! Data I/O and Export to CP2K Full Matrices
1253 CALL copy_dbcsr_to_fm(mat_sigma_x_gamma, fm_sigma_x_gamma(ispin))
1254
1255 END DO ! ispin
1256
1257 IF (bs_env%unit_nr > 0) THEN
1258 WRITE (bs_env%unit_nr, '(T2,A,T58,A,F7.1,A)') &
1259 'Computed Σ^x(k=0),', ' Execution time', m_walltime() - t1, ' s'
1260 WRITE (bs_env%unit_nr, '(A)') ' '
1261 END IF
1262
1263 ! =========================================================================
1264 ! 4. CLEANUP
1265 ! =========================================================================
1266 CALL release_dbcsr_topology_and_matrices(dist=dist_grid_grid, mapped_dist=dist_col_grid, &
1267 m1=mat_sigma_x_gamma, m2=matrix_v_grid)
1268 CALL release_dbcsr_topology_and_matrices(dist=dist_aux_aux, mapped_dist=dist_row_aux)
1269
1270 CALL cp_fm_release(fm_vtr_gamma)
1271
1272 CALL timestop(handle)
1273
1274 END SUBROUTINE compute_sigma_x
1275
1276! **************************************************************************************************
1277!> \brief Computes the correlation part of the GW self-energy
1278!> \param bs_env ...
1279!> \param fm_W_time ...
1280!> \param mat_phi_mu_l ...
1281!> \param mat_Z_lP ...
1282!> \param fm_Sigma_c_Gamma_time ...
1283! **************************************************************************************************
1284
1285 SUBROUTINE compute_sigma_c(bs_env, fm_W_time, mat_phi_mu_l, mat_Z_lP, fm_Sigma_c_Gamma_time)
1286
1287 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1288 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_w_time
1289 TYPE(dbcsr_type), INTENT(INOUT) :: mat_phi_mu_l, mat_z_lp
1290 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: fm_sigma_c_gamma_time
1291
1292 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_Sigma_c'
1293
1294 INTEGER :: handle, i_t, ispin
1295 INTEGER, DIMENSION(:), POINTER :: blk_aux, blk_grid, dist_col_grid, &
1296 dist_row_aux
1297 REAL(kind=dp) :: t1, tau
1298 TYPE(dbcsr_distribution_type) :: dist_aux_aux, dist_grid_grid
1299 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_sigma_neg_tau, mat_sigma_pos_tau
1300 TYPE(dbcsr_type) :: matrix_g_occ_grid, matrix_g_vir_grid, matrix_sigma_neg_grid, &
1301 matrix_sigma_pos_grid, matrix_w_aux, matrix_w_grid
1302
1303 CALL timeset(routinen, handle)
1304
1305 ! =========================================================================
1306 ! 1. SETUP CORE TOPOLOGIES AND PRE-ALLOCATE OUTPUT ARRAYS
1307 ! =========================================================================
1308 CALL setup_square_topology(mat_phi_mu_l, 'ROW', dist_grid_grid, blk_grid, dist_col_grid)
1309 CALL setup_square_topology(mat_z_lp, 'COL', dist_aux_aux, blk_aux, dist_row_aux)
1310
1311 ! Pre-allocate local DBCSR matrices to act as targets for final output
1312 NULLIFY (mat_sigma_neg_tau, mat_sigma_pos_tau)
1313 ALLOCATE (mat_sigma_neg_tau(bs_env%num_time_freq_points, bs_env%n_spin))
1314 ALLOCATE (mat_sigma_pos_tau(bs_env%num_time_freq_points, bs_env%n_spin))
1315
1316 DO i_t = 1, bs_env%num_time_freq_points
1317 DO ispin = 1, bs_env%n_spin
1318 ALLOCATE (mat_sigma_neg_tau(i_t, ispin)%matrix)
1319 ALLOCATE (mat_sigma_pos_tau(i_t, ispin)%matrix)
1320 CALL dbcsr_create(mat_sigma_neg_tau(i_t, ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
1321 CALL dbcsr_create(mat_sigma_pos_tau(i_t, ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
1322 END DO
1323 END DO
1324
1325 ! =========================================================================
1326 ! 2. MAIN IMAGINARY TIME LOOP
1327 ! =========================================================================
1328 DO i_t = 1, bs_env%num_time_freq_points
1329 tau = bs_env%time_frequency_grid%imaginary_time(i_t)
1330
1331 ! -------------------------------------------------------------------
1332 ! Compute W_grid = Z * W_aux * Z^T
1333 ! -------------------------------------------------------------------
1334 CALL dbcsr_create(matrix_w_aux, "W_aux", dist_aux_aux, dbcsr_type_no_symmetry, blk_aux, blk_aux)
1335 CALL dbcsr_create(matrix_w_grid, "W_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1336
1337 CALL copy_fm_to_dbcsr(fm_w_time(i_t), matrix_w_aux, keep_sparsity=.false.)
1338
1339 ! W^MIC_ll'(iτ,k=0) = sum_PQ Z_lP W^MIC_PQ(iτ) Z_l'Q
1340 CALL dbcsr_contract_aba("N", "T", mat_z_lp, matrix_w_aux, matrix_w_grid, &
1341 bs_env%eps_filter)
1342
1343 CALL dbcsr_release(matrix_w_aux) ! Clean up aux basis immediately
1344
1345 DO ispin = 1, bs_env%n_spin
1346 t1 = m_walltime()
1347
1348 ! -------------------------------------------------------------------
1349 ! A. Transform Green's Functions to the Grid
1350 ! -------------------------------------------------------------------
1351 CALL dbcsr_create(matrix_g_occ_grid, "G_occ_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1352 CALL dbcsr_create(matrix_g_vir_grid, "G_vir_grid", dist_grid_grid, dbcsr_type_no_symmetry, blk_grid, blk_grid)
1353
1354 ! G^occ_µλ(i|τ|,k=0) = sum_G^occ_µλn^occ C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
1355 ! G^occ_ll'(i|τ|,k=0) = sum_µν ϕ_µ(r_l) G^occ_µν ϕ_ν(r_l')
1356 CALL build_g_grid(bs_env, tau, ispin, .true., .false., mat_phi_mu_l, matrix_g_occ_grid, bs_env%eps_filter)
1357
1358 ! G^vir_µλ(i|τ|,k=0) = sum_n^vir C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
1359 ! G^vir_ll'(i|τ|,k=0) = sum_µν ϕ_µ(r_l) G^vir_µν ϕ_ν(r_l')
1360 CALL build_g_grid(bs_env, tau, ispin, .false., .true., mat_phi_mu_l, matrix_g_vir_grid, bs_env%eps_filter)
1361
1362 ! -------------------------------------------------------------------
1363 ! B. Element-wise Hadamard Products for Sigma_c on Grid
1364 ! Σ_neg_grid = G_occ_grid ◦ W_grid
1365 ! Σ_pos_grid = G_vir_grid ◦ W_grid
1366 ! -------------------------------------------------------------------
1367 CALL dbcsr_create(matrix_sigma_neg_grid, template=matrix_w_grid)
1368 CALL dbcsr_create(matrix_sigma_pos_grid, template=matrix_w_grid)
1369
1370 ! Σ^c_ll'(iτ,k=0) = -G^occ_ll'(i|τ|,k=0) * W^MIC_ll'(iτ,k=0), for τ < 0
1371 CALL hadamard_product(matrix_g_occ_grid, matrix_w_grid, matrix_sigma_neg_grid, 1.0_dp)
1372
1373 ! Σ^c_ll'(iτ,k=0) = G^vir_ll'(i|τ|,k=0) * W^MIC_ll'(iτ,k=0), for τ > 0
1374 CALL hadamard_product(matrix_g_vir_grid, matrix_w_grid, matrix_sigma_pos_grid, 1.0_dp)
1375
1376 ! Instantly purge massive G_grid arrays to save memory
1377 CALL dbcsr_release(matrix_g_occ_grid)
1378 CALL dbcsr_release(matrix_g_vir_grid)
1379
1380 ! -------------------------------------------------------------------
1381 ! C. Transform Sigma back to AO Basis
1382 ! Σ_AO = phi^T * Σ_grid * phi
1383 ! -------------------------------------------------------------------
1384
1385 ! Σ^c_λσ(iτ,k=0) = sum_ll' ϕ_λ(r_l) Σ^c_ll'(iτ,k=0) ϕ_σ(r_l'), for τ < 0
1386 CALL dbcsr_contract_aba("T", "N", mat_phi_mu_l, matrix_sigma_neg_grid, &
1387 mat_sigma_neg_tau(i_t, ispin)%matrix, bs_env%eps_filter)
1388 CALL dbcsr_scale(mat_sigma_neg_tau(i_t, ispin)%matrix, -1.0_dp)
1389
1390 ! Σ^c_λσ(iτ,k=0) = sum_ll' ϕ_λ(r_l) Σ^c_ll'(iτ,k=0) ϕ_σ(r_l'), for τ > 0
1391 CALL dbcsr_contract_aba("T", "N", mat_phi_mu_l, matrix_sigma_pos_grid, &
1392 mat_sigma_pos_tau(i_t, ispin)%matrix, bs_env%eps_filter)
1393
1394 ! Purge Grid Sigma arrays
1395 CALL dbcsr_release(matrix_sigma_neg_grid)
1396 CALL dbcsr_release(matrix_sigma_pos_grid)
1397
1398 IF (bs_env%unit_nr > 0) THEN
1399 WRITE (bs_env%unit_nr, '(T2,A,I10,A,I3,A,F7.1,A)') &
1400 'Computed Σ^c(iτ,k=0) for time point ', i_t, ' /', bs_env%num_time_freq_points, &
1401 ', Execution time', m_walltime() - t1, ' s'
1402 END IF
1403
1404 END DO ! ispin
1405
1406 ! Release the W_grid for this time point
1407 CALL dbcsr_release(matrix_w_grid)
1408
1409 END DO ! i_t
1410
1411 IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
1412
1413 ! -------------------------------------------------------------------------
1414 ! 3. FINALIZE AND CLEANUP
1415 ! -------------------------------------------------------------------------
1416 CALL fill_fm_sigma_c_gamma_time(fm_sigma_c_gamma_time, bs_env, &
1417 mat_sigma_pos_tau, mat_sigma_neg_tau)
1418
1419 CALL cp_fm_release(fm_w_time)
1420
1421 CALL dbcsr_deallocate_matrix_set(mat_sigma_neg_tau)
1422 CALL dbcsr_deallocate_matrix_set(mat_sigma_pos_tau)
1423
1424 CALL release_dbcsr_topology_and_matrices(dist=dist_grid_grid, mapped_dist=dist_col_grid)
1425 CALL release_dbcsr_topology_and_matrices(dist=dist_aux_aux, mapped_dist=dist_row_aux)
1426
1427 CALL delete_unnecessary_files(bs_env)
1428 CALL timestop(handle)
1429
1430 END SUBROUTINE compute_sigma_c
1431
1432! **************************************************************************************************
1433!> \brief DBCSR Topology Generation
1434!> \param matrix_template ...
1435!> \param dim_type ...
1436!> \param square_dist ...
1437!> \param blk_sizes ...
1438!> \param mapped_dist ...
1439! **************************************************************************************************
1440
1441 SUBROUTINE setup_square_topology(matrix_template, dim_type, square_dist, blk_sizes, mapped_dist)
1442
1443 TYPE(dbcsr_type), INTENT(IN) :: matrix_template
1444 CHARACTER(LEN=*), INTENT(IN) :: dim_type
1445 TYPE(dbcsr_distribution_type), INTENT(OUT) :: square_dist
1446 INTEGER, DIMENSION(:), INTENT(OUT), POINTER :: blk_sizes, mapped_dist
1447
1448 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_square_topology'
1449
1450 INTEGER :: handle, i, np, npcols, nprows
1451 INTEGER, DIMENSION(:), POINTER :: col_blk, col_dist, row_blk, row_dist
1452 TYPE(dbcsr_distribution_type) :: dist_template
1453
1454 CALL timeset(routinen, handle)
1455
1456 CALL dbcsr_get_info(matrix_template, distribution=dist_template, &
1457 row_blk_size=row_blk, col_blk_size=col_blk)
1458 CALL dbcsr_distribution_get(dist_template, row_dist=row_dist, col_dist=col_dist, &
1459 nprows=nprows, npcols=npcols)
1460
1461 IF (trim(dim_type) == 'ROW') THEN
1462 ! Creates ROW x ROW (e.g., Grid x Grid from mat_phi_mu_l)
1463 blk_sizes => row_blk
1464 np = npcols
1465 ALLOCATE (mapped_dist(SIZE(blk_sizes)))
1466 DO i = 1, SIZE(blk_sizes)
1467 mapped_dist(i) = mod(i - 1, np)
1468 END DO
1469 CALL dbcsr_distribution_new(square_dist, template=dist_template, &
1470 row_dist=row_dist, col_dist=mapped_dist)
1471
1472 ELSE IF (trim(dim_type) == 'COL') THEN
1473 ! Creates COL x COL (e.g., Aux x Aux from mat_Z_lP)
1474 blk_sizes => col_blk
1475 np = nprows
1476 ALLOCATE (mapped_dist(SIZE(blk_sizes)))
1477 DO i = 1, SIZE(blk_sizes)
1478 mapped_dist(i) = mod(i - 1, np)
1479 END DO
1480 CALL dbcsr_distribution_new(square_dist, template=dist_template, &
1481 row_dist=mapped_dist, col_dist=col_dist)
1482 END IF
1483
1484 CALL timestop(handle)
1485
1486 END SUBROUTINE setup_square_topology
1487
1488! **************************************************************************************************
1489!> \brief DBCSR matrices deallocation
1490!> \param dist ...
1491!> \param mapped_dist ...
1492!> \param m1 ...
1493!> \param m2 ...
1494!> \param m3 ...
1495!> \param m4 ...
1496! **************************************************************************************************
1497
1498 SUBROUTINE release_dbcsr_topology_and_matrices(dist, mapped_dist, m1, m2, m3, m4)
1499
1500 TYPE(dbcsr_distribution_type), INTENT(INOUT), &
1501 OPTIONAL :: dist
1502 INTEGER, DIMENSION(:), INTENT(INOUT), OPTIONAL, &
1503 POINTER :: mapped_dist
1504 TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL :: m1, m2, m3, m4
1505
1506 CHARACTER(LEN=*), PARAMETER :: routinen = 'release_dbcsr_topology_and_matrices'
1507
1508 INTEGER :: handle
1509
1510 CALL timeset(routinen, handle)
1511
1512 IF (PRESENT(dist)) CALL dbcsr_distribution_release(dist)
1513 IF (PRESENT(mapped_dist)) THEN
1514 IF (ASSOCIATED(mapped_dist)) THEN
1515 DEALLOCATE (mapped_dist)
1516 NULLIFY (mapped_dist)
1517 END IF
1518 END IF
1519 IF (PRESENT(m1)) CALL dbcsr_release(m1)
1520 IF (PRESENT(m2)) CALL dbcsr_release(m2)
1521 IF (PRESENT(m3)) CALL dbcsr_release(m3)
1522 IF (PRESENT(m4)) CALL dbcsr_release(m4)
1523
1524 CALL timestop(handle)
1525
1527
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Define the atomic kind types and their sub types.
Handles all functions related to the CELL.
Definition cell_types.F:15
subroutine, public get_cell(cell, alpha, beta, gamma, deth, orthorhombic, abc, periodic, h, h_inv, symmetry_id, tag)
Get informations about a simulation cell.
Definition cell_types.F:233
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_release(blacs_env)
releases the given blacs_env
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
subroutine, public dbcsr_distribution_release(dist)
...
subroutine, public dbcsr_scale(matrix, alpha_scalar)
...
subroutine, public dbcsr_distribution_new(dist, template, group, pgrid, row_dist, col_dist, reuse_arrays)
...
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_binary_write(matrix, filepath)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_binary_read(filepath, distribution, matrix_new)
...
subroutine, public dbcsr_put_block(matrix, row, col, block, summation)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
subroutine, public dbcsr_distribution_get(dist, row_dist, col_dist, nrows, ncols, has_threads, group, mynode, numnodes, nprows, npcols, myprow, mypcol, pgrid, subgroups_defined, prow_group, pcol_group)
...
DBCSR operations in CP2K.
integer, save, public max_elements_per_block
subroutine, public copy_dbcsr_to_fm(matrix, fm, plan)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
represent the structure of a full matrix
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer, parameter, public cp_p_file
integer function, public cp_print_key_should_output(iteration_info, basis_section, print_key_path, used_print_key, first_time)
returns what should be done with the given property if btest(res,cp_p_store) then the property should...
Shared numerical operations for computing the RI-RS matrix Z_lP.
subroutine, public build_gram_jacobi_blas(phi_local, n_local_grid, n_ao_used, tikhonov, d_local, d_vec_local)
Forms the conditioned dense RI-RS matrix.
subroutine, public scale_rows_by_diag(matrix, diagonal, nrow, ncol)
Multiplies every matrix row by the corresponding diagonal entry: A(l, :) <- d_l A(l,...
subroutine, public build_jacobi_diag_from_phi(phi_local, n_local_grid, n_ao_used, d_vec_local)
Computes d_l = 1/sqrt(D_ll) = 1/Σ_μ ϕ_μ(r_l)² without forming D.
subroutine, public solve_d_lp_distributed(phi_local, d_vec, d_lp, n_loc, n_ao, n_rhs, tikhonov, para_env_sub, blacs_env_sub, fm_struct_d, fm_struct_b, fm_d, fm_b, info)
Solves D Z = d with ScaLAPACK for one RI atom and replicated inputs.
subroutine, public store_z_lp_columns(mat_z_lp, z_local, local_grid_idx, n_local_grid, n_loc_ri, atom_p, r_blk_sizes, row_offset, eps_filter)
Stores dense Z_lP columns in the distributed block-sparse matrix.
Main setup file for RI-RS grids {r_l}.
subroutine, public setup_ri_rs_grid(bs_env, grid_points)
Get RI-RS grid points {r_l}, either by on-the-fly optimization or reading pretabulated atomic grids.
GW using RI-RS Approximation for molecules.
subroutine, public gw_calc_ri_rs_large_cell_gamma(qs_env, bs_env)
GW calculation using RI-RS formalism for molecules.
subroutine, public setup_square_topology(matrix_template, dim_type, square_dist, blk_sizes, mapped_dist)
DBCSR Topology Generation.
subroutine, public release_dbcsr_topology_and_matrices(dist, mapped_dist, m1, m2, m3, m4)
DBCSR matrices deallocation.
Common setup operations used by the periodic and non-periodic GW RI-RS implementations.
subroutine, public precompute_ri_rs_radii(bs_env)
Compute per-atom AO and RI basis radii from the most diffuse Gaussian primitive in the AO ("ORB") and...
Routines from paper [Graml2024].
subroutine, public compute_qp_energies(bs_env, qs_env, fm_sigma_x_gamma, fm_sigma_c_gamma_time)
...
subroutine, public fill_fm_sigma_c_gamma_time(fm_sigma_c_gamma_time, bs_env, mat_sigma_pos_tau, mat_sigma_neg_tau)
...
subroutine, public g_occ_vir(bs_env, tau, fm_g_gamma, ispin, occ, vir)
...
subroutine, public get_w_mic(bs_env, qs_env, mat_chi_gamma_tau, fm_w_mic_time)
...
subroutine, public delete_unnecessary_files(bs_env)
...
Utility method to build 3-center integrals for small cell GW.
subroutine, public gw_3c_ws_create(ws, ctx)
Creates a per-thread 3c workspace: libint object + LIBXSMM contraction buffers.
subroutine, public build_3c_integral_block_ctx(int_3c, ctx, ws, atom_j, atom_k, atom_i, cell_j, cell_k, cell_i, j_offset, k_offset, i_offset, screened)
Computes the 3c integral block (mu(atom_j) nu(atom_k) | P(atom_i)) for ONE atom triple,...
subroutine, public gw_3c_ctx_release(ctx)
Releases the shared 3c-integral context.
subroutine, public gw_3c_ws_release(ws)
Releases a per-thread 3c workspace.
subroutine, public gw_3c_ctx_create(ctx, bs_env, potential_parameter, basis_j, basis_k, basis_i)
Build the shared 3c-integral context from the band-structure environment and explicitly supplied pote...
Common DBCSR matrix operations used by GW modules.
subroutine, public hadamard_product(matrix_a, matrix_b, matrix_c, factor)
Computes the scaled element-wise product C = factor (A ◦ B) while preserving the block structure of A...
subroutine, public dbcsr_contract_aba(trans_a_left, trans_a_right, matrix_a, matrix_b, matrix_c, eps_filter, retain_sparsity)
Computes C=A B A^T or C=A^T B A for DBCSR matrices.
Full-matrix operations not provided by the CP2K FM packages.
Definition gw_utils_fm.F:13
subroutine, public de_init_bs_env(qs_env, bs_env)
Releases the memory-heavy GW intermediates that cannot be freed in bs_env_release,...
Definition gw_utils.F:3411
objects that represent the structure of input sections and the data contained in an input section
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:141
Interface to the message passing library MPI.
Framework for 2c-integrals for RI.
Definition mp2_ri_2c.F:14
subroutine, public ri_2c_integral_mat(qs_env, fm_matrix_minv_l_gamma, fm_matrix_l_struct, dimen_ri, ri_metric, put_mat_ks_env, regularization_ri)
...
Definition mp2_ri_2c.F:578
Provides Cartesian and spherical orbital pointers and indices.
integer, dimension(:), allocatable, public ncoset
integer, dimension(:, :), allocatable, public indco
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, mimic, 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, sab_cneo, 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, matrix_vhxc, 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, xcint_weights, 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, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_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, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
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
type of a logger, at the moment it contains just a print level starting at which level it should be l...
Shared read-only context for repeated 3-center integral block builds: screening parameters,...
Per-thread workspace for 3-center integral block builds: libint object + contraction buffers....
stores all the informations relevant to an mpi environment