65#include "./base/base_uses.f90"
70 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'gw_ri_rs_compute_Z_lP'
98 SUBROUTINE compute_z_lp(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_Z_lP)
101 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT) :: ri_rs_grid_points(:, :)
102 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_phi_mu_l
105 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_Z_lP'
109 CALL timeset(routinen, handle)
111 IF (bs_env%auto_ri%enabled)
THEN
112 CALL compute_z_lp_auto_ri(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_z_lp)
114 CALL compute_z_lp_standard(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_z_lp)
117 CALL timestop(handle)
145 SUBROUTINE compute_z_lp_standard(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_Z_lP)
149 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT) :: ri_rs_grid_points(:, :)
150 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_phi_mu_l
153 CHARACTER(LEN=*),
PARAMETER :: key =
'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
154 routinen =
'compute_Z_lP_standard'
156 INTEGER :: atom_j_mepos, atom_j_stride, atom_p, g, handle, handle_dpotrf, handle_dpotrs, &
157 i_blk, iatom,
idx, info, iphase, j, max_ao_size, my_group, n_ao_total, n_ao_used, n_big, &
158 n_done, n_groups, n_loc_ri, n_local_grid, n_my_atoms, n_small, natom, npcol_phi, &
159 num_grid_chunks, phase_hi
160 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ao_col_map, big_list, local_grid_idx, &
161 my_atoms_a, my_atoms_b, &
162 n_local_grid_atom, row_offset, &
164 INTEGER,
DIMENSION(:),
POINTER :: col_dist_ri, r_blk_sizes, ri_blk_sizes, &
166 LOGICAL :: do_scatter, use_dist
167 REAL(kind=
dp) :: balance_a, balance_b, cutoff_ri, &
168 item_start_time, r_c, t1
169 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: cutoff_ri_per_atom, d_vec_local
170 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_local, d_lp_local, phi_local
180 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
183 CALL timeset(routinen, handle)
187 CALL get_qs_env(qs_env, para_env=para_env, particle_set=particle_set, input=input, &
188 qs_kind_set=qs_kind_set, cell=cell)
190 NULLIFY (para_env_sub, blacs_env_sub)
192 natom = bs_env%n_atom
193 n_ao_total = bs_env%i_ao_end_from_atom(natom)
200 CALL dbcsr_get_info(mat_phi_mu_l, row_blk_size=r_blk_sizes, distribution=dist_phi)
203 num_grid_chunks =
SIZE(r_blk_sizes)
205 ALLOCATE (row_offset(num_grid_chunks))
207 DO i_blk = 2, num_grid_chunks
208 row_offset(i_blk) = row_offset(i_blk - 1) + r_blk_sizes(i_blk - 1)
211 ALLOCATE (ri_blk_sizes(natom), col_dist_ri(natom))
213 ri_blk_sizes(iatom) = &
214 bs_env%i_RI_end_from_atom(iatom) - bs_env%i_RI_start_from_atom(iatom) + 1
215 col_dist_ri(iatom) = mod(iatom - 1, npcol_phi)
219 row_dist=row_dist_grid, col_dist=col_dist_ri)
221 IF (bs_env%ri_rs%Z_lP_exists)
THEN
223 distribution=dist_z, &
225 IF (bs_env%unit_nr > 0)
THEN
226 WRITE (bs_env%unit_nr,
'(T2,A,T57,A,F7.1,A)') &
227 'Read Z_lP from file ',
' Execution time',
m_walltime() - t1,
' s'
231 WRITE (bs_env%unit_nr,
'(T2,A)') &
232 '*** NOTE: Z_lP restart must match the current (spatial) grid row ordering ***'
233 WRITE (bs_env%unit_nr,
'(A)')
' '
237 IF (bs_env%unit_nr > 0)
THEN
238 WRITE (bs_env%unit_nr,
'(A)')
' '
239 WRITE (bs_env%unit_nr,
'(T2,A)')
'Started computing Z_lP'
242 CALL dbcsr_create(mat_z_lp, name=
"mat_Z_lP", dist=dist_z, &
243 matrix_type=dbcsr_type_no_symmetry, &
244 row_blk_size=r_blk_sizes, col_blk_size=ri_blk_sizes)
248 DO j = 1, bs_env%n_atom
249 max_ao_size = max(max_ao_size, &
250 bs_env%i_ao_end_from_atom(j) - &
251 bs_env%i_ao_start_from_atom(j) + 1)
259 ALLOCATE (cutoff_ri_per_atom(natom))
261 IF (bs_env%ri_rs%cutoff_radius_ri_rs > 0.0_dp)
THEN
262 cutoff_ri_per_atom(:) = bs_env%ri_rs%cutoff_radius_ri_rs
264 r_c = bs_env%ri_metric%cutoff_radius
266 cutoff_ri_per_atom(iatom) = r_c + bs_env%ri_rs%radius_ri_per_atom(iatom)
270 CALL print_sphere_cutoff_table(bs_env, cutoff_ri_per_atom)
278 CALL classify_z_lp_atoms(bs_env, ri_rs_grid_points, cutoff_ri_per_atom, ri_blk_sizes, &
279 n_local_grid_atom, small_list, n_small, big_list, n_big, g)
284 CALL lpt_assign_atoms(small_list, n_small, n_local_grid_atom, para_env%num_pe, &
285 para_env%mepos, my_atoms_a, balance_a)
287 n_groups = para_env%num_pe/g
288 my_group = min(para_env%mepos/g, n_groups - 1)
289 CALL lpt_assign_atoms(big_list, n_big, n_local_grid_atom, n_groups, my_group, &
290 my_atoms_b, balance_b)
292 ALLOCATE (my_atoms_b(0))
297 n_my_atoms =
SIZE(my_atoms_a) +
SIZE(my_atoms_b)
302 basis_j=bs_env%basis_set_AO, basis_k=bs_env%basis_set_AO, &
303 basis_i=bs_env%basis_set_RI)
313 IF (iphase == 1)
THEN
317 phase_hi =
SIZE(my_atoms_a)
319 IF (n_big == 0) cycle
321 n_groups = para_env%num_pe/g
322 my_group = min(para_env%mepos/g, n_groups - 1)
323 ALLOCATE (para_env_sub)
324 CALL para_env_sub%from_split(para_env, my_group)
326 atom_j_mepos = para_env_sub%mepos
327 atom_j_stride = para_env_sub%num_pe
330 phase_hi =
SIZE(my_atoms_b)
335 IF (iphase == 1)
THEN
336 atom_p = my_atoms_a(
idx)
338 atom_p = my_atoms_b(
idx)
341 n_loc_ri = ri_blk_sizes(atom_p)
342 cutoff_ri = cutoff_ri_per_atom(atom_p)
349 CALL build_phi_on_sphere(bs_env, qs_kind_set, &
350 ri_rs_grid_points, atom_p, cutoff_ri, n_ao_total, &
351 local_grid_idx, n_local_grid, phi_local, &
352 ao_col_map, n_ao_used)
357 ALLOCATE (d_lp_local(n_local_grid, n_loc_ri))
360 CALL compute_d_lp(bs_env, ctx_3c, phi_local, ao_col_map, d_lp_local, n_local_grid, &
361 n_loc_ri, atom_p, max_ao_size, atom_j_mepos, atom_j_stride)
366 CALL para_env_sub%sum(d_lp_local)
373 ALLOCATE (d_vec_local(n_local_grid))
375 IF (.NOT. use_dist)
THEN
377 bs_env%ri_rs%tikhonov, d_local, d_vec_local)
395 IF (.NOT. use_dist)
THEN
396 CALL timeset(routinen//
"_dpotrf", handle_dpotrf)
397 CALL dpotrf(
'L', n_local_grid, d_local, n_local_grid, info)
398 CALL timestop(handle_dpotrf)
399 IF (info /= 0) cpabort(
"RI-RS Cholesky factorization failed")
400 CALL timeset(routinen//
"_dpotrs", handle_dpotrs)
401 CALL dpotrs(
'L', n_local_grid, n_loc_ri, d_local, n_local_grid, &
402 d_lp_local, n_local_grid, info)
403 CALL timestop(handle_dpotrs)
404 IF (info /= 0) cpabort(
"RI-RS Cholesky solve failed")
408 n_local_grid, n_ao_used, n_loc_ri, &
409 bs_env%ri_rs%tikhonov, &
410 para_env_sub, blacs_env_sub, &
411 fm_struct_d, fm_struct_b, fm_d, fm_b, info)
412 IF (info /= 0) cpabort(
"Distributed RI-RS Cholesky solve failed")
424 IF (use_dist) do_scatter = (para_env_sub%mepos == 0)
427 n_loc_ri, atom_p, r_blk_sizes, row_offset, &
431 DEALLOCATE (d_vec_local, d_lp_local)
432 DEALLOCATE (local_grid_idx, phi_local, ao_col_map)
437 CALL print_z_lp_progress(bs_env, n_done, n_my_atoms, &
442 IF (iphase == 2)
THEN
444 CALL para_env_sub%free()
445 DEALLOCATE (para_env_sub)
449 DEALLOCATE (cutoff_ri_per_atom)
450 DEALLOCATE (small_list, big_list)
457 CALL print_z_lp_progress(bs_env, natom, natom,
m_walltime() - t1, &
458 all_mpi_ranks=.true.)
468 DEALLOCATE (row_offset, ri_blk_sizes, col_dist_ri)
471 DEALLOCATE (ri_rs_grid_points)
473 CALL timestop(handle)
475 END SUBROUTINE compute_z_lp_standard
482 SUBROUTINE print_sphere_cutoff_table(bs_env, cutoff_ri_per_atom)
485 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: cutoff_ri_per_atom
487 CHARACTER(LEN=*),
PARAMETER :: routinen =
'print_sphere_cutoff_table'
489 INTEGER :: handle, iatom, ikind, nkind
490 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: cutoff_ri_per_kind
494 CALL timeset(routinen, handle)
496 atomic_kind_set => bs_env%ri_rs%atomic_kind_set
497 particle_set => bs_env%ri_rs%particle_set
499 IF (bs_env%unit_nr <= 0)
THEN
500 CALL timestop(handle)
504 nkind =
SIZE(atomic_kind_set)
505 ALLOCATE (cutoff_ri_per_kind(nkind))
506 cutoff_ri_per_kind(:) = 0.0_dp
508 DO iatom = 1, bs_env%n_atom
509 ikind = particle_set(iatom)%atomic_kind%kind_number
510 cutoff_ri_per_kind(ikind) = max(cutoff_ri_per_kind(ikind), cutoff_ri_per_atom(iatom))
513 WRITE (bs_env%unit_nr,
'(T2,A)')
'Per-kind maximum RI-RS sphere cutoff (Å):'
514 WRITE (bs_env%unit_nr,
'(T4,A4,A14)')
'Kind',
'cutoff (Å)'
516 WRITE (bs_env%unit_nr,
'(T4,A4,F14.4)') &
517 atomic_kind_set(ikind)%element_symbol, &
520 WRITE (bs_env%unit_nr,
'(A)')
' '
522 DEALLOCATE (cutoff_ri_per_kind)
524 CALL timestop(handle)
526 END SUBROUTINE print_sphere_cutoff_table
541 SUBROUTINE lpt_assign_atoms(atom_list, n_atoms, n_local_grid_atom, n_workers, my_worker, &
542 my_atoms, max_over_mean)
544 INTEGER,
DIMENSION(:),
INTENT(IN) :: atom_list
545 INTEGER,
INTENT(IN) :: n_atoms
546 INTEGER,
DIMENSION(:),
INTENT(IN) :: n_local_grid_atom
547 INTEGER,
INTENT(IN) :: n_workers, my_worker
548 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: my_atoms
549 REAL(kind=
dp),
INTENT(OUT) :: max_over_mean
551 CHARACTER(LEN=*),
PARAMETER :: routinen =
'lpt_assign_atoms'
553 INTEGER :: handle, i, iw, n_mine, w_min
554 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: mine_tmp, perm
555 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: cost, load
557 CALL timeset(routinen, handle)
559 max_over_mean = 1.0_dp
560 IF (n_atoms <= 0)
THEN
561 ALLOCATE (my_atoms(0))
562 CALL timestop(handle)
566 ALLOCATE (cost(n_atoms), perm(n_atoms), mine_tmp(n_atoms), load(n_workers))
568 cost(i) = real(n_local_grid_atom(atom_list(i)),
dp)**3
570 CALL sort(cost, n_atoms, perm)
574 DO i = n_atoms, 1, -1
577 IF (load(iw) < load(w_min)) w_min = iw
579 load(w_min) = load(w_min) + cost(i)
580 IF (w_min - 1 == my_worker)
THEN
582 mine_tmp(n_mine) = atom_list(perm(i))
586 ALLOCATE (my_atoms(n_mine))
587 my_atoms(:) = mine_tmp(1:n_mine)
588 IF (sum(load) > 0.0_dp) max_over_mean = maxval(load)*real(n_workers,
dp)/sum(load)
590 CALL timestop(handle)
592 END SUBROUTINE lpt_assign_atoms
615 SUBROUTINE compute_d_lp(bs_env, ctx, phi_val, ao_col_map, d_lp, n_grid_total, n_loc_ri, atom_P, &
616 max_ao_size, atom_j_mepos, atom_j_stride)
620 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: phi_val
621 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_col_map
622 INTEGER,
INTENT(IN) :: n_grid_total, n_loc_ri
623 REAL(kind=
dp),
INTENT(INOUT) :: d_lp(n_grid_total, n_loc_ri)
624 INTEGER,
INTENT(IN) :: atom_p, max_ao_size, atom_j_mepos, &
627 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_d_lp'
628 INTEGER,
PARAMETER :: grid_chunk = 1024
630 INTEGER :: atom_j, atom_k, c, handle, handle_dgemm, &
631 j, jk_idx, jsize, jstart, k, ksize, &
632 kstart, l, l0, n_grid_pair, point, ri
633 INTEGER,
ALLOCATABLE :: grid_index(:)
635 LOGICAL,
ALLOCATABLE :: skip_grid_point(:, :)
636 REAL(kind=
dp) :: pair_factor
637 REAL(kind=
dp),
ALLOCATABLE :: grid_result(:, :)
638 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_lp_prv, int_2d_prv, rho_chunk
639 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: int_3c_prv
642 CALL timeset(routinen, handle)
652 ALLOCATE (int_3c_prv(max_ao_size, max_ao_size, n_loc_ri))
653 ALLOCATE (int_2d_prv(max_ao_size*max_ao_size, n_loc_ri))
654 ALLOCATE (rho_chunk(grid_chunk, max_ao_size*max_ao_size))
655 ALLOCATE (d_lp_prv(n_grid_total, n_loc_ri))
656 ALLOCATE (grid_index(n_grid_total), grid_result(grid_chunk, n_loc_ri))
657 d_lp_prv(:, :) = 0.0_dp
660 ALLOCATE (skip_grid_point(n_grid_total, bs_env%n_atom))
661 CALL compute_skip_grid_point(bs_env, phi_val, ao_col_map, skip_grid_point)
667 DO atom_j = atom_j_mepos + 1, bs_env%n_atom, atom_j_stride
668 DO atom_k = atom_j, bs_env%n_atom
669 jstart = ao_col_map(bs_env%i_ao_start_from_atom(atom_j))
670 kstart = ao_col_map(bs_env%i_ao_start_from_atom(atom_k))
671 IF (jstart == 0 .OR. kstart == 0) cycle
672 jsize = bs_env%i_ao_end_from_atom(atom_j) - bs_env%i_ao_start_from_atom(atom_j) + 1
673 ksize = bs_env%i_ao_end_from_atom(atom_k) - bs_env%i_ao_start_from_atom(atom_k) + 1
676 DO point = 1, n_grid_total
677 IF (skip_grid_point(point, atom_j) .OR. skip_grid_point(point, atom_k)) cycle
678 n_grid_pair = n_grid_pair + 1
679 grid_index(n_grid_pair) = point
681 IF (n_grid_pair == 0) cycle
684 IF (atom_j /= atom_k) pair_factor = 2.0_dp
686 int_3c_prv(1:jsize, 1:ksize, 1:n_loc_ri) = 0.0_dp
691 ctx, ws, atom_j=atom_j, atom_k=atom_k, atom_i=atom_p, &
700 jk_idx = (k - 1)*jsize + j
701 int_2d_prv(jk_idx, ri) = int_3c_prv(j, k, ri)
708 DO l0 = 1, n_grid_pair, grid_chunk
709 c = min(grid_chunk, n_grid_pair - l0 + 1)
712 jk_idx = (k - 1)*jsize + j
714 point = grid_index(l0 + l - 1)
715 rho_chunk(l, jk_idx) = phi_val(point, jstart + j - 1)* &
716 phi_val(point, kstart + k - 1)
720 CALL timeset(routinen//
"_dgemm", handle_dgemm)
721 CALL dgemm(
"N",
"N", c, n_loc_ri, jsize*ksize, &
722 pair_factor, rho_chunk, grid_chunk, &
723 int_2d_prv, max_ao_size*max_ao_size, &
724 0.0_dp, grid_result, grid_chunk)
727 point = grid_index(l0 + l - 1)
728 d_lp_prv(point, ri) = d_lp_prv(point, ri) + grid_result(l, ri)
731 CALL timestop(handle_dgemm)
738 d_lp(1:n_grid_total, 1:n_loc_ri) = d_lp(1:n_grid_total, 1:n_loc_ri) + &
739 d_lp_prv(1:n_grid_total, 1:n_loc_ri)
742 DEALLOCATE (int_3c_prv, int_2d_prv, rho_chunk, d_lp_prv, grid_index, grid_result)
746 DEALLOCATE (skip_grid_point)
751 CALL timestop(handle)
753 END SUBROUTINE compute_d_lp
762 SUBROUTINE compute_skip_grid_point(bs_env, phi_val, ao_col_map, skip_grid_point)
765 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: phi_val
766 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_col_map
767 LOGICAL,
DIMENSION(:, :),
INTENT(OUT) :: skip_grid_point
769 INTEGER ::
atom, first_ao, number_of_aos
771 skip_grid_point(:, :) = .true.
772 DO atom = 1, bs_env%n_atom
773 first_ao = ao_col_map(bs_env%i_ao_start_from_atom(
atom))
774 IF (first_ao == 0) cycle
775 number_of_aos = bs_env%i_ao_end_from_atom(
atom) - bs_env%i_ao_start_from_atom(
atom) + 1
776 skip_grid_point(:,
atom) = all(phi_val(:, first_ao:first_ao + number_of_aos - 1) == 0.0_dp, dim=2)
779 END SUBROUTINE compute_skip_grid_point
805 SUBROUTINE compute_z_lp_auto_ri(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_Z_lP)
808 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
809 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_phi_mu_l
812 CHARACTER(LEN=*),
PARAMETER :: key =
'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
813 routinen =
'compute_Z_lP_auto_ri'
815 INTEGER :: ab_block, atom_a, atom_b, block_size_b, column_first, first_p_ab, fit_atom, &
816 handle, handle_dpotrf, handle_dpotrs, info, max_ao_size, max_nri_ref, mypcol, myprow, &
817 n_ao_total, n_ao_used, n_done, n_my_atoms, n_to_a, natom, ncol, ngrid, nri, nri_ref_a, &
818 nri_ref_b, output_offset, ri_atom
819 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ao_col_map, local_grid_idx, row_offset
820 INTEGER,
DIMENSION(:),
POINTER :: col_dist_ri, ri_blk_sizes, &
821 row_dist_grid, row_size_grid
822 LOGICAL :: ab_block_local, common_grid_available, &
823 have_fitted_columns, &
824 reuse_atomic_integrals
825 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: active_atom
826 REAL(kind=
dp) :: cutoff_ri, item_start_time, r_c, t1
827 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: d_vec
828 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_local, d_lp_all, d_lp_local, &
830 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: u_pp_by_atom
831 REAL(kind=
dp),
DIMENSION(3) :: center
839 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
842 CALL timeset(routinen, handle)
844 IF (bs_env%unit_nr > 0)
THEN
845 WRITE (bs_env%unit_nr,
'(A)')
' '
846 WRITE (bs_env%unit_nr,
'(T2,A)')
'Started computing Z_lP'
849 CALL get_qs_env(qs_env, para_env=para_env, particle_set=particle_set, input=input, &
850 qs_kind_set=qs_kind_set, cell=cell)
851 NULLIFY (para_env_col)
853 natom = bs_env%n_atom
854 n_ao_total = bs_env%i_ao_end_from_atom(natom)
855 cpassert(bs_env%auto_ri%AB_block_count > 0)
856 cpassert(
SIZE(particle_set) == natom)
858 CALL prepare_z_lp_auto_ri(bs_env, mat_phi_mu_l, mat_z_lp, dist_z, row_size_grid, &
859 row_dist_grid, col_dist_ri, ri_blk_sizes, row_offset, &
860 myprow, mypcol, max_ao_size)
863 basis_j=bs_env%basis_set_AO, basis_k=bs_env%basis_set_AO, &
864 basis_i=bs_env%basis_set_RI)
867 CALL common_z_lp_grid_available(bs_env, ri_rs_grid_points, &
868 common_grid_available, have_fitted_columns)
870 IF (common_grid_available .AND. have_fitted_columns)
THEN
872 CALL build_phi_on_complete_grid(bs_env, qs_kind_set, &
873 ri_rs_grid_points, n_ao_total, local_grid_idx, ngrid, &
874 phi_local, ao_col_map, n_ao_used)
875 nri = sum(ri_blk_sizes)
876 ALLOCATE (d_lp_all(ngrid, nri), source=0.0_dp)
878 CALL compute_d_lp_auto_ri_batch(bs_env, ctx_3c, phi_local, ao_col_map, d_lp_all, ngrid, &
879 max_ao_size, para_env%mepos, para_env%num_pe)
880 CALL para_env%sum(d_lp_all)
881 ALLOCATE (d_vec(ngrid))
886 CALL timeset(routinen//
'_dpotrf', handle_dpotrf)
887 CALL dpotrf(
'L', ngrid, d_local, ngrid, info)
888 CALL timestop(handle_dpotrf)
890 CALL timeset(routinen//
'_dpotrs', handle_dpotrs)
891 CALL dpotrs(
'L', ngrid, nri, d_local, ngrid, d_lp_all, ngrid, info)
892 CALL timestop(handle_dpotrs)
896 DO ab_block = 1, bs_env%auto_ri%AB_block_count
897 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
898 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
899 ab_block_local = col_dist_ri(atom_a) == mypcol
900 IF (atom_b /= atom_a) ab_block_local = ab_block_local .OR. col_dist_ri(atom_b) == mypcol
901 IF (.NOT. ab_block_local) cycle
902 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block)
903 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
904 IF (n_to_a > 0 .AND. col_dist_ri(atom_a) == mypcol)
THEN
905 output_offset = sum(ri_blk_sizes(:atom_a - 1)) + &
906 bs_env%auto_ri%AB_first_p_A(ab_block) - 1
907 CALL add_z_lp_columns(mat_z_lp, &
908 d_lp_all(:, output_offset + 1:output_offset + n_to_a), &
909 local_grid_idx, ngrid, atom_a, &
910 bs_env%auto_ri%AB_first_p_A(ab_block), &
911 ri_blk_sizes(atom_a), row_size_grid, row_offset, &
913 myprow, bs_env%eps_filter)
915 IF (n_to_a < ncol)
THEN
916 cpassert(atom_b /= atom_a)
917 IF (col_dist_ri(atom_b) == mypcol)
THEN
918 block_size_b = ri_blk_sizes(atom_b)
919 output_offset = sum(ri_blk_sizes(:atom_b - 1)) + &
920 bs_env%auto_ri%AB_first_p_B(ab_block) - 1
921 CALL add_z_lp_columns(mat_z_lp, &
922 d_lp_all(:, output_offset + 1: &
923 output_offset + ncol - n_to_a), &
924 local_grid_idx, ngrid, atom_b, &
925 bs_env%auto_ri%AB_first_p_B(ab_block), block_size_b, &
926 row_size_grid, row_offset, row_dist_grid, myprow, &
931 DEALLOCATE (d_local, d_vec, d_lp_all, local_grid_idx, phi_local, ao_col_map)
933 reuse_atomic_integrals = &
934 bs_env%ri_rs%cutoff_radius_ri_ao <= 0.0_dp .OR. &
935 bs_env%ri_rs%cutoff_radius_ri_ao <= &
936 minval(bs_env%ri_rs%radius_ao_per_atom)
937 IF (reuse_atomic_integrals)
THEN
939 CALL compute_auto_ri_d_lp(qs_env, bs_env, ctx_3c, &
940 ri_rs_grid_points, mat_phi_mu_l, mat_rhs, &
943 CALL dbcsr_create(mat_z_lp, name=
'mat_Z_lP localized AA/AB', dist=dist_z, &
944 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size_grid, &
945 col_blk_size=ri_blk_sizes)
947 CALL fit_auto_ri_z_lp(qs_env, bs_env, ri_rs_grid_points, mat_rhs, mat_z_lp)
950 ALLOCATE (para_env_col)
951 CALL para_env_col%from_split(para_env, mypcol)
953 DO fit_atom = 1, natom
954 IF (col_dist_ri(fit_atom) /= mypcol) cycle
955 IF (ri_blk_sizes(fit_atom) == 0) cycle
956 n_my_atoms = n_my_atoms + 1
960 DO ri_atom = 1, natom
961 max_nri_ref = max(max_nri_ref, get_ref_ri_size(bs_env, ri_atom))
963 DO fit_atom = 1, natom
964 IF (col_dist_ri(fit_atom) /= mypcol) cycle
965 ncol = ri_blk_sizes(fit_atom)
968 ALLOCATE (u_pp_by_atom(max_nri_ref, ncol, natom), source=0.0_dp)
969 ALLOCATE (active_atom(natom), source=.false.)
971 DO ab_block = 1, bs_env%auto_ri%AB_block_count
972 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
973 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
974 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
975 IF (fit_atom == atom_a .AND. n_to_a > 0)
THEN
976 column_first = bs_env%auto_ri%AB_first_p_A(ab_block)
979 ELSE IF (fit_atom == atom_b .AND. &
980 n_to_a < bs_env%auto_ri%AB_size_opt_RI(ab_block))
THEN
981 column_first = bs_env%auto_ri%AB_first_p_B(ab_block)
982 first_p_ab = n_to_a + 1
983 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block) - n_to_a
987 CALL get_u_pp_ab(bs_env%auto_ri, ab_block, u_pp_ab)
989 nri_ref_a = get_ref_ri_size(bs_env, atom_a)
990 u_pp_by_atom(1:nri_ref_a, &
991 column_first:column_first + ncol - 1, atom_a) = &
993 1:nri_ref_a, first_p_ab:first_p_ab + ncol - 1)
994 active_atom(atom_a) = .true.
995 IF (atom_b /= atom_a)
THEN
996 nri_ref_b = get_ref_ri_size(bs_env, atom_b)
997 u_pp_by_atom(1:nri_ref_b, &
998 column_first:column_first + ncol - 1, atom_b) = &
1000 nri_ref_a + 1:nri_ref_a + nri_ref_b, &
1001 first_p_ab:first_p_ab + ncol - 1)
1002 active_atom(atom_b) = .true.
1004 DEALLOCATE (u_pp_ab)
1007 center = particle_set(fit_atom)%r
1008 IF (bs_env%ri_rs%cutoff_radius_ri_rs > 0.0_dp)
THEN
1009 cutoff_ri = bs_env%ri_rs%cutoff_radius_ri_rs
1011 r_c = bs_env%ri_metric%cutoff_radius
1013 DO ri_atom = 1, natom
1014 IF (.NOT. active_atom(ri_atom)) cycle
1015 cutoff_ri = max(cutoff_ri, &
1016 r_c + bs_env%ri_rs%radius_ri_per_atom(ri_atom) + &
1017 norm2(center - particle_set(ri_atom)%r))
1020 CALL build_phi_on_sphere(bs_env, qs_kind_set, &
1021 ri_rs_grid_points, fit_atom, cutoff_ri, n_ao_total, &
1022 local_grid_idx, ngrid, phi_local, ao_col_map, n_ao_used, &
1024 ncol = ri_blk_sizes(fit_atom)
1025 ALLOCATE (d_lp_local(ngrid, ncol), source=0.0_dp)
1027 CALL compute_d_lp_auto_ri_atoms(bs_env, ctx_3c, phi_local, ao_col_map, &
1028 d_lp_local, ngrid, u_pp_by_atom, &
1029 active_atom, max_ao_size, &
1030 para_env_col%mepos, para_env_col%num_pe)
1031 CALL para_env_col%sum(d_lp_local)
1032 ALLOCATE (d_vec(ngrid))
1037 CALL timeset(routinen//
'_dpotrf', handle_dpotrf)
1038 CALL dpotrf(
'L', ngrid, d_local, ngrid, info)
1039 CALL timestop(handle_dpotrf)
1041 CALL timeset(routinen//
'_dpotrs', handle_dpotrs)
1042 CALL dpotrs(
'L', ngrid, ncol, d_local, ngrid, d_lp_local, ngrid, info)
1043 CALL timestop(handle_dpotrs)
1046 CALL add_z_lp_columns(mat_z_lp, d_lp_local, local_grid_idx, ngrid, fit_atom, 1, &
1047 ri_blk_sizes(fit_atom), row_size_grid, row_offset, &
1049 myprow, bs_env%eps_filter)
1050 DEALLOCATE (d_local, d_vec, d_lp_local, local_grid_idx, phi_local, ao_col_map)
1051 DEALLOCATE (u_pp_by_atom, active_atom)
1053 CALL print_z_lp_progress(bs_env, n_done, n_my_atoms, &
1056 CALL para_env_col%free()
1057 DEALLOCATE (para_env_col)
1064 CALL para_env%sync()
1065 CALL print_z_lp_progress(bs_env, natom, natom,
m_walltime() - t1, &
1066 all_mpi_ranks=.true.)
1069 CALL dbcsr_binary_write(matrix=mat_z_lp, filepath=trim(bs_env%prefix)//
'Z_lP.matrix')
1072 DEALLOCATE (row_offset, ri_blk_sizes, col_dist_ri)
1074 CALL timestop(handle)
1076 END SUBROUTINE compute_z_lp_auto_ri
1086 SUBROUTINE print_z_lp_progress(bs_env, n_done, n_total, execution_time, all_mpi_ranks)
1088 INTEGER,
INTENT(IN) :: n_done, n_total
1089 REAL(kind=
dp),
INTENT(IN) :: execution_time
1090 LOGICAL,
INTENT(IN),
OPTIONAL :: all_mpi_ranks
1092 CHARACTER(LEN=*),
PARAMETER :: routinen =
'print_Z_lP_progress'
1095 LOGICAL :: completed
1097 CALL timeset(routinen, handle)
1099 IF (bs_env%unit_nr > 0)
THEN
1101 IF (
PRESENT(all_mpi_ranks)) completed = all_mpi_ranks
1103 WRITE (bs_env%unit_nr,
'(T2,A,T58,A,F7.1,A,/)') &
1104 'Computed Z_lP (all MPI ranks) for all atoms,', &
1105 'Execution time', execution_time,
' s'
1107 WRITE (bs_env%unit_nr,
'(T2,A,I11,A,I3,A,F7.1,A)') &
1108 'Computed Z_lP (MPI rank 0) for atom', n_done,
' /', n_total, &
1109 ', Execution time', execution_time,
' s'
1114 CALL timestop(handle)
1116 END SUBROUTINE print_z_lp_progress
1135 SUBROUTINE prepare_z_lp_auto_ri(bs_env, mat_phi_mu_l, mat_Z_lP, dist_Z, row_size_grid, &
1136 row_dist_grid, col_dist_ri, ri_blk_sizes, row_offset, &
1137 myprow, mypcol, max_ao_size)
1142 INTEGER,
DIMENSION(:),
POINTER :: row_size_grid, row_dist_grid, &
1143 col_dist_ri, ri_blk_sizes
1144 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: row_offset
1145 INTEGER,
INTENT(OUT) :: myprow, mypcol, max_ao_size
1147 CHARACTER(LEN=*),
PARAMETER :: routinen =
'prepare_Z_lP_auto_ri'
1149 INTEGER :: handle, i_blk, iatom, npcol
1152 CALL timeset(routinen, handle)
1154 CALL dbcsr_get_info(mat_phi_mu_l, row_blk_size=row_size_grid, distribution=dist_phi)
1156 myprow=myprow, mypcol=mypcol)
1157 ALLOCATE (row_offset(
SIZE(row_size_grid)))
1159 DO i_blk = 2,
SIZE(row_size_grid)
1160 row_offset(i_blk) = row_offset(i_blk - 1) + row_size_grid(i_blk - 1)
1163 ALLOCATE (ri_blk_sizes(bs_env%n_atom), col_dist_ri(bs_env%n_atom))
1164 ri_blk_sizes = bs_env%auto_ri%sizes_opt_RI
1165 DO iatom = 1, bs_env%n_atom
1166 col_dist_ri(iatom) = mod(iatom - 1, npcol)
1169 col_dist=col_dist_ri)
1170 CALL dbcsr_create(mat_z_lp, name=
'mat_Z_lP localized AA/AB', dist=dist_z, &
1171 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size_grid, &
1172 col_blk_size=ri_blk_sizes)
1177 DO iatom = 1, bs_env%n_atom
1178 max_ao_size = max(max_ao_size, bs_env%i_ao_end_from_atom(iatom) - &
1179 bs_env%i_ao_start_from_atom(iatom) + 1)
1182 CALL timestop(handle)
1184 END SUBROUTINE prepare_z_lp_auto_ri
1203 SUBROUTINE common_z_lp_grid_available(bs_env, ri_rs_grid_points, &
1204 common_grid_available, have_fitted_columns)
1206 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
1207 LOGICAL,
INTENT(OUT) :: common_grid_available, &
1210 CHARACTER(LEN=*),
PARAMETER :: routinen =
'common_Z_lP_grid_available'
1212 INTEGER :: ab_block, atom_a, atom_b, fit_atom, &
1213 handle, iatom, igrid, n_to_a, natom
1214 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: active_atom
1215 REAL(kind=
dp) :: cutoff_ri
1216 REAL(kind=
dp),
DIMENSION(3) :: center
1219 CALL timeset(routinen, handle)
1221 particle_set => bs_env%ri_rs%particle_set
1222 natom = bs_env%n_atom
1223 common_grid_available = .true.
1224 have_fitted_columns = .false.
1225 ALLOCATE (active_atom(natom))
1226 DO fit_atom = 1, natom
1227 IF (bs_env%auto_ri%sizes_opt_RI(fit_atom) == 0) cycle
1228 have_fitted_columns = .true.
1229 active_atom = .false.
1230 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1231 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1232 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1233 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
1234 IF (.NOT. (fit_atom == atom_a .AND. n_to_a > 0) .AND. &
1235 .NOT. (fit_atom == atom_b .AND. &
1236 n_to_a < bs_env%auto_ri%AB_size_opt_RI(ab_block))) cycle
1237 active_atom(atom_a) = .true.
1238 IF (atom_b /= atom_a) active_atom(atom_b) = .true.
1241 center = particle_set(fit_atom)%r
1242 IF (bs_env%ri_rs%cutoff_radius_ri_rs > 0.0_dp)
THEN
1243 cutoff_ri = bs_env%ri_rs%cutoff_radius_ri_rs
1247 IF (.NOT. active_atom(iatom)) cycle
1248 cutoff_ri = max(cutoff_ri, bs_env%ri_metric%cutoff_radius + &
1249 bs_env%ri_rs%radius_ri_per_atom(iatom) + &
1250 norm2(center - particle_set(iatom)%r))
1254 DO igrid = 1, bs_env%ri_rs%n_grid_points
1255 IF (norm2(ri_rs_grid_points(1:3, igrid) - center) > cutoff_ri)
THEN
1256 common_grid_available = .false.
1260 IF (.NOT. common_grid_available)
EXIT
1263 IF (norm2(particle_set(iatom)%r - center) > &
1264 bs_env%ri_rs%radius_ao_per_atom(iatom) + cutoff_ri)
THEN
1265 common_grid_available = .false.
1269 IF (.NOT. common_grid_available)
EXIT
1271 DEALLOCATE (active_atom)
1273 CALL timestop(handle)
1275 END SUBROUTINE common_z_lp_grid_available
1296 SUBROUTINE build_phi_on_complete_grid(bs_env, qs_kind_set, &
1297 ri_rs_grid_points, n_ao_total, local_grid_idx, ngrid, &
1298 phi_local, ao_col_map, n_ao_used)
1300 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
1301 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
1302 INTEGER,
INTENT(IN) :: n_ao_total
1303 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: local_grid_idx
1304 INTEGER,
INTENT(OUT) :: ngrid
1305 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
1306 INTENT(OUT) :: phi_local
1307 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: ao_col_map
1308 INTEGER,
INTENT(OUT) :: n_ao_used
1310 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_phi_on_complete_grid'
1312 INTEGER :: handle, iatom, igrid, reference_atom
1313 REAL(kind=
dp) :: cutoff_ri
1314 REAL(kind=
dp),
DIMENSION(3) :: center
1317 CALL timeset(routinen, handle)
1319 particle_set => bs_env%ri_rs%particle_set
1321 center = particle_set(reference_atom)%r
1323 DO igrid = 1, bs_env%ri_rs%n_grid_points
1324 cutoff_ri = max(cutoff_ri, norm2(ri_rs_grid_points(1:3, igrid) - center))
1326 DO iatom = 1, bs_env%n_atom
1327 cutoff_ri = max(cutoff_ri, norm2(particle_set(iatom)%r - center))
1329 cutoff_ri = cutoff_ri + 1.0_dp
1331 CALL build_phi_on_sphere(bs_env, qs_kind_set, &
1332 ri_rs_grid_points, reference_atom, cutoff_ri, n_ao_total, &
1333 local_grid_idx, ngrid, phi_local, ao_col_map, n_ao_used, &
1336 CALL timestop(handle)
1338 END SUBROUTINE build_phi_on_complete_grid
1357 SUBROUTINE add_z_lp_columns(mat_Z_lP, z_block, local_grid_idx, n_local_grid, atom_index, &
1358 first_column, atom_block_size, r_blk_sizes, row_offset, row_dist, &
1362 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: z_block
1363 INTEGER,
DIMENSION(:),
INTENT(IN) :: local_grid_idx
1364 INTEGER,
INTENT(IN) :: n_local_grid, atom_index, first_column, &
1366 INTEGER,
DIMENSION(:),
INTENT(IN) :: r_blk_sizes, row_offset, row_dist
1367 INTEGER,
INTENT(IN) :: myprow
1368 REAL(kind=
dp),
INTENT(IN) :: eps_filter
1370 CHARACTER(LEN=*),
PARAMETER :: routinen =
'add_Z_lP_columns'
1372 INTEGER :: current_chunk_size, g_pt, handle, i_blk, &
1373 loc_ptr, ncolumn, r_end, r_start
1374 LOGICAL :: row_owned
1375 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: z_blk
1377 CALL timeset(routinen, handle)
1379 ncolumn =
SIZE(z_block, 2)
1380 cpassert(first_column > 0)
1381 cpassert(first_column + ncolumn - 1 <= atom_block_size)
1382 ALLOCATE (z_blk(maxval(r_blk_sizes), atom_block_size), source=0.0_dp)
1384 DO i_blk = 1,
SIZE(r_blk_sizes)
1385 r_start = row_offset(i_blk) + 1
1386 r_end = row_offset(i_blk) + r_blk_sizes(i_blk)
1387 current_chunk_size = r_blk_sizes(i_blk)
1388 row_owned = row_dist(i_blk) == myprow
1390 DO WHILE (loc_ptr <= n_local_grid)
1391 g_pt = local_grid_idx(loc_ptr)
1392 IF (g_pt > r_end)
EXIT
1394 z_blk(g_pt - r_start + 1, first_column:first_column + ncolumn - 1) = &
1395 z_block(loc_ptr, 1:ncolumn)
1397 loc_ptr = loc_ptr + 1
1399 IF (row_owned .AND. maxval(abs(z_blk(1:current_chunk_size, :))) > eps_filter)
THEN
1401 block=z_blk(1:current_chunk_size, :), summation=.true.)
1406 CALL timestop(handle)
1408 END SUBROUTINE add_z_lp_columns
1422 SUBROUTINE compute_nonzero_ao_grid_mask(bs_env, phi_val, ao_col_map, nonzero_ao)
1424 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: phi_val
1425 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_col_map
1426 LOGICAL,
ALLOCATABLE,
DIMENSION(:, :),
INTENT(OUT) :: nonzero_ao
1428 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_nonzero_AO_grid_mask'
1430 INTEGER :: col, first, handle, iatom, last, natom, &
1433 CALL timeset(routinen, handle)
1435 ngrid =
SIZE(phi_val, 1)
1436 natom = bs_env%n_atom
1437 ALLOCATE (nonzero_ao(ngrid, natom), source=.false.)
1442 first = ao_col_map(bs_env%i_ao_start_from_atom(iatom))
1443 IF (first == 0) cycle
1444 last = ao_col_map(bs_env%i_ao_end_from_atom(iatom))
1445 DO col = first, last
1447 nonzero_ao(point, iatom) = &
1448 nonzero_ao(point, iatom) .OR. phi_val(point, col) /= 0.0_dp
1454 CALL timestop(handle)
1455 END SUBROUTINE compute_nonzero_ao_grid_mask
1470 SUBROUTINE compute_d_lp_auto_ri_atom(bs_env, ctx, phi_val, ao_col_map, d_lp, n_grid, iatom, &
1475 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1476 INTENT(IN) :: phi_val
1477 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_col_map
1478 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_lp
1479 INTEGER,
INTENT(IN) :: n_grid, iatom
1480 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1482 INTEGER,
INTENT(IN) :: max_ao_size
1484 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_d_lp_auto_ri_atom'
1485 INTEGER,
PARAMETER :: grid_chunk = 1024
1487 INTEGER :: jatom, katom, c, handle, i_thread, j, jk_idx, jsize, jstart, k, ksize, &
1488 kstart, l, l0, ncol, nri_ref, nthreads, ri, thread_id
1490 REAL(kind=
dp) :: pair_factor
1491 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: int_2d_prv, rho_chunk
1492 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: d_lp_threads, int_3c_prv
1495 LOGICAL,
ALLOCATABLE,
DIMENSION(:, :) :: nonzero_ao
1496 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: grid_index
1497 INTEGER :: n_grid_pair, grid_l, point
1498 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: grid_result
1500 CALL timeset(routinen, handle)
1501 ncol =
SIZE(u_pp, 2)
1502 nri_ref = get_ref_ri_size(bs_env, iatom)
1505 cpassert(
SIZE(d_lp, 1) == n_grid)
1506 cpassert(
SIZE(d_lp, 2) == ncol)
1507 cpassert(
SIZE(u_pp, 1) == nri_ref)
1508 ALLOCATE (d_lp_threads(n_grid, ncol, nthreads), source=0.0_dp)
1510 CALL compute_nonzero_ao_grid_mask(bs_env, phi_val, ao_col_map, nonzero_ao)
1526 ALLOCATE (int_3c_prv(max_ao_size, max_ao_size, ncol))
1527 ALLOCATE (int_2d_prv(max_ao_size*max_ao_size, ncol))
1528 ALLOCATE (rho_chunk(grid_chunk, max_ao_size*max_ao_size))
1529 ALLOCATE (grid_index(n_grid), grid_result(grid_chunk, ncol))
1532 DO jatom = 1, bs_env%n_atom
1533 DO katom = jatom, bs_env%n_atom
1534 jstart = ao_col_map(bs_env%i_ao_start_from_atom(jatom))
1535 kstart = ao_col_map(bs_env%i_ao_start_from_atom(katom))
1536 IF (jstart == 0 .OR. kstart == 0) cycle
1537 jsize = bs_env%i_ao_end_from_atom(jatom) - bs_env%i_ao_start_from_atom(jatom) + 1
1538 ksize = bs_env%i_ao_end_from_atom(katom) - bs_env%i_ao_start_from_atom(katom) + 1
1540 DO grid_l = 1, n_grid
1541 IF (.NOT. (nonzero_ao(grid_l, jatom) .AND. nonzero_ao(grid_l, katom))) cycle
1542 n_grid_pair = n_grid_pair + 1
1543 grid_index(n_grid_pair) = grid_l
1545 IF (n_grid_pair == 0) cycle
1546 int_3c_prv(1:jsize, 1:ksize, 1:ncol) = 0.0_dp
1547 CALL build_3c_integral_block_auto_ri_ctx( &
1548 int_3c_prv(1:jsize, 1:ksize, 1:ncol), ctx, ws, &
1549 atom_j=jatom, atom_k=katom, atom_i=iatom, &
1550 transform=u_pp, transform_row=1, screened=screened)
1555 jk_idx = (k - 1)*jsize + j
1556 int_2d_prv(jk_idx, ri) = int_3c_prv(j, k, ri)
1560 pair_factor = 1.0_dp
1561 IF (jatom /= katom) pair_factor = 2.0_dp
1562 DO l0 = 1, n_grid_pair, grid_chunk
1563 c = min(grid_chunk, n_grid_pair - l0 + 1)
1566 jk_idx = (k - 1)*jsize + j
1568 point = grid_index(l0 + l - 1)
1569 rho_chunk(l, jk_idx) = phi_val(point, jstart + j - 1)* &
1570 phi_val(point, kstart + k - 1)
1574 CALL dgemm(
'N',
'N', c, ncol, jsize*ksize, pair_factor, rho_chunk, grid_chunk, &
1575 int_2d_prv, max_ao_size*max_ao_size, 0.0_dp, &
1576 grid_result, grid_chunk)
1579 point = grid_index(l0 + l - 1)
1580 d_lp_threads(point, ri, thread_id) = &
1581 d_lp_threads(point, ri, thread_id) + grid_result(l, ri)
1592 DO i_thread = 1, nthreads
1593 d_lp(l, ri) = d_lp(l, ri) + d_lp_threads(l, ri, i_thread)
1598 DEALLOCATE (int_3c_prv, int_2d_prv, rho_chunk)
1599 DEALLOCATE (grid_index, grid_result)
1603 DEALLOCATE (d_lp_threads)
1605 DEALLOCATE (nonzero_ao)
1607 CALL timestop(handle)
1609 END SUBROUTINE compute_d_lp_auto_ri_atom
1626 SUBROUTINE compute_d_lp_auto_ri_atoms(bs_env, ctx, phi_val, ao_col_map, d_lp, n_grid, &
1627 ri_coefficients, active_atom, max_ao_size, atom_j_mepos, &
1632 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1633 INTENT(IN) :: phi_val
1634 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_col_map
1635 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_lp
1636 INTEGER,
INTENT(IN) :: n_grid
1637 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: ri_coefficients
1638 LOGICAL,
DIMENSION(:),
INTENT(IN) :: active_atom
1639 INTEGER,
INTENT(IN) :: max_ao_size, atom_j_mepos, atom_j_stride
1641 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_d_lp_auto_ri_atoms'
1642 INTEGER,
PARAMETER :: grid_chunk = 1024
1644 INTEGER :: active_column, iatom, jatom, katom, c, handle, i_thread, j, jk_idx, jsize, &
1645 jstart, k, ksize, kstart, l, l0, &
1646 max_active, nactive, ncol, nri_ref, nthreads, ri, thread_id
1647 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_ncol
1648 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: atom_column
1649 LOGICAL :: any_integral, screened
1650 REAL(kind=
dp) :: pair_factor
1651 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: int_2d_prv, rho_chunk
1652 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: coefficient_compact, d_lp_threads, &
1653 int_3c_prv, int_3c_atom
1656 LOGICAL,
ALLOCATABLE,
DIMENSION(:, :) :: nonzero_ao
1657 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: grid_index
1658 INTEGER :: n_grid_pair, grid_l, point
1659 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: grid_result
1661 CALL timeset(routinen, handle)
1662 ncol =
SIZE(d_lp, 2)
1665 cpassert(
SIZE(d_lp, 1) == n_grid)
1666 cpassert(
SIZE(ri_coefficients, 2) == ncol)
1667 cpassert(
SIZE(ri_coefficients, 3) ==
SIZE(active_atom))
1668 ALLOCATE (atom_ncol(
SIZE(active_atom)), atom_column(ncol,
SIZE(active_atom)))
1671 DO iatom = 1,
SIZE(active_atom)
1672 IF (.NOT. active_atom(iatom)) cycle
1673 nri_ref = get_ref_ri_size(bs_env, iatom)
1675 IF (.NOT. any(ri_coefficients(1:nri_ref, ri, iatom) /= 0.0_dp)) cycle
1676 atom_ncol(iatom) = atom_ncol(iatom) + 1
1677 atom_column(atom_ncol(iatom), iatom) = ri
1680 max_active = maxval(atom_ncol)
1681 cpassert(max_active > 0)
1682 ALLOCATE (coefficient_compact(
SIZE(ri_coefficients, 1), max_active, &
1683 SIZE(active_atom)), source=0.0_dp)
1684 DO iatom = 1,
SIZE(active_atom)
1685 nri_ref = get_ref_ri_size(bs_env, iatom)
1686 DO active_column = 1, atom_ncol(iatom)
1687 ri = atom_column(active_column, iatom)
1688 coefficient_compact(1:nri_ref, active_column, iatom) = &
1689 ri_coefficients(1:nri_ref, ri, iatom)
1692 ALLOCATE (d_lp_threads(n_grid, ncol, nthreads), source=0.0_dp)
1694 CALL compute_nonzero_ao_grid_mask(bs_env, phi_val, ao_col_map, nonzero_ao)
1712 ALLOCATE (int_3c_prv(max_ao_size, max_ao_size, ncol))
1713 ALLOCATE (int_3c_atom(max_ao_size, max_ao_size, max_active))
1714 ALLOCATE (int_2d_prv(max_ao_size*max_ao_size, ncol))
1715 ALLOCATE (rho_chunk(grid_chunk, max_ao_size*max_ao_size))
1716 ALLOCATE (grid_index(n_grid), grid_result(grid_chunk, ncol))
1719 DO jatom = atom_j_mepos + 1, bs_env%n_atom, atom_j_stride
1720 DO katom = jatom, bs_env%n_atom
1721 jstart = ao_col_map(bs_env%i_ao_start_from_atom(jatom))
1722 kstart = ao_col_map(bs_env%i_ao_start_from_atom(katom))
1723 IF (jstart == 0 .OR. kstart == 0) cycle
1724 jsize = bs_env%i_ao_end_from_atom(jatom) - bs_env%i_ao_start_from_atom(jatom) + 1
1725 ksize = bs_env%i_ao_end_from_atom(katom) - bs_env%i_ao_start_from_atom(katom) + 1
1727 DO grid_l = 1, n_grid
1728 IF (.NOT. (nonzero_ao(grid_l, jatom) .AND. nonzero_ao(grid_l, katom))) cycle
1729 n_grid_pair = n_grid_pair + 1
1730 grid_index(n_grid_pair) = grid_l
1732 IF (n_grid_pair == 0) cycle
1733 int_3c_prv(1:jsize, 1:ksize, 1:ncol) = 0.0_dp
1734 any_integral = .false.
1735 DO iatom = 1,
SIZE(active_atom)
1736 IF (.NOT. active_atom(iatom)) cycle
1737 nri_ref = get_ref_ri_size(bs_env, iatom)
1738 nactive = atom_ncol(iatom)
1739 int_3c_atom(1:jsize, 1:ksize, 1:nactive) = 0.0_dp
1740 CALL build_3c_integral_block_auto_ri_ctx( &
1741 int_3c_atom(1:jsize, 1:ksize, 1:nactive), ctx, ws, &
1742 atom_j=jatom, atom_k=katom, atom_i=iatom, &
1743 transform=coefficient_compact(1:nri_ref, 1:nactive, iatom), &
1744 transform_row=1, screened=screened)
1745 IF (.NOT. screened)
THEN
1746 any_integral = .true.
1747 DO active_column = 1, nactive
1748 ri = atom_column(active_column, iatom)
1749 int_3c_prv(1:jsize, 1:ksize, ri) = &
1750 int_3c_prv(1:jsize, 1:ksize, ri) + &
1751 int_3c_atom(1:jsize, 1:ksize, active_column)
1755 IF (.NOT. any_integral) cycle
1760 jk_idx = (k - 1)*jsize + j
1761 int_2d_prv(jk_idx, ri) = int_3c_prv(j, k, ri)
1766 pair_factor = 1.0_dp
1767 IF (jatom /= katom) pair_factor = 2.0_dp
1768 DO l0 = 1, n_grid_pair, grid_chunk
1769 c = min(grid_chunk, n_grid_pair - l0 + 1)
1772 jk_idx = (k - 1)*jsize + j
1774 point = grid_index(l0 + l - 1)
1775 rho_chunk(l, jk_idx) = phi_val(point, jstart + j - 1)* &
1776 phi_val(point, kstart + k - 1)
1780 CALL dgemm(
'N',
'N', c, ncol, jsize*ksize, pair_factor, rho_chunk, grid_chunk, &
1781 int_2d_prv, max_ao_size*max_ao_size, 0.0_dp, &
1782 grid_result, grid_chunk)
1785 point = grid_index(l0 + l - 1)
1786 d_lp_threads(point, ri, thread_id) = &
1787 d_lp_threads(point, ri, thread_id) + grid_result(l, ri)
1798 DO i_thread = 1, nthreads
1799 d_lp(l, ri) = d_lp(l, ri) + d_lp_threads(l, ri, i_thread)
1804 DEALLOCATE (int_3c_prv, int_3c_atom, int_2d_prv, rho_chunk)
1805 DEALLOCATE (grid_index, grid_result)
1809 DEALLOCATE (coefficient_compact, d_lp_threads, atom_column, atom_ncol)
1811 DEALLOCATE (nonzero_ao)
1813 CALL timestop(handle)
1815 END SUBROUTINE compute_d_lp_auto_ri_atoms
1829 SUBROUTINE compute_d_lp_auto_ri_batch(bs_env, ctx, phi_val, ao_col_map, d_lp, n_grid, &
1830 max_ao_size, mepos, num_pe)
1833 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1834 INTENT(IN) :: phi_val
1835 INTEGER,
DIMENSION(:),
INTENT(IN) :: ao_col_map
1836 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_lp
1837 INTEGER,
INTENT(IN) :: n_grid, max_ao_size, mepos, num_pe
1839 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_d_lp_auto_ri_batch'
1841 INTEGER :: column, handle, iatom, n_done, n_total, &
1843 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: global_map
1844 REAL(kind=
dp) :: item_start_time
1845 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_lp_batch, u_pp
1847 CALL timeset(routinen, handle)
1850 DO iatom = mepos + 1, bs_env%n_atom, num_pe
1851 n_total = n_total + 1
1855 DO iatom = mepos + 1, bs_env%n_atom, num_pe
1857 CALL collect_auto_ri_columns_for_atom(bs_env, iatom, u_pp, global_map)
1858 ncol_batch =
SIZE(global_map)
1859 IF (ncol_batch == 0)
THEN
1860 DEALLOCATE (u_pp, global_map)
1862 CALL print_z_lp_progress(bs_env, n_done, n_total, &
1867 ALLOCATE (d_lp_batch(n_grid, ncol_batch), source=0.0_dp)
1868 CALL compute_d_lp_auto_ri_atom(bs_env, ctx, phi_val, ao_col_map, d_lp_batch, &
1869 n_grid, iatom, u_pp, max_ao_size)
1870 DO column = 1, ncol_batch
1871 d_lp(:, global_map(column)) = d_lp(:, global_map(column)) + d_lp_batch(:, column)
1873 DEALLOCATE (u_pp, global_map, d_lp_batch)
1875 CALL print_z_lp_progress(bs_env, n_done, n_total, &
1878 CALL timestop(handle)
1880 END SUBROUTINE compute_d_lp_auto_ri_batch
1893 SUBROUTINE collect_auto_ri_columns_for_atom(bs_env, iatom, U_Pp, global_map)
1895 INTEGER,
INTENT(IN) :: iatom
1896 REAL(kind=
dp),
ALLOCATABLE,
INTENT(OUT) :: u_pp(:, :)
1897 INTEGER,
ALLOCATABLE,
INTENT(OUT) :: global_map(:)
1899 CHARACTER(LEN=*),
PARAMETER :: routinen =
'collect_auto_ri_columns_for_atom'
1901 INTEGER :: ab_block, atom_a, atom_b, column, global_column, handle, local_column, ncol, &
1902 ncol_batch, nri_ref, nri_ref_a, output_offset, row_first
1903 REAL(kind=
dp),
ALLOCATABLE :: u_pp_ab(:, :)
1905 CALL timeset(routinen, handle)
1908 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1909 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1910 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1911 IF (iatom == atom_a .OR. iatom == atom_b)
THEN
1912 ncol_batch = ncol_batch + bs_env%auto_ri%AB_size_opt_RI(ab_block)
1916 nri_ref = get_ref_ri_size(bs_env, iatom)
1917 ALLOCATE (u_pp(nri_ref, ncol_batch), source=0.0_dp)
1918 ALLOCATE (global_map(ncol_batch))
1920 DO ab_block = 1, bs_env%auto_ri%AB_block_count
1921 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
1922 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
1923 IF (iatom /= atom_a .AND. iatom /= atom_b) cycle
1924 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block)
1925 CALL get_u_pp_ab(bs_env%auto_ri, ab_block, u_pp_ab)
1927 IF (iatom == atom_b .AND. atom_b /= atom_a)
THEN
1928 nri_ref_a = get_ref_ri_size(bs_env, atom_a)
1929 row_first = 1 + nri_ref_a
1931 u_pp(:, column + 1:column + ncol) = &
1933 row_first:row_first + nri_ref - 1, 1:ncol)
1935 DO local_column = 1, ncol
1936 IF (local_column <= bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block))
THEN
1937 output_offset = sum(bs_env%auto_ri%sizes_opt_RI(:atom_a - 1)) + &
1938 bs_env%auto_ri%AB_first_p_A(ab_block) - 1
1939 global_column = output_offset + local_column
1941 cpassert(atom_b /= atom_a)
1942 output_offset = sum(bs_env%auto_ri%sizes_opt_RI(:atom_b - 1)) + &
1943 bs_env%auto_ri%AB_first_p_B(ab_block) - 1
1944 global_column = output_offset + local_column - &
1945 bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
1947 global_map(column + local_column) = global_column
1949 column = column + ncol
1950 DEALLOCATE (u_pp_ab)
1952 cpassert(column == ncol_batch)
1954 CALL timestop(handle)
1956 END SUBROUTINE collect_auto_ri_columns_for_atom
1964 SUBROUTINE get_u_pp_ab(auto_ri, AB_block, U_Pp)
1966 INTEGER,
INTENT(IN) :: ab_block
1967 REAL(kind=
dp),
ALLOCATABLE,
INTENT(OUT) :: u_pp(:, :)
1969 INTEGER :: first, last, ncolumn, nrow
1971 nrow = auto_ri%AB_size_ref_RI(ab_block)
1972 ncolumn = auto_ri%AB_size_opt_RI(ab_block)
1973 first = auto_ri%U_Pp_AB_offset(ab_block)
1974 last = first + nrow*ncolumn - 1
1975 ALLOCATE (u_pp(nrow, ncolumn))
1976 u_pp(:, :) = reshape(auto_ri%U_Pp_AB(first:last), [nrow, ncolumn])
1978 END SUBROUTINE get_u_pp_ab
1988 SUBROUTINE compute_auto_ri_grid_radii(bs_env, radius)
1990 REAL(kind=
dp),
INTENT(OUT) :: radius(:)
1992 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_auto_ri_grid_radii'
1994 INTEGER :: a, ab_block, b, handle, n_to_a, ncol
1995 REAL(kind=
dp) :: cutoff, distance
1998 CALL timeset(routinen, handle)
2000 particle_set => bs_env%ri_rs%particle_set
2001 radius = bs_env%ri_rs%cutoff_radius_ri_rs
2002 IF (bs_env%ri_rs%cutoff_radius_ri_rs > 0.0_dp)
THEN
2003 CALL timestop(handle)
2007 cutoff = bs_env%ri_metric%cutoff_radius
2008 DO ab_block = 1, bs_env%auto_ri%AB_block_count
2009 a = bs_env%auto_ri%AB_atom_A(ab_block)
2010 b = bs_env%auto_ri%AB_atom_B(ab_block)
2011 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
2012 ncol = bs_env%auto_ri%AB_size_opt_RI(ab_block)
2013 IF (n_to_a > 0)
THEN
2014 radius(a) = max(radius(a), cutoff + bs_env%ri_rs%radius_ri_per_atom(a))
2016 distance = norm2(particle_set(a)%r - particle_set(b)%r)
2017 radius(a) = max(radius(a), cutoff + bs_env%ri_rs%radius_ri_per_atom(b) + distance)
2020 IF (n_to_a < ncol)
THEN
2022 distance = norm2(particle_set(b)%r - particle_set(a)%r)
2023 radius(b) = max(radius(b), cutoff + bs_env%ri_rs%radius_ri_per_atom(b), &
2024 cutoff + bs_env%ri_rs%radius_ri_per_atom(a) + distance)
2028 CALL timestop(handle)
2029 END SUBROUTINE compute_auto_ri_grid_radii
2047 SUBROUTINE compute_auto_ri_d_lp(qs_env, bs_env, ctx, grid, mat_phi, mat_rhs, max_ao_size)
2051 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: grid
2054 INTEGER,
INTENT(IN) :: max_ao_size
2056 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_auto_ri_d_lp'
2058 INTEGER :: ab_block, atom_a, atom_b, first, fit_atom, handle, handle_project, handle_rhs, l, &
2059 last, n_done, n_first_p_abs, n_to_a, n_total, n_union, nao, natom, ncol, ngrid, npcol, &
2061 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ao_map, global_map, local_index, &
2062 row_offset, union_index
2063 INTEGER,
DIMENSION(:),
POINTER :: ab_row_dist, col_dist, &
2064 first_p_abs_per_atom, retained_size, &
2066 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: needed_fit_atom, union_mask
2067 REAL(kind=
dp) :: item_start_time, radius
2068 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: fit_radius
2069 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: column_map, phi, rhs, u_pp, union_grid
2075 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
2077 CALL timeset(routinen, handle)
2078 CALL get_qs_env(qs_env, para_env=para_env, particle_set=particle_set, &
2079 qs_kind_set=qs_kind_set, cell=cell)
2080 natom = bs_env%n_atom
2081 CALL dbcsr_get_info(mat_phi, row_blk_size=row_size, distribution=dist_phi)
2083 ALLOCATE (first_p_abs_per_atom(natom), col_dist(natom), ab_row_dist(natom), &
2084 retained_size(natom), row_offset(
SIZE(row_size)))
2085 retained_size(:) = bs_env%auto_ri%sizes_opt_RI
2086 DO ri_atom = 1, natom
2087 first_p_abs_per_atom(ri_atom) = 0
2088 DO ab_block = 1, bs_env%auto_ri%AB_block_count
2089 IF (ri_atom == bs_env%auto_ri%AB_atom_A(ab_block) .OR. &
2090 ri_atom == bs_env%auto_ri%AB_atom_B(ab_block))
THEN
2091 first_p_abs_per_atom(ri_atom) = &
2092 first_p_abs_per_atom(ri_atom) + &
2093 bs_env%auto_ri%AB_size_opt_RI(ab_block)
2096 col_dist(ri_atom) = mod(ri_atom - 1, npcol)
2097 ab_row_dist(ri_atom) = mod(ri_atom - 1, nprow)
2100 DO l = 2,
SIZE(row_size)
2101 row_offset(l) = row_offset(l - 1) + row_size(l - 1)
2104 row_dist=row_dist, col_dist=col_dist)
2105 CALL dbcsr_create(ab_d_lp, name=
'AUTO_RI AA/AB d_lp', dist=dist_ab, &
2106 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size, &
2107 col_blk_size=first_p_abs_per_atom)
2109 row_dist=ab_row_dist, col_dist=col_dist)
2110 CALL dbcsr_create(transform, name=
'AUTO_RI U_Pp', dist=dist_t, &
2111 matrix_type=dbcsr_type_no_symmetry, row_blk_size=first_p_abs_per_atom, &
2112 col_blk_size=retained_size)
2113 CALL dbcsr_create(mat_rhs, name=
'AUTO_RI optimized d_lp', dist=dist_ab, &
2114 matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_size, &
2115 col_blk_size=retained_size)
2116 ALLOCATE (fit_radius(natom))
2117 CALL compute_auto_ri_grid_radii(bs_env, fit_radius)
2118 ALLOCATE (needed_fit_atom(natom), union_mask(
SIZE(grid, 2)))
2120 DO ri_atom = para_env%mepos + 1, natom, para_env%num_pe
2121 n_total = n_total + 1
2124 CALL timeset(routinen//
'_AB_d_lp', handle_rhs)
2125 DO ri_atom = para_env%mepos + 1, natom, para_env%num_pe
2127 needed_fit_atom = .false.
2128 DO ab_block = 1, bs_env%auto_ri%AB_block_count
2129 atom_a = bs_env%auto_ri%AB_atom_A(ab_block)
2130 atom_b = bs_env%auto_ri%AB_atom_B(ab_block)
2131 IF (ri_atom /= atom_a .AND. ri_atom /= atom_b) cycle
2132 n_to_a = bs_env%auto_ri%AB_size_opt_RI_to_A(ab_block)
2133 IF (n_to_a > 0) needed_fit_atom(atom_a) = .true.
2134 IF (n_to_a < bs_env%auto_ri%AB_size_opt_RI(ab_block))
THEN
2135 needed_fit_atom(atom_b) = .true.
2138 IF (.NOT. any(needed_fit_atom))
THEN
2140 CALL print_z_lp_progress(bs_env, n_done, n_total, &
2144 union_mask = .false.
2146 DO fit_atom = 1, natom
2147 IF (.NOT. needed_fit_atom(fit_atom)) cycle
2148 radius = max(radius, fit_radius(fit_atom) + &
2149 norm2(particle_set(fit_atom)%r - particle_set(ri_atom)%r))
2150 DO l = 1,
SIZE(grid, 2)
2151 IF (norm2(grid(:, l) - particle_set(fit_atom)%r) <= &
2152 fit_radius(fit_atom)) union_mask(l) = .true.
2155 n_union = count(union_mask)
2156 ALLOCATE (union_index(n_union), union_grid(3, n_union))
2158 DO l = 1,
SIZE(grid, 2)
2159 IF (.NOT. union_mask(l)) cycle
2160 n_union = n_union + 1
2161 union_index(n_union) = l
2162 union_grid(:, n_union) = grid(:, l)
2164 CALL build_phi_on_sphere(bs_env, qs_kind_set, union_grid, ri_atom, &
2165 radius + 1.0_dp, bs_env%i_ao_end_from_atom(natom), local_index, &
2166 ngrid, phi, ao_map, nao)
2167 local_index(1:ngrid) = union_index(local_index(1:ngrid))
2168 n_first_p_abs = first_p_abs_per_atom(ri_atom)
2169 CALL collect_auto_ri_columns_for_atom(bs_env, ri_atom, u_pp, global_map)
2170 cpassert(
SIZE(global_map) == n_first_p_abs)
2172 DO fit_atom = 1, natom
2173 ncol = retained_size(fit_atom)
2174 last = first + ncol - 1
2175 IF (any(global_map >= first .AND. global_map <= last))
THEN
2176 ALLOCATE (column_map(n_first_p_abs, ncol), source=0.0_dp)
2177 DO l = 1, n_first_p_abs
2178 IF (global_map(l) < first .OR. global_map(l) > last) cycle
2179 column_map(l, global_map(l) - first + 1) = 1.0_dp
2182 DEALLOCATE (column_map)
2186 ALLOCATE (rhs(ngrid, n_first_p_abs), source=0.0_dp)
2187 CALL compute_d_lp_auto_ri_atom(bs_env, ctx, phi, ao_map, rhs, ngrid, &
2188 ri_atom, u_pp, max_ao_size)
2190 row_size, row_offset, 0.0_dp)
2191 DEALLOCATE (rhs, u_pp, global_map, phi, ao_map, local_index, &
2192 union_grid, union_index)
2194 CALL print_z_lp_progress(bs_env, n_done, n_total, &
2199 CALL timestop(handle_rhs)
2200 CALL timeset(routinen//
'_transform', handle_project)
2201 CALL dbcsr_multiply(
'N',
'N', 1.0_dp, ab_d_lp, transform, 0.0_dp, &
2202 mat_rhs, filter_eps=0.0_dp)
2203 CALL timestop(handle_project)
2208 DEALLOCATE (first_p_abs_per_atom, retained_size, col_dist, ab_row_dist, row_offset, &
2209 fit_radius, needed_fit_atom, union_mask)
2210 CALL timestop(handle)
2211 END SUBROUTINE compute_auto_ri_d_lp
2221 SUBROUTINE extract_atom_d_lp(mat_rhs, atom_index, local_index, row_offset, rhs)
2223 INTEGER,
INTENT(IN) :: atom_index
2224 INTEGER,
DIMENSION(:),
INTENT(IN) :: local_index, row_offset
2225 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: rhs
2227 CHARACTER(LEN=*),
PARAMETER :: routinen =
'extract_atom_d_lp'
2229 INTEGER :: handle, l, next_row, row
2231 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
2233 CALL timeset(routinen, handle)
2239 DO l = 1,
SIZE(rhs, 1)
2240 DO WHILE (next_row <=
SIZE(row_offset))
2241 IF (row_offset(next_row) >= local_index(l))
EXIT
2243 next_row = next_row + 1
2245 IF (.NOT. found)
NULLIFY (block)
2247 IF (
ASSOCIATED(block)) rhs(l, :) = block(local_index(l) - row_offset(row), :)
2250 CALL timestop(handle)
2251 END SUBROUTINE extract_atom_d_lp
2262 SUBROUTINE fit_auto_ri_z_lp(qs_env, bs_env, grid, mat_rhs, mat_z)
2265 REAL(kind=
dp),
INTENT(IN) :: grid(:, :)
2266 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_rhs, mat_z
2268 CHARACTER(LEN=*),
PARAMETER :: routinen =
'fit_auto_ri_z_lp'
2270 INTEGER :: atom_index, base, group_size, handle, &
2271 handle_gather, i, info, mypcol, n_big, &
2272 n_small, nao, natom, ncol, ngrid, &
2274 INTEGER,
ALLOCATABLE :: all_index(:), ao_map(:), big_list(:), &
2275 grid_size(:), local_index(:), &
2276 row_offset(:), small_list(:)
2277 INTEGER,
POINTER :: row_size(:)
2278 LOGICAL,
ALLOCATABLE :: single_rank(:)
2279 REAL(kind=
dp),
ALLOCATABLE :: atom_rhs(:, :), buffer(:, :), &
2280 diagonal(:), gram(:, :), &
2281 local_rhs(:, :), phi(:, :), radius(:)
2286 CALL timeset(routinen, handle)
2287 CALL get_qs_env(qs_env, para_env=para_env, qs_kind_set=qs_kinds)
2288 CALL dbcsr_get_info(mat_rhs, distribution=distribution, row_blk_size=row_size)
2290 ALLOCATE (column_env)
2291 CALL column_env%from_split(para_env, mypcol)
2292 natom = bs_env%n_atom
2293 ALLOCATE (radius(natom), all_index(
SIZE(grid, 2)), row_offset(
SIZE(row_size)))
2294 CALL compute_auto_ri_grid_radii(bs_env, radius)
2295 CALL classify_z_lp_atoms(bs_env, grid, radius, &
2296 bs_env%auto_ri%sizes_opt_RI, grid_size, &
2297 small_list, n_small, big_list, n_big, group_size)
2298 ALLOCATE (single_rank(natom), source=.false.)
2299 single_rank(small_list(:n_small)) = .true.
2300 DO i = 1,
SIZE(all_index)
2304 DO i = 2,
SIZE(row_size)
2305 row_offset(i) = row_offset(i - 1) + row_size(i - 1)
2307 DO base = mypcol + 1, natom, npcol*column_env%num_pe
2308 CALL timeset(routinen//
'_gather_rhs', handle_gather)
2309 DO slot = 0, column_env%num_pe - 1
2310 atom_index = base + slot*npcol
2311 IF (atom_index > natom)
EXIT
2312 IF (.NOT. single_rank(atom_index)) cycle
2313 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2314 IF (ncol == 0) cycle
2315 ALLOCATE (buffer(
SIZE(grid, 2), ncol))
2316 CALL extract_atom_d_lp(mat_rhs, atom_index, all_index, row_offset, buffer)
2317 CALL column_env%sum(buffer, slot)
2318 IF (column_env%mepos == slot)
THEN
2319 CALL move_alloc(buffer, atom_rhs)
2324 CALL timestop(handle_gather)
2325 atom_index = base + column_env%mepos*npcol
2326 IF (atom_index > natom) cycle
2327 IF (.NOT. single_rank(atom_index)) cycle
2328 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2329 IF (ncol == 0) cycle
2330 CALL build_phi_on_sphere(bs_env, qs_kinds, grid, atom_index, &
2331 radius(atom_index), bs_env%i_ao_end_from_atom(natom), &
2332 local_index, ngrid, phi, ao_map, nao)
2333 ALLOCATE (local_rhs(ngrid, ncol), diagonal(ngrid))
2335 local_rhs(i, :) = atom_rhs(local_index(i), :)
2337 DEALLOCATE (atom_rhs)
2340 CALL dpotrf(
'L', ngrid, gram, ngrid, info)
2342 CALL dpotrs(
'L', ngrid, ncol, gram, ngrid, local_rhs, ngrid, info)
2346 row_size, row_offset, 0.0_dp)
2347 DEALLOCATE (local_rhs, diagonal, gram, phi, ao_map, local_index)
2350 CALL fit_distributed_auto_ri_z_lp(qs_env, bs_env, grid, mat_rhs, mat_z, radius, &
2351 big_list(:n_big), group_size, row_size, row_offset, &
2354 DEALLOCATE (radius, all_index, row_offset, single_rank, grid_size, small_list, big_list)
2355 CALL column_env%free()
2356 DEALLOCATE (column_env)
2358 CALL timestop(handle)
2359 END SUBROUTINE fit_auto_ri_z_lp
2377 SUBROUTINE fit_distributed_auto_ri_z_lp(qs_env, bs_env, grid, mat_rhs, mat_z, radius, &
2378 atom_list, group_size, row_size, row_offset, &
2382 REAL(kind=
dp),
INTENT(IN) :: grid(:, :)
2383 TYPE(
dbcsr_type),
INTENT(INOUT) :: mat_rhs, mat_z
2384 REAL(kind=
dp),
INTENT(IN) :: radius(:)
2385 INTEGER,
INTENT(IN) :: atom_list(:), group_size, row_size(:), &
2386 row_offset(:), all_index(:)
2388 CHARACTER(LEN=*),
PARAMETER :: routinen =
'fit_distributed_auto_ri_z_lp'
2390 INTEGER :: atom_index, base, handle, i, info, &
2391 my_group, nao, ncol, ngrid, ngroups, &
2393 INTEGER,
ALLOCATABLE :: ao_map(:), local_index(:)
2394 REAL(kind=
dp),
ALLOCATABLE :: atom_rhs(:, :), buffer(:, :), &
2395 diagonal(:), local_rhs(:, :), phi(:, :)
2402 CALL timeset(routinen, handle)
2403 CALL get_qs_env(qs_env, para_env=para_env, qs_kind_set=qs_kinds)
2404 ngroups = max(1, para_env%num_pe/group_size)
2405 my_group = min(para_env%mepos/group_size, ngroups - 1)
2406 ALLOCATE (group_env)
2407 CALL group_env%from_split(para_env, my_group)
2408 NULLIFY (blacs_env, gram_struct, rhs_struct)
2410 DO base = 1,
SIZE(atom_list), ngroups
2411 DO slot = 0, ngroups - 1
2412 IF (base + slot >
SIZE(atom_list))
EXIT
2413 atom_index = atom_list(base + slot)
2414 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2415 IF (ncol == 0) cycle
2416 root = slot*group_size
2417 ALLOCATE (buffer(
SIZE(grid, 2), ncol))
2418 CALL extract_atom_d_lp(mat_rhs, atom_index, all_index, row_offset, buffer)
2419 CALL para_env%sum(buffer, root)
2420 IF (para_env%mepos == root)
THEN
2421 CALL move_alloc(buffer, atom_rhs)
2426 IF (base + my_group >
SIZE(atom_list)) cycle
2427 atom_index = atom_list(base + my_group)
2428 ncol = bs_env%auto_ri%sizes_opt_RI(atom_index)
2429 IF (ncol == 0) cycle
2430 IF (group_env%mepos /= 0)
ALLOCATE (atom_rhs(
SIZE(grid, 2), ncol))
2431 CALL group_env%bcast(atom_rhs, 0)
2432 CALL build_phi_on_sphere(bs_env, qs_kinds, grid, atom_index, &
2433 radius(atom_index), bs_env%i_ao_end_from_atom(bs_env%n_atom), &
2434 local_index, ngrid, phi, ao_map, nao)
2435 ALLOCATE (local_rhs(ngrid, ncol), diagonal(ngrid))
2437 local_rhs(i, :) = atom_rhs(local_index(i), :)
2439 DEALLOCATE (atom_rhs)
2443 bs_env%ri_rs%tikhonov, group_env, blacs_env, &
2444 gram_struct, rhs_struct, gram, rhs, info)
2447 IF (group_env%mepos == 0)
THEN
2449 row_size, row_offset, 0.0_dp)
2451 DEALLOCATE (local_rhs, diagonal, phi, ao_map, local_index)
2454 CALL group_env%free()
2455 DEALLOCATE (group_env)
2456 CALL timestop(handle)
2457 END SUBROUTINE fit_distributed_auto_ri_z_lp
2486 SUBROUTINE classify_z_lp_atoms(bs_env, ri_rs_grid_points, cutoff_ri_per_atom, ri_blk_sizes, &
2487 n_local_grid_atom, small_list, n_small, big_list, n_big, G)
2492 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
2494 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: cutoff_ri_per_atom
2495 INTEGER,
DIMENSION(:),
INTENT(IN) :: ri_blk_sizes
2496 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: n_local_grid_atom, small_list, big_list
2497 INTEGER,
INTENT(OUT) :: n_small, n_big, g
2498 CHARACTER(LEN=*),
PARAMETER :: routinen =
'classify_z_lp_atoms'
2503 REAL(kind=
dp),
PARAMETER :: mem_safety = 0.8_dp
2507 REAL(kind=
dp),
PARAMETER :: scalapack_loc_limit = 2.0e9_dp
2509 INTEGER :: g_atom, g_int32, g_int32_max, l, &
2510 n_ao_used_atom, n_grid_total, &
2511 n_local_grid, natom, nthreads_cls, &
2513 LOGICAL :: auto_mode
2514 REAL(kind=
dp) :: budget_bytes, cutoff_ri, dlp_bytes, &
2515 mem_avail_gb, ng, nri, peak_bytes, &
2517 REAL(kind=
dp),
DIMENSION(3) :: pos_p
2521 CALL timeset(routinen, handle)
2523 para_env => bs_env%para_env
2524 particle_set => bs_env%ri_rs%particle_set
2525 natom = bs_env%n_atom
2526 n_grid_total = bs_env%ri_rs%n_grid_points
2527 cpassert(
SIZE(ri_rs_grid_points, 2) == n_grid_total)
2532 ALLOCATE (n_local_grid_atom(natom), small_list(natom), big_list(natom))
2533 DO p_loop_atom = 1, natom
2534 pos_p(:) = particle_set(p_loop_atom)%r(:)
2535 cutoff_ri = cutoff_ri_per_atom(p_loop_atom)
2537 DO l = 1, n_grid_total
2538 IF (sum((ri_rs_grid_points(1:3, l) - pos_p(1:3))**2) <= cutoff_ri**2)
THEN
2539 n_local_grid = n_local_grid + 1
2542 n_local_grid_atom(p_loop_atom) = n_local_grid
2550 auto_mode = (bs_env%ri_rs%n_procs_per_atom_z_lp <= 0)
2552 budget_bytes = mem_safety*mem_avail_gb*1.0e9_dp
2559 IF (bs_env%ri_rs%n_procs_per_atom_z_lp == 1)
THEN
2561 DO p_loop_atom = 1, natom
2562 n_small = n_small + 1
2563 small_list(n_small) = p_loop_atom
2565 ELSE IF (mem_avail_gb <= 0.0_dp)
THEN
2568 IF (bs_env%unit_nr > 0)
THEN
2569 cpwarn(
"RI-RS Z_lP: no meminfo; single-rank solve for all atoms")
2571 DO p_loop_atom = 1, natom
2572 n_small = n_small + 1
2573 small_list(n_small) = p_loop_atom
2577 DO p_loop_atom = 1, natom
2578 ng = real(n_local_grid_atom(p_loop_atom),
dp)
2579 g_int32_max = max(g_int32_max, ceiling(ng*ng/scalapack_loc_limit))
2581 big_list(n_big) = p_loop_atom
2583 g = min(bs_env%ri_rs%n_procs_per_atom_z_lp, para_env%num_pe)
2584 IF (g < g_int32_max)
THEN
2585 g = min(g_int32_max, para_env%num_pe)
2586 IF (bs_env%unit_nr > 0)
THEN
2587 cpwarn(
"RI-RS Z_lP: raised G to avoid ScaLAPACK overflow")
2594 DO p_loop_atom = 1, natom
2595 ng = real(n_local_grid_atom(p_loop_atom),
dp)
2596 nri = real(ri_blk_sizes(p_loop_atom),
dp)
2597 CALL get_n_ao_in_sphere(bs_env, p_loop_atom, &
2598 cutoff_ri_per_atom(p_loop_atom), n_ao_used_atom)
2599 phi_bytes = 8.0_dp*ng*real(n_ao_used_atom,
dp)
2600 dlp_bytes = 8.0_dp*ng*nri*real(1 + nthreads_cls,
dp)
2601 peak_bytes = 8.0_dp*ng*ng + phi_bytes + dlp_bytes
2602 IF (peak_bytes <= budget_bytes)
THEN
2603 n_small = n_small + 1
2604 small_list(n_small) = p_loop_atom
2607 big_list(n_big) = p_loop_atom
2610 g_int32 = ceiling(ng*ng/scalapack_loc_limit)
2611 g_int32_max = max(g_int32_max, g_int32)
2612 g_atom = max(g_atom, g_int32, &
2613 ceiling(8.0_dp*ng*ng/max(budget_bytes - phi_bytes - dlp_bytes, 1.0_dp)))
2619 IF (g_atom > para_env%num_pe)
THEN
2620 CALL cp_abort(__location__, &
2621 "RI-RS Z_lP: an atom is too large to fit even when "// &
2622 "distributed over all ranks. Add nodes, use fewer MPI ranks "// &
2623 "per node, lower CUTOFF_RADIUS_RL_RI, or raise EPS_FILTER "// &
2624 "for more grid screening.")
2626 g = min(max(g_atom, 2), para_env%num_pe)
2630 g = min(bs_env%ri_rs%n_procs_per_atom_z_lp, para_env%num_pe)
2631 IF (g < g_int32_max)
THEN
2632 g = min(g_int32_max, para_env%num_pe)
2633 IF (bs_env%unit_nr > 0)
THEN
2634 cpwarn(
"RI-RS Z_lP: raised G to avoid ScaLAPACK overflow")
2636 ELSE IF (g < g_atom .AND. bs_env%unit_nr > 0)
THEN
2637 cpwarn(
"RI-RS Z_lP: N_PROCS_PER_ATOM_Z_LP too small for the largest atom")
2643 CALL timestop(handle)
2645 END SUBROUTINE classify_z_lp_atoms
2654 SUBROUTINE get_n_ao_in_sphere(bs_env, atom_P, cutoff_ri, n_ao_used)
2657 INTEGER,
INTENT(IN) :: atom_p
2658 REAL(kind=
dp),
INTENT(IN) :: cutoff_ri
2659 INTEGER,
INTENT(OUT) :: n_ao_used
2661 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_n_ao_in_sphere'
2663 INTEGER :: handle, ri_atom
2666 CALL timeset(routinen, handle)
2668 particle_set => bs_env%ri_rs%particle_set
2670 DO ri_atom = 1, bs_env%n_atom
2671 IF (norm2(particle_set(ri_atom)%r(:) - particle_set(atom_p)%r(:)) > &
2672 bs_env%ri_rs%radius_ao_per_atom(ri_atom) + cutoff_ri) cycle
2673 n_ao_used = n_ao_used + bs_env%i_ao_end_from_atom(ri_atom) - &
2674 bs_env%i_ao_start_from_atom(ri_atom) + 1
2677 CALL timestop(handle)
2679 END SUBROUTINE get_n_ao_in_sphere
2696 SUBROUTINE build_phi_on_sphere(bs_env, qs_kind_set, ri_rs_grid_points, &
2697 atom_P, cutoff_ri, n_ao_total, local_grid_idx, n_local_grid, &
2698 phi_local, ao_col_map, n_ao_used, center)
2701 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
2702 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ri_rs_grid_points
2703 INTEGER,
INTENT(IN) :: atom_p
2704 REAL(kind=
dp),
INTENT(IN) :: cutoff_ri
2705 INTEGER,
INTENT(IN) :: n_ao_total
2706 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: local_grid_idx
2707 INTEGER,
INTENT(OUT) :: n_local_grid
2708 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
2709 INTENT(OUT) :: phi_local
2710 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: ao_col_map
2711 INTEGER,
INTENT(OUT) :: n_ao_used
2712 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN),
OPTIONAL :: center
2714 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_phi_on_sphere'
2716 INTEGER :: col_end, col_start, handle, j, k, l, &
2717 loc_idx, n_grid_total, n_keep, ri_atom
2718 REAL(kind=
dp) :: d_sp, dist, r2_threshold
2719 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: w_pt
2720 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: phi_keep, sphere_grid
2721 REAL(kind=
dp),
DIMENSION(3) :: pos_p
2725 CALL timeset(routinen, handle)
2727 cell => bs_env%ri_rs%cell
2728 particle_set => bs_env%ri_rs%particle_set
2730 n_grid_total =
SIZE(ri_rs_grid_points, 2)
2731 IF (
PRESENT(center))
THEN
2732 pos_p(:) = center(:)
2734 pos_p(:) = particle_set(atom_p)%r(:)
2738 DO l = 1, n_grid_total
2739 dist = norm2(ri_rs_grid_points(1:3, l) - pos_p(1:3))
2740 IF (dist <= cutoff_ri) n_local_grid = n_local_grid + 1
2743 ALLOCATE (local_grid_idx(n_local_grid))
2746 DO l = 1, n_grid_total
2747 dist = norm2(ri_rs_grid_points(1:3, l) - pos_p(1:3))
2748 IF (dist <= cutoff_ri)
THEN
2749 n_local_grid = n_local_grid + 1
2750 local_grid_idx(n_local_grid) = l
2754 ALLOCATE (sphere_grid(3, n_local_grid))
2755 DO loc_idx = 1, n_local_grid
2756 sphere_grid(:, loc_idx) = ri_rs_grid_points(:, local_grid_idx(loc_idx))
2760 ALLOCATE (ao_col_map(n_ao_total))
2763 DO ri_atom = 1, bs_env%n_atom
2764 d_sp = norm2(particle_set(ri_atom)%r(:) - pos_p(:))
2765 IF (d_sp > bs_env%ri_rs%radius_ao_per_atom(ri_atom) + cutoff_ri) cycle
2767 DO j = bs_env%i_ao_start_from_atom(ri_atom), bs_env%i_ao_end_from_atom(ri_atom)
2768 n_ao_used = n_ao_used + 1
2769 ao_col_map(j) = n_ao_used
2773 ALLOCATE (phi_local(n_local_grid, n_ao_used))
2776 DO ri_atom = 1, bs_env%n_atom
2777 d_sp = norm2(particle_set(ri_atom)%r(:) - pos_p(:))
2778 IF (d_sp > bs_env%ri_rs%radius_ao_per_atom(ri_atom) + cutoff_ri) cycle
2780 col_start = ao_col_map(bs_env%i_ao_start_from_atom(ri_atom))
2781 col_end = ao_col_map(bs_env%i_ao_end_from_atom(ri_atom))
2784 IF (bs_env%ri_rs%cutoff_radius_ri_ao > 0.0_dp)
THEN
2785 r2_threshold = bs_env%ri_rs%cutoff_radius_ri_ao**2
2787 r2_threshold = bs_env%ri_rs%radius_ao_per_atom(ri_atom)**2
2791 ri_atom, particle_set, qs_kind_set, cell, &
2792 cutoff_squared=r2_threshold)
2795 DEALLOCATE (sphere_grid)
2797 IF (n_local_grid > 0)
THEN
2798 ALLOCATE (w_pt(n_local_grid))
2802 DO l = 1, n_local_grid
2805 w_pt(l) = max(w_pt(l), abs(phi_local(l, j)))
2809 n_keep = count(w_pt > bs_env%eps_filter)
2810 IF (n_keep < n_local_grid)
THEN
2811 ALLOCATE (phi_keep(n_keep, n_ao_used))
2813 DO l = 1, n_local_grid
2814 IF (w_pt(l) > bs_env%eps_filter)
THEN
2816 phi_keep(k, :) = phi_local(l, :)
2817 local_grid_idx(k) = local_grid_idx(l)
2820 CALL move_alloc(phi_keep, phi_local)
2821 n_local_grid = n_keep
2826 CALL timestop(handle)
2828 END SUBROUTINE build_phi_on_sphere
2849 SUBROUTINE build_3c_integral_block_auto_ri_ctx(int_3c, ctx, ws, atom_j, atom_k, atom_i, &
2850 transform, transform_row, screened)
2851 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(INOUT) :: int_3c
2854 INTEGER,
INTENT(IN) :: atom_j, atom_k, atom_i
2855 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: transform
2856 INTEGER,
INTENT(IN) :: transform_row
2857 LOGICAL,
INTENT(OUT),
OPTIONAL :: screened
2859 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_3c_integral_block_auto_ri_ctx'
2861 INTEGER :: handle_contract, handle_eri, ikind, iset, jkind, jset, kkind, kset, l, ncoi, &
2862 ncoj, ncok, ncol, npgf_group, nseti, nsetj, nsetk, primitive_first, sgfi, sgfj, sgfk
2863 INTEGER,
DIMENSION(:),
POINTER :: lmax_i, lmax_j, lmax_k, lmin_i, lmin_j, &
2864 lmin_k, npgfi, npgfj, npgfk, nsgfi, &
2866 INTEGER,
DIMENSION(:, :),
POINTER :: first_sgf_i, first_sgf_j, first_sgf_k
2867 REAL(kind=
dp) :: dij, dik, djk, group_radius, &
2868 kind_radius_i, kind_radius_j, &
2869 kind_radius_k, sijk_ext
2870 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: rpgf_group, zet_group
2871 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: spi_group
2872 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: sijk, sijk_contr
2873 REAL(kind=
dp),
DIMENSION(3) :: ri, rij, rik, rj, rjk, rk
2874 REAL(kind=
dp),
DIMENSION(:),
POINTER :: set_radius_i, set_radius_j, set_radius_k
2875 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: rpgf_i, rpgf_j, rpgf_k, zeti, zetj, zetk
2877 IF (
PRESENT(screened)) screened = .false.
2878 ri =
pbc(ctx%particle_set(atom_i)%r(1:3), ctx%cell)
2879 rj =
pbc(ctx%particle_set(atom_j)%r(1:3), ctx%cell)
2880 rk =
pbc(ctx%particle_set(atom_k)%r(1:3), ctx%cell)
2888 ikind = ctx%kind_of(atom_i)
2889 jkind = ctx%kind_of(atom_j)
2890 kkind = ctx%kind_of(atom_k)
2891 CALL get_gto_basis_set(ctx%basis_i(ikind)%gto_basis_set, first_sgf=first_sgf_i, &
2892 lmax=lmax_i, lmin=lmin_i, npgf=npgfi, nset=nseti, &
2893 nsgf_set=nsgfi, pgf_radius=rpgf_i, set_radius=set_radius_i, &
2894 zet=zeti, kind_radius=kind_radius_i)
2895 CALL get_gto_basis_set(ctx%basis_j(jkind)%gto_basis_set, first_sgf=first_sgf_j, &
2896 lmax=lmax_j, lmin=lmin_j, npgf=npgfj, nset=nsetj, &
2897 nsgf_set=nsgfj, pgf_radius=rpgf_j, set_radius=set_radius_j, &
2898 zet=zetj, kind_radius=kind_radius_j)
2899 CALL get_gto_basis_set(ctx%basis_k(kkind)%gto_basis_set, first_sgf=first_sgf_k, &
2900 lmax=lmax_k, lmin=lmin_k, npgf=npgfk, nset=nsetk, &
2901 nsgf_set=nsgfk, pgf_radius=rpgf_k, set_radius=set_radius_k, &
2902 zet=zetk, kind_radius=kind_radius_k)
2904 IF (kind_radius_j + kind_radius_i + ctx%dr_ij < dij .OR. &
2905 kind_radius_j + kind_radius_k + ctx%dr_jk < djk .OR. &
2906 kind_radius_k + kind_radius_i + ctx%dr_ik < dik)
THEN
2907 IF (
PRESENT(screened)) screened = .true.
2911 ncol =
SIZE(transform, 2)
2912 cpassert(
SIZE(int_3c, 3) == ncol)
2915 group_radius = 0.0_dp
2917 IF (lmin_i(iset) /= l .OR. lmax_i(iset) /= l) cycle
2918 npgf_group = npgf_group + npgfi(iset)
2919 group_radius = max(group_radius, set_radius_i(iset))
2921 IF (npgf_group == 0) cycle
2922 ncoi = npgf_group*
ncoset(l)
2923 ALLOCATE (zet_group(npgf_group), rpgf_group(npgf_group))
2924 ALLOCATE (spi_group(ncoi, ncol), source=0.0_dp)
2927 IF (lmin_i(iset) /= l .OR. lmax_i(iset) /= l) cycle
2928 zet_group(primitive_first:primitive_first + npgfi(iset) - 1) = &
2929 zeti(1:npgfi(iset), iset)
2930 rpgf_group(primitive_first:primitive_first + npgfi(iset) - 1) = &
2931 rpgf_i(1:npgfi(iset), iset)
2932 sgfi = first_sgf_i(1, iset)
2933 spi_group((primitive_first - 1)*
ncoset(l) + 1: &
2934 (primitive_first + npgfi(iset) - 1)*
ncoset(l), :) = &
2935 matmul(ctx%spi(iset, ikind)%array, &
2936 transform(transform_row + sgfi - 1: &
2937 transform_row + sgfi + nsgfi(iset) - 2, :))
2938 primitive_first = primitive_first + npgfi(iset)
2942 IF (set_radius_j(jset) + group_radius + ctx%dr_ij < dij) cycle
2944 IF (set_radius_j(jset) + set_radius_k(kset) + ctx%dr_jk < djk) cycle
2945 IF (set_radius_k(kset) + group_radius + ctx%dr_ik < dik) cycle
2946 ncoj = npgfj(jset)*
ncoset(lmax_j(jset))
2947 ncok = npgfk(kset)*
ncoset(lmax_k(kset))
2948 sgfj = first_sgf_j(1, jset)
2949 sgfk = first_sgf_k(1, kset)
2950 IF (ncoj*ncok*ncoi <= 0) cycle
2951 ALLOCATE (sijk(ncoj, ncok, ncoi), source=0.0_dp)
2952 CALL timeset(routinen//
'_eri', handle_eri)
2954 lmin_j(jset), lmax_j(jset), npgfj(jset), zetj(:, jset), &
2955 rpgf_j(:, jset), rj, &
2956 lmin_k(kset), lmax_k(kset), npgfk(kset), zetk(:, kset), &
2957 rpgf_k(:, kset), rk, l, l, npgf_group, zet_group, &
2958 rpgf_group, ri, djk, dij, dik, ws%lib, ctx%potential_parameter, &
2959 int_abc_ext=sijk_ext)
2960 CALL timestop(handle_eri)
2961 ALLOCATE (sijk_contr(nsgfj(jset), nsgfk(kset), ncol))
2962 CALL timeset(routinen//
'_contract', handle_contract)
2964 ctx%spk(kset, kkind)%array, spi_group, ncoj, ncok, ncoi, &
2965 nsgfj(jset), nsgfk(kset), ncol, ws%cpp_buffer, ws%ccp_buffer)
2966 CALL timestop(handle_contract)
2968 int_3c(sgfj:sgfj + nsgfj(jset) - 1, sgfk:sgfk + nsgfk(kset) - 1, :) = &
2969 int_3c(sgfj:sgfj + nsgfj(jset) - 1, sgfk:sgfk + nsgfk(kset) - 1, :) + &
2971 DEALLOCATE (sijk_contr)
2974 DEALLOCATE (zet_group, rpgf_group, spi_group)
2977 END SUBROUTINE build_3c_integral_block_auto_ri_ctx
2985 INTEGER FUNCTION get_ref_ri_size(bs_env, iatom)
RESULT(n)
2987 INTEGER,
INTENT(IN) :: iatom
2991 ikind = bs_env%ri_rs%particle_set(iatom)%atomic_kind%kind_number
2992 n = bs_env%basis_set_RI(ikind)%gto_basis_set%nsgf
2994 END FUNCTION get_ref_ri_size
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.
represent the structure of a full matrix
represent a full matrix distributed on many processors
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.
Shared numerical operations for computing the RI-RS matrix Z_lP.
subroutine, public build_gram_jacobi_blas(phi_local, n_local_grid, n_ao_used, tikhonov, d_local, d_vec_local)
Forms the conditioned dense RI-RS matrix.
subroutine, public scale_rows_by_diag(matrix, diagonal, nrow, ncol)
Multiplies every matrix row by the corresponding diagonal entry: A(l, :) <- d_l A(l,...
subroutine, public build_jacobi_diag_from_phi(phi_local, n_local_grid, n_ao_used, d_vec_local)
Computes d_l = 1/sqrt(D_ll) = 1/Σ_μ ϕ_μ(r_l)² without forming D.
subroutine, public solve_d_lp_distributed(phi_local, d_vec, d_lp, n_loc, n_ao, n_rhs, tikhonov, para_env_sub, blacs_env_sub, fm_struct_d, fm_struct_b, fm_d, fm_b, info)
Solves D Z = d with ScaLAPACK for one RI atom and replicated inputs.
subroutine, public store_z_lp_columns(mat_z_lp, z_local, local_grid_idx, n_local_grid, n_loc_ri, atom_p, r_blk_sizes, row_offset, eps_filter)
Stores dense Z_lP columns in the distributed block-sparse matrix.
Computes the RI-RS fitting matrix Z_lP.
subroutine, public compute_z_lp(qs_env, bs_env, ri_rs_grid_points, mat_phi_mu_l, mat_z_lp)
Computes Z_lP for (1) a tabulated RI basis set or (2) an on-the-fly generated RI basis set.
Common setup operations used by the periodic and non-periodic GW RI-RS implementations.
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.
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 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.
All kind of helpful little routines.
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...
keeps the information about the structure of a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
Shared read-only context for repeated 3-center integral block builds: screening parameters,...
Per-thread workspace for 3-center integral block builds: libint object + contraction buffers....
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.