(git:6344619)
Loading...
Searching...
No Matches
ri_rs_matrices.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 DBCSR collocation, layouts and panel contractions for real-space resolution of the identity.
10! **************************************************************************************************
14 USE cp_dbcsr_api, ONLY: &
20 dbcsr_type_no_symmetry
23 USE cp_fm_types, ONLY: cp_fm_create,&
30 USE kinds, ONLY: dp,&
31 int_8,&
33 USE libint_2c_3c, ONLY: libint_potential_type
34 USE machine, ONLY: m_flush
39 USE ri_rs_types, ONLY: ri_rs_env
41#include "./base/base_uses.f90"
42
43 IMPLICIT NONE
44 PRIVATE
51
52 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ri_rs_matrices'
53
54CONTAINS
55
56! **************************************************************************************************
57!> \brief Builds the grid-by-AO collocation matrix with bounded dense evaluation panels.
58!> The molecular path uses atom-aligned row blocks and minimum-image AO values.
59!> The Gamma path uses uniform row blocks and sums neighbouring periodic images.
60!> \param ri_rs grid, borrowed geometry references and output collocation matrix
61!> \param basis_set_AO AO basis sets, one per atomic kind
62!> \param matrix_template template for the process grid and AO column block sizes
63!> \param para_env parallel environment
64!> \param eps_filter block screening threshold
65!> \param msg_elem_limit maximum number of elements per DBCSR message
66!> \param unit_nr output unit
67!> \param periodic_images select neighbouring-image summation for Gamma
68! **************************************************************************************************
69 SUBROUTINE atomic_basis_at_grid_point(ri_rs, basis_set_AO, matrix_template, &
70 para_env, eps_filter, msg_elem_limit, unit_nr, periodic_images)
71 TYPE(ri_rs_env), INTENT(INOUT) :: ri_rs
72 TYPE(gto_basis_set_p_type), INTENT(IN) :: basis_set_ao(:)
73 TYPE(dbcsr_type), INTENT(IN) :: matrix_template
74 TYPE(mp_para_env_type), POINTER :: para_env
75 REAL(kind=dp), INTENT(IN) :: eps_filter
76 INTEGER(KIND=int_8), INTENT(IN) :: msg_elem_limit
77 INTEGER, INTENT(IN) :: unit_nr
78 LOGICAL, INTENT(IN) :: periodic_images
79
80 CHARACTER(LEN=*), PARAMETER :: routinen = 'atomic_basis_at_grid_point'
81 INTEGER, PARAMETER :: grid_panel_size = 4096
82
83 INTEGER :: blocks_per_panel, bs_eff, c_size, first_block, handle, i, i_blk, ia, iatom, &
84 ikind, last_block, n_grid, natom, npcol, nprow, num_grid_chunks, panel_size, panel_start, &
85 r_end, r_start, remaining, row_first, row_last, run, safe_max
86 INTEGER, ALLOCATABLE :: blk_row_start(:)
87 INTEGER, POINTER :: c_blk_sizes(:), col_dist(:), &
88 r_blk_sizes(:), row_dist(:)
89 REAL(kind=dp) :: cutoff_squared
90 REAL(kind=dp), ALLOCATABLE :: atom_col_buffer(:, :)
91 TYPE(dbcsr_distribution_type) :: dist, template_dist
92 TYPE(gto_basis_set_type), POINTER :: ao_basis
93
94 CALL timeset(routinen, handle)
95 cpassert(ASSOCIATED(ri_rs%cell))
96 cpassert(ASSOCIATED(para_env))
97 cpassert(ASSOCIATED(ri_rs%particle_set))
98 CALL dbcsr_get_info(matrix_template, distribution=template_dist, col_blk_size=c_blk_sizes)
99 natom = SIZE(c_blk_sizes)
100 n_grid = SIZE(ri_rs%grid_points, 2)
101 cpassert(SIZE(ri_rs%particle_set) == natom)
102 cpassert(n_grid == ri_rs%n_grid_points)
103 CALL dbcsr_distribution_get(template_dist, nprows=nprow, npcols=npcol)
104
106 IF (.NOT. periodic_images) THEN
107 safe_max = int(msg_elem_limit*max(min(nprow, npcol), 1)/n_grid/2)
108 bs_eff = max(1, min(bs_eff, max(1, safe_max)))
109 END IF
110 IF (periodic_images) THEN
111 num_grid_chunks = n_grid/bs_eff
112 IF (mod(n_grid, bs_eff) /= 0) num_grid_chunks = num_grid_chunks + 1
113 ELSE
114 num_grid_chunks = 0
115 DO ia = 1, natom
116 run = ri_rs%grid_atom_boundaries(ia + 1) - ri_rs%grid_atom_boundaries(ia)
117 IF (run > 0) num_grid_chunks = num_grid_chunks + (run + bs_eff - 1)/bs_eff
118 END DO
119 END IF
120 ALLOCATE (r_blk_sizes(num_grid_chunks), blk_row_start(num_grid_chunks))
121 i_blk = 0
122 r_start = 1
123 DO ia = 1, merge(1, natom, periodic_images)
124 IF (periodic_images) THEN
125 remaining = n_grid
126 ELSE
127 remaining = ri_rs%grid_atom_boundaries(ia + 1) - ri_rs%grid_atom_boundaries(ia)
128 END IF
129 DO WHILE (remaining > 0)
130 i_blk = i_blk + 1
131 r_blk_sizes(i_blk) = min(bs_eff, remaining)
132 blk_row_start(i_blk) = r_start
133 r_start = r_start + r_blk_sizes(i_blk)
134 remaining = remaining - r_blk_sizes(i_blk)
135 END DO
136 END DO
137
138 IF (.NOT. periodic_images) THEN
139 IF (unit_nr > 0) THEN
140 WRITE (unit_nr, '(T2,A,T71,I12)') 'RI-RS grid row-blocks of ϕ_μ(r_l)', num_grid_chunks
141 WRITE (unit_nr, '(T2,A,T69,I12)') 'RI-RS grid points per block (max)', bs_eff
142 END IF
143 IF (ri_rs%cutoff_radius_v_w > 0.0_dp .OR. ri_rs%cutoff_radius_w0 > 0.0_dp) THEN
144 IF (ALLOCATED(ri_rs%chunk_centroids)) DEALLOCATE (ri_rs%chunk_centroids)
145 ALLOCATE (ri_rs%chunk_centroids(3, num_grid_chunks))
146 DO i_blk = 1, num_grid_chunks
147 r_start = blk_row_start(i_blk)
148 r_end = r_start + r_blk_sizes(i_blk) - 1
149 DO i = 1, 3
150 ri_rs%chunk_centroids(i, i_blk) = &
151 sum(ri_rs%grid_points(i, r_start:r_end))/real(r_blk_sizes(i_blk), dp)
152 END DO
153 END DO
154 END IF
155 END IF
156
157 ALLOCATE (row_dist(num_grid_chunks), col_dist(natom))
158 DO i = 1, num_grid_chunks
159 row_dist(i) = mod(i - 1, nprow)
160 END DO
161 DO i = 1, natom
162 col_dist(i) = mod(i - 1, npcol)
163 END DO
164 CALL dbcsr_distribution_new(dist, template=template_dist, row_dist=row_dist, col_dist=col_dist)
165 CALL dbcsr_create(ri_rs%mat_phi_mu_l, name='phi_val_sparse', dist=dist, &
166 matrix_type=dbcsr_type_no_symmetry, row_blk_size=r_blk_sizes, col_blk_size=c_blk_sizes)
167
168 blocks_per_panel = max(1, grid_panel_size/maxval(r_blk_sizes))
169 DO iatom = para_env%mepos + 1, natom, para_env%num_pe
170 c_size = c_blk_sizes(iatom)
171 ALLOCATE (atom_col_buffer(min(n_grid, blocks_per_panel*maxval(r_blk_sizes)), c_size))
172 cutoff_squared = ri_rs%radius_ao_per_atom(iatom)**2
173 IF (.NOT. periodic_images .AND. ri_rs%cutoff_radius_ri_ao > 0.0_dp) THEN
174 cutoff_squared = ri_rs%cutoff_radius_ri_ao**2
175 END IF
176 ikind = ri_rs%particle_set(iatom)%atomic_kind%kind_number
177 ao_basis => basis_set_ao(ikind)%gto_basis_set
178 DO first_block = 1, num_grid_chunks, blocks_per_panel
179 last_block = min(first_block + blocks_per_panel - 1, num_grid_chunks)
180 panel_start = blk_row_start(first_block)
181 panel_size = blk_row_start(last_block) + r_blk_sizes(last_block) - panel_start
182 atom_col_buffer(:panel_size, :) = 0.0_dp
183 CALL evaluate_ao_basis_on_points(atom_col_buffer(:panel_size, :), &
184 ri_rs%grid_points(:, panel_start:panel_start + panel_size - 1), &
185 ao_basis, ri_rs%particle_set(iatom)%r, ri_rs%cell, &
186 cutoff_squared=cutoff_squared, periodic_images=periodic_images)
187 DO i_blk = first_block, last_block
188 row_first = blk_row_start(i_blk) - panel_start + 1
189 row_last = row_first + r_blk_sizes(i_blk) - 1
190 IF (maxval(abs(atom_col_buffer(row_first:row_last, :))) > eps_filter) THEN
191 CALL dbcsr_put_block(ri_rs%mat_phi_mu_l, row=i_blk, col=iatom, &
192 block=atom_col_buffer(row_first:row_last, :))
193 END IF
194 END DO
195 END DO
196 DEALLOCATE (atom_col_buffer)
197 END DO
198 CALL dbcsr_finalize(ri_rs%mat_phi_mu_l)
199 DEALLOCATE (r_blk_sizes, row_dist, col_dist)
201 CALL timestop(handle)
202 END SUBROUTINE atomic_basis_at_grid_point
203
204! **************************************************************************************************
205!> \brief Creates a square topology from a selected row or column layout.
206!> \param matrix_template source matrix
207!> \param dim_type ROW or COL
208!> \param square_dist output distribution
209!> \param blk_sizes borrowed block sizes
210!> \param mapped_dist owned mapping in the other process-grid direction
211! **************************************************************************************************
212 SUBROUTINE setup_square_topology(matrix_template, dim_type, square_dist, blk_sizes, mapped_dist)
213
214 TYPE(dbcsr_type), INTENT(IN) :: matrix_template
215 CHARACTER(LEN=*), INTENT(IN) :: dim_type
216 TYPE(dbcsr_distribution_type), INTENT(OUT) :: square_dist
217 INTEGER, DIMENSION(:), INTENT(OUT), POINTER :: blk_sizes, mapped_dist
218
219 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_square_topology'
220
221 INTEGER :: handle, i, np, npcols, nprows
222 INTEGER, DIMENSION(:), POINTER :: col_blk, col_dist, row_blk, row_dist
223 TYPE(dbcsr_distribution_type) :: dist_template
224
225 CALL timeset(routinen, handle)
226
227 CALL dbcsr_get_info(matrix_template, distribution=dist_template, &
228 row_blk_size=row_blk, col_blk_size=col_blk)
229 CALL dbcsr_distribution_get(dist_template, row_dist=row_dist, col_dist=col_dist, &
230 nprows=nprows, npcols=npcols)
231
232 IF (trim(dim_type) == 'ROW') THEN
233 ! Creates ROW x ROW (e.g., Grid x Grid from mat_phi_mu_l)
234 blk_sizes => row_blk
235 np = npcols
236 ALLOCATE (mapped_dist(SIZE(blk_sizes)))
237 DO i = 1, SIZE(blk_sizes)
238 mapped_dist(i) = mod(i - 1, np)
239 END DO
240 CALL dbcsr_distribution_new(square_dist, template=dist_template, &
241 row_dist=row_dist, col_dist=mapped_dist)
242
243 ELSE IF (trim(dim_type) == 'COL') THEN
244 ! Creates COL x COL (e.g., Aux x Aux from mat_Z_lP)
245 blk_sizes => col_blk
246 np = nprows
247 ALLOCATE (mapped_dist(SIZE(blk_sizes)))
248 DO i = 1, SIZE(blk_sizes)
249 mapped_dist(i) = mod(i - 1, np)
250 END DO
251 CALL dbcsr_distribution_new(square_dist, template=dist_template, &
252 row_dist=mapped_dist, col_dist=col_dist)
253 END IF
254
255 CALL timestop(handle)
256
257 END SUBROUTINE setup_square_topology
258
259! **************************************************************************************************
260!> \brief Releases RI-RS topology mappings and temporary DBCSR matrices.
261!> \param dist distribution to release
262!> \param mapped_dist owned mapping to deallocate
263!> \param m1 optional matrix
264!> \param m2 optional matrix
265!> \param m3 optional matrix
266!> \param m4 optional matrix
267! **************************************************************************************************
268 SUBROUTINE release_dbcsr_topology_and_matrices(dist, mapped_dist, m1, m2, m3, m4)
269
270 TYPE(dbcsr_distribution_type), INTENT(INOUT), &
271 OPTIONAL :: dist
272 INTEGER, DIMENSION(:), INTENT(INOUT), OPTIONAL, &
273 POINTER :: mapped_dist
274 TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL :: m1, m2, m3, m4
275
276 CHARACTER(LEN=*), PARAMETER :: routinen = 'release_dbcsr_topology_and_matrices'
277
278 INTEGER :: handle
279
280 CALL timeset(routinen, handle)
281
282 IF (PRESENT(dist)) CALL dbcsr_distribution_release(dist)
283 IF (PRESENT(mapped_dist)) THEN
284 IF (ASSOCIATED(mapped_dist)) THEN
285 DEALLOCATE (mapped_dist)
286 NULLIFY (mapped_dist)
287 END IF
288 END IF
289 IF (PRESENT(m1)) CALL dbcsr_release(m1)
290 IF (PRESENT(m2)) CALL dbcsr_release(m2)
291 IF (PRESENT(m3)) CALL dbcsr_release(m3)
292 IF (PRESENT(m4)) CALL dbcsr_release(m4)
293
294 CALL timestop(handle)
295
297
298! **************************************************************************************************
299!> \brief Reserves grid blocks with block-centre distances within a fixed radius.
300!> \param matrix target matrix
301!> \param centers block-centre coordinates
302!> \param radius truncation radius
303! **************************************************************************************************
304 SUBROUTINE reserve_blocks_within_radius(matrix, centers, radius)
305
306 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
307 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: centers
308 REAL(kind=dp), INTENT(IN) :: radius
309
310 CHARACTER(LEN=*), PARAMETER :: routinen = 'reserve_blocks_within_radius'
311
312 INTEGER :: handle, i, j, my_pcol, my_prow, &
313 nblkcols, nblkrows
314 INTEGER, DIMENSION(:), POINTER :: col_blk, col_dist, row_blk, row_dist
315 REAL(kind=dp) :: radius2
316 REAL(kind=dp), ALLOCATABLE :: zero_blk(:, :)
317 TYPE(dbcsr_distribution_type) :: dist
318
319 CALL timeset(routinen, handle)
320
321 CALL dbcsr_get_info(matrix, nblkrows_total=nblkrows, nblkcols_total=nblkcols, &
322 row_blk_size=row_blk, col_blk_size=col_blk, distribution=dist)
323 CALL dbcsr_distribution_get(dist, row_dist=row_dist, col_dist=col_dist, &
324 myprow=my_prow, mypcol=my_pcol)
325 cpassert(nblkrows == SIZE(centers, 2))
326 cpassert(nblkcols == SIZE(centers, 2))
327
328 radius2 = radius**2
329 ALLOCATE (zero_blk(maxval(row_blk(1:nblkrows)), maxval(col_blk(1:nblkcols))))
330 zero_blk(:, :) = 0.0_dp
331
332 DO i = 1, nblkrows
333 IF (row_dist(i) /= my_prow) cycle
334 DO j = 1, nblkcols
335 IF (col_dist(j) /= my_pcol) cycle
336 IF (dot_product(centers(:, i) - centers(:, j), centers(:, i) - centers(:, j)) <= radius2) THEN
337 CALL dbcsr_put_block(matrix, i, j, zero_blk(1:row_blk(i), 1:col_blk(j)))
338 END IF
339 END DO
340 END DO
341 CALL dbcsr_finalize(matrix)
342
343 DEALLOCATE (zero_blk)
344 CALL timestop(handle)
345
346 END SUBROUTINE reserve_blocks_within_radius
347
348! **************************************************************************************************
349!> \brief Prints the percentage of non-zero elements in a distributed RI-RS matrix.
350!> \param matrix Distributed matrix whose occupation is reported
351!> \param label Mathematical matrix label used in the output
352!> \param para_env communicator shared by all matrix ranks
353!> \param unit_nr output unit; nonpositive values suppress printing
354!> \param msg_elem_limit maximum number of elements per DBCSR message
355!> \param suffix Optional text appended to the matrix label
356! **************************************************************************************************
357 SUBROUTINE print_matrix_occupation(matrix, label, para_env, unit_nr, msg_elem_limit, suffix)
358
359 TYPE(dbcsr_type), INTENT(IN) :: matrix
360 CHARACTER(LEN=*), INTENT(IN) :: label
361 TYPE(mp_para_env_type), INTENT(IN) :: para_env
362 INTEGER, INTENT(IN) :: unit_nr
363 INTEGER(KIND=int_8), INTENT(IN) :: msg_elem_limit
364 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: suffix
365
366 CHARACTER(LEN=*), PARAMETER :: routinen = 'print_matrix_occupation'
367
368 CHARACTER(LEN=32) :: output_format
369 CHARACTER(LEN=max_line_length) :: msg, output_label
370 INTEGER :: handle, i, unicode_shift
371 REAL(kind=dp) :: frac_2p31, max_loc, occ
372
373 CALL timeset(routinen, handle)
374
375 occ = dbcsr_get_occupation(matrix)
376 max_loc = real(dbcsr_get_data_size(matrix), dp)
377 CALL para_env%max(max_loc)
378
379 IF (unit_nr > 0) THEN
380 frac_2p31 = max_loc/real(msg_elem_limit, dp)
381 output_label = 'Percentage of non-zero matrix elements in '//trim(label)
382 IF (PRESENT(suffix)) output_label = trim(output_label)//trim(suffix)
383 ! Fortran counts UTF-8 bytes, whereas the terminal displays each Greek letter in one
384 ! column. Shift the absolute output tab once for every continuation byte.
385 unicode_shift = 0
386 DO i = 1, len_trim(output_label)
387 IF (iand(iachar(output_label(i:i)), 192) == 128) unicode_shift = unicode_shift + 1
388 END DO
389 WRITE (output_format, '(A,I0,A)') '(T2,A,T', 72 + unicode_shift, ',F7.2,A)'
390 WRITE (unit_nr, output_format) trim(output_label), occ*100.0_dp, ' %'
391 IF (frac_2p31 > 0.5_dp) THEN
392 WRITE (msg, '(3A,F0.2,A)') &
393 "The largest per-rank message of ", trim(label), " reaches ", frac_2p31, &
394 " of the 32-bit limit that DBCSR uses for its message length. Beyond it the "// &
395 "length overflows and multiply_cannon fails. Reduce the per-rank block size, "// &
396 "for instance with more MPI ranks."
397 cpwarn(trim(msg))
398 END IF
399 CALL m_flush(unit_nr)
400 END IF
401
402 CALL timestop(handle)
403
404 END SUBROUTINE print_matrix_occupation
405
406! **************************************************************************************************
407!> \brief Marks the grid blocks whose centroid lies within cutoff of the bounding box of the
408!> panel [blk0, blk1]'s chunk centroids.
409!> \param centroids ...
410!> \param blk0 ...
411!> \param blk1 ...
412!> \param cutoff ...
413!> \param used ...
414! **************************************************************************************************
415 SUBROUTINE mask_grid_blocks_near_panel(centroids, blk0, blk1, cutoff, used)
416
417 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: centroids
418 INTEGER, INTENT(IN) :: blk0, blk1
419 REAL(kind=dp), INTENT(IN) :: cutoff
420 LOGICAL, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: used
421
422 CHARACTER(LEN=*), PARAMETER :: routinen = 'mask_grid_blocks_near_panel'
423
424 INTEGER :: c, handle, k
425 REAL(kind=dp) :: cutoff2, d2, dx
426 REAL(kind=dp), DIMENSION(3) :: hi, lo
427
428 CALL timeset(routinen, handle)
429
430 cutoff2 = cutoff**2
431 lo(:) = minval(centroids(:, blk0:blk1), dim=2)
432 hi(:) = maxval(centroids(:, blk0:blk1), dim=2)
433
434 ALLOCATE (used(SIZE(centroids, 2)))
435 DO c = 1, SIZE(centroids, 2)
436 d2 = 0.0_dp
437 DO k = 1, 3
438 dx = max(0.0_dp, lo(k) - centroids(k, c), centroids(k, c) - hi(k))
439 d2 = d2 + dx*dx
440 END DO
441 used(c) = (d2 <= cutoff2)
442 END DO
443
444 CALL timestop(handle)
445
446 END SUBROUTINE mask_grid_blocks_near_panel
447
448! **************************************************************************************************
449!> \brief Exact allocated-element count of the geo template of panel [blk0, blk1]: the very same
450!> per-block-pair centroid test as build_geo_template_panel, so this is the true DBCSR
451!> data size of A_pan/B_pan (DBCSR stores whole blocks).
452!> \param r_blk_sizes ...
453!> \param centroids ...
454!> \param used ...
455!> \param blk0 ...
456!> \param blk1 ...
457!> \param cutoff ...
458!> \param nze_tmpl ...
459! **************************************************************************************************
460 SUBROUTINE panel_template_elems(r_blk_sizes, centroids, used, blk0, blk1, cutoff, nze_tmpl)
461
462 INTEGER, DIMENSION(:), INTENT(IN) :: r_blk_sizes
463 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: centroids
464 LOGICAL, DIMENSION(:), INTENT(IN) :: used
465 INTEGER, INTENT(IN) :: blk0, blk1
466 REAL(kind=dp), INTENT(IN) :: cutoff
467 INTEGER(KIND=int_8), INTENT(OUT) :: nze_tmpl
468
469 CHARACTER(LEN=*), PARAMETER :: routinen = 'panel_template_elems'
470
471 INTEGER :: c, handle, ib, n_used
472 INTEGER, ALLOCATABLE, DIMENSION(:) :: used_idx
473 REAL(kind=dp) :: cutoff2
474
475 CALL timeset(routinen, handle)
476
477 ! Compress the near mask once so the pair loop only visits candidate columns.
478 n_used = count(used)
479 ALLOCATE (used_idx(n_used))
480 n_used = 0
481 DO c = 1, SIZE(used)
482 IF (used(c)) THEN
483 n_used = n_used + 1
484 used_idx(n_used) = c
485 END IF
486 END DO
487
488 cutoff2 = cutoff**2
489 nze_tmpl = 0_int_8
490 !$OMP PARALLEL DO DEFAULT(NONE) SHARED(blk0, blk1, n_used, used_idx, centroids, cutoff2, &
491 !$OMP r_blk_sizes) PRIVATE(ib, c) REDUCTION(+:nze_tmpl)
492 DO ib = blk0, blk1
493 DO c = 1, n_used
494 IF (sum((centroids(:, ib) - centroids(:, used_idx(c)))**2) <= cutoff2) THEN
495 nze_tmpl = nze_tmpl + int(r_blk_sizes(ib), int_8)*int(r_blk_sizes(used_idx(c)), int_8)
496 END IF
497 END DO
498 END DO
499 !$OMP END PARALLEL DO
500
501 CALL timestop(handle)
502
503 END SUBROUTINE panel_template_elems
504
505! **************************************************************************************************
506!> \brief Per-rank peak memory (GB) of one panel step of the neighborhood-restricted
507!> contractions: up to three grid x grid panels (two A operands and the shared B operand)
508!> plus the grid x RI intermediates (tmp2 and the accumulation operand) and the
509!> grid x AO intermediate (tmpA), whose column support is the panel's geometric
510!> neighborhood fraction f_near = width/n_grid. Used by planning and memory reporting.
511!> \param nze_tmpl ...
512!> \param pan_rows ...
513!> \param width ...
514!> \param n_grid_total ...
515!> \param n_RI ...
516!> \param n_ao ...
517!> \param n_procs ...
518!> \param mem_GB ...
519! **************************************************************************************************
520 SUBROUTINE panel_mem_estimate_gb(nze_tmpl, pan_rows, width, n_grid_total, n_RI, n_ao, &
521 n_procs, mem_GB)
522
523 INTEGER(KIND=int_8), INTENT(IN) :: nze_tmpl
524 INTEGER, INTENT(IN) :: pan_rows, width, n_grid_total, n_ri, &
525 n_ao, n_procs
526 REAL(kind=dp), INTENT(OUT) :: mem_gb
527
528 REAL(kind=dp) :: f_near
529
530 f_near = real(width, dp)/real(max(n_grid_total, 1), dp)
531 mem_gb = (3.0_dp*real(nze_tmpl, dp) + &
532 REAL(pan_rows, dp)*f_near*(2.0_dp*REAL(n_RI, dp) + REAL(n_ao, dp)))* &
533 8.0_dp/REAL(MAX(n_procs, 1), dp)*1.0e-9_dp
534
535 END SUBROUTINE panel_mem_estimate_gb
536
537! **************************************************************************************************
538!> \brief Plans whole-grid-block panels using a message-size target without a cutoff.
539!> A positive cutoff additionally checks estimated message and memory costs.
540!> A single indivisible cutoff block exceeding an estimated limit is reported
541!> and accepted, since the panel cannot be split further.
542!> \param msg_elem_limit maximum number of elements per DBCSR message
543!> \param r_blk_sizes grid row-block sizes
544!> \param min_dim smaller dimension of the DBCSR process grid
545!> \param pan_first first grid block of each panel
546!> \param pan_last last grid block of each panel
547!> \param n_RI auxiliary basis dimension
548!> \param n_ao AO basis dimension
549!> \param n_procs number of MPI processes
550!> \param mem_budget_GB per-rank panel memory budget; nonpositive disables the memory check
551!> \param centroids optional grid-block centres
552!> \param cutoff optional geometric truncation radius
553! **************************************************************************************************
554 SUBROUTINE plan_grid_panels(msg_elem_limit, r_blk_sizes, min_dim, pan_first, pan_last, &
555 n_RI, n_ao, n_procs, mem_budget_GB, centroids, cutoff)
556
557 INTEGER(KIND=int_8), INTENT(IN) :: msg_elem_limit
558 INTEGER, DIMENSION(:), INTENT(IN) :: r_blk_sizes
559 INTEGER, INTENT(IN) :: min_dim
560 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: pan_first, pan_last
561 INTEGER, INTENT(IN) :: n_ri, n_ao, n_procs
562 REAL(kind=dp), INTENT(IN) :: mem_budget_gb
563 REAL(kind=dp), DIMENSION(:, :), INTENT(IN), &
564 OPTIONAL :: centroids
565 REAL(kind=dp), INTENT(IN), OPTIONAL :: cutoff
566
567 CHARACTER(LEN=*), PARAMETER :: routinen = 'plan_grid_panels'
568
569 INTEGER :: blk0, blk1, handle, ib, n_grid_blocks, &
570 n_grid_total, n_panels, panel_size, &
571 rows_acc, TARGET, width
572 INTEGER(KIND=int_8) :: msg, msg_limit, nze_tmpl, side
573 INTEGER, ALLOCATABLE :: tmp_first(:), tmp_last(:)
574 LOGICAL :: fits, use_cutoff, warned_memory, &
575 warned_message
576 LOGICAL, ALLOCATABLE :: used(:)
577 REAL(kind=dp) :: f_near, mem_gb
578
579 CALL timeset(routinen, handle)
580
581 use_cutoff = PRESENT(centroids) .AND. PRESENT(cutoff)
582 IF (use_cutoff) use_cutoff = cutoff > 0.0_dp
583 msg_limit = msg_elem_limit/4
584 warned_memory = .false.
585 warned_message = .false.
586 n_grid_blocks = SIZE(r_blk_sizes)
587 n_grid_total = sum(r_blk_sizes)
588 panel_size = n_grid_total
589 IF (.NOT. use_cutoff) THEN
590 ! Preserve the original message-derived target and whole-block growth.
591 panel_size = int(0.5_dp*real(msg_elem_limit, dp)*real(min_dim, dp)/real(n_grid_total, dp))
592 panel_size = max(1, min(panel_size, n_grid_total))
593 END IF
594 ALLOCATE (tmp_first(n_grid_blocks), tmp_last(n_grid_blocks))
595
596 n_panels = 0
597 blk0 = 1
598 DO WHILE (blk0 <= n_grid_blocks)
599 TARGET = panel_size
600 DO
601 rows_acc = 0
602 DO ib = blk0, n_grid_blocks
603 rows_acc = rows_acc + r_blk_sizes(ib)
604 blk1 = ib
605 IF (rows_acc >= TARGET) EXIT
606 END DO
607 IF (.NOT. use_cutoff) EXIT
608 CALL mask_grid_blocks_near_panel(centroids, blk0, blk1, cutoff, used)
609 width = sum(r_blk_sizes, mask=used)
610 CALL panel_template_elems(r_blk_sizes, centroids, used, blk0, blk1, cutoff, nze_tmpl)
611 f_near = real(width, dp)/real(max(n_grid_total, 1), dp)
612 side = int(real(rows_acc, dp)*f_near*real(max(n_ri, n_ao), dp), int_8)
613 msg = max(nze_tmpl, side)/int(max(min_dim, 1), int_8)
614 CALL panel_mem_estimate_gb(nze_tmpl, rows_acc, width, n_grid_total, &
615 n_ri, n_ao, n_procs, mem_gb)
616 fits = msg <= msg_limit
617 IF (mem_budget_gb > 0.0_dp) fits = fits .AND. mem_gb <= mem_budget_gb
618 IF (fits) EXIT
619 IF (blk1 == blk0) THEN
620 IF (msg > msg_limit .AND. .NOT. warned_message) THEN
621 cpwarn("A single RI-RS grid block exceeds the estimated panel message limit.")
622 warned_message = .true.
623 END IF
624 IF (mem_budget_gb > 0.0_dp .AND. mem_gb > mem_budget_gb .AND. .NOT. warned_memory) THEN
625 cpwarn("A single RI-RS grid block exceeds the estimated panel memory budget.")
626 warned_memory = .true.
627 END IF
628 EXIT
629 END IF
630 ! Preserve whole blocks and prefer large panels to reduce the number of multiplies.
631 TARGET = max(1, min(TARGET, rows_acc)/2)
632 END DO
633 n_panels = n_panels + 1
634 tmp_first(n_panels) = blk0
635 tmp_last(n_panels) = blk1
636 blk0 = blk1 + 1
637 END DO
638
639 ALLOCATE (pan_first, source=tmp_first(:n_panels))
640 ALLOCATE (pan_last, source=tmp_last(:n_panels))
641 CALL timestop(handle)
642
643 END SUBROUTINE plan_grid_panels
644
645! **************************************************************************************************
646!> \brief Creates an empty (panel_chunks x neighborhood_chunks) DBCSR matrix with zero blocks
647!> pre-allocated only where |centroid(panel_row r) - centroid(column c)| <= cutoff.
648!> Used with retain_sparsity=.TRUE. in the subsequent dbcsr_multiply so distant blocks
649!> of the grid-basis panels (ϕ G ϕ^T, Z W Z^T, ...) are never computed at all.
650!> \param L_pan ...
651!> \param L_full ...
652!> \param centroids ...
653!> \param cutoff ...
654!> \param blk0 ...
655!> \param A_template ...
656!> \param col_map ...
657! **************************************************************************************************
658 SUBROUTINE build_geo_template_panel(L_pan, L_full, centroids, cutoff, blk0, A_template, col_map)
659 TYPE(dbcsr_type), INTENT(IN) :: l_pan, l_full
660 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: centroids
661 REAL(kind=dp), INTENT(IN) :: cutoff
662 INTEGER, INTENT(IN) :: blk0
663 TYPE(dbcsr_type), INTENT(OUT) :: a_template
664 INTEGER, DIMENSION(:), INTENT(IN) :: col_map
665
666 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_geo_template_panel'
667
668 INTEGER :: c, cg, cs, handle, my_pcol, my_prow, &
669 n_grid_blks, n_pan_blks, npcols, &
670 nprows, r, rs
671 INTEGER, DIMENSION(:), POINTER :: grid_blk_sizes, pan_blk_sizes
672 REAL(kind=dp) :: cutoff2
673 REAL(kind=dp), ALLOCATABLE :: zero_blk(:, :)
674 TYPE(dbcsr_distribution_type) :: dist
675
676 CALL timeset(routinen, handle)
677
678 cutoff2 = cutoff**2
679 CALL dbcsr_get_info(l_pan, nblkrows_total=n_pan_blks, row_blk_size=pan_blk_sizes)
680 CALL dbcsr_get_info(l_full, nblkrows_total=n_grid_blks, row_blk_size=grid_blk_sizes)
681
682 ! create_product_matrix assigns row r to process MOD(r-1,nprows) and
683 ! col c to MOD(c-1,npcols), so we can determine local ownership analytically.
684 CALL create_product_matrix(l_pan, l_full, 'T', a_template)
685 CALL dbcsr_get_info(a_template, distribution=dist)
686 CALL dbcsr_distribution_get(dist, nprows=nprows, npcols=npcols, &
687 myprow=my_prow, mypcol=my_pcol)
688
689 ALLOCATE (zero_blk(maxval(pan_blk_sizes(1:n_pan_blks)), &
690 maxval(grid_blk_sizes(1:n_grid_blks))))
691 zero_blk(:, :) = 0.0_dp
692
693 DO r = 1, n_pan_blks
694 IF (mod(r - 1, nprows) /= my_prow) cycle
695 rs = pan_blk_sizes(r)
696 DO c = 1, n_grid_blks
697 IF (mod(c - 1, npcols) /= my_pcol) cycle
698 cg = col_map(c)
699 IF ((centroids(1, blk0 + r - 1) - centroids(1, cg))**2 + &
700 (centroids(2, blk0 + r - 1) - centroids(2, cg))**2 + &
701 (centroids(3, blk0 + r - 1) - centroids(3, cg))**2 <= cutoff2) THEN
702 cs = grid_blk_sizes(c)
703 CALL dbcsr_put_block(a_template, r, c, zero_blk(1:rs, 1:cs))
704 END IF
705 END DO
706 END DO
707 CALL dbcsr_finalize(a_template)
708
709 DEALLOCATE (zero_blk)
710 CALL timestop(handle)
711
712 END SUBROUTINE build_geo_template_panel
713
714! **************************************************************************************************
715!> \brief Slices a contiguous range of grid row-blocks [blk0, blk1] out of a (grid x n) DBCSR
716!> matrix into a new (P x n) panel matrix: iterate the source's local blocks, put the
717!> in-range ones into the panel with a remapped row-block index, then finalize. Row-block
718!> index i of the panel corresponds to source row-block blk0+i-1.
719!> \param mat_full ...
720!> \param blk0 ...
721!> \param blk1 ...
722!> \param mat_panel ...
723! **************************************************************************************************
724 SUBROUTINE extract_grid_panel(mat_full, blk0, blk1, mat_panel)
725
726 TYPE(dbcsr_type), INTENT(INOUT) :: mat_full
727 INTEGER, INTENT(IN) :: blk0, blk1
728 TYPE(dbcsr_type), INTENT(OUT) :: mat_panel
729
730 CHARACTER(LEN=*), PARAMETER :: routinen = 'extract_grid_panel'
731
732 INTEGER :: handle, ib, jb, npb
733 INTEGER, DIMENSION(:), POINTER :: col_blk_full, col_dist_full, &
734 row_blk_full, row_blk_pan, &
735 row_dist_full, row_dist_pan
736 REAL(kind=dp), DIMENSION(:, :), POINTER :: blk
737 TYPE(dbcsr_distribution_type) :: dist_full, dist_pan
738 TYPE(dbcsr_iterator_type) :: iter
739
740 CALL timeset(routinen, handle)
741
742 CALL dbcsr_get_info(mat_full, distribution=dist_full, &
743 row_blk_size=row_blk_full, col_blk_size=col_blk_full)
744 CALL dbcsr_distribution_get(dist_full, row_dist=row_dist_full, col_dist=col_dist_full)
745
746 npb = blk1 - blk0 + 1
747 ALLOCATE (row_dist_pan(npb), row_blk_pan(npb))
748 row_dist_pan(:) = row_dist_full(blk0:blk1)
749 row_blk_pan(:) = row_blk_full(blk0:blk1)
750
751 CALL dbcsr_distribution_new(dist_pan, template=dist_full, &
752 row_dist=row_dist_pan, col_dist=col_dist_full)
753 CALL dbcsr_create(mat_panel, name="grid_panel", dist=dist_pan, &
754 matrix_type=dbcsr_type_no_symmetry, &
755 row_blk_size=row_blk_pan, col_blk_size=col_blk_full)
756
757 CALL dbcsr_iterator_start(iter, mat_full)
758 DO WHILE (dbcsr_iterator_blocks_left(iter))
759 CALL dbcsr_iterator_next_block(iter, ib, jb, blk)
760 IF (ib < blk0 .OR. ib > blk1) cycle
761 CALL dbcsr_put_block(mat_panel, ib - blk0 + 1, jb, blk)
762 END DO
763 CALL dbcsr_iterator_stop(iter)
764 CALL dbcsr_finalize(mat_panel)
765
766 CALL dbcsr_distribution_release(dist_pan)
767 DEALLOCATE (row_dist_pan, row_blk_pan)
768
769 CALL timestop(handle)
770
771 END SUBROUTINE extract_grid_panel
772
773! **************************************************************************************************
774!> \brief Marks which column blocks of a DBCSR matrix carry at least one non-zero block anywhere
775!> (global union). Used to restrict the inner index of the panel multiplies to the
776!> AO/RI atoms that actually touch the panel (exact: dropped rows only meet zeros).
777!> \param matrix ...
778!> \param para_env ...
779!> \param used ...
780! **************************************************************************************************
781 SUBROUTINE collect_used_col_blocks(matrix, para_env, used)
782
783 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
784 TYPE(mp_para_env_type), INTENT(IN), POINTER :: para_env
785 LOGICAL, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: used
786
787 CHARACTER(LEN=*), PARAMETER :: routinen = 'collect_used_col_blocks'
788
789 INTEGER :: handle, ib, jb, nblkcols
790 INTEGER, ALLOCATABLE, DIMENSION(:) :: iused
791 REAL(kind=dp), DIMENSION(:, :), POINTER :: blk
792 TYPE(dbcsr_iterator_type) :: iter
793
794 CALL timeset(routinen, handle)
795
796 CALL dbcsr_get_info(matrix, nblkcols_total=nblkcols)
797 ALLOCATE (iused(nblkcols))
798 iused(:) = 0
799
800 CALL dbcsr_iterator_start(iter, matrix)
801 DO WHILE (dbcsr_iterator_blocks_left(iter))
802 CALL dbcsr_iterator_next_block(iter, ib, jb, blk)
803 iused(jb) = 1
804 END DO
805 CALL dbcsr_iterator_stop(iter)
806
807 CALL para_env%sum(iused)
808
809 ALLOCATE (used(nblkcols))
810 used(:) = (iused(:) > 0)
811 DEALLOCATE (iused)
812
813 CALL timestop(handle)
814
815 END SUBROUTINE collect_used_col_blocks
816
817! **************************************************************************************************
818!> \brief Copies the flagged block rows (compress_rows=.TRUE.) or block columns (.FALSE.) of a
819!> DBCSR matrix into a compressed matrix. The subset keeps the parent's process assignment
820!> along the compressed dimension, so every block stays on its owning rank: the extraction
821!> is purely local (zero communication), like extract_grid_panel.
822!> \param mat_full ...
823!> \param used ...
824!> \param mat_out ...
825!> \param compress_rows ...
826!> \param blk_map ...
827! **************************************************************************************************
828 SUBROUTINE extract_masked_blocks(mat_full, used, mat_out, compress_rows, blk_map)
829
830 TYPE(dbcsr_type), INTENT(INOUT) :: mat_full
831 LOGICAL, DIMENSION(:), INTENT(IN) :: used
832 TYPE(dbcsr_type), INTENT(OUT) :: mat_out
833 LOGICAL, INTENT(IN) :: compress_rows
834 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT), &
835 OPTIONAL :: blk_map
836
837 CHARACTER(LEN=*), PARAMETER :: routinen = 'extract_masked_blocks'
838
839 INTEGER :: handle, ib, jb, n_blk, n_sub, r
840 INTEGER, ALLOCATABLE, DIMENSION(:) :: inv_map
841 INTEGER, DIMENSION(:), POINTER :: blk_full, blk_sub, col_blk_full, &
842 col_dist_full, dist_full_1d, &
843 dist_sub_1d, row_blk_full, &
844 row_dist_full
845 REAL(kind=dp), DIMENSION(:, :), POINTER :: blk
846 TYPE(dbcsr_distribution_type) :: dist_full, dist_sub
847 TYPE(dbcsr_iterator_type) :: iter
848
849 CALL timeset(routinen, handle)
850
851 CALL dbcsr_get_info(mat_full, distribution=dist_full, &
852 row_blk_size=row_blk_full, col_blk_size=col_blk_full)
853 CALL dbcsr_distribution_get(dist_full, row_dist=row_dist_full, col_dist=col_dist_full)
854
855 IF (compress_rows) THEN
856 blk_full => row_blk_full
857 dist_full_1d => row_dist_full
858 ELSE
859 blk_full => col_blk_full
860 dist_full_1d => col_dist_full
861 END IF
862 n_blk = SIZE(blk_full)
863
864 n_sub = count(used)
865 cpassert(n_sub > 0)
866 ALLOCATE (inv_map(n_blk), blk_sub(n_sub), dist_sub_1d(n_sub))
867 IF (PRESENT(blk_map)) ALLOCATE (blk_map(n_sub))
868 inv_map(:) = 0
869 r = 0
870 DO ib = 1, n_blk
871 IF (used(ib)) THEN
872 r = r + 1
873 inv_map(ib) = r
874 blk_sub(r) = blk_full(ib)
875 dist_sub_1d(r) = dist_full_1d(ib)
876 IF (PRESENT(blk_map)) blk_map(r) = ib
877 END IF
878 END DO
879
880 IF (compress_rows) THEN
881 CALL dbcsr_distribution_new(dist_sub, template=dist_full, &
882 row_dist=dist_sub_1d, col_dist=col_dist_full)
883 CALL dbcsr_create(mat_out, name="row_subset", dist=dist_sub, &
884 matrix_type=dbcsr_type_no_symmetry, &
885 row_blk_size=blk_sub, col_blk_size=col_blk_full)
886 ELSE
887 CALL dbcsr_distribution_new(dist_sub, template=dist_full, &
888 row_dist=row_dist_full, col_dist=dist_sub_1d)
889 CALL dbcsr_create(mat_out, name="col_subset", dist=dist_sub, &
890 matrix_type=dbcsr_type_no_symmetry, &
891 row_blk_size=row_blk_full, col_blk_size=blk_sub)
892 END IF
893
894 CALL dbcsr_iterator_start(iter, mat_full)
895 DO WHILE (dbcsr_iterator_blocks_left(iter))
896 CALL dbcsr_iterator_next_block(iter, ib, jb, blk)
897 IF (compress_rows) THEN
898 IF (inv_map(ib) > 0) CALL dbcsr_put_block(mat_out, inv_map(ib), jb, blk)
899 ELSE
900 IF (inv_map(jb) > 0) CALL dbcsr_put_block(mat_out, ib, inv_map(jb), blk)
901 END IF
902 END DO
903 CALL dbcsr_iterator_stop(iter)
904 CALL dbcsr_finalize(mat_out)
905
906 CALL dbcsr_distribution_release(dist_sub)
907 DEALLOCATE (inv_map, blk_sub, dist_sub_1d)
908
909 CALL timestop(handle)
910
911 END SUBROUTINE extract_masked_blocks
912
913! **************************************************************************************************
914!> \brief Creates the (empty) result matrix of op(mat_left) * op(mat_right) with the correct block
915!> structure and a distribution on the shared process grid, ready to be filled by
916!> dbcsr_multiply. Row structure comes from op(left), column structure from op(right).
917!> \param mat_left ...
918!> \param mat_right ...
919!> \param transb 'N' or 'T' applied to mat_right
920!> \param mat_out ...
921! **************************************************************************************************
922 SUBROUTINE create_product_matrix(mat_left, mat_right, transb, mat_out)
923
924 TYPE(dbcsr_type), INTENT(IN) :: mat_left, mat_right
925 CHARACTER(LEN=1), INTENT(IN) :: transb
926 TYPE(dbcsr_type), INTENT(OUT) :: mat_out
927
928 CHARACTER(LEN=*), PARAMETER :: routinen = 'create_product_matrix'
929
930 INTEGER :: handle, i, npcols, nprows
931 INTEGER, DIMENSION(:), POINTER :: col_blk_r, out_col_blk, out_col_dist, &
932 out_row_blk, out_row_dist, row_blk_l, &
933 row_blk_r
934 TYPE(dbcsr_distribution_type) :: dist_l, dist_out
935
936 CALL timeset(routinen, handle)
937
938 CALL dbcsr_get_info(mat_left, distribution=dist_l, row_blk_size=row_blk_l)
939 CALL dbcsr_get_info(mat_right, row_blk_size=row_blk_r, col_blk_size=col_blk_r)
940 CALL dbcsr_distribution_get(dist_l, nprows=nprows, npcols=npcols)
941
942 ! block SIZES follow op(left)/op(right); DISTRIBUTIONS are freshly round-robined onto the
943 ! shared process grid (a transposed operand's row-dist is NOT a valid col-dist on a
944 ! non-square grid). dbcsr_multiply redistributes internally, so any valid mapping works.
945 out_row_blk => row_blk_l
946 IF (transb == 'N') THEN
947 out_col_blk => col_blk_r
948 ELSE
949 out_col_blk => row_blk_r
950 END IF
951
952 ALLOCATE (out_row_dist(SIZE(out_row_blk)), out_col_dist(SIZE(out_col_blk)))
953 DO i = 1, SIZE(out_row_blk)
954 out_row_dist(i) = mod(i - 1, nprows)
955 END DO
956 DO i = 1, SIZE(out_col_blk)
957 out_col_dist(i) = mod(i - 1, npcols)
958 END DO
959
960 CALL dbcsr_distribution_new(dist_out, template=dist_l, &
961 row_dist=out_row_dist, col_dist=out_col_dist)
962 CALL dbcsr_create(mat_out, name="panel_product", dist=dist_out, &
963 matrix_type=dbcsr_type_no_symmetry, &
964 row_blk_size=out_row_blk, col_blk_size=out_col_blk)
965 CALL dbcsr_distribution_release(dist_out)
966 DEALLOCATE (out_row_dist, out_col_dist)
967
968 CALL timestop(handle)
969
970 END SUBROUTINE create_product_matrix
971
972! **************************************************************************************************
973!> \brief Projects two operators onto grid panels, takes their Hadamard product, and
974!> back-projects it: out += scale * L_out^T (A_grid ∘ B_grid) L_out,
975!> where A_grid = L_A M_A L_A^T and B_grid = L_B M_B L_B^T.
976!> Each L has shape (grid, basis), and its M has shape (basis, basis).
977!> The three L matrices must share the ordered grid rows, row blocking and process grid.
978!> Only panel x grid slabs are formed; contributions are accumulated over all panels.
979!> The sequence of EPS_FILTER screening and floating-point reductions may differ from
980!> a full-grid evaluation.
981!>
982!> The physical contractions and their signs/spin factors are specified in gw_ri_rs_kernels:
983!> χ: L_A=L_B=ϕ, M_A=G_occ, M_B=G_vir, L_out=Z -> RI x RI
984!> Σx: L_A=ϕ, M_A=D, L_B=Z, M_B=M^-1 V^tr M^-1, L_out=ϕ -> AO x AO
985!> Σc: L_A=ϕ, M_A=[G_occ,G_vir], L_B=Z, M_B=W, L_out=ϕ -> two AO x AO outputs.
986!> The second Σc output reuses the same W grid panel; its projection and back-projection
987!> otherwise follow the same operations as the first output.
988!> \param L_A grid-by-basis collocation or fitting matrix for the first operand
989!> \param M_A one or two square operators, with row/column blocking matching the columns of L_A
990!> \param L_B grid-by-basis collocation or fitting matrix for the second operand
991!> \param M_B second square operator, with row/column blocking matching the columns of L_B
992!> \param L_out grid-by-output-basis matrix for back-projection
993!> \param mat_out borrowed pointers to pre-created outputs, one per M_A, with the column blocking of L_out
994!> \param scale prefactor of the Hadamard product, including the caller's sign/spin convention
995!> \param eps DBCSR multiplication screening threshold
996!> \param para_env communicator containing all matrix ranks
997!> \param pan_first first global grid row-block of each ordered, nonoverlapping panel
998!> \param pan_last last global grid row-block of each panel; panels together cover the grid
999!> \param lb_eq_la L_B equals L_A in values and layout, allowing their grid/AO slices to be shared
1000!> \param lout_eq_la L_out equals L_A in values and layout, allowing back-projection slices to be shared
1001!> \param zero_out clear the output matrices before accumulating, otherwise add to their existing values
1002!> \param centroids optional global grid-block centres, paired with a positive cutoff for truncation
1003!> \param cutoff retain grid-block pairs within this centroid distance; nonpositive disables truncation
1004!> \param grid_occupation allocated-element fraction of the first grid operand before the Hadamard product
1005! **************************************************************************************************
1006 SUBROUTINE contract_grid_panels(L_A, M_A, L_B, M_B, L_out, mat_out, scale, eps, para_env, &
1007 pan_first, pan_last, lb_eq_la, lout_eq_la, zero_out, &
1008 centroids, cutoff, grid_occupation)
1009
1010 TYPE(dbcsr_type), INTENT(INOUT), TARGET :: l_a
1011 TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT) :: m_a
1012 TYPE(dbcsr_type), INTENT(INOUT), TARGET :: l_b
1013 TYPE(dbcsr_type), INTENT(INOUT) :: m_b
1014 TYPE(dbcsr_type), INTENT(INOUT), TARGET :: l_out
1015 TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN) :: mat_out
1016 REAL(kind=dp), INTENT(IN) :: scale, eps
1017 TYPE(mp_para_env_type), INTENT(IN), POINTER :: para_env
1018 INTEGER, DIMENSION(:), INTENT(IN) :: pan_first, pan_last
1019 LOGICAL, INTENT(IN) :: lb_eq_la, lout_eq_la, zero_out
1020 REAL(kind=dp), DIMENSION(:, :), INTENT(IN), &
1021 OPTIONAL :: centroids
1022 REAL(kind=dp), INTENT(IN), OPTIONAL :: cutoff
1023 REAL(kind=dp), INTENT(OUT), OPTIONAL :: grid_occupation
1024
1025 CHARACTER(LEN=*), PARAMETER :: routinen = 'contract_grid_panels'
1026
1027 INTEGER :: blk0, blk1, handle, i_a, ipan, &
1028 n_grid_total, ncols_pan, nrows_pan
1029 INTEGER, ALLOCATABLE, DIMENSION(:) :: gmap
1030 LOGICAL :: use_cutoff
1031 LOGICAL, ALLOCATABLE, DIMENSION(:) :: grid_used, useda, usedb
1032 TYPE(dbcsr_type) :: a_pan(2), b_pan, lb_pan, lb_panc, &
1033 ma_sub, mb_sub, tmp2, tmpa, tmpb
1034 TYPE(dbcsr_type), POINTER :: panel_out, rb_a, rb_b, rb_out
1035 TYPE(dbcsr_type), TARGET :: la_near, la_pan, la_panc, lb_near, &
1036 lout_near, lout_pan
1037
1038 CALL timeset(routinen, handle)
1039
1040 cpassert(SIZE(m_a) >= 1 .AND. SIZE(m_a) <= 2)
1041 cpassert(SIZE(mat_out) == SIZE(m_a))
1042
1043 use_cutoff = PRESENT(centroids) .AND. PRESENT(cutoff)
1044 IF (use_cutoff) use_cutoff = cutoff > 0.0_dp
1045 IF (PRESENT(grid_occupation)) grid_occupation = 0.0_dp
1046
1047 CALL dbcsr_get_info(l_a, nfullrows_total=n_grid_total)
1048
1049 IF (zero_out) THEN
1050 DO i_a = 1, SIZE(mat_out)
1051 CALL dbcsr_set(mat_out(i_a)%matrix, 0.0_dp)
1052 END DO
1053 END IF
1054
1055 DO ipan = 1, SIZE(pan_first)
1056 blk0 = pan_first(ipan)
1057 blk1 = pan_last(ipan)
1058
1059 ! Slice only the current grid rows; compact away AO/RI columns that are exactly absent.
1060 CALL extract_grid_panel(l_a, blk0, blk1, la_pan)
1061 CALL collect_used_col_blocks(la_pan, para_env, useda)
1062 IF (.NOT. lb_eq_la) THEN
1063 CALL extract_grid_panel(l_b, blk0, blk1, lb_pan)
1064 CALL collect_used_col_blocks(lb_pan, para_env, usedb)
1065 ELSE
1066 IF (ALLOCATED(usedb)) DEALLOCATE (usedb)
1067 ALLOCATE (usedb, source=useda)
1068 END IF
1069 IF (.NOT. any(useda) .OR. .NOT. any(usedb)) THEN
1070 CALL dbcsr_release(la_pan)
1071 IF (.NOT. lb_eq_la) CALL dbcsr_release(lb_pan)
1072 cycle
1073 END IF
1074 IF (lout_eq_la) THEN
1075 panel_out => la_pan
1076 ELSE
1077 CALL extract_grid_panel(l_out, blk0, blk1, lout_pan)
1078 panel_out => lout_pan
1079 END IF
1080 CALL extract_masked_blocks(la_pan, useda, la_panc, compress_rows=.false.)
1081
1082 ! Grid rows within reach of the panel: with the CUTOFF_RADIUS_RL_W truncation only
1083 ! they can appear as columns of the panel products / inner rows of the L_out multiply,
1084 ! so the system-wide phi/Z right operands are cut down to this neighborhood slice
1085 ! (local extraction, zero communication; exact w.r.t. the geo template).
1086 IF (use_cutoff) THEN
1087 CALL mask_grid_blocks_near_panel(centroids, blk0, blk1, cutoff, grid_used)
1088 CALL extract_masked_blocks(l_a, grid_used, la_near, compress_rows=.true., blk_map=gmap)
1089 IF (.NOT. lb_eq_la) CALL extract_masked_blocks(l_b, grid_used, lb_near, compress_rows=.true.)
1090 IF (.NOT. lout_eq_la) CALL extract_masked_blocks(l_out, grid_used, lout_near, compress_rows=.true.)
1091 rb_a => la_near
1092 ELSE
1093 rb_a => l_a
1094 END IF
1095 IF (lb_eq_la) THEN
1096 rb_b => rb_a
1097 ELSE IF (use_cutoff) THEN
1098 rb_b => lb_near
1099 ELSE
1100 rb_b => l_b
1101 END IF
1102 IF (lout_eq_la) THEN
1103 rb_out => rb_a
1104 ELSE IF (use_cutoff) THEN
1105 rb_out => lout_near
1106 ELSE
1107 rb_out => l_out
1108 END IF
1109
1110 DO i_a = 1, SIZE(m_a)
1111 ! A_pan(i_A) = LA_pan * M_A(i_A) * L_A^T (P x grid_near).
1112 ! When cutoff is active, A_pan(i_A) is pre-seeded with only nearby blocks via
1113 ! build_geo_template_panel, and the multiply uses retain_sparsity to skip
1114 ! computing distant blocks entirely within the chosen grid cutoff.
1115 CALL extract_masked_blocks(m_a(i_a), useda, ma_sub, compress_rows=.true.)
1116 CALL create_product_matrix(la_panc, ma_sub, 'N', tmpa)
1117 CALL dbcsr_multiply('N', 'N', 1.0_dp, la_panc, ma_sub, 0.0_dp, tmpa, filter_eps=eps)
1118 CALL dbcsr_release(ma_sub)
1119 IF (use_cutoff) THEN
1120 CALL build_geo_template_panel(la_pan, la_near, centroids, cutoff, blk0, a_pan(i_a), &
1121 col_map=gmap)
1122 ELSE
1123 CALL create_product_matrix(tmpa, rb_a, 'T', a_pan(i_a))
1124 END IF
1125 CALL dbcsr_multiply('N', 'T', 1.0_dp, tmpa, rb_a, 0.0_dp, a_pan(i_a), &
1126 filter_eps=eps, retain_sparsity=use_cutoff)
1127 CALL dbcsr_release(tmpa)
1128
1129 ! Grid-basis occupation of A_pan(i_A) = ϕ G ϕ^T, accumulated over ALL panels into the
1130 ! occupation of the (never formed) full grid x grid object:
1131 ! sum_panels nnz(A_pan(i_A)) / n_grid^2, with nnz = occ * pan_rows * pan_cols.
1132 ! Panel-independent by construction -- a single-panel sample would instead report the
1133 ! local neighbor count of whichever region happens to land in that panel.
1134 IF (PRESENT(grid_occupation) .AND. i_a == 1) THEN
1135 CALL dbcsr_get_info(a_pan(i_a), nfullrows_total=nrows_pan, nfullcols_total=ncols_pan)
1136 grid_occupation = grid_occupation + dbcsr_get_occupation(a_pan(i_a))* &
1137 REAL(ncols_pan, dp)*REAL(nrows_pan, dp)/ &
1138 (REAL(n_grid_total, dp)*REAL(n_grid_total, dp))
1139 END IF
1140 END DO
1141
1142 ! B_pan = LB_pan * M_B * L_B^T (P x grid_near); reuse the L_A slices when L_B == L_A.
1143 ! B_pan retains the union of the A panels' block structures so that
1144 ! retain_sparsity forces the final multiply to fill only those blocks (exact for ∘).
1145 IF (lb_eq_la) THEN
1146 CALL extract_masked_blocks(m_b, useda, mb_sub, compress_rows=.true.)
1147 CALL create_product_matrix(la_panc, mb_sub, 'N', tmpb)
1148 CALL dbcsr_multiply('N', 'N', 1.0_dp, la_panc, mb_sub, 0.0_dp, tmpb, filter_eps=eps)
1149 ELSE
1150 CALL extract_masked_blocks(lb_pan, usedb, lb_panc, compress_rows=.false.)
1151 CALL extract_masked_blocks(m_b, usedb, mb_sub, compress_rows=.true.)
1152 CALL create_product_matrix(lb_panc, mb_sub, 'N', tmpb)
1153 CALL dbcsr_multiply('N', 'N', 1.0_dp, lb_panc, mb_sub, 0.0_dp, tmpb, filter_eps=eps)
1154 CALL dbcsr_release(lb_panc)
1155 END IF
1156 CALL dbcsr_release(mb_sub)
1157 CALL dbcsr_create(b_pan, template=a_pan(1))
1158 CALL dbcsr_copy(b_pan, a_pan(1))
1159 IF (SIZE(m_a) == 2) CALL dbcsr_add(b_pan, a_pan(2), 1.0_dp, 1.0_dp)
1160 CALL dbcsr_set(b_pan, 0.0_dp)
1161 ! The output pattern is already fixed. Omitting redundant on-the-fly filtering also
1162 ! avoids overflowing DBCSR's single-precision screening norms for conditioned Z fits.
1163 CALL dbcsr_multiply('N', 'T', 1.0_dp, tmpb, rb_b, 0.0_dp, b_pan, &
1164 retain_sparsity=.true.)
1165 CALL dbcsr_release(tmpb)
1166 CALL dbcsr_release(la_panc)
1167
1168 DO i_a = 1, SIZE(m_a)
1169 ! Reuse A_pan storage for its Hadamard product with the shared B panel.
1170 CALL hadamard_product_inplace(a_pan(i_a), b_pan, scale)
1171 CALL create_product_matrix(a_pan(i_a), rb_out, 'N', tmp2)
1172 CALL dbcsr_multiply('N', 'N', 1.0_dp, a_pan(i_a), rb_out, 0.0_dp, tmp2, filter_eps=eps)
1173 CALL dbcsr_release(a_pan(i_a))
1174
1175 ! mat_out += L_out_pan^T * tmp2.
1176 CALL dbcsr_multiply('T', 'N', 1.0_dp, panel_out, tmp2, 1.0_dp, mat_out(i_a)%matrix, filter_eps=eps)
1177 CALL dbcsr_release(tmp2)
1178 END DO
1179 CALL dbcsr_release(b_pan)
1180 IF (.NOT. lout_eq_la) CALL dbcsr_release(lout_pan)
1181 IF (.NOT. lb_eq_la) CALL dbcsr_release(lb_pan)
1182 CALL dbcsr_release(la_pan)
1183 IF (use_cutoff) THEN
1184 CALL dbcsr_release(la_near)
1185 IF (.NOT. lb_eq_la) CALL dbcsr_release(lb_near)
1186 IF (.NOT. lout_eq_la) CALL dbcsr_release(lout_near)
1187 END IF
1188
1189 END DO
1190
1191 CALL timestop(handle)
1192
1193 END SUBROUTINE contract_grid_panels
1194
1195! **************************************************************************************************
1196!> \brief Build the unfiltered auxiliary interaction M^-1 V^tr M^-1 in the Z-column layout.
1197!> AUTO_RI uses its already transformed Coulomb matrix in the optimized auxiliary basis.
1198!> Filtering and cache lifetime are owned by the caller.
1199!> \param qs_env electronic-structure environment for ordinary RI integrals
1200!> \param metric_inverse inverse auxiliary metric
1201!> \param trunc_coulomb Coulomb operator for ordinary RI integrals
1202!> \param auto_ri optimized auxiliary basis and its Coulomb matrix
1203!> \param mat_Z_lP template defining the auxiliary blocking and process grid
1204!> \param matrix_V_aux output bare interaction in the auxiliary basis
1205! **************************************************************************************************
1206 SUBROUTINE build_ri_rs_bare_aux_interaction(qs_env, metric_inverse, trunc_coulomb, auto_ri, &
1207 mat_Z_lP, matrix_V_aux)
1208 TYPE(qs_environment_type), POINTER :: qs_env
1209 TYPE(cp_fm_type), INTENT(IN) :: metric_inverse
1210 TYPE(libint_potential_type), INTENT(IN) :: trunc_coulomb
1211 TYPE(auto_ri_type), INTENT(IN) :: auto_ri
1212 TYPE(dbcsr_type), INTENT(IN) :: mat_z_lp
1213 TYPE(dbcsr_type), INTENT(OUT) :: matrix_v_aux
1214
1215 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_ri_rs_bare_aux_interaction'
1216
1217 INTEGER :: handle
1218 INTEGER, POINTER :: blk_aux(:), dist_row_aux(:)
1219 TYPE(cp_fm_type), ALLOCATABLE :: fm_vtr_gamma(:, :)
1220 TYPE(dbcsr_distribution_type) :: dist_aux_aux
1221
1222 CALL timeset(routinen, handle)
1223 IF (auto_ri%enabled) THEN
1224 cpassert(auto_ri%ready)
1225 ALLOCATE (fm_vtr_gamma(1, 1))
1226 CALL cp_fm_create(fm_vtr_gamma(1, 1), metric_inverse%matrix_struct)
1227 CALL cp_fm_to_fm(auto_ri%V_pq, fm_vtr_gamma(1, 1))
1228 ELSE
1229 CALL ri_2c_integral_mat(qs_env, fm_vtr_gamma, metric_inverse%matrix_struct, &
1230 metric_inverse%matrix_struct%nrow_global, trunc_coulomb)
1231 END IF
1232 CALL fm_contract_aba(metric_inverse, fm_vtr_gamma(:, 1))
1233 CALL setup_square_topology(mat_z_lp, 'COL', dist_aux_aux, blk_aux, dist_row_aux)
1234 CALL dbcsr_create(matrix_v_aux, "V_aux", dist_aux_aux, dbcsr_type_no_symmetry, blk_aux, blk_aux)
1235 CALL copy_fm_to_dbcsr(fm_vtr_gamma(1, 1), matrix_v_aux, keep_sparsity=.false.)
1236 CALL cp_fm_release(fm_vtr_gamma)
1237 CALL release_dbcsr_topology_and_matrices(dist=dist_aux_aux, mapped_dist=dist_row_aux)
1238 CALL timestop(handle)
1240
1241! **************************************************************************************************
1242!> \brief Resolve and cache grid-panel boundaries for RI-RS streaming contractions.
1243!> \param ri_rs collocation and fitting matrices, grid geometry and owned panel cache
1244!> \param para_env parallel environment
1245!> \param msg_elem_limit maximum number of elements per DBCSR message
1246!> \param pan_first ...
1247!> \param pan_last ...
1248!> \param cutoff grid-centroid distance cutoff; zero disables geometric truncation
1249! **************************************************************************************************
1250 SUBROUTINE resolve_grid_panels(ri_rs, para_env, msg_elem_limit, pan_first, pan_last, cutoff)
1251
1252 TYPE(ri_rs_env), INTENT(INOUT) :: ri_rs
1253 TYPE(mp_para_env_type), POINTER :: para_env
1254 INTEGER(KIND=int_8), INTENT(IN) :: msg_elem_limit
1255 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: pan_first, pan_last
1256 REAL(kind=dp), INTENT(IN) :: cutoff
1257
1258 CHARACTER(LEN=*), PARAMETER :: routinen = 'resolve_grid_panels'
1259
1260 INTEGER :: handle, min_dim, n_ao, n_grid_total, &
1261 n_ri, npcols, nprows
1262 INTEGER, DIMENSION(:), POINTER :: r_blk_sizes
1263 LOGICAL :: use_cutoff
1264 REAL(kind=dp) :: effective_cutoff, mem_avail_gb, &
1265 mem_budget_gb
1266 TYPE(dbcsr_distribution_type) :: dist
1267
1268 CALL timeset(routinen, handle)
1269
1270 use_cutoff = cutoff > 0.0_dp .AND. &
1271 ALLOCATED(ri_rs%chunk_centroids)
1272 effective_cutoff = 0.0_dp
1273 IF (use_cutoff) effective_cutoff = cutoff
1274 IF (ALLOCATED(ri_rs%pan_first)) THEN
1275 ! This is an exact cache key, not a tolerance-based geometric comparison.
1276 IF (ri_rs%panel_plan_cutoff == effective_cutoff) THEN
1277 ALLOCATE (pan_first, source=ri_rs%pan_first)
1278 ALLOCATE (pan_last, source=ri_rs%pan_last)
1279 CALL timestop(handle)
1280 RETURN
1281 END IF
1282 DEALLOCATE (ri_rs%pan_first, ri_rs%pan_last)
1283 END IF
1284
1285 ! MIN(nprows, npcols) is the divisor that bounds the worst-rank Cannon message: a
1286 ! P x n_grid panel is replicated into block row strips (P/nprows x n_grid) or column
1287 ! strips (P x n_grid/npcols) during multiply_cannon, so the largest single-rank
1288 ! message is ~ P*n_grid / MIN(nprows,npcols) elements.
1289 CALL dbcsr_get_info(ri_rs%mat_phi_mu_l, nfullrows_total=n_grid_total, nfullcols_total=n_ao, &
1290 row_blk_size=r_blk_sizes, distribution=dist)
1291 CALL dbcsr_distribution_get(dist, nprows=nprows, npcols=npcols)
1292 min_dim = max(min(nprows, npcols), 1)
1293
1294 CALL dbcsr_get_info(ri_rs%mat_Z_lP, nfullcols_total=n_ri)
1295 ! Only the cutoff path uses the measured free memory to limit panel sizes.
1296 mem_budget_gb = 0.0_dp
1297 IF (use_cutoff) THEN
1298 CALL mp_mem_avail_per_rank_gb(para_env, mem_avail_gb)
1299 mem_budget_gb = 0.5_dp*mem_avail_gb
1300 END IF
1301 CALL plan_grid_panels(msg_elem_limit, r_blk_sizes, min_dim, pan_first, pan_last, &
1302 n_ri, n_ao, para_env%num_pe, mem_budget_gb, &
1303 centroids=ri_rs%chunk_centroids, cutoff=effective_cutoff)
1304
1305 ALLOCATE (ri_rs%pan_first, source=pan_first)
1306 ALLOCATE (ri_rs%pan_last, source=pan_last)
1307 ri_rs%panel_plan_cutoff = effective_cutoff
1308
1309 CALL timestop(handle)
1310
1311 END SUBROUTINE resolve_grid_panels
1312
1313END MODULE ri_rs_matrices
subroutine, public dbcsr_distribution_release(dist)
...
integer function, public dbcsr_get_data_size(matrix)
...
subroutine, public dbcsr_distribution_new(dist, template, group, pgrid, row_dist, col_dist, reuse_arrays)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_multiply(transa, transb, alpha, matrix_a, matrix_b, beta, matrix_c, first_row, last_row, first_column, last_column, first_k, last_k, retain_sparsity, filter_eps, flop)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
real(kind=dp) function, public dbcsr_get_occupation(matrix)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
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_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr 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
Input and persistent data for automatic RI basis optimization.
Common DBCSR matrix operations used by GW modules.
subroutine, public hadamard_product_inplace(matrix_a, matrix_b, factor)
Form A = factor * (A element-wise B) without changing A's block structure.
Full-matrix operations not provided by the CP2K FM packages.
Definition gw_utils_fm.F:13
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public max_line_length
Definition kinds.F:59
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
2- and 3-center electron repulsion integral routines based on libint2 Currently available operators: ...
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:127
Interface to the message passing library MPI.
subroutine, public mp_mem_avail_per_rank_gb(comm, mem_avail_gb)
Memory that is currently free on the node, per MPI rank of that node, in GB.
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:576
DBCSR collocation, layouts and panel contractions for real-space resolution of the identity.
subroutine, public release_dbcsr_topology_and_matrices(dist, mapped_dist, m1, m2, m3, m4)
Releases RI-RS topology mappings and temporary DBCSR matrices.
subroutine, public resolve_grid_panels(ri_rs, para_env, msg_elem_limit, pan_first, pan_last, cutoff)
Resolve and cache grid-panel boundaries for RI-RS streaming contractions.
subroutine, public panel_template_elems(r_blk_sizes, centroids, used, blk0, blk1, cutoff, nze_tmpl)
Exact allocated-element count of the geo template of panel [blk0, blk1]: the very same per-block-pair...
subroutine, public setup_square_topology(matrix_template, dim_type, square_dist, blk_sizes, mapped_dist)
Creates a square topology from a selected row or column layout.
subroutine, public print_matrix_occupation(matrix, label, para_env, unit_nr, msg_elem_limit, suffix)
Prints the percentage of non-zero elements in a distributed RI-RS matrix.
subroutine, public panel_mem_estimate_gb(nze_tmpl, pan_rows, width, n_grid_total, n_ri, n_ao, n_procs, mem_gb)
Per-rank peak memory (GB) of one panel step of the neighborhood-restricted contractions: up to three ...
subroutine, public mask_grid_blocks_near_panel(centroids, blk0, blk1, cutoff, used)
Marks the grid blocks whose centroid lies within cutoff of the bounding box of the panel [blk0,...
subroutine, public build_ri_rs_bare_aux_interaction(qs_env, metric_inverse, trunc_coulomb, auto_ri, mat_z_lp, matrix_v_aux)
Build the unfiltered auxiliary interaction M^-1 V^tr M^-1 in the Z-column layout. AUTO_RI uses its al...
subroutine, public reserve_blocks_within_radius(matrix, centers, radius)
Reserves grid blocks with block-centre distances within a fixed radius.
subroutine, public atomic_basis_at_grid_point(ri_rs, basis_set_ao, matrix_template, para_env, eps_filter, msg_elem_limit, unit_nr, periodic_images)
Builds the grid-by-AO collocation matrix with bounded dense evaluation panels. The molecular path use...
subroutine, public contract_grid_panels(l_a, m_a, l_b, m_b, l_out, mat_out, scale, eps, para_env, pan_first, pan_last, lb_eq_la, lout_eq_la, zero_out, centroids, cutoff, grid_occupation)
Projects two operators onto grid panels, takes their Hadamard product, and back-projects it: out += s...
Shared real-space resolution-of-identity grid and matrix data.
Definition ri_rs_types.F:11
Geometry and AO evaluation for real-space resolution of the identity.
Definition ri_rs_utils.F:11
subroutine, public evaluate_ao_basis_on_points(phi, grid_points, basis, source_position, cell, dphi, cutoff_squared, periodic_images)
Evaluate one explicitly supplied contracted Gaussian basis on Cartesian points.
represent a full matrix
stores all the informations relevant to an mpi environment