68#include "./base/base_uses.f90"
73 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'ri_rs_setup'
89 CHARACTER(LEN=*),
PARAMETER :: routinen =
'ensure_ri_rs_representation'
92 REAL(kind=
dp) :: build_start
94 CALL timeset(routinen, handle)
95 IF (.NOT. bs_env%ri_rs%grid_built)
THEN
97 CALL get_qs_env(qs_env, atomic_kind_set=bs_env%ri_rs%atomic_kind_set, &
98 cell=bs_env%ri_rs%cell, particle_set=bs_env%ri_rs%particle_set)
100 IF (.NOT.
ALLOCATED(bs_env%ri_rs%radius_ao_per_atom))
THEN
102 bs_env%eps_filter, bs_env%unit_nr)
108 bs_env%mat_ao_ao%matrix, bs_env%para_env, bs_env%eps_filter, &
109 bs_env%dbcsr_msg_elem_limit, bs_env%unit_nr, &
110 periodic_images=bs_env%do_periodic)
112 bs_env%para_env, bs_env%unit_nr, bs_env%dbcsr_msg_elem_limit)
114 CALL compute_z_lp(qs_env, bs_env, bs_env%ri_rs%grid_points, &
115 bs_env%ri_rs%mat_phi_mu_l, bs_env%ri_rs%mat_Z_lP, &
116 periodic_images=bs_env%do_periodic)
117 bs_env%ri_rs%grid_built = .true.
118 IF (bs_env%unit_nr > 0)
THEN
119 WRITE (bs_env%unit_nr,
'(T2,A,T58,A,F7.1,A)') &
120 'Built RI-RS representation,',
' Execution time',
m_walltime() - build_start,
' s'
121 WRITE (bs_env%unit_nr,
'(A)')
' '
124 CALL timestop(handle)
150 SUBROUTINE compute_z_lp(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_Z_lP, periodic_images)
153 REAL(kind=
dp),
INTENT(IN) :: ri_rs_grid_points(:, :)
154 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_phi_mu_l
156 LOGICAL,
INTENT(IN),
OPTIONAL :: periodic_images
158 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_Z_lP'
161 LOGICAL :: sum_images
162 REAL(kind=
dp) :: fitting_stats(2)
164 CALL timeset(routinen, handle)
166 IF (
PRESENT(periodic_images)) sum_images = periodic_images
168 bs_env%ri_rs%fit_max_grid = 0
169 bs_env%ri_rs%fit_peak_bytes = 0.0_dp
170 IF (bs_env%auto_ri%enabled)
THEN
171 CALL compute_z_lp_auto_ri(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_z_lp)
173 fitting_stats = [real(bs_env%ri_rs%fit_max_grid,
dp), bs_env%ri_rs%fit_peak_bytes]
174 CALL bs_env%para_env%max(fitting_stats)
175 bs_env%ri_rs%fit_max_grid = nint(fitting_stats(1))
176 bs_env%ri_rs%fit_peak_bytes = fitting_stats(2)
178 CALL compute_z_lp_standard(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_z_lp, sum_images)
181 CALL timestop(handle)
216 SUBROUTINE compute_z_lp_standard(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_Z_lP, periodic_images)
220 REAL(kind=
dp),
INTENT(IN) :: ri_rs_grid_points(:, :)
221 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_phi_mu_l
223 LOGICAL,
INTENT(IN) :: periodic_images
225 CHARACTER(LEN=*),
PARAMETER :: key =
'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
226 routinen =
'compute_Z_lP_standard'
228 INTEGER :: atom_j_mepos, atom_j_stride, atom_p, g, handle, i_blk, iatom,
idx, iphase, j, &
229 max_ao_size, my_group, n_big, n_done, n_groups, n_loc_ri, n_local_grid, n_my_atoms, &
230 n_small, natom, npcol_phi, num_grid_chunks, phase_hi
231 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ao_atoms, ao_col_start, big_list, local_grid_idx, &
232 my_atoms_a, my_atoms_b, n_local_grid_atom, row_offset, small_list
233 INTEGER,
DIMENSION(:),
POINTER :: col_dist_ri, r_blk_sizes, ri_blk_sizes, &
235 LOGICAL :: do_scatter, use_dist
236 LOGICAL,
ALLOCATABLE :: ao_nonzero(:, :)
237 REAL(kind=
dp) :: cutoff_ri, item_start_time, r_c, t1
238 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: cutoff_ri_per_atom
239 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_lp_local, phi_local
247 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
250 CALL timeset(routinen, handle)
254 CALL get_qs_env(qs_env, para_env=para_env, particle_set=particle_set, input=input, &
255 qs_kind_set=qs_kind_set, cell=cell)
257 NULLIFY (para_env_sub, blacs_env_sub)
259 natom = bs_env%n_atom
266 CALL dbcsr_get_info(mat_phi_mu_l, row_blk_size=r_blk_sizes, distribution=dist_phi)
269 num_grid_chunks =
SIZE(r_blk_sizes)
271 ALLOCATE (row_offset(num_grid_chunks))
273 DO i_blk = 2, num_grid_chunks
274 row_offset(i_blk) = row_offset(i_blk - 1) + r_blk_sizes(i_blk - 1)
277 ALLOCATE (ri_blk_sizes(natom), col_dist_ri(natom))
279 ri_blk_sizes(iatom) = &
280 bs_env%i_RI_end_from_atom(iatom) - bs_env%i_RI_start_from_atom(iatom) + 1
281 col_dist_ri(iatom) = mod(iatom - 1, npcol_phi)
285 row_dist=row_dist_grid, col_dist=col_dist_ri)
287 IF (bs_env%ri_rs%Z_lP_exists)
THEN
289 distribution=dist_z, &
291 IF (bs_env%unit_nr > 0)
THEN
292 WRITE (bs_env%unit_nr,
'(T2,A,T57,A,F7.1,A)') &
293 'Read Z_lP from file ',
' Execution time',
m_walltime() - t1,
' s'
297 WRITE (bs_env%unit_nr,
'(T2,A)') &
298 '*** NOTE: Z_lP restart must match the current (spatial) grid row ordering ***'
299 WRITE (bs_env%unit_nr,
'(A)')
' '
303 IF (bs_env%unit_nr > 0)
THEN
304 WRITE (bs_env%unit_nr,
'(A)')
' '
305 WRITE (bs_env%unit_nr,
'(T2,A)')
'Started computing Z_lP'
308 CALL dbcsr_create(mat_z_lp, name=
"mat_Z_lP", dist=dist_z, &
309 matrix_type=dbcsr_type_no_symmetry, &
310 row_blk_size=r_blk_sizes, col_blk_size=ri_blk_sizes)
314 DO j = 1, bs_env%n_atom
315 max_ao_size = max(max_ao_size, &
316 bs_env%i_ao_end_from_atom(j) - &
317 bs_env%i_ao_start_from_atom(j) + 1)
322 ALLOCATE (cutoff_ri_per_atom(natom))
324 r_c = bs_env%ri_metric%cutoff_radius
326 IF (periodic_images)
THEN
327 cutoff_ri_per_atom(iatom) = r_c + bs_env%ri_rs%radius_ao_per_atom(iatom)
329 cutoff_ri_per_atom(iatom) = r_c + bs_env%ri_rs%radius_ri_per_atom(iatom)
333 CALL print_sphere_cutoff_table(bs_env, cutoff_ri_per_atom)
341 CALL classify_z_lp_atoms(bs_env, ri_rs_grid_points, cutoff_ri_per_atom, ri_blk_sizes, &
342 n_local_grid_atom, small_list, n_small, big_list, n_big, g, periodic_images)
347 CALL lpt_assign_atoms(small_list, n_small, n_local_grid_atom, para_env%num_pe, &
348 para_env%mepos, my_atoms_a)
350 n_groups = para_env%num_pe/g
351 my_group = min(para_env%mepos/g, n_groups - 1)
352 CALL lpt_assign_atoms(big_list, n_big, n_local_grid_atom, n_groups, my_group, &
355 ALLOCATE (my_atoms_b(0))
359 n_my_atoms =
SIZE(my_atoms_a) +
SIZE(my_atoms_b)
364 basis_j=bs_env%basis_set_AO, basis_k=bs_env%basis_set_AO, &
365 basis_i=bs_env%basis_set_RI)
375 IF (iphase == 1)
THEN
379 phase_hi =
SIZE(my_atoms_a)
381 IF (n_big == 0) cycle
383 n_groups = para_env%num_pe/g
384 my_group = min(para_env%mepos/g, n_groups - 1)
385 ALLOCATE (para_env_sub)
386 CALL para_env_sub%from_split(para_env, my_group)
388 atom_j_mepos = para_env_sub%mepos
389 atom_j_stride = para_env_sub%num_pe
392 phase_hi =
SIZE(my_atoms_b)
397 IF (iphase == 1)
THEN
398 atom_p = my_atoms_a(
idx)
400 atom_p = my_atoms_b(
idx)
403 n_loc_ri = ri_blk_sizes(atom_p)
404 cutoff_ri = cutoff_ri_per_atom(atom_p)
411 CALL build_phi_on_sphere(bs_env, qs_kind_set, &
412 ri_rs_grid_points, atom_p, cutoff_ri, &
413 local_grid_idx, n_local_grid, phi_local, &
414 ao_atoms, ao_col_start, periodic_images=periodic_images, ao_nonzero=ao_nonzero)
419 ALLOCATE (d_lp_local(n_local_grid, n_loc_ri))
422 CALL compute_d_lp(bs_env, ctx_3c, phi_local, ao_atoms, ao_col_start, ao_nonzero, d_lp_local, n_local_grid, &
423 n_loc_ri, atom_p, max_ao_size, atom_j_mepos, atom_j_stride, periodic_images)
425 DEALLOCATE (ao_atoms, ao_col_start, ao_nonzero)
430 CALL para_env_sub%sum(d_lp_local)
438 para_env_sub, blacs_env_sub)
447 IF (use_dist) do_scatter = (para_env_sub%mepos == 0)
450 n_loc_ri, atom_p, r_blk_sizes, row_offset, &
454 DEALLOCATE (d_lp_local)
455 DEALLOCATE (local_grid_idx, phi_local)
460 CALL print_z_lp_progress(bs_env, n_done, n_my_atoms, &
465 IF (iphase == 2)
THEN
467 CALL para_env_sub%free()
468 DEALLOCATE (para_env_sub)
472 DEALLOCATE (cutoff_ri_per_atom)
473 DEALLOCATE (small_list, big_list)
480 CALL print_z_lp_progress(bs_env, natom, natom,
m_walltime() - t1, &
481 all_mpi_ranks=.true.)
491 DEALLOCATE (row_offset, ri_blk_sizes, col_dist_ri)
494 CALL timestop(handle)
496 END SUBROUTINE compute_z_lp_standard
503 SUBROUTINE print_sphere_cutoff_table(bs_env, cutoff_ri_per_atom)
506 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: cutoff_ri_per_atom
508 CHARACTER(LEN=*),
PARAMETER :: routinen =
'print_sphere_cutoff_table'
510 INTEGER :: handle, iatom, ikind, nkind
511 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: cutoff_ri_per_kind
515 CALL timeset(routinen, handle)
517 atomic_kind_set => bs_env%ri_rs%atomic_kind_set
518 particle_set => bs_env%ri_rs%particle_set
520 IF (bs_env%unit_nr <= 0)
THEN
521 CALL timestop(handle)
525 nkind =
SIZE(atomic_kind_set)
526 ALLOCATE (cutoff_ri_per_kind(nkind))
527 cutoff_ri_per_kind(:) = 0.0_dp
529 DO iatom = 1, bs_env%n_atom
530 ikind = particle_set(iatom)%atomic_kind%kind_number
531 cutoff_ri_per_kind(ikind) = max(cutoff_ri_per_kind(ikind), cutoff_ri_per_atom(iatom))
534 WRITE (bs_env%unit_nr,
'(T2,A)')
'Per-kind maximum RI-RS sphere cutoff (Å):'
535 WRITE (bs_env%unit_nr,
'(T4,A4,A14)')
'Kind',
'cutoff (Å)'
537 WRITE (bs_env%unit_nr,
'(T4,A4,F14.4)') &
538 atomic_kind_set(ikind)%element_symbol, &
541 WRITE (bs_env%unit_nr,
'(A)')
' '
543 DEALLOCATE (cutoff_ri_per_kind)
545 CALL timestop(handle)
547 END SUBROUTINE print_sphere_cutoff_table
561 SUBROUTINE lpt_assign_atoms(atom_list, n_atoms, n_local_grid_atom, n_workers, my_worker, &
564 INTEGER,
DIMENSION(:),
INTENT(IN) :: atom_list
565 INTEGER,
INTENT(IN) :: n_atoms
566 INTEGER,
DIMENSION(:),
INTENT(IN) :: n_local_grid_atom
567 INTEGER,
INTENT(IN) :: n_workers, my_worker
568 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: my_atoms
570 CHARACTER(LEN=*),
PARAMETER :: routinen =
'lpt_assign_atoms'
572 INTEGER :: handle, i, iw, n_mine, w_min
573 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: mine_tmp, perm
574 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: cost, load
576 CALL timeset(routinen, handle)
578 IF (n_atoms <= 0)
THEN
579 ALLOCATE (my_atoms(0))
580 CALL timestop(handle)
584 ALLOCATE (cost(n_atoms), perm(n_atoms), mine_tmp(n_atoms), load(n_workers))
586 cost(i) = real(n_local_grid_atom(atom_list(i)),
dp)**3
588 CALL sort(cost, n_atoms, perm)
592 DO i = n_atoms, 1, -1
595 IF (load(iw) < load(w_min)) w_min = iw
597 load(w_min) = load(w_min) + cost(i)
598 IF (w_min - 1 == my_worker)
THEN
600 mine_tmp(n_mine) = atom_list(perm(i))
604 ALLOCATE (my_atoms(n_mine))
605 my_atoms(:) = mine_tmp(1:n_mine)
607 CALL timestop(handle)
609 END SUBROUTINE lpt_assign_atoms
637 SUBROUTINE compute_d_lp(bs_env, ctx, phi_val, ao_atoms, ao_col_start, ao_nonzero, d_lp, n_grid_total, n_loc_ri, atom_P, &
638 max_ao_size, atom_j_mepos, atom_j_stride, periodic_images)
642 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: phi_val
643 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_atoms, ao_col_start
644 LOGICAL,
DIMENSION(:, :),
INTENT(IN) :: ao_nonzero
645 INTEGER,
INTENT(IN) :: n_grid_total, n_loc_ri
646 REAL(kind=
dp),
INTENT(INOUT) :: d_lp(n_grid_total, n_loc_ri)
647 INTEGER,
INTENT(IN) :: atom_p, max_ao_size, atom_j_mepos, &
649 LOGICAL,
INTENT(IN) :: periodic_images
651 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_d_lp'
652 INTEGER,
PARAMETER :: grid_chunk = 1024
654 INTEGER :: atom_j, atom_k, c, cell_r_vec(3), cell_s_vec(3), handle, handle2, &
655 image_extent(3), ix_r, ix_s, iy_r, iy_s, iz_r, iz_s, j, jj, jk_idx, jsize, jstart, k, kk, &
656 ksize, kstart, l, l0, n_grid_pair, point, ri
657 INTEGER,
ALLOCATABLE :: grid_index(:)
658 LOGICAL :: any_kept, screened
659 REAL(kind=
dp) :: pair_factor
660 REAL(kind=
dp),
ALLOCATABLE :: grid_result(:, :), int_3c_prv(:, :, :)
661 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_lp_prv, int_2d_prv, rho_chunk
664 CALL timeset(routinen, handle)
666 IF (periodic_images) image_extent = bs_env%ri_rs%cell%perd
679 ALLOCATE (int_3c_prv(max_ao_size, max_ao_size, n_loc_ri))
680 ALLOCATE (int_2d_prv(max_ao_size*max_ao_size, n_loc_ri))
681 ALLOCATE (rho_chunk(grid_chunk, max_ao_size*max_ao_size))
682 ALLOCATE (d_lp_prv(n_grid_total, n_loc_ri))
683 ALLOCATE (grid_index(n_grid_total), grid_result(grid_chunk, n_loc_ri))
684 d_lp_prv(:, :) = 0.0_dp
689 DO jj = 1,
SIZE(ao_atoms)
690 atom_j = ao_atoms(jj)
691 IF (mod(atom_j - 1, atom_j_stride) /= atom_j_mepos) cycle
692 DO kk = jj,
SIZE(ao_atoms)
693 atom_k = ao_atoms(kk)
694 jstart = ao_col_start(jj)
695 kstart = ao_col_start(kk)
696 jsize = ao_col_start(jj + 1) - jstart
697 ksize = ao_col_start(kk + 1) - kstart
700 DO point = 1, n_grid_total
701 IF (.NOT. (ao_nonzero(point, jj) .AND. ao_nonzero(point, kk))) cycle
702 n_grid_pair = n_grid_pair + 1
703 grid_index(n_grid_pair) = point
705 IF (n_grid_pair == 0) cycle
708 IF (atom_j /= atom_k) pair_factor = 2.0_dp
715 int_3c_prv(1:jsize, 1:ksize, 1:n_loc_ri) = 0.0_dp
717 DO ix_r = -image_extent(1), image_extent(1)
718 DO iy_r = -image_extent(2), image_extent(2)
719 DO iz_r = -image_extent(3), image_extent(3)
720 cell_r_vec = [ix_r, iy_r, iz_r]
721 DO ix_s = -image_extent(1), image_extent(1)
722 DO iy_s = -image_extent(2), image_extent(2)
723 DO iz_s = -image_extent(3), image_extent(3)
724 cell_s_vec = [ix_s, iy_s, iz_s]
726 ctx, ws, atom_j=atom_j, atom_k=atom_k, atom_i=atom_p, &
727 cell_j=cell_r_vec, cell_k=cell_s_vec, screened=screened)
736 IF (.NOT. any_kept) cycle
742 jk_idx = (k - 1)*jsize + j
743 int_2d_prv(jk_idx, ri) = int_3c_prv(j, k, ri)
750 DO l0 = 1, n_grid_pair, grid_chunk
751 c = min(grid_chunk, n_grid_pair - l0 + 1)
754 jk_idx = (k - 1)*jsize + j
756 point = grid_index(l0 + l - 1)
757 rho_chunk(l, jk_idx) = phi_val(point, jstart + j - 1)* &
758 phi_val(point, kstart + k - 1)
762 CALL timeset(routinen//
"_dgemm", handle2)
763 CALL dgemm(
"N",
"N", c, n_loc_ri, jsize*ksize, &
764 pair_factor, rho_chunk, grid_chunk, &
765 int_2d_prv, max_ao_size*max_ao_size, &
766 0.0_dp, grid_result, grid_chunk)
769 point = grid_index(l0 + l - 1)
770 d_lp_prv(point, ri) = d_lp_prv(point, ri) + grid_result(l, ri)
773 CALL timestop(handle2)
781 d_lp(1:n_grid_total, 1:n_loc_ri) = d_lp(1:n_grid_total, 1:n_loc_ri) + &
782 d_lp_prv(1:n_grid_total, 1:n_loc_ri)
785 DEALLOCATE (int_3c_prv, int_2d_prv, rho_chunk, d_lp_prv, grid_index, grid_result)
790 CALL timestop(handle)
792 END SUBROUTINE compute_d_lp
818 SUBROUTINE compute_z_lp_auto_ri(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_Z_lP)
821 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
822 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_phi_mu_l
825 CHARACTER(LEN=*),
PARAMETER :: key =
'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
826 routinen =
'compute_Z_lP_auto_ri'
828 INTEGER :: ab_block, atom_a, atom_b, block_size_b, column_first, first_p_ab, fit_atom, &
829 handle, last_atom, max_ao_size, max_nri_ref, mypcol, myprow, n_active, n_candidate, &
830 n_done, n_my_atoms, n_to_a, natom, ncol, ngrid, nri, nri_ref_a, nri_ref_b, output_offset, &
832 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ao_atoms, ao_col_start, candidate_order, &
833 candidates, local_grid_idx, ri_atoms, &
835 INTEGER,
DIMENSION(:),
POINTER :: col_dist_ri, ri_blk_sizes, &
836 row_dist_grid, row_size_grid
837 LOGICAL :: ab_block_local, common_grid_available, &
838 have_fitted_columns, &
839 reuse_atomic_integrals
840 LOGICAL,
ALLOCATABLE :: ao_nonzero(:, :)
841 REAL(kind=
dp) :: cutoff_ri, item_start_time, &
842 mem_avail_gb, previous_fit_peak, r_c, &
844 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_lp_all, d_lp_local, phi_local, u_pp_ab
845 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: u_active
846 REAL(kind=
dp),
DIMENSION(3) :: center
854 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
857 CALL timeset(routinen, handle)
859 IF (bs_env%unit_nr > 0)
THEN
860 WRITE (bs_env%unit_nr,
'(A)')
' '
861 WRITE (bs_env%unit_nr,
'(T2,A)')
'Started computing Z_lP'
864 CALL get_qs_env(qs_env, para_env=para_env, particle_set=particle_set, input=input, &
865 qs_kind_set=qs_kind_set, cell=cell)
866 NULLIFY (para_env_col)
868 natom = bs_env%n_atom
869 cpassert(bs_env%auto_ri%AB_block_count > 0)
870 cpassert(
SIZE(particle_set) == natom)
872 CALL prepare_z_lp_auto_ri(bs_env, mat_phi_mu_l, mat_z_lp, dist_z, row_size_grid, &
873 row_dist_grid, col_dist_ri, ri_blk_sizes, row_offset, &
874 myprow, mypcol, max_ao_size)
877 basis_j=bs_env%basis_set_AO, basis_k=bs_env%basis_set_AO, &
878 basis_i=bs_env%basis_set_RI)
881 CALL common_z_lp_grid_available(bs_env, ri_rs_grid_points, &
882 common_grid_available, have_fitted_columns)
884 IF (common_grid_available .AND. have_fitted_columns)
THEN
887 CALL build_phi_on_complete_grid(bs_env, qs_kind_set, &
888 ri_rs_grid_points, local_grid_idx, ngrid, &
889 phi_local, ao_atoms, ao_col_start, ao_nonzero)
890 nri = sum(ri_blk_sizes)
891 CALL record_fit_memory(bs_env%ri_rs, ngrid,
SIZE(phi_local, 2), nri)
892 CALL print_fit_memory_estimate(bs_env, mem_avail_gb)
893 ALLOCATE (d_lp_all(ngrid, nri), source=0.0_dp)
895 CALL compute_d_lp_auto_ri_batch(bs_env, ctx_3c, phi_local, ao_atoms, ao_col_start, ao_nonzero, d_lp_all, ngrid, &
896 max_ao_size, para_env%mepos, para_env%num_pe)
897 DEALLOCATE (ao_atoms, ao_col_start, ao_nonzero)
898 CALL para_env%sum(d_lp_all)
901 DO ab_block = 1, bs_env%auto_ri%AB_block_count
902 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
903 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
904 ab_block_local = col_dist_ri(atom_a) == mypcol
905 IF (atom_b /= atom_a) ab_block_local = ab_block_local .OR. col_dist_ri(atom_b) == mypcol
906 IF (.NOT. ab_block_local) cycle
907 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block)
908 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
909 IF (n_to_a > 0 .AND. col_dist_ri(atom_a) == mypcol)
THEN
910 output_offset = sum(ri_blk_sizes(:atom_a - 1)) + &
911 bs_env%auto_ri%AB_first_p_A(ab_block) - 1
912 CALL add_z_lp_columns(mat_z_lp, &
913 d_lp_all(:, output_offset + 1:output_offset + n_to_a), &
914 local_grid_idx, ngrid, atom_a, &
915 bs_env%auto_ri%AB_first_p_A(ab_block), &
916 ri_blk_sizes(atom_a), row_size_grid, row_offset, &
918 myprow, bs_env%eps_filter)
920 IF (n_to_a < ncol)
THEN
921 cpassert(atom_b /= atom_a)
922 IF (col_dist_ri(atom_b) == mypcol)
THEN
923 block_size_b = ri_blk_sizes(atom_b)
924 output_offset = sum(ri_blk_sizes(:atom_b - 1)) + &
925 bs_env%auto_ri%AB_first_p_B(ab_block) - 1
926 CALL add_z_lp_columns(mat_z_lp, &
927 d_lp_all(:, output_offset + 1: &
928 output_offset + ncol - n_to_a), &
929 local_grid_idx, ngrid, atom_b, &
930 bs_env%auto_ri%AB_first_p_B(ab_block), block_size_b, &
931 row_size_grid, row_offset, row_dist_grid, myprow, &
936 DEALLOCATE (d_lp_all, local_grid_idx, phi_local)
938 reuse_atomic_integrals = &
939 bs_env%ri_rs%cutoff_radius_ri_ao <= 0.0_dp .OR. &
940 bs_env%ri_rs%cutoff_radius_ri_ao <= &
941 minval(bs_env%ri_rs%radius_ao_per_atom)
942 IF (reuse_atomic_integrals)
THEN
944 CALL compute_auto_ri_d_lp(qs_env, bs_env, ctx_3c, &
945 ri_rs_grid_points, mat_phi_mu_l, mat_rhs, &
948 CALL dbcsr_create(mat_z_lp, name=
'mat_Z_lP localized AA/AB', dist=dist_z, &
949 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size_grid, &
950 col_blk_size=ri_blk_sizes)
952 CALL fit_auto_ri_z_lp(qs_env, bs_env, ri_rs_grid_points, mat_rhs, mat_z_lp)
957 ALLOCATE (para_env_col)
958 CALL para_env_col%from_split(para_env, mypcol)
960 DO fit_atom = 1, natom
961 IF (col_dist_ri(fit_atom) /= mypcol) cycle
962 IF (ri_blk_sizes(fit_atom) == 0) cycle
963 n_my_atoms = n_my_atoms + 1
966 ALLOCATE (candidates(2*bs_env%auto_ri%AB_block_count), &
967 candidate_order(2*bs_env%auto_ri%AB_block_count))
968 DO fit_atom = 1, natom
969 IF (col_dist_ri(fit_atom) /= mypcol) cycle
970 ncol = ri_blk_sizes(fit_atom)
975 DO ab_block = 1, bs_env%auto_ri%AB_block_count
976 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
977 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
978 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
979 IF (.NOT. ((fit_atom == atom_a .AND. n_to_a > 0) .OR. &
980 (fit_atom == atom_b .AND. &
981 n_to_a < bs_env%auto_ri%AB_size_opt_RI(ab_block)))) cycle
982 n_candidate = n_candidate + 1
983 candidates(n_candidate) = atom_a
984 IF (atom_b == atom_a) cycle
985 n_candidate = n_candidate + 1
986 candidates(n_candidate) = atom_b
988 cpassert(n_candidate > 0)
989 CALL sort(candidates, n_candidate, candidate_order)
992 DO slot = 1, n_candidate
993 ri_atom = candidates(slot)
994 IF (ri_atom == last_atom) cycle
995 n_active = n_active + 1
996 candidates(n_active) = ri_atom
999 ALLOCATE (ri_atoms(n_active), source=candidates(:n_active))
1001 DO slot = 1, n_active
1002 max_nri_ref = max(max_nri_ref, get_ref_ri_size(bs_env, ri_atoms(slot)))
1004 ALLOCATE (u_active(max_nri_ref, ncol, n_active), source=0.0_dp)
1006 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1007 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1008 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1009 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
1010 IF (fit_atom == atom_a .AND. n_to_a > 0)
THEN
1011 column_first = bs_env%auto_ri%AB_first_p_A(ab_block)
1014 ELSE IF (fit_atom == atom_b .AND. &
1015 n_to_a < bs_env%auto_ri%AB_size_opt_RI(ab_block))
THEN
1016 column_first = bs_env%auto_ri%AB_first_p_B(ab_block)
1017 first_p_ab = n_to_a + 1
1018 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block) - n_to_a
1022 CALL get_u_pp_ab(bs_env%auto_ri, ab_block, u_pp_ab)
1024 slot =
locate(ri_atoms, atom_a)
1025 nri_ref_a = get_ref_ri_size(bs_env, atom_a)
1026 u_active(1:nri_ref_a, &
1027 column_first:column_first + ncol - 1, slot) = &
1029 1:nri_ref_a, first_p_ab:first_p_ab + ncol - 1)
1030 IF (atom_b /= atom_a)
THEN
1031 slot =
locate(ri_atoms, atom_b)
1032 nri_ref_b = get_ref_ri_size(bs_env, atom_b)
1033 u_active(1:nri_ref_b, &
1034 column_first:column_first + ncol - 1, slot) = &
1036 nri_ref_a + 1:nri_ref_a + nri_ref_b, &
1037 first_p_ab:first_p_ab + ncol - 1)
1039 DEALLOCATE (u_pp_ab)
1042 center = particle_set(fit_atom)%r
1043 r_c = bs_env%ri_metric%cutoff_radius
1045 DO slot = 1, n_active
1046 ri_atom = ri_atoms(slot)
1047 cutoff_ri = max(cutoff_ri, &
1048 r_c + bs_env%ri_rs%radius_ri_per_atom(ri_atom) + &
1049 norm2(center - particle_set(ri_atom)%r))
1051 CALL build_phi_on_sphere(bs_env, qs_kind_set, &
1052 ri_rs_grid_points, fit_atom, cutoff_ri, &
1053 local_grid_idx, ngrid, phi_local, ao_atoms, ao_col_start, &
1054 center=center, ao_nonzero=ao_nonzero)
1055 ncol = ri_blk_sizes(fit_atom)
1056 previous_fit_peak = bs_env%ri_rs%fit_peak_bytes
1057 CALL record_fit_memory(bs_env%ri_rs, ngrid,
SIZE(phi_local, 2), ncol)
1058 IF (bs_env%ri_rs%fit_peak_bytes > previous_fit_peak)
THEN
1059 CALL print_fit_memory_estimate(bs_env, mem_avail_gb)
1061 ALLOCATE (d_lp_local(ngrid, ncol), source=0.0_dp)
1063 CALL compute_d_lp_auto_ri(bs_env, ctx_3c, phi_local, ao_atoms, ao_col_start, ao_nonzero, &
1064 d_lp_local, ri_atoms, u_active, max_ao_size, &
1065 para_env_col%mepos, para_env_col%num_pe)
1066 DEALLOCATE (ao_atoms, ao_col_start, ao_nonzero)
1067 CALL para_env_col%sum(d_lp_local)
1069 CALL add_z_lp_columns(mat_z_lp, d_lp_local, local_grid_idx, ngrid, fit_atom, 1, &
1070 ri_blk_sizes(fit_atom), row_size_grid, row_offset, &
1072 myprow, bs_env%eps_filter)
1073 DEALLOCATE (d_lp_local, local_grid_idx, phi_local)
1074 DEALLOCATE (u_active, ri_atoms)
1076 CALL print_z_lp_progress(bs_env, n_done, n_my_atoms, &
1079 DEALLOCATE (candidates, candidate_order)
1080 CALL para_env_col%free()
1081 DEALLOCATE (para_env_col)
1088 CALL para_env%sync()
1089 CALL print_z_lp_progress(bs_env, natom, natom,
m_walltime() - t1, &
1090 all_mpi_ranks=.true.)
1093 CALL dbcsr_binary_write(matrix=mat_z_lp, filepath=trim(bs_env%prefix)//
'Z_lP.matrix')
1096 DEALLOCATE (row_offset, ri_blk_sizes, col_dist_ri)
1098 CALL timestop(handle)
1100 END SUBROUTINE compute_z_lp_auto_ri
1110 SUBROUTINE print_z_lp_progress(bs_env, n_done, n_total, execution_time, all_mpi_ranks)
1112 INTEGER,
INTENT(IN) :: n_done, n_total
1113 REAL(kind=
dp),
INTENT(IN) :: execution_time
1114 LOGICAL,
INTENT(IN),
OPTIONAL :: all_mpi_ranks
1116 CHARACTER(LEN=*),
PARAMETER :: routinen =
'print_Z_lP_progress'
1119 LOGICAL :: completed
1121 CALL timeset(routinen, handle)
1123 IF (bs_env%unit_nr > 0)
THEN
1125 IF (
PRESENT(all_mpi_ranks)) completed = all_mpi_ranks
1127 WRITE (bs_env%unit_nr,
'(T2,A,T58,A,F7.1,A,/)') &
1128 'Computed Z_lP (all MPI ranks) for all atoms,', &
1129 'Execution time', execution_time,
' s'
1131 WRITE (bs_env%unit_nr,
'(T2,A,I11,A,I3,A,F7.1,A)') &
1132 'Computed Z_lP (MPI rank 0) for atom', n_done,
' /', n_total, &
1133 ', Execution time', execution_time,
' s'
1138 CALL timestop(handle)
1140 END SUBROUTINE print_z_lp_progress
1159 SUBROUTINE prepare_z_lp_auto_ri(bs_env, mat_phi_mu_l, mat_Z_lP, dist_Z, row_size_grid, &
1160 row_dist_grid, col_dist_ri, ri_blk_sizes, row_offset, &
1161 myprow, mypcol, max_ao_size)
1166 INTEGER,
DIMENSION(:),
POINTER :: row_size_grid, row_dist_grid, &
1167 col_dist_ri, ri_blk_sizes
1168 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: row_offset
1169 INTEGER,
INTENT(OUT) :: myprow, mypcol, max_ao_size
1171 CHARACTER(LEN=*),
PARAMETER :: routinen =
'prepare_Z_lP_auto_ri'
1173 INTEGER :: handle, i_blk, iatom, npcol
1176 CALL timeset(routinen, handle)
1178 CALL dbcsr_get_info(mat_phi_mu_l, row_blk_size=row_size_grid, distribution=dist_phi)
1180 myprow=myprow, mypcol=mypcol)
1181 ALLOCATE (row_offset(
SIZE(row_size_grid)))
1183 DO i_blk = 2,
SIZE(row_size_grid)
1184 row_offset(i_blk) = row_offset(i_blk - 1) + row_size_grid(i_blk - 1)
1187 ALLOCATE (ri_blk_sizes(bs_env%n_atom), col_dist_ri(bs_env%n_atom))
1188 ri_blk_sizes = bs_env%auto_ri%sizes_opt_RI
1189 DO iatom = 1, bs_env%n_atom
1190 col_dist_ri(iatom) = mod(iatom - 1, npcol)
1193 col_dist=col_dist_ri)
1194 CALL dbcsr_create(mat_z_lp, name=
'mat_Z_lP localized AA/AB', dist=dist_z, &
1195 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size_grid, &
1196 col_blk_size=ri_blk_sizes)
1201 DO iatom = 1, bs_env%n_atom
1202 max_ao_size = max(max_ao_size, bs_env%i_ao_end_from_atom(iatom) - &
1203 bs_env%i_ao_start_from_atom(iatom) + 1)
1206 CALL timestop(handle)
1208 END SUBROUTINE prepare_z_lp_auto_ri
1227 SUBROUTINE common_z_lp_grid_available(bs_env, ri_rs_grid_points, &
1228 common_grid_available, have_fitted_columns)
1230 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
1231 LOGICAL,
INTENT(OUT) :: common_grid_available, &
1234 CHARACTER(LEN=*),
PARAMETER :: routinen =
'common_Z_lP_grid_available'
1236 INTEGER :: ab_block, atom_a, atom_b, fit_atom, &
1237 handle, iatom, igrid, n_to_a, natom
1238 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: active_atom
1239 REAL(kind=
dp) :: cutoff_ri
1240 REAL(kind=
dp),
DIMENSION(3) :: center
1243 CALL timeset(routinen, handle)
1245 particle_set => bs_env%ri_rs%particle_set
1246 natom = bs_env%n_atom
1247 common_grid_available = .true.
1248 have_fitted_columns = .false.
1249 ALLOCATE (active_atom(natom))
1250 DO fit_atom = 1, natom
1251 IF (bs_env%auto_ri%sizes_opt_RI(fit_atom) == 0) cycle
1252 have_fitted_columns = .true.
1253 active_atom = .false.
1254 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1255 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1256 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1257 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
1258 IF (.NOT. (fit_atom == atom_a .AND. n_to_a > 0) .AND. &
1259 .NOT. (fit_atom == atom_b .AND. &
1260 n_to_a < bs_env%auto_ri%AB_size_opt_RI(ab_block))) cycle
1261 active_atom(atom_a) = .true.
1262 IF (atom_b /= atom_a) active_atom(atom_b) = .true.
1265 center = particle_set(fit_atom)%r
1268 IF (.NOT. active_atom(iatom)) cycle
1269 cutoff_ri = max(cutoff_ri, bs_env%ri_metric%cutoff_radius + &
1270 bs_env%ri_rs%radius_ri_per_atom(iatom) + &
1271 norm2(center - particle_set(iatom)%r))
1274 DO igrid = 1, bs_env%ri_rs%n_grid_points
1275 IF (norm2(ri_rs_grid_points(1:3, igrid) - center) > cutoff_ri)
THEN
1276 common_grid_available = .false.
1280 IF (.NOT. common_grid_available)
EXIT
1283 IF (norm2(particle_set(iatom)%r - center) > &
1284 bs_env%ri_rs%radius_ao_per_atom(iatom) + cutoff_ri)
THEN
1285 common_grid_available = .false.
1289 IF (.NOT. common_grid_available)
EXIT
1291 DEALLOCATE (active_atom)
1293 CALL timestop(handle)
1295 END SUBROUTINE common_z_lp_grid_available
1316 SUBROUTINE build_phi_on_complete_grid(bs_env, qs_kind_set, &
1317 ri_rs_grid_points, local_grid_idx, ngrid, &
1318 phi_local, ao_atoms, ao_col_start, ao_nonzero)
1320 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
1321 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
1322 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: local_grid_idx
1323 INTEGER,
INTENT(OUT) :: ngrid
1324 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
1325 INTENT(OUT) :: phi_local
1326 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: ao_atoms, ao_col_start
1327 LOGICAL,
ALLOCATABLE,
INTENT(OUT) :: ao_nonzero(:, :)
1329 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_phi_on_complete_grid'
1331 INTEGER :: handle, iatom, igrid, reference_atom
1332 REAL(kind=
dp) :: cutoff_ri
1333 REAL(kind=
dp),
DIMENSION(3) :: center
1336 CALL timeset(routinen, handle)
1338 particle_set => bs_env%ri_rs%particle_set
1340 center = particle_set(reference_atom)%r
1342 DO igrid = 1, bs_env%ri_rs%n_grid_points
1343 cutoff_ri = max(cutoff_ri, norm2(ri_rs_grid_points(1:3, igrid) - center))
1345 DO iatom = 1, bs_env%n_atom
1346 cutoff_ri = max(cutoff_ri, norm2(particle_set(iatom)%r - center))
1348 cutoff_ri = cutoff_ri + 1.0_dp
1350 CALL build_phi_on_sphere(bs_env, qs_kind_set, &
1351 ri_rs_grid_points, reference_atom, cutoff_ri, &
1352 local_grid_idx, ngrid, phi_local, ao_atoms, ao_col_start, &
1353 center=center, ao_nonzero=ao_nonzero)
1355 CALL timestop(handle)
1357 END SUBROUTINE build_phi_on_complete_grid
1376 SUBROUTINE add_z_lp_columns(mat_Z_lP, z_block, local_grid_idx, n_local_grid, atom_index, &
1377 first_column, atom_block_size, r_blk_sizes, row_offset, row_dist, &
1381 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: z_block
1382 INTEGER,
DIMENSION(:),
INTENT(IN) :: local_grid_idx
1383 INTEGER,
INTENT(IN) :: n_local_grid, atom_index, first_column, &
1385 INTEGER,
DIMENSION(:),
INTENT(IN) :: r_blk_sizes, row_offset, row_dist
1386 INTEGER,
INTENT(IN) :: myprow
1387 REAL(kind=
dp),
INTENT(IN) :: eps_filter
1389 CHARACTER(LEN=*),
PARAMETER :: routinen =
'add_Z_lP_columns'
1391 INTEGER :: current_chunk_size, g_pt, handle, i_blk, &
1392 loc_ptr, ncolumn, r_end, r_start
1393 LOGICAL :: row_owned
1394 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: z_blk
1396 CALL timeset(routinen, handle)
1398 ncolumn =
SIZE(z_block, 2)
1399 cpassert(first_column > 0)
1400 cpassert(first_column + ncolumn - 1 <= atom_block_size)
1401 ALLOCATE (z_blk(maxval(r_blk_sizes), atom_block_size), source=0.0_dp)
1403 DO i_blk = 1,
SIZE(r_blk_sizes)
1404 r_start = row_offset(i_blk) + 1
1405 r_end = row_offset(i_blk) + r_blk_sizes(i_blk)
1406 current_chunk_size = r_blk_sizes(i_blk)
1407 row_owned = row_dist(i_blk) == myprow
1409 DO WHILE (loc_ptr <= n_local_grid)
1410 g_pt = local_grid_idx(loc_ptr)
1411 IF (g_pt > r_end)
EXIT
1413 z_blk(g_pt - r_start + 1, first_column:first_column + ncolumn - 1) = &
1414 z_block(loc_ptr, 1:ncolumn)
1416 loc_ptr = loc_ptr + 1
1418 IF (row_owned .AND. maxval(abs(z_blk(1:current_chunk_size, :))) > eps_filter)
THEN
1420 block=z_blk(1:current_chunk_size, :), summation=.true.)
1425 CALL timestop(handle)
1427 END SUBROUTINE add_z_lp_columns
1445 SUBROUTINE compute_d_lp_auto_ri(bs_env, ctx, phi_val, ao_atoms, ao_col_start, ao_nonzero, d_lp, &
1446 ri_atoms, ri_coefficients, max_ao_size, atom_j_mepos, &
1451 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1452 INTENT(IN) :: phi_val
1453 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_atoms, ao_col_start
1454 LOGICAL,
DIMENSION(:, :),
INTENT(IN) :: ao_nonzero
1455 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_lp
1456 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :, :),
INTENT(IN) :: ri_coefficients
1457 INTEGER,
DIMENSION(:),
INTENT(IN) :: ri_atoms
1458 INTEGER,
INTENT(IN) :: max_ao_size, atom_j_mepos, atom_j_stride
1460 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_d_lp_auto_ri'
1461 INTEGER,
PARAMETER :: grid_chunk = 1024
1463 INTEGER :: jj, kk, active_column, iatom, jatom, katom, c, handle, i_thread, j, jk_idx, jsize, &
1464 jstart, k, ksize, kstart, l, l0, &
1465 max_active, nactive, ncol, n_grid, nri_ref, nthreads, ri, slot, thread_id
1466 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_ncol
1467 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: atom_column
1468 LOGICAL :: any_integral, screened, single_atom
1469 REAL(kind=
dp) :: pair_factor
1470 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: int_2d_prv, rho_chunk
1471 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: coefficient_compact, d_lp_threads, &
1472 int_3c_prv, int_3c_atom
1475 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: grid_index
1476 INTEGER :: n_grid_pair, grid_l, point
1477 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: grid_result
1479 CALL timeset(routinen, handle)
1480 n_grid =
SIZE(d_lp, 1)
1481 ncol =
SIZE(d_lp, 2)
1482 single_atom =
SIZE(ri_atoms) == 1
1485 cpassert(
SIZE(ri_coefficients, 2) == ncol)
1486 cpassert(
SIZE(ri_coefficients, 3) ==
SIZE(ri_atoms))
1487 cpassert(
SIZE(ri_atoms) > 0)
1489 IF (.NOT. single_atom)
THEN
1490 ALLOCATE (atom_ncol(
SIZE(ri_atoms)), atom_column(ncol,
SIZE(ri_atoms)))
1493 DO slot = 1,
SIZE(ri_atoms)
1494 nri_ref = get_ref_ri_size(bs_env, ri_atoms(slot))
1496 IF (.NOT. any(ri_coefficients(1:nri_ref, ri, slot) /= 0.0_dp)) cycle
1497 atom_ncol(slot) = atom_ncol(slot) + 1
1498 atom_column(atom_ncol(slot), slot) = ri
1501 max_active = maxval(atom_ncol)
1502 cpassert(max_active > 0)
1503 ALLOCATE (coefficient_compact(
SIZE(ri_coefficients, 1), max_active, &
1504 SIZE(ri_atoms)), source=0.0_dp)
1505 DO slot = 1,
SIZE(ri_atoms)
1506 nri_ref = get_ref_ri_size(bs_env, ri_atoms(slot))
1507 DO active_column = 1, atom_ncol(slot)
1508 ri = atom_column(active_column, slot)
1509 coefficient_compact(1:nri_ref, active_column, slot) = &
1510 ri_coefficients(1:nri_ref, ri, slot)
1514 ALLOCATE (d_lp_threads(n_grid, ncol, nthreads), source=0.0_dp)
1532 ALLOCATE (int_3c_prv(max_ao_size, max_ao_size, ncol))
1533 IF (.NOT. single_atom)
ALLOCATE (int_3c_atom(max_ao_size, max_ao_size, max_active))
1534 ALLOCATE (int_2d_prv(max_ao_size*max_ao_size, ncol))
1535 ALLOCATE (rho_chunk(grid_chunk, max_ao_size*max_ao_size))
1536 ALLOCATE (grid_index(n_grid), grid_result(grid_chunk, ncol))
1539 DO jj = 1,
SIZE(ao_atoms)
1540 jatom = ao_atoms(jj)
1541 IF (mod(jatom - 1, atom_j_stride) /= atom_j_mepos) cycle
1542 DO kk = jj,
SIZE(ao_atoms)
1543 katom = ao_atoms(kk)
1544 jstart = ao_col_start(jj)
1545 kstart = ao_col_start(kk)
1546 jsize = ao_col_start(jj + 1) - jstart
1547 ksize = ao_col_start(kk + 1) - kstart
1550 DO grid_l = 1, n_grid
1551 IF (.NOT. (ao_nonzero(grid_l, jj) .AND. ao_nonzero(grid_l, kk))) cycle
1552 n_grid_pair = n_grid_pair + 1
1553 grid_index(n_grid_pair) = grid_l
1555 IF (n_grid_pair == 0) cycle
1556 int_3c_prv(1:jsize, 1:ksize, 1:ncol) = 0.0_dp
1557 IF (single_atom)
THEN
1559 CALL build_3c_integral_block_auto_ri_ctx( &
1560 int_3c_prv(1:jsize, 1:ksize, 1:ncol), ctx, ws, &
1561 atom_j=jatom, atom_k=katom, atom_i=ri_atoms(1), &
1562 transform=ri_coefficients(:, :, 1), transform_row=1, screened=screened)
1565 any_integral = .false.
1566 DO slot = 1,
SIZE(ri_atoms)
1567 iatom = ri_atoms(slot)
1568 nactive = atom_ncol(slot)
1569 IF (nactive == 0) cycle
1570 nri_ref = get_ref_ri_size(bs_env, iatom)
1571 int_3c_atom(1:jsize, 1:ksize, 1:nactive) = 0.0_dp
1572 CALL build_3c_integral_block_auto_ri_ctx( &
1573 int_3c_atom(1:jsize, 1:ksize, 1:nactive), ctx, ws, &
1574 atom_j=jatom, atom_k=katom, atom_i=iatom, &
1575 transform=coefficient_compact(1:nri_ref, 1:nactive, slot), &
1576 transform_row=1, screened=screened)
1577 IF (.NOT. screened)
THEN
1578 any_integral = .true.
1579 DO active_column = 1, nactive
1580 ri = atom_column(active_column, slot)
1581 int_3c_prv(1:jsize, 1:ksize, ri) = &
1582 int_3c_prv(1:jsize, 1:ksize, ri) + &
1583 int_3c_atom(1:jsize, 1:ksize, active_column)
1587 IF (.NOT. any_integral) cycle
1593 jk_idx = (k - 1)*jsize + j
1594 int_2d_prv(jk_idx, ri) = int_3c_prv(j, k, ri)
1599 pair_factor = 1.0_dp
1600 IF (jatom /= katom) pair_factor = 2.0_dp
1601 DO l0 = 1, n_grid_pair, grid_chunk
1602 c = min(grid_chunk, n_grid_pair - l0 + 1)
1605 jk_idx = (k - 1)*jsize + j
1607 point = grid_index(l0 + l - 1)
1608 rho_chunk(l, jk_idx) = phi_val(point, jstart + j - 1)* &
1609 phi_val(point, kstart + k - 1)
1613 CALL dgemm(
'N',
'N', c, ncol, jsize*ksize, pair_factor, rho_chunk, grid_chunk, &
1614 int_2d_prv, max_ao_size*max_ao_size, 0.0_dp, &
1615 grid_result, grid_chunk)
1618 point = grid_index(l0 + l - 1)
1619 d_lp_threads(point, ri, thread_id) = &
1620 d_lp_threads(point, ri, thread_id) + grid_result(l, ri)
1631 DO i_thread = 1, nthreads
1632 d_lp(l, ri) = d_lp(l, ri) + d_lp_threads(l, ri, i_thread)
1637 IF (.NOT. single_atom)
DEALLOCATE (int_3c_atom)
1638 DEALLOCATE (int_3c_prv, int_2d_prv, rho_chunk)
1639 DEALLOCATE (grid_index, grid_result)
1643 IF (.NOT. single_atom)
DEALLOCATE (coefficient_compact, atom_column, atom_ncol)
1644 DEALLOCATE (d_lp_threads)
1646 CALL timestop(handle)
1648 END SUBROUTINE compute_d_lp_auto_ri
1664 SUBROUTINE compute_d_lp_auto_ri_batch(bs_env, ctx, phi_val, ao_atoms, ao_col_start, ao_nonzero, d_lp, n_grid, &
1665 max_ao_size, mepos, num_pe)
1668 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1669 INTENT(IN) :: phi_val
1670 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_atoms, ao_col_start
1671 LOGICAL,
DIMENSION(:, :),
INTENT(IN) :: ao_nonzero
1672 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_lp
1673 INTEGER,
INTENT(IN) :: n_grid, max_ao_size, mepos, num_pe
1675 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_d_lp_auto_ri_batch'
1677 INTEGER :: column, handle, iatom, n_done, n_total, &
1679 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: global_map
1680 REAL(kind=
dp) :: item_start_time
1681 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_lp_batch
1682 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: u_pp
1684 CALL timeset(routinen, handle)
1687 DO iatom = mepos + 1, bs_env%n_atom, num_pe
1688 n_total = n_total + 1
1692 DO iatom = mepos + 1, bs_env%n_atom, num_pe
1694 CALL collect_auto_ri_columns_for_atom(bs_env, iatom, u_pp, global_map)
1695 ncol_batch =
SIZE(global_map)
1696 IF (ncol_batch == 0)
THEN
1697 DEALLOCATE (u_pp, global_map)
1699 CALL print_z_lp_progress(bs_env, n_done, n_total, &
1704 ALLOCATE (d_lp_batch(n_grid, ncol_batch), source=0.0_dp)
1705 CALL compute_d_lp_auto_ri(bs_env, ctx, phi_val, ao_atoms, ao_col_start, ao_nonzero, d_lp_batch, &
1706 [iatom], u_pp, max_ao_size, 0, 1)
1707 DO column = 1, ncol_batch
1708 d_lp(:, global_map(column)) = d_lp(:, global_map(column)) + d_lp_batch(:, column)
1710 DEALLOCATE (u_pp, global_map, d_lp_batch)
1712 CALL print_z_lp_progress(bs_env, n_done, n_total, &
1715 CALL timestop(handle)
1717 END SUBROUTINE compute_d_lp_auto_ri_batch
1730 SUBROUTINE collect_auto_ri_columns_for_atom(bs_env, iatom, U_Pp, global_map)
1732 INTEGER,
INTENT(IN) :: iatom
1733 REAL(kind=
dp),
ALLOCATABLE,
INTENT(OUT) :: u_pp(:, :, :)
1734 INTEGER,
ALLOCATABLE,
INTENT(OUT) :: global_map(:)
1736 CHARACTER(LEN=*),
PARAMETER :: routinen =
'collect_auto_ri_columns_for_atom'
1738 INTEGER :: ab_block, atom_a, atom_b, column, global_column, handle, local_column, ncol, &
1739 ncol_batch, nri_ref, nri_ref_a, output_offset, row_first
1740 REAL(kind=
dp),
ALLOCATABLE :: u_pp_ab(:, :)
1742 CALL timeset(routinen, handle)
1745 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1746 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1747 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1748 IF (iatom == atom_a .OR. iatom == atom_b)
THEN
1749 ncol_batch = ncol_batch + bs_env%auto_ri%AB_size_opt_RI(ab_block)
1753 nri_ref = get_ref_ri_size(bs_env, iatom)
1754 ALLOCATE (u_pp(nri_ref, ncol_batch, 1), source=0.0_dp)
1755 ALLOCATE (global_map(ncol_batch))
1757 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1758 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1759 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1760 IF (iatom /= atom_a .AND. iatom /= atom_b) cycle
1761 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block)
1762 CALL get_u_pp_ab(bs_env%auto_ri, ab_block, u_pp_ab)
1764 IF (iatom == atom_b .AND. atom_b /= atom_a)
THEN
1765 nri_ref_a = get_ref_ri_size(bs_env, atom_a)
1766 row_first = 1 + nri_ref_a
1768 u_pp(:, column + 1:column + ncol, 1) = &
1770 row_first:row_first + nri_ref - 1, 1:ncol)
1772 DO local_column = 1, ncol
1773 IF (local_column <= bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block))
THEN
1774 output_offset = sum(bs_env%auto_ri%sizes_opt_RI(:atom_a - 1)) + &
1775 bs_env%auto_ri%AB_first_p_A(ab_block) - 1
1776 global_column = output_offset + local_column
1778 cpassert(atom_b /= atom_a)
1779 output_offset = sum(bs_env%auto_ri%sizes_opt_RI(:atom_b - 1)) + &
1780 bs_env%auto_ri%AB_first_p_B(ab_block) - 1
1781 global_column = output_offset + local_column - &
1782 bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
1784 global_map(column + local_column) = global_column
1786 column = column + ncol
1787 DEALLOCATE (u_pp_ab)
1789 cpassert(column == ncol_batch)
1791 CALL timestop(handle)
1793 END SUBROUTINE collect_auto_ri_columns_for_atom
1801 SUBROUTINE get_u_pp_ab(auto_ri, AB_block, U_Pp)
1803 INTEGER,
INTENT(IN) :: ab_block
1804 REAL(kind=
dp),
ALLOCATABLE,
INTENT(OUT) :: u_pp(:, :)
1806 INTEGER :: first, last, ncolumn, nrow
1808 nrow = auto_ri%AB_size_ref_RI(ab_block)
1809 ncolumn = auto_ri%AB_size_opt_RI(ab_block)
1810 first = auto_ri%U_Pp_AB_offset(ab_block)
1811 last = first + nrow*ncolumn - 1
1812 ALLOCATE (u_pp(nrow, ncolumn))
1813 u_pp(:, :) = reshape(auto_ri%U_Pp_AB(first:last), [nrow, ncolumn])
1815 END SUBROUTINE get_u_pp_ab
1825 SUBROUTINE compute_auto_ri_grid_radii(bs_env, radius)
1827 REAL(kind=
dp),
INTENT(OUT) :: radius(:)
1829 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_auto_ri_grid_radii'
1831 INTEGER :: a, ab_block, b, handle, n_to_a, ncol
1832 REAL(kind=
dp) :: cutoff, distance
1835 CALL timeset(routinen, handle)
1837 particle_set => bs_env%ri_rs%particle_set
1839 cutoff = bs_env%ri_metric%cutoff_radius
1840 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1841 a = bs_env%auto_ri%AB_atom_A(ab_block)
1842 b = bs_env%auto_ri%AB_atom_B(ab_block)
1843 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
1844 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block)
1845 IF (n_to_a > 0)
THEN
1846 radius(a) = max(radius(a), cutoff + bs_env%ri_rs%radius_ri_per_atom(a))
1848 distance = norm2(particle_set(a)%r - particle_set(b)%r)
1849 radius(a) = max(radius(a), cutoff + bs_env%ri_rs%radius_ri_per_atom(b) + distance)
1852 IF (n_to_a < ncol)
THEN
1854 distance = norm2(particle_set(b)%r - particle_set(a)%r)
1855 radius(b) = max(radius(b), cutoff + bs_env%ri_rs%radius_ri_per_atom(b), &
1856 cutoff + bs_env%ri_rs%radius_ri_per_atom(a) + distance)
1860 CALL timestop(handle)
1861 END SUBROUTINE compute_auto_ri_grid_radii
1879 SUBROUTINE compute_auto_ri_d_lp(qs_env, bs_env, ctx, grid, mat_phi, mat_rhs, max_ao_size)
1883 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: grid
1886 INTEGER,
INTENT(IN) :: max_ao_size
1888 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_auto_ri_d_lp'
1890 INTEGER :: ab_block, atom_a, atom_b, first, fit_atom, handle, handle_project, handle_rhs, l, &
1891 last, n_done, n_first_p_abs, n_to_a, n_total, n_union, natom, ncol, ngrid, npcol, nprow, &
1893 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ao_atoms, ao_col_start, global_map, &
1894 local_index, row_offset, union_index
1895 INTEGER,
DIMENSION(:),
POINTER :: ab_row_dist, col_dist, &
1896 first_p_abs_per_atom, retained_size, &
1898 LOGICAL,
ALLOCATABLE :: ao_nonzero(:, :)
1899 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: needed_fit_atom, union_mask
1900 REAL(kind=
dp) :: item_start_time, radius
1901 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: fit_radius
1902 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: column_map, phi, rhs, union_grid
1903 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: u_pp
1909 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
1911 CALL timeset(routinen, handle)
1912 CALL get_qs_env(qs_env, para_env=para_env, particle_set=particle_set, &
1913 qs_kind_set=qs_kind_set, cell=cell)
1914 natom = bs_env%n_atom
1915 CALL dbcsr_get_info(mat_phi, row_blk_size=row_size, distribution=dist_phi)
1917 ALLOCATE (first_p_abs_per_atom(natom), col_dist(natom), ab_row_dist(natom), &
1918 retained_size(natom), row_offset(
SIZE(row_size)))
1919 retained_size(:) = bs_env%auto_ri%sizes_opt_RI
1920 DO ri_atom = 1, natom
1921 first_p_abs_per_atom(ri_atom) = 0
1922 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1923 IF (ri_atom == bs_env%auto_ri%AB_atom_A(ab_block) .OR. &
1924 ri_atom == bs_env%auto_ri%AB_atom_B(ab_block))
THEN
1925 first_p_abs_per_atom(ri_atom) = &
1926 first_p_abs_per_atom(ri_atom) + &
1927 bs_env%auto_ri%AB_size_opt_RI(ab_block)
1930 col_dist(ri_atom) = mod(ri_atom - 1, npcol)
1931 ab_row_dist(ri_atom) = mod(ri_atom - 1, nprow)
1934 DO l = 2,
SIZE(row_size)
1935 row_offset(l) = row_offset(l - 1) + row_size(l - 1)
1938 row_dist=row_dist, col_dist=col_dist)
1939 CALL dbcsr_create(ab_d_lp, name=
'AUTO_RI AA/AB d_lp', dist=dist_ab, &
1940 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size, &
1941 col_blk_size=first_p_abs_per_atom)
1943 row_dist=ab_row_dist, col_dist=col_dist)
1944 CALL dbcsr_create(transform, name=
'AUTO_RI U_Pp', dist=dist_t, &
1945 matrix_type=dbcsr_type_no_symmetry, row_blk_size=first_p_abs_per_atom, &
1946 col_blk_size=retained_size)
1947 CALL dbcsr_create(mat_rhs, name=
'AUTO_RI optimized d_lp', dist=dist_ab, &
1948 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size, &
1949 col_blk_size=retained_size)
1950 ALLOCATE (fit_radius(natom))
1951 CALL compute_auto_ri_grid_radii(bs_env, fit_radius)
1952 ALLOCATE (needed_fit_atom(natom), union_mask(
SIZE(grid, 2)))
1954 DO ri_atom = para_env%mepos + 1, natom, para_env%num_pe
1955 n_total = n_total + 1
1958 CALL timeset(routinen//
'_AB_d_lp', handle_rhs)
1959 DO ri_atom = para_env%mepos + 1, natom, para_env%num_pe
1961 needed_fit_atom = .false.
1962 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1963 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1964 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1965 IF (ri_atom /= atom_a .AND. ri_atom /= atom_b) cycle
1966 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
1967 IF (n_to_a > 0) needed_fit_atom(atom_a) = .true.
1968 IF (n_to_a < bs_env%auto_ri%AB_size_opt_RI(ab_block))
THEN
1969 needed_fit_atom(atom_b) = .true.
1972 IF (.NOT. any(needed_fit_atom))
THEN
1974 CALL print_z_lp_progress(bs_env, n_done, n_total, &
1978 union_mask = .false.
1980 DO fit_atom = 1, natom
1981 IF (.NOT. needed_fit_atom(fit_atom)) cycle
1982 radius = max(radius, fit_radius(fit_atom) + &
1983 norm2(particle_set(fit_atom)%r - particle_set(ri_atom)%r))
1984 DO l = 1,
SIZE(grid, 2)
1985 IF (norm2(grid(:, l) - particle_set(fit_atom)%r) <= &
1986 fit_radius(fit_atom)) union_mask(l) = .true.
1989 n_union = count(union_mask)
1990 ALLOCATE (union_index(n_union), union_grid(3, n_union))
1992 DO l = 1,
SIZE(grid, 2)
1993 IF (.NOT. union_mask(l)) cycle
1994 n_union = n_union + 1
1995 union_index(n_union) = l
1996 union_grid(:, n_union) = grid(:, l)
1998 CALL build_phi_on_sphere(bs_env, qs_kind_set, union_grid, ri_atom, &
1999 radius + 1.0_dp, local_index, ngrid, phi, ao_atoms, ao_col_start, &
2000 ao_nonzero=ao_nonzero)
2001 local_index(1:ngrid) = union_index(local_index(1:ngrid))
2002 n_first_p_abs = first_p_abs_per_atom(ri_atom)
2003 CALL collect_auto_ri_columns_for_atom(bs_env, ri_atom, u_pp, global_map)
2004 cpassert(
SIZE(global_map) == n_first_p_abs)
2006 DO fit_atom = 1, natom
2007 ncol = retained_size(fit_atom)
2008 last = first + ncol - 1
2009 IF (any(global_map >= first .AND. global_map <= last))
THEN
2010 ALLOCATE (column_map(n_first_p_abs, ncol), source=0.0_dp)
2011 DO l = 1, n_first_p_abs
2012 IF (global_map(l) < first .OR. global_map(l) > last) cycle
2013 column_map(l, global_map(l) - first + 1) = 1.0_dp
2016 DEALLOCATE (column_map)
2020 ALLOCATE (rhs(ngrid, n_first_p_abs), source=0.0_dp)
2021 CALL compute_d_lp_auto_ri(bs_env, ctx, phi, ao_atoms, ao_col_start, ao_nonzero, rhs, &
2022 [ri_atom], u_pp, max_ao_size, 0, 1)
2023 DEALLOCATE (ao_atoms, ao_col_start, ao_nonzero)
2025 row_size, row_offset, 0.0_dp)
2026 DEALLOCATE (rhs, u_pp, global_map, phi, local_index, &
2027 union_grid, union_index)
2029 CALL print_z_lp_progress(bs_env, n_done, n_total, &
2034 CALL timestop(handle_rhs)
2035 CALL timeset(routinen//
'_transform', handle_project)
2036 CALL dbcsr_multiply(
'N',
'N', 1.0_dp, ab_d_lp, transform, 0.0_dp, &
2037 mat_rhs, filter_eps=0.0_dp)
2038 CALL timestop(handle_project)
2043 DEALLOCATE (first_p_abs_per_atom, retained_size, col_dist, ab_row_dist, row_offset, &
2044 fit_radius, needed_fit_atom, union_mask)
2045 CALL timestop(handle)
2046 END SUBROUTINE compute_auto_ri_d_lp
2056 SUBROUTINE extract_atom_d_lp(mat_rhs, atom_index, local_index, row_offset, rhs)
2058 INTEGER,
INTENT(IN) :: atom_index
2059 INTEGER,
DIMENSION(:),
INTENT(IN) :: local_index, row_offset
2060 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: rhs
2062 CHARACTER(LEN=*),
PARAMETER :: routinen =
'extract_atom_d_lp'
2064 INTEGER :: handle, l, next_row, row
2066 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
2068 CALL timeset(routinen, handle)
2074 DO l = 1,
SIZE(rhs, 1)
2075 DO WHILE (next_row <=
SIZE(row_offset))
2076 IF (row_offset(next_row) >= local_index(l))
EXIT
2078 next_row = next_row + 1
2080 IF (.NOT. found)
NULLIFY (block)
2082 IF (
ASSOCIATED(block)) rhs(l, :) = block(local_index(l) - row_offset(row), :)
2085 CALL timestop(handle)
2086 END SUBROUTINE extract_atom_d_lp
2097 SUBROUTINE fit_auto_ri_z_lp(qs_env, bs_env, grid, mat_rhs, mat_z)
2100 REAL(kind=
dp),
INTENT(IN) :: grid(:, :)
2101 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_rhs, mat_z
2103 CHARACTER(LEN=*),
PARAMETER :: routinen =
'fit_auto_ri_z_lp'
2105 INTEGER :: atom_index, base, group_size, handle, &
2106 handle_gather, i, mypcol, n_big, &
2107 n_small, natom, ncol, ngrid, npcol, &
2109 INTEGER,
ALLOCATABLE :: all_index(:), ao_atoms(:), ao_col_start(:), big_list(:), &
2110 grid_size(:), local_index(:), row_offset(:), small_list(:)
2111 INTEGER,
POINTER :: row_size(:)
2112 LOGICAL,
ALLOCATABLE :: single_rank(:)
2113 REAL(kind=
dp),
ALLOCATABLE :: atom_rhs(:, :), buffer(:, :), &
2114 local_rhs(:, :), phi(:, :), radius(:)
2119 CALL timeset(routinen, handle)
2120 CALL get_qs_env(qs_env, para_env=para_env, qs_kind_set=qs_kinds)
2121 CALL dbcsr_get_info(mat_rhs, distribution=distribution, row_blk_size=row_size)
2123 ALLOCATE (column_env)
2124 CALL column_env%from_split(para_env, mypcol)
2125 natom = bs_env%n_atom
2126 ALLOCATE (radius(natom), all_index(
SIZE(grid, 2)), row_offset(
SIZE(row_size)))
2127 CALL compute_auto_ri_grid_radii(bs_env, radius)
2128 CALL classify_z_lp_atoms(bs_env, grid, radius, &
2129 bs_env%auto_ri%sizes_opt_RI, grid_size, &
2130 small_list, n_small, big_list, n_big, group_size)
2131 ALLOCATE (single_rank(natom), source=.false.)
2132 single_rank(small_list(:n_small)) = .true.
2133 DO i = 1,
SIZE(all_index)
2137 DO i = 2,
SIZE(row_size)
2138 row_offset(i) = row_offset(i - 1) + row_size(i - 1)
2140 DO base = mypcol + 1, natom, npcol*column_env%num_pe
2141 CALL timeset(routinen//
'_gather_rhs', handle_gather)
2142 DO slot = 0, column_env%num_pe - 1
2143 atom_index = base + slot*npcol
2144 IF (atom_index > natom)
EXIT
2145 IF (.NOT. single_rank(atom_index)) cycle
2146 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2147 IF (ncol == 0) cycle
2148 ALLOCATE (buffer(
SIZE(grid, 2), ncol))
2149 CALL extract_atom_d_lp(mat_rhs, atom_index, all_index, row_offset, buffer)
2150 CALL column_env%sum(buffer, slot)
2151 IF (column_env%mepos == slot)
THEN
2152 CALL move_alloc(buffer, atom_rhs)
2157 CALL timestop(handle_gather)
2158 atom_index = base + column_env%mepos*npcol
2159 IF (atom_index > natom) cycle
2160 IF (.NOT. single_rank(atom_index)) cycle
2161 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2162 IF (ncol == 0) cycle
2163 CALL build_phi_on_sphere(bs_env, qs_kinds, grid, atom_index, &
2164 radius(atom_index), local_index, ngrid, phi, ao_atoms, ao_col_start)
2165 DEALLOCATE (ao_atoms, ao_col_start)
2166 ALLOCATE (local_rhs(ngrid, ncol))
2168 local_rhs(i, :) = atom_rhs(local_index(i), :)
2170 DEALLOCATE (atom_rhs)
2173 row_size, row_offset, 0.0_dp)
2174 DEALLOCATE (local_rhs, phi, local_index)
2177 CALL fit_distributed_auto_ri_z_lp(qs_env, bs_env, grid, mat_rhs, mat_z, radius, &
2178 big_list(:n_big), group_size, row_size, row_offset, &
2181 DEALLOCATE (radius, all_index, row_offset, single_rank, grid_size, small_list, big_list)
2182 CALL column_env%free()
2183 DEALLOCATE (column_env)
2185 CALL timestop(handle)
2186 END SUBROUTINE fit_auto_ri_z_lp
2204 SUBROUTINE fit_distributed_auto_ri_z_lp(qs_env, bs_env, grid, mat_rhs, mat_z, radius, &
2205 atom_list, group_size, row_size, row_offset, &
2209 REAL(kind=
dp),
INTENT(IN) :: grid(:, :)
2210 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_rhs, mat_z
2211 REAL(kind=
dp),
INTENT(IN) :: radius(:)
2212 INTEGER,
INTENT(IN) :: atom_list(:), group_size, row_size(:), &
2213 row_offset(:), all_index(:)
2215 CHARACTER(LEN=*),
PARAMETER :: routinen =
'fit_distributed_auto_ri_z_lp'
2217 INTEGER :: atom_index, base, handle, i, my_group, &
2218 ncol, ngrid, ngroups, root, slot
2219 INTEGER,
ALLOCATABLE :: ao_atoms(:), ao_col_start(:), &
2221 REAL(kind=
dp),
ALLOCATABLE :: atom_rhs(:, :), buffer(:, :), &
2222 local_rhs(:, :), phi(:, :)
2227 CALL timeset(routinen, handle)
2228 CALL get_qs_env(qs_env, para_env=para_env, qs_kind_set=qs_kinds)
2229 ngroups = max(1, para_env%num_pe/group_size)
2230 my_group = min(para_env%mepos/group_size, ngroups - 1)
2231 ALLOCATE (group_env)
2232 CALL group_env%from_split(para_env, my_group)
2235 DO base = 1,
SIZE(atom_list), ngroups
2236 DO slot = 0, ngroups - 1
2237 IF (base + slot >
SIZE(atom_list))
EXIT
2238 atom_index = atom_list(base + slot)
2239 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2240 IF (ncol == 0) cycle
2241 root = slot*group_size
2242 ALLOCATE (buffer(
SIZE(grid, 2), ncol))
2243 CALL extract_atom_d_lp(mat_rhs, atom_index, all_index, row_offset, buffer)
2244 CALL para_env%sum(buffer, root)
2245 IF (para_env%mepos == root)
THEN
2246 CALL move_alloc(buffer, atom_rhs)
2251 IF (base + my_group >
SIZE(atom_list)) cycle
2252 atom_index = atom_list(base + my_group)
2253 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2254 IF (ncol == 0) cycle
2255 IF (group_env%mepos /= 0)
ALLOCATE (atom_rhs(
SIZE(grid, 2), ncol))
2256 CALL group_env%bcast(atom_rhs, 0)
2257 CALL build_phi_on_sphere(bs_env, qs_kinds, grid, atom_index, &
2258 radius(atom_index), local_index, ngrid, phi, ao_atoms, ao_col_start)
2259 DEALLOCATE (ao_atoms, ao_col_start)
2260 ALLOCATE (local_rhs(ngrid, ncol))
2262 local_rhs(i, :) = atom_rhs(local_index(i), :)
2264 DEALLOCATE (atom_rhs)
2265 CALL solve_ri_rs_fit(phi, local_rhs, bs_env%ri_rs%tikhonov, group_env, blacs_env)
2266 IF (group_env%mepos == 0)
THEN
2268 row_size, row_offset, 0.0_dp)
2270 DEALLOCATE (local_rhs, phi, local_index)
2273 CALL group_env%free()
2274 DEALLOCATE (group_env)
2275 CALL timestop(handle)
2276 END SUBROUTINE fit_distributed_auto_ri_z_lp
2304 SUBROUTINE classify_z_lp_atoms(bs_env, ri_rs_grid_points, cutoff_ri_per_atom, ri_blk_sizes, &
2305 n_local_grid_atom, small_list, n_small, big_list, n_big, G, periodic_images)
2310 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
2312 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: cutoff_ri_per_atom
2313 INTEGER,
DIMENSION(:),
INTENT(IN) :: ri_blk_sizes
2314 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: n_local_grid_atom, small_list, big_list
2315 INTEGER,
INTENT(OUT) :: n_small, n_big, g
2316 LOGICAL,
INTENT(IN),
OPTIONAL :: periodic_images
2317 CHARACTER(LEN=*),
PARAMETER :: routinen =
'classify_z_lp_atoms'
2322 REAL(kind=
dp),
PARAMETER :: mem_safety = 0.8_dp
2326 REAL(kind=
dp),
PARAMETER :: scalapack_loc_limit = 2.0e9_dp
2328 INTEGER :: g_atom, g_int32, l, n_ao_used_atom, &
2329 n_grid_total, n_local_grid, natom, &
2330 nthreads_cls, p_loop_atom
2331 REAL(kind=
dp) :: budget_bytes, cutoff_ri, dlp_bytes, &
2332 mem_avail_gb, ng, nri, peak_bytes, &
2334 REAL(kind=
dp),
DIMENSION(3) :: pos_p, displacement
2335 LOGICAL :: sum_images
2339 CALL timeset(routinen, handle)
2340 sum_images = .false.
2341 IF (
PRESENT(periodic_images)) sum_images = periodic_images
2343 para_env => bs_env%para_env
2344 particle_set => bs_env%ri_rs%particle_set
2345 natom = bs_env%n_atom
2346 n_grid_total = bs_env%ri_rs%n_grid_points
2347 cpassert(
SIZE(ri_rs_grid_points, 2) == n_grid_total)
2352 ALLOCATE (n_local_grid_atom(natom), small_list(natom), big_list(natom))
2353 DO p_loop_atom = 1, natom
2354 pos_p(:) = particle_set(p_loop_atom)%r(:)
2355 cutoff_ri = cutoff_ri_per_atom(p_loop_atom)
2357 DO l = 1, n_grid_total
2358 displacement = ri_rs_grid_points(:, l) - pos_p
2359 IF (sum_images) displacement =
pbc(ri_rs_grid_points(:, l), pos_p, bs_env%ri_rs%cell)
2360 IF (norm2(displacement) <= cutoff_ri)
THEN
2361 n_local_grid = n_local_grid + 1
2364 n_local_grid_atom(p_loop_atom) = n_local_grid
2370 budget_bytes = mem_safety*mem_avail_gb*1.0e9_dp
2376 IF (mem_avail_gb <= 0.0_dp .AND. bs_env%unit_nr > 0)
THEN
2377 cpwarn(
"RI-RS Z_lP: no meminfo; single-rank solve for all atoms")
2379 DO p_loop_atom = 1, natom
2380 ng = real(n_local_grid_atom(p_loop_atom),
dp)
2381 nri = real(ri_blk_sizes(p_loop_atom),
dp)
2382 CALL get_n_ao_in_sphere(bs_env, p_loop_atom, &
2383 cutoff_ri_per_atom(p_loop_atom), n_ao_used_atom, sum_images)
2384 CALL record_fit_memory(bs_env%ri_rs, n_local_grid_atom(p_loop_atom), &
2385 n_ao_used_atom, ri_blk_sizes(p_loop_atom), peak_bytes)
2386 IF (mem_avail_gb <= 0.0_dp .OR. peak_bytes <= budget_bytes)
THEN
2387 n_small = n_small + 1
2388 small_list(n_small) = p_loop_atom
2391 big_list(n_big) = p_loop_atom
2392 phi_bytes = 8.0_dp*ng*real(n_ao_used_atom,
dp)
2393 dlp_bytes = 8.0_dp*ng*nri*real(1 + nthreads_cls,
dp)
2395 g_int32 = ceiling(ng*ng/scalapack_loc_limit)
2396 g_atom = max(g_atom, g_int32, &
2397 ceiling(8.0_dp*ng*ng/max(budget_bytes - phi_bytes - dlp_bytes, 1.0_dp)))
2400 CALL print_fit_memory_estimate(bs_env, mem_avail_gb)
2402 IF (g_atom > para_env%num_pe)
THEN
2403 CALL cp_abort(__location__, &
2404 "RI-RS Z_lP: an atom is too large to fit even when "// &
2405 "distributed over all ranks. Add nodes, use fewer MPI ranks "// &
2406 "per node, lower CUTOFF_RADIUS_RI, or raise EPS_FILTER "// &
2407 "for more grid screening.")
2409 g = min(max(g_atom, 2), para_env%num_pe)
2412 CALL timestop(handle)
2414 END SUBROUTINE classify_z_lp_atoms
2424 SUBROUTINE get_n_ao_in_sphere(bs_env, atom_P, cutoff_ri, n_ao_used, periodic_images)
2427 INTEGER,
INTENT(IN) :: atom_p
2428 REAL(kind=
dp),
INTENT(IN) :: cutoff_ri
2429 INTEGER,
INTENT(OUT) :: n_ao_used
2430 LOGICAL,
INTENT(IN) :: periodic_images
2432 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_n_ao_in_sphere'
2434 INTEGER :: handle, ri_atom
2435 REAL(kind=
dp) :: displacement(3)
2438 CALL timeset(routinen, handle)
2440 particle_set => bs_env%ri_rs%particle_set
2442 DO ri_atom = 1, bs_env%n_atom
2443 displacement = particle_set(ri_atom)%r - particle_set(atom_p)%r
2444 IF (periodic_images) displacement =
pbc(particle_set(ri_atom)%r, particle_set(atom_p)%r, bs_env%ri_rs%cell)
2445 IF (norm2(displacement) > &
2446 bs_env%ri_rs%radius_ao_per_atom(ri_atom) + cutoff_ri) cycle
2447 n_ao_used = n_ao_used + bs_env%i_ao_end_from_atom(ri_atom) - &
2448 bs_env%i_ao_start_from_atom(ri_atom) + 1
2451 CALL timestop(handle)
2453 END SUBROUTINE get_n_ao_in_sphere
2471 SUBROUTINE build_phi_on_sphere(bs_env, qs_kind_set, ri_rs_grid_points, &
2472 atom_P, cutoff_ri, local_grid_idx, n_local_grid, &
2473 phi_local, ao_atoms, ao_col_start, center, periodic_images, ao_nonzero)
2476 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
2477 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
2478 INTEGER,
INTENT(IN) :: atom_p
2479 REAL(kind=
dp),
INTENT(IN) :: cutoff_ri
2480 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: local_grid_idx
2481 INTEGER,
INTENT(OUT) :: n_local_grid
2482 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
2483 INTENT(OUT) :: phi_local
2484 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: ao_atoms, ao_col_start
2485 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN),
OPTIONAL :: center
2486 LOGICAL,
INTENT(IN),
OPTIONAL :: periodic_images
2487 LOGICAL,
ALLOCATABLE,
INTENT(OUT),
OPTIONAL :: ao_nonzero(:, :)
2489 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_phi_on_sphere'
2491 INTEGER :: col_end, col_start, handle, iactive, j, &
2492 k, l, loc_idx, n_active, n_ao_used, &
2493 n_grid_total, n_keep, ri_atom
2494 INTEGER,
ALLOCATABLE :: atom_candidates(:)
2495 LOGICAL :: sum_images
2496 REAL(kind=
dp) :: d_sp, dist, r2_threshold
2497 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: w_pt
2498 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: phi_keep, sphere_grid
2499 REAL(kind=
dp),
DIMENSION(3) :: displacement, pos_p
2503 CALL timeset(routinen, handle)
2504 sum_images = .false.
2505 IF (
PRESENT(periodic_images)) sum_images = periodic_images
2507 cell => bs_env%ri_rs%cell
2508 particle_set => bs_env%ri_rs%particle_set
2510 n_grid_total =
SIZE(ri_rs_grid_points, 2)
2511 IF (
PRESENT(center))
THEN
2512 pos_p(:) = center(:)
2514 pos_p(:) = particle_set(atom_p)%r(:)
2518 DO l = 1, n_grid_total
2519 displacement = ri_rs_grid_points(:, l) - pos_p
2520 IF (sum_images) displacement =
pbc(ri_rs_grid_points(:, l), pos_p, cell)
2521 dist = norm2(displacement)
2522 IF (dist <= cutoff_ri) n_local_grid = n_local_grid + 1
2525 ALLOCATE (local_grid_idx(n_local_grid))
2528 DO l = 1, n_grid_total
2529 displacement = ri_rs_grid_points(:, l) - pos_p
2530 IF (sum_images) displacement =
pbc(ri_rs_grid_points(:, l), pos_p, cell)
2531 dist = norm2(displacement)
2532 IF (dist <= cutoff_ri)
THEN
2533 n_local_grid = n_local_grid + 1
2534 local_grid_idx(n_local_grid) = l
2538 ALLOCATE (sphere_grid(3, n_local_grid))
2539 DO loc_idx = 1, n_local_grid
2540 sphere_grid(:, loc_idx) = ri_rs_grid_points(:, local_grid_idx(loc_idx))
2544 ALLOCATE (atom_candidates(bs_env%n_atom))
2546 DO ri_atom = 1, bs_env%n_atom
2547 displacement = particle_set(ri_atom)%r - pos_p
2548 IF (sum_images) displacement =
pbc(particle_set(ri_atom)%r, pos_p, cell)
2549 d_sp = norm2(displacement)
2550 IF (d_sp > bs_env%ri_rs%radius_ao_per_atom(ri_atom) + cutoff_ri) cycle
2551 IF (bs_env%i_ao_end_from_atom(ri_atom) < bs_env%i_ao_start_from_atom(ri_atom)) cycle
2552 n_active = n_active + 1
2553 atom_candidates(n_active) = ri_atom
2555 ALLOCATE (ao_atoms(n_active), source=atom_candidates(:n_active))
2556 DEALLOCATE (atom_candidates)
2557 ALLOCATE (ao_col_start(n_active + 1))
2559 DO iactive = 1, n_active
2560 ri_atom = ao_atoms(iactive)
2561 ao_col_start(iactive + 1) = ao_col_start(iactive) + &
2562 bs_env%i_ao_end_from_atom(ri_atom) - bs_env%i_ao_start_from_atom(ri_atom) + 1
2564 n_ao_used = ao_col_start(n_active + 1) - 1
2565 ALLOCATE (phi_local(n_local_grid, n_ao_used), source=0.0_dp)
2567 DO iactive = 1, n_active
2568 ri_atom = ao_atoms(iactive)
2569 col_start = ao_col_start(iactive)
2570 col_end = ao_col_start(iactive + 1) - 1
2573 IF (.NOT. sum_images .AND. bs_env%ri_rs%cutoff_radius_ri_ao > 0.0_dp)
THEN
2574 r2_threshold = bs_env%ri_rs%cutoff_radius_ri_ao**2
2576 r2_threshold = bs_env%ri_rs%radius_ao_per_atom(ri_atom)**2
2579 IF (sum_images)
THEN
2581 bs_env%basis_set_AO( &
2582 particle_set(ri_atom)%atomic_kind%kind_number)%gto_basis_set, &
2583 particle_set(ri_atom)%r, cell, &
2584 cutoff_squared=r2_threshold, periodic_images=.true.)
2587 ri_atom, particle_set, qs_kind_set, cell, &
2588 cutoff_squared=r2_threshold)
2592 DEALLOCATE (sphere_grid)
2594 IF (.NOT. sum_images .AND. n_local_grid > 0)
THEN
2595 ALLOCATE (w_pt(n_local_grid))
2599 DO l = 1, n_local_grid
2602 w_pt(l) = max(w_pt(l), abs(phi_local(l, j)))
2606 n_keep = count(w_pt > bs_env%eps_filter)
2607 IF (n_keep < n_local_grid)
THEN
2608 ALLOCATE (phi_keep(n_keep, n_ao_used))
2610 DO l = 1, n_local_grid
2611 IF (w_pt(l) > bs_env%eps_filter)
THEN
2613 phi_keep(k, :) = phi_local(l, :)
2614 local_grid_idx(k) = local_grid_idx(l)
2617 CALL move_alloc(phi_keep, phi_local)
2618 n_local_grid = n_keep
2623 IF (
PRESENT(ao_nonzero))
THEN
2625 ALLOCATE (ao_nonzero(n_local_grid, n_active), source=.false.)
2629 DO iactive = 1, n_active
2630 DO j = ao_col_start(iactive), ao_col_start(iactive + 1) - 1
2631 DO l = 1, n_local_grid
2632 ao_nonzero(l, iactive) = ao_nonzero(l, iactive) .OR. phi_local(l, j) /= 0.0_dp
2639 CALL timestop(handle)
2641 END SUBROUTINE build_phi_on_sphere
2662 SUBROUTINE build_3c_integral_block_auto_ri_ctx(int_3c, ctx, ws, atom_j, atom_k, atom_i, &
2663 transform, transform_row, screened)
2664 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(INOUT) :: int_3c
2667 INTEGER,
INTENT(IN) :: atom_j, atom_k, atom_i
2668 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: transform
2669 INTEGER,
INTENT(IN) :: transform_row
2670 LOGICAL,
INTENT(OUT),
OPTIONAL :: screened
2672 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_3c_integral_block_auto_ri_ctx'
2674 INTEGER :: handle_contract, handle_eri, ikind, iset, jkind, jset, kkind, kset, l, ncoi, &
2675 ncoj, ncok, ncol, npgf_group, nseti, nsetj, nsetk, primitive_first, sgfi, sgfj, sgfk
2676 INTEGER,
DIMENSION(:),
POINTER :: lmax_i, lmax_j, lmax_k, lmin_i, lmin_j, &
2677 lmin_k, npgfi, npgfj, npgfk, nsgfi, &
2679 INTEGER,
DIMENSION(:, :),
POINTER :: first_sgf_i, first_sgf_j, first_sgf_k
2680 REAL(kind=
dp) :: dij, dik, djk, group_radius, &
2681 kind_radius_i, kind_radius_j, &
2682 kind_radius_k, sijk_ext
2683 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: rpgf_group, zet_group
2684 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: spi_group
2685 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: sijk, sijk_contr
2686 REAL(kind=
dp),
DIMENSION(3) :: ri, rij, rik, rj, rjk, rk
2687 REAL(kind=
dp),
DIMENSION(:),
POINTER :: set_radius_i, set_radius_j, set_radius_k
2688 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: rpgf_i, rpgf_j, rpgf_k, zeti, zetj, zetk
2690 IF (
PRESENT(screened)) screened = .false.
2691 ri =
pbc(ctx%particle_set(atom_i)%r(1:3), ctx%cell)
2692 rj =
pbc(ctx%particle_set(atom_j)%r(1:3), ctx%cell)
2693 rk =
pbc(ctx%particle_set(atom_k)%r(1:3), ctx%cell)
2701 ikind = ctx%kind_of(atom_i)
2702 jkind = ctx%kind_of(atom_j)
2703 kkind = ctx%kind_of(atom_k)
2704 CALL get_gto_basis_set(ctx%basis_i(ikind)%gto_basis_set, first_sgf=first_sgf_i, &
2705 lmax=lmax_i, lmin=lmin_i, npgf=npgfi, nset=nseti, &
2706 nsgf_set=nsgfi, pgf_radius=rpgf_i, set_radius=set_radius_i, &
2707 zet=zeti, kind_radius=kind_radius_i)
2708 CALL get_gto_basis_set(ctx%basis_j(jkind)%gto_basis_set, first_sgf=first_sgf_j, &
2709 lmax=lmax_j, lmin=lmin_j, npgf=npgfj, nset=nsetj, &
2710 nsgf_set=nsgfj, pgf_radius=rpgf_j, set_radius=set_radius_j, &
2711 zet=zetj, kind_radius=kind_radius_j)
2712 CALL get_gto_basis_set(ctx%basis_k(kkind)%gto_basis_set, first_sgf=first_sgf_k, &
2713 lmax=lmax_k, lmin=lmin_k, npgf=npgfk, nset=nsetk, &
2714 nsgf_set=nsgfk, pgf_radius=rpgf_k, set_radius=set_radius_k, &
2715 zet=zetk, kind_radius=kind_radius_k)
2717 IF (kind_radius_j + kind_radius_i + ctx%dr_ij < dij .OR. &
2718 kind_radius_j + kind_radius_k + ctx%dr_jk < djk .OR. &
2719 kind_radius_k + kind_radius_i + ctx%dr_ik < dik)
THEN
2720 IF (
PRESENT(screened)) screened = .true.
2724 ncol =
SIZE(transform, 2)
2725 cpassert(
SIZE(int_3c, 3) == ncol)
2728 group_radius = 0.0_dp
2730 IF (lmin_i(iset) /= l .OR. lmax_i(iset) /= l) cycle
2731 npgf_group = npgf_group + npgfi(iset)
2732 group_radius = max(group_radius, set_radius_i(iset))
2734 IF (npgf_group == 0) cycle
2735 ncoi = npgf_group*
ncoset(l)
2736 ALLOCATE (zet_group(npgf_group), rpgf_group(npgf_group))
2737 ALLOCATE (spi_group(ncoi, ncol), source=0.0_dp)
2740 IF (lmin_i(iset) /= l .OR. lmax_i(iset) /= l) cycle
2741 zet_group(primitive_first:primitive_first + npgfi(iset) - 1) = &
2742 zeti(1:npgfi(iset), iset)
2743 rpgf_group(primitive_first:primitive_first + npgfi(iset) - 1) = &
2744 rpgf_i(1:npgfi(iset), iset)
2745 sgfi = first_sgf_i(1, iset)
2746 spi_group((primitive_first - 1)*
ncoset(l) + 1: &
2747 (primitive_first + npgfi(iset) - 1)*
ncoset(l), :) = &
2748 matmul(ctx%spi(iset, ikind)%array, &
2749 transform(transform_row + sgfi - 1: &
2750 transform_row + sgfi + nsgfi(iset) - 2, :))
2751 primitive_first = primitive_first + npgfi(iset)
2755 IF (set_radius_j(jset) + group_radius + ctx%dr_ij < dij) cycle
2757 IF (set_radius_j(jset) + set_radius_k(kset) + ctx%dr_jk < djk) cycle
2758 IF (set_radius_k(kset) + group_radius + ctx%dr_ik < dik) cycle
2759 ncoj = npgfj(jset)*
ncoset(lmax_j(jset))
2760 ncok = npgfk(kset)*
ncoset(lmax_k(kset))
2761 sgfj = first_sgf_j(1, jset)
2762 sgfk = first_sgf_k(1, kset)
2763 IF (ncoj*ncok*ncoi <= 0) cycle
2764 ALLOCATE (sijk(ncoj, ncok, ncoi), source=0.0_dp)
2765 CALL timeset(routinen//
'_eri', handle_eri)
2767 lmin_j(jset), lmax_j(jset), npgfj(jset), zetj(:, jset), &
2768 rpgf_j(:, jset), rj, &
2769 lmin_k(kset), lmax_k(kset), npgfk(kset), zetk(:, kset), &
2770 rpgf_k(:, kset), rk, l, l, npgf_group, zet_group, &
2771 rpgf_group, ri, djk, dij, dik, ws%lib, ctx%potential_parameter, &
2772 int_abc_ext=sijk_ext)
2773 CALL timestop(handle_eri)
2774 ALLOCATE (sijk_contr(nsgfj(jset), nsgfk(kset), ncol))
2775 CALL timeset(routinen//
'_contract', handle_contract)
2777 ctx%spk(kset, kkind)%array, spi_group, ncoj, ncok, ncoi, &
2778 nsgfj(jset), nsgfk(kset), ncol, ws%cpp_buffer, ws%ccp_buffer)
2779 CALL timestop(handle_contract)
2781 int_3c(sgfj:sgfj + nsgfj(jset) - 1, sgfk:sgfk + nsgfk(kset) - 1, :) = &
2782 int_3c(sgfj:sgfj + nsgfj(jset) - 1, sgfk:sgfk + nsgfk(kset) - 1, :) + &
2784 DEALLOCATE (sijk_contr)
2787 DEALLOCATE (zet_group, rpgf_group, spi_group)
2790 END SUBROUTINE build_3c_integral_block_auto_ri_ctx
2798 INTEGER FUNCTION get_ref_ri_size(bs_env, iatom)
RESULT(n)
2800 INTEGER,
INTENT(IN) :: iatom
2804 ikind = bs_env%ri_rs%particle_set(iatom)%atomic_kind%kind_number
2805 n = bs_env%basis_set_RI(ikind)%gto_basis_set%nsgf
2807 END FUNCTION get_ref_ri_size
2818 SUBROUTINE record_fit_memory(ri_rs, n_grid, n_ao, n_ri, peak_bytes)
2821 INTEGER,
INTENT(IN) :: n_grid, n_ao, n_ri
2822 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: peak_bytes
2825 REAL(kind=
dp) :: ng, peak
2829 ng = real(n_grid,
dp)
2830 peak = 8.0_dp*ng*ng + 8.0_dp*ng*real(n_ao,
dp) + &
2831 8.0_dp*ng*real(n_ri,
dp)*real(1 + nthreads,
dp)
2832 ri_rs%fit_max_grid = max(ri_rs%fit_max_grid, n_grid)
2833 ri_rs%fit_peak_bytes = max(ri_rs%fit_peak_bytes, peak)
2834 IF (
PRESENT(peak_bytes)) peak_bytes = peak
2835 END SUBROUTINE record_fit_memory
2842 SUBROUTINE print_fit_memory_estimate(bs_env, mem_avail_GB)
2844 REAL(kind=
dp),
INTENT(IN) :: mem_avail_gb
2846 CHARACTER(LEN=max_line_length) :: msg
2847 REAL(kind=
dp) :: mem_gram_gb, mem_zlp_peak_gb
2849 mem_gram_gb = 8.0_dp*real(bs_env%ri_rs%fit_max_grid,
dp)**2*1.0e-9_dp
2850 mem_zlp_peak_gb = bs_env%ri_rs%fit_peak_bytes*1.0e-9_dp
2851 IF (bs_env%unit_nr > 0)
THEN
2852 WRITE (bs_env%unit_nr,
'(T2,A)')
'RI-RS fitting memory estimate per MPI process:'
2853 WRITE (bs_env%unit_nr,
'(T4,A,F37.2,A)') &
2854 'Available memory per process (system)', mem_avail_gb,
' GB'
2855 WRITE (bs_env%unit_nr,
'(T4,A,F17.2,A)') &
2856 'Required for Z_lP fit (Gram+phi+RHS, single-rank bound)', mem_zlp_peak_gb,
' GB'
2857 WRITE (bs_env%unit_nr,
'(T4,A,T69,I12)') &
2858 'Largest fitting-grid number of grid points:', bs_env%ri_rs%fit_max_grid
2859 WRITE (bs_env%unit_nr,
'(T4,A,T69,F9.2,A)') &
2860 'Largest dense Gram matrix:', mem_gram_gb,
' GB'
2864 IF (mem_avail_gb > 0.0_dp .AND. mem_zlp_peak_gb > mem_avail_gb)
THEN
2865 WRITE (msg,
'(A,F0.2,A,F0.2,A)') &
2866 "The estimated peak memory of the Z_lP solve, ", mem_zlp_peak_gb, &
2867 " GB per process, exceeds the available ", mem_avail_gb, &
2868 " GB. The dense Gram matrix scales as n_local_grid^2; "// &
2869 "the estimate assumes a single-rank solve. Localized fits may distribute the Gram "// &
2870 "matrix over a ScaLAPACK subgroup. Use fewer MPI ranks per node if more memory "// &
2871 "per rank is needed."
2874 END SUBROUTINE print_fit_memory_estimate
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
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.
Contraction of integrals over primitive Cartesian Gaussians based on the contraction matrix sphi whic...
subroutine, public abc_contract_xsmm(abcint, sabc, sphi_a, sphi_b, sphi_c, ncoa, ncob, ncoc, nsgfa, nsgfb, nsgfc, cpp_buffer, ccp_buffer, prefac, pstfac)
3-center contraction routine from primitive cartesian Gaussians to spherical Gaussian functions using...
Define the atomic kind types and their sub types.
subroutine, public get_gto_basis_set(gto_basis_set, name, aliases, norm_type, kind_radius, ncgf, nset, nsgf, cgf_symbol, sgf_symbol, norm_cgf, set_radius, lmax, lmin, lx, ly, lz, m, ncgf_set, npgf, nsgf_set, nshell, cphi, pgf_radius, sphi, scon, zet, first_cgf, first_sgf, l, last_cgf, last_sgf, n, gcc, maxco, maxl, maxpgf, maxsgf_set, maxshell, maxso, nco_sum, npgf_sum, nshell_sum, maxder, short_kind_radius, npgf_seg_sum, ccon)
...
Handles all functions related to the CELL.
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_distribution_new(dist, template, group, pgrid, row_dist, col_dist, reuse_arrays)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
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_filter(matrix, eps)
...
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_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)
...
subroutine, public dbcsr_reserve_all_blocks(matrix)
Reserves all blocks.
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...
Input and persistent data for automatic RI basis optimization.
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...
Defines the basic variable types.
integer, parameter, public max_line_length
integer, parameter, public dp
2- and 3-center electron repulsion integral routines based on libint2 Currently available operators: ...
subroutine, public eri_3center(int_abc, la_min, la_max, npgfa, zeta, rpgfa, ra, lb_min, lb_max, npgfb, zetb, rpgfb, rb, lc_min, lc_max, npgfc, zetc, rpgfc, rc, dab, dac, dbc, lib, potential_parameter, int_abc_ext)
Computes the 3-center electron repulsion integrals (ab|c) for a given set of cartesian gaussian orbit...
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
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.
Provides Cartesian and spherical orbital pointers and indices.
integer, dimension(:), allocatable, public ncoset
Define the data structure for the particle information.
Definition of physical constants:
real(kind=dp), parameter, public angstrom
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.
Define the quickstep kind type and their sub types.
Shared numerical operations for computing the RI-RS matrix Z_lP.
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.
subroutine, public solve_ri_rs_fit(phi_local, d_lp, tikhonov, para_env_sub, blacs_env_sub)
Computes the regularized RI-RS fit from an AO collocation matrix and a replicated RHS.
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.
DBCSR collocation, layouts and panel contractions for real-space resolution of the identity.
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 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...
Builds the shared RI-RS grid, AO collocation and fitting representation.
subroutine, public ensure_ri_rs_representation(qs_env, bs_env)
Populate the RI-RS grid, AO collocation and auxiliary fitting coefficients once. Periodic systems use...
subroutine, public compute_z_lp(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_z_lp, periodic_images)
Computes Z_lP for (1) a tabulated RI basis set or (2) an on-the-fly generated RI basis set.
Shared real-space resolution-of-identity grid and matrix data.
Geometry and AO evaluation for real-space resolution of the identity.
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.
subroutine, public evaluate_ao_on_points(phi, grid_points, iatom, particle_set, qs_kind_set, cell, dphi, cutoff_squared)
Evaluate contracted spherical AOs, and optionally their grid-coordinate derivatives.
subroutine, public precompute_ri_rs_radii(ri_rs, basis_set_ao, basis_set_ri, eps, unit_nr)
Compute per-atom AO and RI basis radii from the most diffuse Gaussian primitive in the AO ("ORB") and...
All kind of helpful little routines.
pure integer function, public locate(array, x)
Purpose: Given an array array(1:n), and given a value x, a value x_index is returned which is the ind...
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
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
Provides all information about a quickstep kind.