28 USE cp_dbcsr_api,
ONLY: dbcsr_convert_sizes_to_offsets, &
72#include "./base/base_uses.f90"
77 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .false.
81 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'task_list_methods'
117 reorder_rs_grid_ranks, skip_load_balance_distributed, &
118 pw_env_external, sab_orb_external, ext_kpoints)
122 CHARACTER(LEN=*),
INTENT(IN) :: basis_type
123 LOGICAL,
INTENT(IN) :: reorder_rs_grid_ranks, &
124 skip_load_balance_distributed
125 TYPE(
pw_env_type),
OPTIONAL,
POINTER :: pw_env_external
127 OPTIONAL,
POINTER :: sab_orb_external
128 TYPE(
kpoint_type),
OPTIONAL,
POINTER :: ext_kpoints
130 CHARACTER(LEN=*),
PARAMETER :: routinen =
'generate_qs_task_list'
131 INTEGER,
PARAMETER :: max_tasks = 2000
133 INTEGER :: cindex, curr_tasks, handle, i, iatom, iatom_old, igrid_level, igrid_level_old, &
134 ikind, ilevel, img, img_old, ipair, ipgf, iset, itask, jatom, jatom_old, jkind, jpgf, &
135 jset, maxpgf, maxset, natoms, nimages, nkind, nseta, nsetb, slot
136 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: blocks
137 INTEGER,
DIMENSION(3) :: cellind
138 INTEGER,
DIMENSION(:),
POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
140 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
142 REAL(kind=
dp) :: kind_radius_a, kind_radius_b
143 REAL(kind=
dp),
DIMENSION(3) :: ra, rab
144 REAL(kind=
dp),
DIMENSION(:),
POINTER :: set_radius_a, set_radius_b
145 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: rpgfa, rpgfb, zeta, zetb
157 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
162 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
164 CALL timeset(routinen, handle)
167 qs_kind_set=qs_kind_set, &
169 particle_set=particle_set, &
170 dft_control=dft_control)
173 IF (
PRESENT(sab_orb_external)) sab_orb => sab_orb_external
176 IF (
PRESENT(pw_env_external)) pw_env => pw_env_external
177 CALL pw_env_get(pw_env, rs_descs=rs_descs, rs_grids=rs_grids)
180 gridlevel_info => pw_env%gridlevel_info
181 cube_info => pw_env%cube_info
184 nkind =
SIZE(qs_kind_set)
185 natoms =
SIZE(particle_set)
189 qs_kind => qs_kind_set(ikind)
191 basis_set=orb_basis_set, basis_type=basis_type)
193 IF (.NOT.
ASSOCIATED(orb_basis_set)) cycle
196 maxset = max(nseta, maxset)
197 maxpgf = max(maxval(npgfa), maxpgf)
201 nimages = dft_control%nimages
203 NULLIFY (cell_to_index)
205 IF (
PRESENT(ext_kpoints))
THEN
206 IF (
ASSOCIATED(ext_kpoints))
THEN
209 nimages =
SIZE(ext_kpoints%index_to_cell, 2)
212 IF (.NOT. dokp .AND. nimages > 1)
THEN
214 CALL get_ks_env(ks_env=ks_env, kpoints=kpoints)
219 IF (
ASSOCIATED(task_list%atom_pair_send))
DEALLOCATE (task_list%atom_pair_send)
220 IF (
ASSOCIATED(task_list%atom_pair_recv))
DEALLOCATE (task_list%atom_pair_recv)
223 IF (.NOT.
ASSOCIATED(task_list%tasks))
THEN
227 curr_tasks =
SIZE(task_list%tasks)
229 ALLOCATE (basis_set_list(nkind))
231 qs_kind => qs_kind_set(ikind)
232 CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, &
233 basis_type=basis_type)
234 IF (
ASSOCIATED(basis_set_a))
THEN
235 basis_set_list(ikind)%gto_basis_set => basis_set_a
237 NULLIFY (basis_set_list(ikind)%gto_basis_set)
249 DO slot = 1, sab_orb(1)%nl_size
250 ikind = sab_orb(1)%nlist_task(slot)%ikind
251 jkind = sab_orb(1)%nlist_task(slot)%jkind
252 iatom = sab_orb(1)%nlist_task(slot)%iatom
253 jatom = sab_orb(1)%nlist_task(slot)%jatom
254 rab(1:3) = sab_orb(1)%nlist_task(slot)%r(1:3)
255 cellind(1:3) = sab_orb(1)%nlist_task(slot)%cell(1:3)
257 basis_set_a => basis_set_list(ikind)%gto_basis_set
258 IF (.NOT.
ASSOCIATED(basis_set_a)) cycle
259 basis_set_b => basis_set_list(jkind)%gto_basis_set
260 IF (.NOT.
ASSOCIATED(basis_set_b)) cycle
261 ra(:) =
pbc(particle_set(iatom)%r, cell)
263 la_max => basis_set_a%lmax
264 la_min => basis_set_a%lmin
265 npgfa => basis_set_a%npgf
266 nseta = basis_set_a%nset
267 rpgfa => basis_set_a%pgf_radius
268 set_radius_a => basis_set_a%set_radius
269 kind_radius_a = basis_set_a%kind_radius
270 zeta => basis_set_a%zet
272 lb_max => basis_set_b%lmax
273 lb_min => basis_set_b%lmin
274 npgfb => basis_set_b%npgf
275 nsetb = basis_set_b%nset
276 rpgfb => basis_set_b%pgf_radius
277 set_radius_b => basis_set_b%set_radius
278 kind_radius_b = basis_set_b%kind_radius
279 zetb => basis_set_b%zet
282 cindex = cell_to_index(cellind(1), cellind(2), cellind(3))
288 rs_descs, dft_control, cube_info, gridlevel_info, cindex, &
289 iatom, jatom, rpgfa, rpgfb, zeta, zetb, kind_radius_b, &
290 set_radius_a, set_radius_b, ra, rab, &
291 la_max, la_min, lb_max, lb_min, npgfa, npgfb, nseta, nsetb)
298 rs_descs=rs_descs, ntasks=task_list%ntasks, natoms=natoms, &
299 tasks=task_list%tasks, atom_pair_send=task_list%atom_pair_send, &
300 atom_pair_recv=task_list%atom_pair_recv, symmetric=.true., &
301 reorder_rs_grid_ranks=reorder_rs_grid_ranks, &
302 skip_load_balance_distributed=skip_load_balance_distributed)
305 ALLOCATE (nsgf(natoms))
306 CALL get_particle_set(particle_set, qs_kind_set, basis=basis_set_list, nsgf=nsgf)
307 IF (
ASSOCIATED(task_list%atom_pair_send))
THEN
309 CALL rs_calc_offsets(pairs=task_list%atom_pair_send, &
311 group_size=rs_descs(1)%rs_desc%group_size, &
312 pair_offsets=task_list%pair_offsets_send, &
313 rank_offsets=task_list%rank_offsets_send, &
314 rank_sizes=task_list%rank_sizes_send, &
315 buffer_size=task_list%buffer_size_send)
318 IF (
ASSOCIATED(task_list%pair_offsets_send))
DEALLOCATE (task_list%pair_offsets_send)
319 IF (
ASSOCIATED(task_list%rank_offsets_send))
DEALLOCATE (task_list%rank_offsets_send)
320 IF (
ASSOCIATED(task_list%rank_sizes_send))
DEALLOCATE (task_list%rank_sizes_send)
321 task_list%buffer_size_send = 0
323 CALL rs_calc_offsets(pairs=task_list%atom_pair_recv, &
325 group_size=rs_descs(1)%rs_desc%group_size, &
326 pair_offsets=task_list%pair_offsets_recv, &
327 rank_offsets=task_list%rank_offsets_recv, &
328 rank_sizes=task_list%rank_sizes_recv, &
329 buffer_size=task_list%buffer_size_recv)
330 IF (
ASSOCIATED(task_list%atom_pair_send))
THEN
331 CALL rs_group_atom_pairs(task_list%atom_pair_send, &
332 task_list%unpack_block_starts, task_list%unpack_pair_indices)
334 CALL rs_group_atom_pairs(task_list%atom_pair_recv, &
335 task_list%unpack_block_starts, task_list%unpack_pair_indices)
337 DEALLOCATE (basis_set_list, nsgf)
340 IF (reorder_rs_grid_ranks)
THEN
341 DO i = 1, gridlevel_info%ngrid_levels
342 IF (rs_descs(i)%rs_desc%distributed)
THEN
349 CALL create_grid_task_list(task_list=task_list, &
350 qs_kind_set=qs_kind_set, &
351 particle_set=particle_set, &
353 basis_type=basis_type, &
359 IF (
ASSOCIATED(task_list%taskstart))
THEN
360 DEALLOCATE (task_list%taskstart)
362 IF (
ASSOCIATED(task_list%taskstop))
THEN
363 DEALLOCATE (task_list%taskstop)
365 IF (
ASSOCIATED(task_list%npairs))
THEN
366 DEALLOCATE (task_list%npairs)
371 ALLOCATE (task_list%npairs(
SIZE(rs_descs)))
373 iatom_old = -1; jatom_old = -1; igrid_level_old = -1; img_old = -1
377 DO i = 1, task_list%ntasks
378 igrid_level = task_list%tasks(i)%grid_level
379 img = task_list%tasks(i)%image
380 iatom = task_list%tasks(i)%iatom
381 jatom = task_list%tasks(i)%jatom
382 iset = task_list%tasks(i)%iset
383 jset = task_list%tasks(i)%jset
384 ipgf = task_list%tasks(i)%ipgf
385 jpgf = task_list%tasks(i)%jpgf
386 IF (igrid_level /= igrid_level_old)
THEN
387 IF (igrid_level_old /= -1)
THEN
388 task_list%npairs(igrid_level_old) = ipair
391 igrid_level_old = igrid_level
395 ELSE IF (iatom /= iatom_old .OR. jatom /= jatom_old .OR. img /= img_old)
THEN
403 IF (task_list%ntasks /= 0)
THEN
404 task_list%npairs(igrid_level) = ipair
411 ALLOCATE (task_list%taskstart(maxval(task_list%npairs),
SIZE(rs_descs)))
412 ALLOCATE (task_list%taskstop(maxval(task_list%npairs),
SIZE(rs_descs)))
414 iatom_old = -1; jatom_old = -1; igrid_level_old = -1; img_old = -1
416 task_list%taskstart = 0
417 task_list%taskstop = 0
419 DO i = 1, task_list%ntasks
420 igrid_level = task_list%tasks(i)%grid_level
421 img = task_list%tasks(i)%image
422 iatom = task_list%tasks(i)%iatom
423 jatom = task_list%tasks(i)%jatom
424 iset = task_list%tasks(i)%iset
425 jset = task_list%tasks(i)%jset
426 ipgf = task_list%tasks(i)%ipgf
427 jpgf = task_list%tasks(i)%jpgf
428 IF (igrid_level /= igrid_level_old)
THEN
429 IF (igrid_level_old /= -1)
THEN
430 task_list%taskstop(ipair, igrid_level_old) = i - 1
433 task_list%taskstart(ipair, igrid_level) = i
434 igrid_level_old = igrid_level
438 ELSE IF (iatom /= iatom_old .OR. jatom /= jatom_old .OR. img /= img_old)
THEN
440 task_list%taskstart(ipair, igrid_level) = i
441 task_list%taskstop(ipair - 1, igrid_level) = i - 1
448 IF (task_list%ntasks /= 0)
THEN
449 task_list%taskstop(ipair, igrid_level) = task_list%ntasks
453 IF (debug_this_module)
THEN
454 tasks => task_list%tasks
456 WRITE (6, *)
"Total number of tasks ", task_list%ntasks
457 DO igrid_level = 1, gridlevel_info%ngrid_levels
458 WRITE (6, *)
"Total number of pairs(grid_level) ", &
459 igrid_level, task_list%npairs(igrid_level)
463 DO igrid_level = 1, gridlevel_info%ngrid_levels
465 ALLOCATE (blocks(natoms, natoms, nimages))
467 DO ipair = 1, task_list%npairs(igrid_level)
468 itask = task_list%taskstart(ipair, igrid_level)
469 ilevel = task_list%tasks(itask)%grid_level
470 img = task_list%tasks(itask)%image
471 iatom = task_list%tasks(itask)%iatom
472 jatom = task_list%tasks(itask)%jatom
473 iset = task_list%tasks(itask)%iset
474 jset = task_list%tasks(itask)%jset
475 ipgf = task_list%tasks(itask)%ipgf
476 jpgf = task_list%tasks(itask)%jpgf
477 IF (blocks(iatom, jatom, img) == -1 .AND. blocks(jatom, iatom, img) == -1)
THEN
478 blocks(iatom, jatom, img) = 1
479 blocks(jatom, iatom, img) = 1
481 WRITE (6, *)
"TASK LIST CONFLICT IN PAIR ", ipair
482 WRITE (6, *)
"Reuse of iatom, jatom, image ", iatom, jatom, img
488 DO itask = task_list%taskstart(ipair, igrid_level), task_list%taskstop(ipair, igrid_level)
489 ilevel = task_list%tasks(itask)%grid_level
490 img = task_list%tasks(itask)%image
491 iatom = task_list%tasks(itask)%iatom
492 jatom = task_list%tasks(itask)%jatom
493 iset = task_list%tasks(itask)%iset
494 jset = task_list%tasks(itask)%jset
495 ipgf = task_list%tasks(itask)%ipgf
496 jpgf = task_list%tasks(itask)%jpgf
497 IF (iatom /= iatom_old .OR. jatom /= jatom_old .OR. img /= img_old)
THEN
498 WRITE (6, *)
"TASK LIST CONFLICT IN TASK ", itask
499 WRITE (6, *)
"Inconsistent iatom, jatom, image ", iatom, jatom, img
500 WRITE (6, *)
"Should be iatom, jatom, image ", iatom_old, jatom_old, img_old
511 CALL timestop(handle)
519 SUBROUTINE create_grid_task_list(task_list, qs_kind_set, particle_set, cell, basis_type, rs_grids)
521 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
524 CHARACTER(LEN=*) :: basis_type
528 INTEGER :: nset, natoms, nkinds, ntasks, &
529 ikind, iatom, itask, nsgf
530 INTEGER,
DIMENSION(:),
ALLOCATABLE :: atom_kinds, level_list, iatom_list, jatom_list, &
531 iset_list, jset_list, ipgf_list, jpgf_list, &
532 border_mask_list, block_num_list
533 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: radius_list
534 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: rab_list, atom_positions
535 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
536 INTEGER,
DIMENSION(:, :),
POINTER :: first_sgf
537 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: sphi, zet
538 INTEGER,
DIMENSION(:),
POINTER :: lmax, lmin, npgf, nsgf_set
540 nkinds =
SIZE(qs_kind_set)
541 natoms =
SIZE(particle_set)
542 ntasks = task_list%ntasks
543 tasks => task_list%tasks
545 IF (.NOT.
ASSOCIATED(task_list%grid_basis_sets))
THEN
547 ALLOCATE (task_list%grid_basis_sets(nkinds))
549 CALL get_qs_kind(qs_kind_set(ikind), basis_type=basis_type, basis_set=orb_basis_set)
555 first_sgf=first_sgf, &
562 maxco=
SIZE(sphi, 1), &
563 maxpgf=
SIZE(zet, 1), &
568 first_sgf=first_sgf, &
571 basis_set=task_list%grid_basis_sets(ikind))
576 ALLOCATE (atom_kinds(natoms), atom_positions(3, natoms))
578 atom_kinds(iatom) = particle_set(iatom)%atomic_kind%kind_number
579 atom_positions(:, iatom) =
pbc(particle_set(iatom)%r, cell)
582 ALLOCATE (level_list(ntasks), iatom_list(ntasks), jatom_list(ntasks))
583 ALLOCATE (iset_list(ntasks), jset_list(ntasks), ipgf_list(ntasks), jpgf_list(ntasks))
584 ALLOCATE (border_mask_list(ntasks), block_num_list(ntasks))
585 ALLOCATE (radius_list(ntasks), rab_list(3, ntasks))
588 level_list(itask) = tasks(itask)%grid_level
589 iatom_list(itask) = tasks(itask)%iatom
590 jatom_list(itask) = tasks(itask)%jatom
591 iset_list(itask) = tasks(itask)%iset
592 jset_list(itask) = tasks(itask)%jset
593 ipgf_list(itask) = tasks(itask)%ipgf
594 jpgf_list(itask) = tasks(itask)%jpgf
595 IF (tasks(itask)%dist_type == 2)
THEN
596 border_mask_list(itask) = iand(63, not(tasks(itask)%subpatch_pattern))
598 border_mask_list(itask) = 0
600 block_num_list(itask) = tasks(itask)%pair_index
601 radius_list(itask) = tasks(itask)%radius
602 rab_list(:, itask) = tasks(itask)%rab(:)
608 nblocks=
SIZE(task_list%pair_offsets_recv), &
609 block_offsets=task_list%pair_offsets_recv, &
610 atom_positions=atom_positions, &
611 atom_kinds=atom_kinds, &
612 basis_sets=task_list%grid_basis_sets, &
613 level_list=level_list, &
614 iatom_list=iatom_list, &
615 jatom_list=jatom_list, &
616 iset_list=iset_list, &
617 jset_list=jset_list, &
618 ipgf_list=ipgf_list, &
619 jpgf_list=jpgf_list, &
620 border_mask_list=border_mask_list, &
621 block_num_list=block_num_list, &
622 radius_list=radius_list, &
625 task_list=task_list%grid_task_list)
630 END SUBROUTINE create_grid_task_list
665 cube_info, gridlevel_info, cindex, &
666 iatom, jatom, rpgfa, rpgfb, zeta, zetb, kind_radius_b, set_radius_a, set_radius_b, ra, rab, &
667 la_max, la_min, lb_max, lb_min, npgfa, npgfb, nseta, nsetb)
669 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
670 INTEGER :: ntasks, curr_tasks
676 INTEGER :: cindex, iatom, jatom
677 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: rpgfa, rpgfb, zeta, zetb
678 REAL(kind=
dp) :: kind_radius_b
679 REAL(kind=
dp),
DIMENSION(:),
POINTER :: set_radius_a, set_radius_b
680 REAL(kind=
dp),
DIMENSION(3) :: ra, rab
681 INTEGER,
DIMENSION(:),
POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
683 INTEGER :: nseta, nsetb
685 INTEGER :: cube_center(3), igrid_level, ipgf, iset, &
686 jpgf, jset, lb_cube(3), ub_cube(3)
687 REAL(kind=
dp) :: dab, rab2, radius, zetp
689 rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
692 loop_iset:
DO iset = 1, nseta
694 IF (set_radius_a(iset) + kind_radius_b < dab) cycle loop_iset
696 loop_jset:
DO jset = 1, nsetb
698 IF (set_radius_a(iset) + set_radius_b(jset) < dab) cycle loop_jset
700 loop_ipgf:
DO ipgf = 1, npgfa(iset)
702 IF (rpgfa(ipgf, iset) + set_radius_b(jset) < dab) cycle loop_ipgf
704 loop_jpgf:
DO jpgf = 1, npgfb(jset)
706 IF (rpgfa(ipgf, iset) + rpgfb(jpgf, jset) < dab) cycle loop_jpgf
708 zetp = zeta(ipgf, iset) + zetb(jpgf, jset)
711 CALL compute_pgf_properties(cube_center, lb_cube, ub_cube, radius, &
712 rs_descs(igrid_level)%rs_desc, cube_info(igrid_level), &
713 la_max(iset), zeta(ipgf, iset), la_min(iset), &
714 lb_max(jset), zetb(jpgf, jset), lb_min(jset), &
715 ra, rab, rab2, dft_control%qs_control%eps_rho_rspace)
717 CALL pgf_to_tasks(tasks, ntasks, curr_tasks, &
718 rab, cindex, iatom, jatom, iset, jset, ipgf, jpgf, &
719 la_max(iset), lb_max(jset), rs_descs(igrid_level)%rs_desc, &
720 igrid_level, gridlevel_info%ngrid_levels, cube_center, &
721 lb_cube, ub_cube, radius)
767 SUBROUTINE compute_pgf_properties(cube_center, lb_cube, ub_cube, radius, &
768 rs_desc, cube_info, la_max, zeta, la_min, lb_max, zetb, lb_min, ra, rab, rab2, eps)
770 INTEGER,
DIMENSION(3),
INTENT(OUT) :: cube_center, lb_cube, ub_cube
771 REAL(kind=
dp),
INTENT(OUT) :: radius
774 INTEGER,
INTENT(IN) :: la_max
775 REAL(kind=
dp),
INTENT(IN) :: zeta
776 INTEGER,
INTENT(IN) :: la_min, lb_max
777 REAL(kind=
dp),
INTENT(IN) :: zetb
778 INTEGER,
INTENT(IN) :: lb_min
779 REAL(kind=
dp),
INTENT(IN) :: ra(3), rab(3), rab2, eps
782 INTEGER,
DIMENSION(:),
POINTER :: sphere_bounds
783 REAL(kind=
dp) :: cutoff, f, prefactor, rb(3), zetp
784 REAL(kind=
dp),
DIMENSION(3) :: rp
789 rp(:) = ra(:) + zetb/zetp*rab(:)
790 rb(:) = ra(:) + rab(:)
793 prefactor = exp(-zeta*f*rab2)
795 zetp=zetp, eps=eps, prefactor=prefactor, cutoff=cutoff)
799 cube_center(:) =
modulo(cube_center(:), rs_desc%npts(:))
800 cube_center(:) = cube_center(:) + rs_desc%lb(:)
802 IF (rs_desc%orthorhombic)
THEN
803 CALL return_cube(cube_info, radius, lb_cube, ub_cube, sphere_bounds)
807 extent(:) = ub_cube(:) - lb_cube(:)
808 lb_cube(:) = -extent(:)/2 - 1
809 ub_cube(:) = extent(:)/2
812 END SUBROUTINE compute_pgf_properties
828 INTEGER FUNCTION cost_model(lb_cube, ub_cube, fraction, lmax, is_ortho)
829 INTEGER,
DIMENSION(3),
INTENT(IN) :: lb_cube, ub_cube
830 REAL(kind=
dp),
INTENT(IN) :: fraction
835 REAL(kind=
dp) :: v1, v2, v3, v4, v5
837 cmax = maxval(((ub_cube - lb_cube) + 1)/2)
852 cost_model = ceiling(((lmax + v1)*(cmax + v2)**3*v3*fraction + v4 + v5*lmax**7)/1000.0_dp)
854 END FUNCTION cost_model
888 SUBROUTINE pgf_to_tasks(tasks, ntasks, curr_tasks, &
889 rab, cindex, iatom, jatom, iset, jset, ipgf, jpgf, &
890 la_max, lb_max, rs_desc, igrid_level, n_levels, &
891 cube_center, lb_cube, ub_cube, radius)
893 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
894 INTEGER,
INTENT(INOUT) :: ntasks, curr_tasks
895 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: rab
896 INTEGER,
INTENT(IN) :: cindex, iatom, jatom, iset, jset, ipgf, &
899 INTEGER,
INTENT(IN) :: igrid_level, n_levels
900 INTEGER,
DIMENSION(3),
INTENT(IN) :: cube_center, lb_cube, ub_cube
901 REAL(kind=
dp),
INTENT(IN) :: radius
903 INTEGER,
PARAMETER :: add_tasks = 1000
904 REAL(kind=
dp),
PARAMETER :: mult_tasks = 2.0_dp
906 INTEGER :: added_tasks, cost, j, lmax
908 REAL(kind=
dp) :: tfraction
912 IF (ntasks > curr_tasks)
THEN
913 curr_tasks = int((curr_tasks + add_tasks)*mult_tasks)
918 IF (rs_desc%distributed)
THEN
922 CALL rs_find_node(rs_desc, igrid_level, n_levels, cube_center, &
923 ntasks=ntasks, tasks=tasks, lb_cube=lb_cube, ub_cube=ub_cube, added_tasks=added_tasks)
926 tasks(ntasks)%destination = encode_rank(rs_desc%my_pos, igrid_level, n_levels)
927 tasks(ntasks)%dist_type = 0
928 tasks(ntasks)%subpatch_pattern = 0
932 lmax = la_max + lb_max
933 is_ortho = (tasks(ntasks)%dist_type == 0 .OR. tasks(ntasks)%dist_type == 1) .AND. rs_desc%orthorhombic
936 tfraction = 1.0_dp/added_tasks
938 cost = cost_model(lb_cube, ub_cube, tfraction, lmax, is_ortho)
940 DO j = 1, added_tasks
941 tasks(ntasks - added_tasks + j)%source = encode_rank(rs_desc%my_pos, igrid_level, n_levels)
942 tasks(ntasks - added_tasks + j)%cost = cost
943 tasks(ntasks - added_tasks + j)%grid_level = igrid_level
944 tasks(ntasks - added_tasks + j)%image = cindex
945 tasks(ntasks - added_tasks + j)%iatom = iatom
946 tasks(ntasks - added_tasks + j)%jatom = jatom
947 tasks(ntasks - added_tasks + j)%iset = iset
948 tasks(ntasks - added_tasks + j)%jset = jset
949 tasks(ntasks - added_tasks + j)%ipgf = ipgf
950 tasks(ntasks - added_tasks + j)%jpgf = jpgf
951 tasks(ntasks - added_tasks + j)%rab = rab
952 tasks(ntasks - added_tasks + j)%radius = radius
955 END SUBROUTINE pgf_to_tasks
967 SUBROUTINE load_balance_distributed(tasks, ntasks, rs_descs, grid_level, natoms)
969 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
973 INTEGER :: grid_level, natoms
975 CHARACTER(LEN=*),
PARAMETER :: routinen =
'load_balance_distributed'
978 INTEGER,
DIMENSION(:, :, :),
POINTER ::
list
980 CALL timeset(routinen, handle)
985 CALL create_destination_list(
list, rs_descs, grid_level)
988 CALL compute_load_list(
list, rs_descs, grid_level, tasks, ntasks, natoms, create_list=.true.)
991 CALL optimize_load_list(
list, rs_descs(1)%rs_desc%group, rs_descs(1)%rs_desc%my_pos)
994 CALL compute_load_list(
list, rs_descs, grid_level, tasks, ntasks, natoms, create_list=.false.)
998 CALL timestop(handle)
1000 END SUBROUTINE load_balance_distributed
1009 SUBROUTINE balance_global_list(list_global)
1010 INTEGER,
DIMENSION(:, :, 0:) :: list_global
1012 CHARACTER(LEN=*),
PARAMETER :: routinen =
'balance_global_list'
1013 INTEGER,
PARAMETER :: max_iter = 100
1014 REAL(kind=
dp),
PARAMETER :: tolerance_factor = 0.005_dp
1016 INTEGER :: dest, handle, icpu, idest, iflux, &
1017 ilocal, k, maxdest, ncpu, nflux
1018 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: flux_connections
1019 LOGICAL :: solution_optimal
1020 REAL(kind=
dp) :: average, load_shift, max_load_shift, &
1022 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: load, optimized_flux, optimized_load
1023 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: flux_limits
1025 CALL timeset(routinen, handle)
1027 ncpu =
SIZE(list_global, 3)
1028 maxdest =
SIZE(list_global, 2)
1029 ALLOCATE (load(0:ncpu - 1))
1031 ALLOCATE (optimized_load(0:ncpu - 1))
1036 DO icpu = 0, ncpu - 1
1037 DO idest = 1, maxdest
1038 dest = list_global(1, idest, icpu)
1039 IF (dest < ncpu .AND. dest > icpu) nflux = nflux + 1
1042 ALLOCATE (optimized_flux(nflux))
1043 ALLOCATE (flux_limits(2, nflux))
1044 ALLOCATE (flux_connections(2, nflux))
1049 DO icpu = 0, ncpu - 1
1050 load(icpu) = sum(list_global(2, :, icpu))
1051 DO idest = 1, maxdest
1052 dest = list_global(1, idest, icpu)
1053 IF (dest < ncpu)
THEN
1054 IF (dest /= icpu)
THEN
1055 IF (dest > icpu)
THEN
1057 flux_limits(2, nflux) = list_global(2, idest, icpu)
1058 flux_connections(1, nflux) = icpu
1059 flux_connections(2, nflux) = dest
1062 IF (flux_connections(1, iflux) == dest .AND. flux_connections(2, iflux) == icpu)
THEN
1063 flux_limits(1, iflux) = -list_global(2, idest, icpu)
1073 solution_optimal = .false.
1074 optimized_flux = 0.0_dp
1081 average = sum(load)/
SIZE(load)
1082 tolerance = tolerance_factor*average
1084 optimized_load(:) = load
1086 max_load_shift = 0.0_dp
1088 load_shift = (optimized_load(flux_connections(1, iflux)) - optimized_load(flux_connections(2, iflux)))/2
1089 load_shift = max(flux_limits(1, iflux) - optimized_flux(iflux), load_shift)
1090 load_shift = min(flux_limits(2, iflux) - optimized_flux(iflux), load_shift)
1091 max_load_shift = max(abs(load_shift), max_load_shift)
1092 optimized_load(flux_connections(1, iflux)) = optimized_load(flux_connections(1, iflux)) - load_shift
1093 optimized_load(flux_connections(2, iflux)) = optimized_load(flux_connections(2, iflux)) + load_shift
1094 optimized_flux(iflux) = optimized_flux(iflux) + load_shift
1096 IF (max_load_shift < tolerance)
THEN
1097 solution_optimal = .true.
1105 DO icpu = 0, ncpu - 1
1106 DO idest = 1, maxdest
1107 IF (list_global(1, idest, icpu) == icpu) ilocal = idest
1109 DO idest = 1, maxdest
1110 dest = list_global(1, idest, icpu)
1111 IF (dest < ncpu)
THEN
1112 IF (dest /= icpu)
THEN
1113 IF (dest > icpu)
THEN
1115 IF (optimized_flux(nflux) > 0)
THEN
1116 list_global(2, ilocal, icpu) = list_global(2, ilocal, icpu) + &
1117 list_global(2, idest, icpu) - nint(optimized_flux(nflux))
1118 list_global(2, idest, icpu) = nint(optimized_flux(nflux))
1120 list_global(2, ilocal, icpu) = list_global(2, ilocal, icpu) + &
1121 list_global(2, idest, icpu)
1122 list_global(2, idest, icpu) = 0
1126 IF (flux_connections(1, iflux) == dest .AND. flux_connections(2, iflux) == icpu)
THEN
1127 IF (optimized_flux(iflux) > 0)
THEN
1128 list_global(2, ilocal, icpu) = list_global(2, ilocal, icpu) + &
1129 list_global(2, idest, icpu)
1130 list_global(2, idest, icpu) = 0
1132 list_global(2, ilocal, icpu) = list_global(2, ilocal, icpu) + &
1133 list_global(2, idest, icpu) + nint(optimized_flux(iflux))
1134 list_global(2, idest, icpu) = -nint(optimized_flux(iflux))
1145 CALL timestop(handle)
1147 END SUBROUTINE balance_global_list
1160 SUBROUTINE optimize_load_list(list, group, my_pos)
1161 INTEGER,
DIMENSION(:, :, 0:) ::
list
1163 INTEGER,
INTENT(IN) :: my_pos
1165 CHARACTER(LEN=*),
PARAMETER :: routinen =
'optimize_load_list'
1166 INTEGER,
PARAMETER :: rank_of_root = 0
1168 INTEGER :: handle, icpu, idest, maxdest, ncpu
1169 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: load_all
1170 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: load_partial
1171 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: list_global
1173 CALL timeset(routinen, handle)
1175 ncpu =
SIZE(
list, 3)
1176 maxdest =
SIZE(
list, 2)
1179 ALLOCATE (load_all(maxdest*ncpu))
1180 load_all(:) = reshape(
list(2, :, :), [maxdest*ncpu])
1181 CALL group%sum(load_all(:), rank_of_root)
1184 ALLOCATE (list_global(2, maxdest, ncpu))
1185 IF (rank_of_root == my_pos)
THEN
1186 list_global(1, :, :) =
list(1, :, :)
1187 list_global(2, :, :) = reshape(load_all, [maxdest, ncpu])
1188 CALL balance_global_list(list_global)
1190 CALL group%bcast(list_global, rank_of_root)
1193 ALLOCATE (load_partial(maxdest, ncpu))
1195 CALL group%sum_partial(reshape(load_all, [maxdest, ncpu]), load_partial(:, :))
1198 DO idest = 1, maxdest
1201 IF (load_partial(idest, icpu) > list_global(2, idest, icpu))
THEN
1202 IF (load_partial(idest, icpu) -
list(2, idest, icpu - 1) < list_global(2, idest, icpu))
THEN
1203 list(2, idest, icpu - 1) = list_global(2, idest, icpu) &
1204 - (load_partial(idest, icpu) -
list(2, idest, icpu - 1))
1206 list(2, idest, icpu - 1) = 0
1214 DEALLOCATE (load_all)
1215 DEALLOCATE (list_global)
1216 DEALLOCATE (load_partial)
1218 CALL timestop(handle)
1219 END SUBROUTINE optimize_load_list
1238 SUBROUTINE compute_load_list(list, rs_descs, grid_level, tasks, ntasks, natoms, create_list)
1239 INTEGER,
DIMENSION(:, :, 0:) ::
list
1242 INTEGER :: grid_level
1243 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
1244 INTEGER :: ntasks, natoms
1245 LOGICAL :: create_list
1247 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_load_list'
1249 INTEGER :: cost, dest, handle, i, iatom, ilevel, img, img_old, iopt, ipgf, iset, itask, &
1250 itask_start, itask_stop, jatom, jpgf, jset, li, maxdest, ncpu, ndest_pair, nopt, nshort, &
1252 INTEGER(KIND=int_8) :: bit_pattern, ipair, ipair_old, natom8
1253 INTEGER(KIND=int_8),
ALLOCATABLE,
DIMENSION(:) :: loads
1254 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: all_dests, index
1255 INTEGER,
DIMENSION(6) :: options
1257 CALL timeset(routinen, handle)
1259 ALLOCATE (loads(0:rs_descs(grid_level)%rs_desc%group_size - 1))
1260 CALL get_current_loads(loads, rs_descs, grid_level, ntasks, tasks, use_reordered_ranks=.false.)
1262 maxdest =
SIZE(
list, 2)
1263 ncpu =
SIZE(
list, 3)
1268 ipair_old = huge(ipair_old)
1270 ALLOCATE (all_dests(0))
1276 itask_start = itask_stop + 1
1277 itask_stop = itask_start
1278 IF (itask_stop > ntasks)
EXIT
1279 ilevel = tasks(itask_stop)%grid_level
1280 img_old = tasks(itask_stop)%image
1281 iatom = tasks(itask_stop)%iatom
1282 jatom = tasks(itask_stop)%jatom
1283 iset = tasks(itask_stop)%iset
1284 jset = tasks(itask_stop)%jset
1285 ipgf = tasks(itask_stop)%ipgf
1286 jpgf = tasks(itask_stop)%jpgf
1288 ipair_old = (iatom - 1)*natom8 + (jatom - 1)
1290 IF (itask_stop + 1 > ntasks)
EXIT
1291 ilevel = tasks(itask_stop + 1)%grid_level
1292 img = tasks(itask_stop + 1)%image
1293 iatom = tasks(itask_stop + 1)%iatom
1294 jatom = tasks(itask_stop + 1)%jatom
1295 iset = tasks(itask_stop + 1)%iset
1296 jset = tasks(itask_stop + 1)%jset
1297 ipgf = tasks(itask_stop + 1)%ipgf
1298 jpgf = tasks(itask_stop + 1)%jpgf
1300 ipair = (iatom - 1)*natom8 + (jatom - 1)
1301 IF (ipair == ipair_old .AND. img == img_old)
THEN
1302 itask_stop = itask_stop + 1
1308 nshort = itask_stop - itask_start + 1
1311 DEALLOCATE (all_dests)
1312 ALLOCATE (all_dests(nshort))
1314 ALLOCATE (index(nshort))
1316 ilevel = tasks(itask_start + i - 1)%grid_level
1317 img = tasks(itask_start + i - 1)%image
1318 iatom = tasks(itask_start + i - 1)%iatom
1319 jatom = tasks(itask_start + i - 1)%jatom
1320 iset = tasks(itask_start + i - 1)%iset
1321 jset = tasks(itask_start + i - 1)%jset
1322 ipgf = tasks(itask_start + i - 1)%ipgf
1323 jpgf = tasks(itask_start + i - 1)%jpgf
1325 IF (ilevel == grid_level)
THEN
1326 all_dests(i) = decode_rank(tasks(itask_start + i - 1)%destination,
SIZE(rs_descs))
1328 all_dests(i) = huge(all_dests(i))
1331 CALL sort(all_dests, nshort, index)
1334 IF ((all_dests(ndest_pair) /= all_dests(i)) .AND. (all_dests(i) /= huge(all_dests(i))))
THEN
1335 ndest_pair = ndest_pair + 1
1336 all_dests(ndest_pair) = all_dests(i)
1340 DO itask = itask_start, itask_stop
1342 dest = decode_rank(tasks(itask)%destination,
SIZE(rs_descs))
1343 ilevel = tasks(itask)%grid_level
1344 img = tasks(itask)%image
1345 iatom = tasks(itask)%iatom
1346 jatom = tasks(itask)%jatom
1347 iset = tasks(itask)%iset
1348 jset = tasks(itask)%jset
1349 ipgf = tasks(itask)%ipgf
1350 jpgf = tasks(itask)%jpgf
1353 IF (ilevel /= grid_level) cycle
1354 ipair = (iatom - 1)*natom8 + (jatom - 1)
1355 cost = int(tasks(itask)%cost)
1357 SELECT CASE (tasks(itask)%dist_type)
1359 bit_pattern = tasks(itask)%subpatch_pattern
1361 IF (btest(bit_pattern, 0))
THEN
1363 IF (any(all_dests(1:ndest_pair) == rank))
THEN
1365 options(nopt) = rank
1368 IF (btest(bit_pattern, 1))
THEN
1370 IF (any(all_dests(1:ndest_pair) == rank))
THEN
1372 options(nopt) = rank
1375 IF (btest(bit_pattern, 2))
THEN
1377 IF (any(all_dests(1:ndest_pair) == rank))
THEN
1379 options(nopt) = rank
1382 IF (btest(bit_pattern, 3))
THEN
1384 IF (any(all_dests(1:ndest_pair) == rank))
THEN
1386 options(nopt) = rank
1389 IF (btest(bit_pattern, 4))
THEN
1391 IF (any(all_dests(1:ndest_pair) == rank))
THEN
1393 options(nopt) = rank
1396 IF (btest(bit_pattern, 5))
THEN
1398 IF (any(all_dests(1:ndest_pair) == rank))
THEN
1400 options(nopt) = rank
1407 IF (loads(rank) > loads(options(iopt))) rank = options(iopt)
1412 li = list_index(
list, rank, dest)
1413 IF (create_list)
THEN
1414 list(2, li, dest) =
list(2, li, dest) + cost
1416 IF (
list(1, li, dest) == dest)
THEN
1417 tasks(itask)%destination = encode_rank(dest, ilevel,
SIZE(rs_descs))
1419 IF (
list(2, li, dest) >= cost)
THEN
1420 list(2, li, dest) =
list(2, li, dest) - cost
1421 tasks(itask)%destination = encode_rank(
list(1, li, dest), ilevel,
SIZE(rs_descs))
1423 tasks(itask)%destination = encode_rank(dest, ilevel,
SIZE(rs_descs))
1428 li = list_index(
list, dest, dest)
1429 IF (create_list)
THEN
1430 list(2, li, dest) =
list(2, li, dest) + cost
1432 IF (
list(1, li, dest) == dest)
THEN
1433 tasks(itask)%destination = encode_rank(dest, ilevel,
SIZE(rs_descs))
1435 IF (
list(2, li, dest) >= cost)
THEN
1436 list(2, li, dest) =
list(2, li, dest) - cost
1437 tasks(itask)%destination = encode_rank(
list(1, li, dest), ilevel,
SIZE(rs_descs))
1439 tasks(itask)%destination = encode_rank(dest, ilevel,
SIZE(rs_descs))
1444 cpabort(
"Unknown task list distribution type")
1451 CALL timestop(handle)
1453 END SUBROUTINE compute_load_list
1464 INTEGER FUNCTION list_index(list, rank, dest)
1465 INTEGER,
DIMENSION(:, :, 0:),
INTENT(IN) ::
list
1466 INTEGER,
INTENT(IN) :: rank, dest
1470 IF (
list(1, list_index, dest) == rank)
EXIT
1471 list_index = list_index + 1
1473 END FUNCTION list_index
1484 SUBROUTINE create_destination_list(list, rs_descs, grid_level)
1485 INTEGER,
DIMENSION(:, :, :),
POINTER ::
list
1488 INTEGER,
INTENT(IN) :: grid_level
1490 CHARACTER(LEN=*),
PARAMETER :: routinen =
'create_destination_list'
1492 INTEGER :: handle, i, icpu, j, maxcount, ncpu, &
1494 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: index, sublist
1496 CALL timeset(routinen, handle)
1498 cpassert(.NOT.
ASSOCIATED(
list))
1499 ncpu = rs_descs(grid_level)%rs_desc%group_size
1502 ALLOCATE (
list(2, ultimate_max, 0:ncpu - 1))
1504 ALLOCATE (index(ultimate_max))
1505 ALLOCATE (sublist(ultimate_max))
1506 sublist = huge(sublist)
1509 DO icpu = 0, ncpu - 1
1518 CALL sort(sublist, ultimate_max, index)
1521 IF (sublist(i) /= sublist(j))
THEN
1523 sublist(j) = sublist(i)
1526 maxcount = max(maxcount, j)
1527 sublist(j + 1:ultimate_max) = huge(sublist)
1528 list(1, :, icpu) = sublist
1529 list(2, :, icpu) = 0
1534 CALL timestop(handle)
1536 END SUBROUTINE create_destination_list
1552 SUBROUTINE get_current_loads(loads, rs_descs, grid_level, ntasks, tasks, use_reordered_ranks)
1553 INTEGER(KIND=int_8),
DIMENSION(:) :: loads
1556 INTEGER :: grid_level, ntasks
1557 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
1558 LOGICAL,
INTENT(IN) :: use_reordered_ranks
1560 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_current_loads'
1562 INTEGER :: handle, i, iatom, ilevel, img, ipgf, &
1563 iset, jatom, jpgf, jset
1564 INTEGER(KIND=int_8) :: total_cost_local
1565 INTEGER(KIND=int_8),
ALLOCATABLE,
DIMENSION(:) :: recv_buf_i, send_buf_i
1568 CALL timeset(routinen, handle)
1570 desc => rs_descs(grid_level)%rs_desc
1573 ALLOCATE (send_buf_i(desc%group_size))
1574 ALLOCATE (recv_buf_i(desc%group_size))
1582 ilevel = tasks(i)%grid_level
1583 img = tasks(i)%image
1584 iatom = tasks(i)%iatom
1585 jatom = tasks(i)%jatom
1586 iset = tasks(i)%iset
1587 jset = tasks(i)%jset
1588 ipgf = tasks(i)%ipgf
1589 jpgf = tasks(i)%jpgf
1590 IF (ilevel /= grid_level) cycle
1591 IF (use_reordered_ranks)
THEN
1592 send_buf_i(rs_descs(ilevel)%rs_desc%virtual2real(decode_rank(tasks(i)%destination,
SIZE(rs_descs))) + 1) = &
1593 send_buf_i(rs_descs(ilevel)%rs_desc%virtual2real(decode_rank(tasks(i)%destination,
SIZE(rs_descs))) + 1) &
1596 send_buf_i(decode_rank(tasks(i)%destination,
SIZE(rs_descs)) + 1) = &
1597 send_buf_i(decode_rank(tasks(i)%destination,
SIZE(rs_descs)) + 1) &
1601 CALL desc%group%alltoall(send_buf_i, recv_buf_i, 1)
1604 total_cost_local = sum(recv_buf_i)
1607 CALL desc%group%allgather(total_cost_local, loads)
1609 CALL timestop(handle)
1611 END SUBROUTINE get_current_loads
1624 SUBROUTINE load_balance_replicated(rs_descs, ntasks, tasks, redistributed)
1629 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
1630 LOGICAL,
INTENT(OUT),
OPTIONAL :: redistributed
1632 CHARACTER(LEN=*),
PARAMETER :: routinen =
'load_balance_replicated'
1634 INTEGER :: handle, i, iatom, ilevel, img, ipgf, &
1635 iset, j, jatom, jpgf, jset, &
1636 no_overloaded, no_underloaded, &
1637 proc_receiving, moved
1638 INTEGER(KIND=int_8) :: average_cost, cost_task_rep, count, &
1639 max_cost, offset, total_cost_global
1640 LOGICAL :: fully_replicated
1641 INTEGER(KIND=int_8),
ALLOCATABLE,
DIMENSION(:) :: load_imbalance, loads, recv_buf_i
1642 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: index
1645 CALL timeset(routinen, handle)
1647 desc => rs_descs(1)%rs_desc
1649 IF (
PRESENT(redistributed)) redistributed = .false.
1650 IF (desc%group_size == 1)
THEN
1651 CALL timestop(handle)
1656 ALLOCATE (recv_buf_i(desc%group_size))
1657 ALLOCATE (loads(desc%group_size))
1659 fully_replicated = .true.
1660 DO i = 1,
SIZE(rs_descs)
1661 fully_replicated = fully_replicated .AND. .NOT. rs_descs(i)%rs_desc%distributed
1664 IF (fully_replicated)
THEN
1668 cost_task_rep = cost_task_rep + tasks(i)%cost
1670 CALL desc%group%allgather(cost_task_rep, recv_buf_i)
1673 DO i = 1,
SIZE(rs_descs)
1674 CALL get_current_loads(loads, rs_descs, i, ntasks, tasks, use_reordered_ranks=.true.)
1675 recv_buf_i(:) = recv_buf_i + loads
1679 total_cost_global = sum(recv_buf_i)
1680 average_cost = total_cost_global/desc%group_size
1681 max_cost = maxval(recv_buf_i)
1683 IF (fully_replicated)
THEN
1685 IF (max_cost <= (total_cost_global + desc%group_size - 1)/desc%group_size)
THEN
1686 CALL timestop(handle)
1697 ALLOCATE (load_imbalance(desc%group_size))
1698 ALLOCATE (index(desc%group_size))
1700 load_imbalance(:) = recv_buf_i - average_cost
1704 DO i = 1, desc%group_size
1705 IF (load_imbalance(i) > 0) no_overloaded = no_overloaded + 1
1706 IF (load_imbalance(i) < 0) no_underloaded = no_underloaded + 1
1711 CALL sort(recv_buf_i,
SIZE(recv_buf_i), index)
1717 IF (tasks(i)%dist_type == 0 &
1718 .AND. decode_rank(tasks(i)%destination,
SIZE(rs_descs)) == decode_rank(tasks(i)%source,
SIZE(rs_descs)))
THEN
1719 cost_task_rep = cost_task_rep + tasks(i)%cost
1725 CALL desc%group%allgather(cost_task_rep, recv_buf_i)
1727 DO i = 1, desc%group_size
1729 IF (load_imbalance(i) > 0) load_imbalance(i) = min(load_imbalance(i), recv_buf_i(i))
1738 IF (load_imbalance(desc%my_pos + 1) > 0)
THEN
1744 DO i = desc%group_size, desc%group_size - no_overloaded + 1, -1
1745 IF (index(i) == desc%my_pos + 1)
THEN
1748 offset = offset + load_imbalance(index(i))
1753 proc_receiving = huge(proc_receiving)
1754 DO i = 1, no_underloaded
1755 offset = offset + load_imbalance(index(i))
1756 IF (offset < 0 .OR. (.NOT. fully_replicated .AND. offset == 0))
THEN
1766 IF (tasks(j)%dist_type == 0 &
1767 .AND. decode_rank(tasks(j)%destination,
SIZE(rs_descs)) == decode_rank(tasks(j)%source,
SIZE(rs_descs)))
THEN
1770 IF (proc_receiving > no_underloaded)
EXIT
1772 ilevel = tasks(j)%grid_level
1773 img = tasks(j)%image
1774 iatom = tasks(j)%iatom
1775 jatom = tasks(j)%jatom
1776 iset = tasks(j)%iset
1777 jset = tasks(j)%jset
1778 ipgf = tasks(j)%ipgf
1779 jpgf = tasks(j)%jpgf
1780 tasks(j)%destination = encode_rank(index(proc_receiving) - 1, ilevel,
SIZE(rs_descs))
1781 offset = offset + tasks(j)%cost
1782 count = count + tasks(j)%cost
1783 IF (count >= load_imbalance(desc%my_pos + 1))
EXIT
1784 IF (offset > 0 .OR. (fully_replicated .AND. offset == 0))
THEN
1785 proc_receiving = proc_receiving + 1
1788 IF (proc_receiving > no_underloaded)
EXIT
1789 offset = load_imbalance(index(proc_receiving))
1796 DEALLOCATE (load_imbalance)
1798 IF (fully_replicated)
THEN
1802 j = decode_rank(tasks(i)%destination,
SIZE(rs_descs)) + 1
1803 loads(j) = loads(j) + tasks(i)%cost
1805 CALL desc%group%sum(loads)
1806 IF (maxval(loads) >= max_cost)
THEN
1808 tasks(i)%destination = tasks(i)%source
1813 IF (
PRESENT(redistributed))
THEN
1816 IF (tasks(i)%destination /= tasks(i)%source) moved = 1
1818 CALL desc%group%max(moved)
1819 redistributed = moved > 0
1822 CALL timestop(handle)
1824 END SUBROUTINE load_balance_replicated
1838 SUBROUTINE create_local_tasks(rs_descs, ntasks, tasks, ntasks_recv, tasks_recv)
1843 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
1844 INTEGER :: ntasks_recv
1845 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks_recv
1847 CHARACTER(LEN=*),
PARAMETER :: routinen =
'create_local_tasks'
1849 INTEGER :: handle, i, j, k, l, rank
1850 INTEGER(KIND=int_8),
ALLOCATABLE,
DIMENSION(:) :: recv_buf, send_buf
1851 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: recv_disps, recv_sizes, send_disps, &
1855 CALL timeset(routinen, handle)
1857 desc => rs_descs(1)%rs_desc
1860 ALLOCATE (send_sizes(desc%group_size))
1861 ALLOCATE (recv_sizes(desc%group_size))
1862 ALLOCATE (send_disps(desc%group_size))
1863 ALLOCATE (recv_disps(desc%group_size))
1864 ALLOCATE (send_buf(desc%group_size))
1865 ALLOCATE (recv_buf(desc%group_size))
1870 rank = rs_descs(decode_level(tasks(i)%destination,
SIZE(rs_descs))) &
1871 %rs_desc%virtual2real(decode_rank(tasks(i)%destination,
SIZE(rs_descs)))
1872 send_buf(rank + 1) = send_buf(rank + 1) + 1
1875 CALL desc%group%alltoall(send_buf, recv_buf, 1)
1886 DO i = 2, desc%group_size
1889 send_disps(i) = send_disps(i - 1) + send_sizes(i - 1)
1890 recv_disps(i) = recv_disps(i - 1) + recv_sizes(i - 1)
1894 DEALLOCATE (send_buf)
1895 DEALLOCATE (recv_buf)
1898 ALLOCATE (send_buf(sum(send_sizes)))
1899 ALLOCATE (recv_buf(sum(recv_sizes)))
1905 i = rs_descs(decode_level(tasks(j)%destination,
SIZE(rs_descs))) &
1906 %rs_desc%virtual2real(decode_rank(tasks(j)%destination,
SIZE(rs_descs))) + 1
1907 l = send_disps(i) + send_sizes(i)
1913 CALL desc%group%alltoall(send_buf, send_sizes, send_disps, recv_buf, recv_sizes, recv_disps)
1915 DEALLOCATE (send_buf)
1918 ALLOCATE (tasks_recv(ntasks_recv))
1922 DO i = 1, desc%group_size
1930 DEALLOCATE (recv_buf)
1931 DEALLOCATE (send_sizes)
1932 DEALLOCATE (recv_sizes)
1933 DEALLOCATE (send_disps)
1934 DEALLOCATE (recv_disps)
1936 CALL timestop(handle)
1938 END SUBROUTINE create_local_tasks
1959 tasks, atom_pair_send, atom_pair_recv, &
1960 symmetric, reorder_rs_grid_ranks, skip_load_balance_distributed, &
1965 INTEGER :: ntasks, natoms
1966 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
1967 TYPE(
atom_pair_type),
DIMENSION(:),
POINTER :: atom_pair_send, atom_pair_recv
1968 LOGICAL,
INTENT(IN) :: symmetric, reorder_rs_grid_ranks, &
1969 skip_load_balance_distributed
1970 LOGICAL,
INTENT(IN),
OPTIONAL :: balance_replicated
1972 CHARACTER(LEN=*),
PARAMETER :: routinen =
'distribute_tasks'
1974 INTEGER :: handle, igrid_level, irank, ntasks_recv
1975 INTEGER(KIND=int_8) :: load_gap, max_load, replicated_load
1976 INTEGER(KIND=int_8),
ALLOCATABLE,
DIMENSION(:) :: total_loads, total_loads_tmp, trial_loads
1977 INTEGER(KIND=int_8),
DIMENSION(:, :),
POINTER :: loads
1978 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: indices, real2virtual, total_index
1979 LOGICAL :: distributed_grids, fixed_first_grid, &
1980 redistribute_matrices, allow_balance
1982 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks_recv
1984 CALL timeset(routinen, handle)
1986 cpassert(
ASSOCIATED(tasks))
1989 distributed_grids = .false.
1990 DO igrid_level = 1,
SIZE(rs_descs)
1991 IF (rs_descs(igrid_level)%rs_desc%distributed)
THEN
1992 distributed_grids = .true.
1995 desc => rs_descs(1)%rs_desc
1997 IF (distributed_grids)
THEN
1999 ALLOCATE (loads(0:desc%group_size - 1,
SIZE(rs_descs)))
2000 ALLOCATE (total_loads(0:desc%group_size - 1))
2006 DO igrid_level = 1,
SIZE(rs_descs)
2007 IF (rs_descs(igrid_level)%rs_desc%distributed)
THEN
2009 IF (.NOT. skip_load_balance_distributed)
THEN
2010 CALL load_balance_distributed(tasks, ntasks, rs_descs, igrid_level, natoms)
2013 CALL get_current_loads(loads(:, igrid_level), rs_descs, igrid_level, ntasks, &
2014 tasks, use_reordered_ranks=.false.)
2016 total_loads(:) = total_loads + loads(:, igrid_level)
2025 DO igrid_level = 1,
SIZE(rs_descs)
2026 IF (.NOT. rs_descs(igrid_level)%rs_desc%distributed)
THEN
2027 CALL get_current_loads(loads(:, igrid_level), rs_descs, igrid_level, ntasks, &
2028 tasks, use_reordered_ranks=.false.)
2029 replicated_load = replicated_load + sum(loads(:, igrid_level))
2035 IF (reorder_rs_grid_ranks)
THEN
2036 fixed_first_grid = .false.
2037 DO igrid_level = 1,
SIZE(rs_descs)
2038 IF (rs_descs(igrid_level)%rs_desc%distributed)
THEN
2039 IF (fixed_first_grid .EQV. .false.)
THEN
2040 total_loads(:) = loads(:, igrid_level)
2041 fixed_first_grid = .true.
2043 ALLOCATE (trial_loads(0:desc%group_size - 1))
2045 trial_loads(:) = total_loads + loads(:, igrid_level)
2046 max_load = maxval(trial_loads)
2048 DO irank = 0, desc%group_size - 1
2049 load_gap = load_gap + max_load - trial_loads(irank)
2054 IF (load_gap > replicated_load*1.05_dp)
THEN
2056 ALLOCATE (indices(0:desc%group_size - 1))
2057 ALLOCATE (total_index(0:desc%group_size - 1))
2058 ALLOCATE (total_loads_tmp(0:desc%group_size - 1))
2059 ALLOCATE (real2virtual(0:desc%group_size - 1))
2061 total_loads_tmp(:) = total_loads
2062 CALL sort(total_loads_tmp, desc%group_size, total_index)
2063 CALL sort(loads(:, igrid_level), desc%group_size, indices)
2067 DO irank = 0, desc%group_size - 1
2068 total_loads(total_index(irank) - 1) = total_loads(total_index(irank) - 1) + &
2069 loads(desc%group_size - irank - 1, igrid_level)
2070 real2virtual(total_index(irank) - 1) = indices(desc%group_size - irank - 1) - 1
2075 DEALLOCATE (indices)
2076 DEALLOCATE (total_index)
2077 DEALLOCATE (total_loads_tmp)
2078 DEALLOCATE (real2virtual)
2080 total_loads(:) = trial_loads
2083 DEALLOCATE (trial_loads)
2091 CALL load_balance_replicated(rs_descs, ntasks, tasks)
2094 DEALLOCATE (total_loads)
2097 redistribute_matrices = distributed_grids
2098 allow_balance = .true.
2099 IF (
PRESENT(balance_replicated)) allow_balance = balance_replicated
2100 IF (.NOT. distributed_grids .AND. allow_balance)
THEN
2101 CALL load_balance_replicated(rs_descs, ntasks, tasks, redistributed=redistribute_matrices)
2104 IF (redistribute_matrices)
THEN
2107 CALL create_local_tasks(rs_descs, ntasks, tasks, ntasks_recv, tasks_recv)
2113 CALL get_atom_pair(atom_pair_send, tasks, ntasks=ntasks, send=.true., symmetric=symmetric, rs_descs=rs_descs)
2115 CALL get_atom_pair(atom_pair_recv, tasks_recv, ntasks=ntasks_recv, send=.false., symmetric=symmetric, rs_descs=rs_descs)
2122 ntasks_recv = ntasks
2123 CALL get_atom_pair(atom_pair_recv, tasks_recv, ntasks=ntasks_recv, send=.false., symmetric=symmetric, rs_descs=rs_descs)
2128 ALLOCATE (indices(ntasks_recv))
2129 CALL tasks_sort(tasks_recv, ntasks_recv, indices)
2130 DEALLOCATE (indices)
2137 ntasks = ntasks_recv
2139 CALL timestop(handle)
2153 SUBROUTINE get_atom_pair(atom_pair, tasks, ntasks, send, symmetric, rs_descs)
2156 TYPE(
task_type),
DIMENSION(:),
INTENT(INOUT) :: tasks
2157 INTEGER,
INTENT(IN) :: ntasks
2158 LOGICAL,
INTENT(IN) :: send, symmetric
2161 INTEGER :: i, ilevel, iatom, jatom, npairs, virt_rank
2162 INTEGER,
DIMENSION(:),
ALLOCATABLE :: indices
2165 cpassert(.NOT.
ASSOCIATED(atom_pair))
2166 IF (ntasks == 0)
THEN
2167 ALLOCATE (atom_pair(0))
2173 ALLOCATE (atom_pair_tmp(ntasks))
2175 atom_pair_tmp(i)%image = tasks(i)%image
2176 iatom = tasks(i)%iatom
2177 jatom = tasks(i)%jatom
2178 IF (symmetric .AND. iatom > jatom)
THEN
2180 atom_pair_tmp(i)%row = jatom
2181 atom_pair_tmp(i)%col = iatom
2183 atom_pair_tmp(i)%row = iatom
2184 atom_pair_tmp(i)%col = jatom
2190 ilevel = tasks(i)%grid_level
2191 virt_rank = decode_rank(tasks(i)%destination,
SIZE(rs_descs))
2192 atom_pair_tmp(i)%rank = rs_descs(ilevel)%rs_desc%virtual2real(virt_rank)
2196 atom_pair_tmp(i)%rank = decode_rank(tasks(i)%source,
SIZE(rs_descs))
2201 ALLOCATE (indices(ntasks))
2202 CALL atom_pair_sort(atom_pair_tmp, ntasks, indices)
2204 tasks(indices(1))%pair_index = 1
2206 IF (atom_pair_less_than(atom_pair_tmp(i - 1), atom_pair_tmp(i)))
THEN
2208 atom_pair_tmp(npairs) = atom_pair_tmp(i)
2210 tasks(indices(i))%pair_index = npairs
2212 DEALLOCATE (indices)
2215 ALLOCATE (atom_pair(npairs))
2216 atom_pair(:) = atom_pair_tmp(:npairs)
2217 DEALLOCATE (atom_pair_tmp)
2219 END SUBROUTINE get_atom_pair
2235 nimages, scatter, hmats)
2240 TYPE(
atom_pair_type),
DIMENSION(:),
POINTER :: atom_pair_send, atom_pair_recv
2246 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rs_distribute_matrix'
2248 INTEGER :: acol, arow, handle, i, img, j, k, l, me, &
2249 nblkcols_total, nblkrows_total, ncol, &
2250 nrow, nthread, nthread_left
2251 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: first_col, first_row, last_col, last_row, recv_disps, &
2252 recv_pair_count, recv_pair_disps, recv_sizes, send_disps, send_pair_count, &
2253 send_pair_disps, send_sizes
2254 INTEGER,
DIMENSION(:),
POINTER :: col_blk_size, row_blk_size
2256 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:),
TARGET :: recv_buf_r, send_buf_r
2257 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: h_block, p_block
2260 REAL(kind=
dp),
DIMENSION(:),
POINTER :: vector
2264 CALL timeset(routinen, handle)
2266 IF (.NOT. scatter)
THEN
2267 cpassert(
PRESENT(hmats))
2270 desc => rs_descs(1)%rs_desc
2271 me = desc%my_pos + 1
2274 ALLOCATE (send_sizes(desc%group_size))
2275 ALLOCATE (recv_sizes(desc%group_size))
2276 ALLOCATE (send_disps(desc%group_size))
2277 ALLOCATE (recv_disps(desc%group_size))
2278 ALLOCATE (send_pair_count(desc%group_size))
2279 ALLOCATE (recv_pair_count(desc%group_size))
2280 ALLOCATE (send_pair_disps(desc%group_size))
2281 ALLOCATE (recv_pair_disps(desc%group_size))
2283 pmat => pmats(1)%matrix
2285 row_blk_size=row_blk_size, &
2286 col_blk_size=col_blk_size, &
2287 nblkrows_total=nblkrows_total, &
2288 nblkcols_total=nblkcols_total)
2289 ALLOCATE (first_row(nblkrows_total), last_row(nblkrows_total), &
2290 first_col(nblkcols_total), last_col(nblkcols_total))
2291 CALL dbcsr_convert_sizes_to_offsets(row_blk_size, first_row, last_row)
2292 CALL dbcsr_convert_sizes_to_offsets(col_blk_size, first_col, last_col)
2297 DO i = 1,
SIZE(atom_pair_send)
2298 k = atom_pair_send(i)%rank + 1
2299 arow = atom_pair_send(i)%row
2300 acol = atom_pair_send(i)%col
2301 nrow = last_row(arow) - first_row(arow) + 1
2302 ncol = last_col(acol) - first_col(acol) + 1
2303 send_sizes(k) = send_sizes(k) + nrow*ncol
2304 send_pair_count(k) = send_pair_count(k) + 1
2309 DO i = 2, desc%group_size
2310 send_disps(i) = send_disps(i - 1) + send_sizes(i - 1)
2311 send_pair_disps(i) = send_pair_disps(i - 1) + send_pair_count(i - 1)
2314 ALLOCATE (send_buf_r(sum(send_sizes)))
2320 DO i = 1,
SIZE(atom_pair_recv)
2321 k = atom_pair_recv(i)%rank + 1
2322 arow = atom_pair_recv(i)%row
2323 acol = atom_pair_recv(i)%col
2324 nrow = last_row(arow) - first_row(arow) + 1
2325 ncol = last_col(acol) - first_col(acol) + 1
2326 recv_sizes(k) = recv_sizes(k) + nrow*ncol
2327 recv_pair_count(k) = recv_pair_count(k) + 1
2332 DO i = 2, desc%group_size
2333 recv_disps(i) = recv_disps(i - 1) + recv_sizes(i - 1)
2334 recv_pair_disps(i) = recv_pair_disps(i - 1) + recv_pair_count(i - 1)
2336 ALLOCATE (recv_buf_r(sum(recv_sizes)))
2355 DO l = 1, desc%group_size
2358 DO i = 1, send_pair_count(l)
2359 arow = atom_pair_send(send_pair_disps(l) + i)%row
2360 acol = atom_pair_send(send_pair_disps(l) + i)%col
2361 img = atom_pair_send(send_pair_disps(l) + i)%image
2362 nrow = last_row(arow) - first_row(arow) + 1
2363 ncol = last_col(acol) - first_col(acol) + 1
2364 pmat => pmats(img)%matrix
2365 CALL dbcsr_get_block_p(matrix=pmat, row=arow, col=acol, block=p_block, found=found)
2370 send_buf_r(send_disps(l) + send_sizes(l) + j + (k - 1)*nrow) = p_block(j, k)
2373 send_sizes(l) = send_sizes(l) + nrow*ncol
2378 IF (.NOT. scatter)
THEN
2393 CALL desc%group%alltoall(send_buf_r, send_sizes, send_disps, &
2394 recv_buf_r, recv_sizes, recv_disps)
2399 IF (.NOT. scatter)
THEN
2403 DO i = 1, send_pair_count(me)
2404 arow = atom_pair_send(send_pair_disps(me) + i)%row
2405 acol = atom_pair_send(send_pair_disps(me) + i)%col
2406 img = atom_pair_send(send_pair_disps(me) + i)%image
2407 nrow = last_row(arow) - first_row(arow) + 1
2408 ncol = last_col(acol) - first_col(acol) + 1
2409 hmat => hmats(img)%matrix
2410 pmat => pmats(img)%matrix
2411 CALL dbcsr_get_block_p(matrix=hmat, row=arow, col=acol, block=h_block, found=found)
2413 CALL dbcsr_get_block_p(matrix=pmat, row=arow, col=acol, block=p_block, found=found)
2419 h_block(j, k) = h_block(j, k) + p_block(j, k)
2428 pmat => pmats(img)%matrix
2430 nblks_guess=
SIZE(atom_pair_recv)/nthread, sizedata_guess=
SIZE(recv_buf_r)/nthread, &
2440 DO l = 1, desc%group_size
2443 DO i = 1, recv_pair_count(l)
2444 arow = atom_pair_recv(recv_pair_disps(l) + i)%row
2445 acol = atom_pair_recv(recv_pair_disps(l) + i)%col
2446 img = atom_pair_recv(recv_pair_disps(l) + i)%image
2447 nrow = last_row(arow) - first_row(arow) + 1
2448 ncol = last_col(acol) - first_col(acol) + 1
2449 pmat => pmats(img)%matrix
2451 CALL dbcsr_get_block_p(matrix=pmat, row=arow, col=acol, block=p_block, found=found)
2453 IF (
PRESENT(hmats))
THEN
2454 hmat => hmats(img)%matrix
2455 CALL dbcsr_get_block_p(matrix=hmat, row=arow, col=acol, block=h_block, found=found)
2459 IF (scatter .AND. .NOT.
ASSOCIATED(p_block))
THEN
2460 vector => recv_buf_r(recv_disps(l) + recv_sizes(l) + 1:recv_disps(l) + recv_sizes(l) + nrow*ncol)
2461 CALL dbcsr_put_block(pmat, arow, acol, block=reshape(vector, [nrow, ncol]))
2463 IF (.NOT. scatter)
THEN
2467 h_block(j, k) = h_block(j, k) + recv_buf_r(recv_disps(l) + recv_sizes(l) + j + (k - 1)*nrow)
2472 recv_sizes(l) = recv_sizes(l) + nrow*ncol
2494 pmat => pmats(img)%matrix
2500 DEALLOCATE (send_buf_r)
2501 DEALLOCATE (recv_buf_r)
2503 DEALLOCATE (send_sizes)
2504 DEALLOCATE (recv_sizes)
2505 DEALLOCATE (send_disps)
2506 DEALLOCATE (recv_disps)
2507 DEALLOCATE (send_pair_count)
2508 DEALLOCATE (recv_pair_count)
2509 DEALLOCATE (send_pair_disps)
2510 DEALLOCATE (recv_pair_disps)
2512 DEALLOCATE (first_row, last_row, first_col, last_col)
2514 CALL timestop(handle)
2522 SUBROUTINE rs_calc_offsets(pairs, nsgf, group_size, &
2523 pair_offsets, rank_offsets, rank_sizes, buffer_size)
2525 INTEGER,
DIMENSION(:),
INTENT(IN) :: nsgf
2526 INTEGER,
INTENT(IN) :: group_size
2527 INTEGER,
DIMENSION(:),
POINTER :: pair_offsets, rank_offsets, rank_sizes
2528 INTEGER,
INTENT(INOUT) :: buffer_size
2530 INTEGER :: acol, arow, i, block_size, total_size, k, prev_k
2532 IF (
ASSOCIATED(pair_offsets))
DEALLOCATE (pair_offsets)
2533 IF (
ASSOCIATED(rank_offsets))
DEALLOCATE (rank_offsets)
2534 IF (
ASSOCIATED(rank_sizes))
DEALLOCATE (rank_sizes)
2537 ALLOCATE (pair_offsets(
SIZE(pairs)))
2539 DO i = 1,
SIZE(pairs)
2540 pair_offsets(i) = total_size
2543 block_size = nsgf(arow)*nsgf(acol)
2544 total_size = total_size + block_size
2546 buffer_size = total_size
2549 ALLOCATE (rank_offsets(group_size))
2550 ALLOCATE (rank_sizes(group_size))
2553 IF (
SIZE(pairs) > 0)
THEN
2554 prev_k = pairs(1)%rank + 1
2555 DO i = 1,
SIZE(pairs)
2556 k = pairs(i)%rank + 1
2557 cpassert(k >= prev_k)
2558 IF (k > prev_k)
THEN
2559 rank_offsets(k) = pair_offsets(i)
2560 rank_sizes(prev_k) = rank_offsets(k) - rank_offsets(prev_k)
2564 rank_sizes(k) = buffer_size - rank_offsets(k)
2567 END SUBROUTINE rs_calc_offsets
2576 SUBROUTINE rs_group_atom_pairs(pairs, block_starts, pair_indices)
2578 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: block_starts, pair_indices
2580 INTEGER :: i, nblocks, npairs
2581 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: starts
2584 npairs =
SIZE(pairs)
2585 ALLOCATE (sorted_pairs(npairs), pair_indices(npairs), starts(npairs + 1))
2586 sorted_pairs(:) = pairs(:)
2588 sorted_pairs(:)%rank = 0
2589 CALL atom_pair_sort(sorted_pairs, npairs, pair_indices)
2594 IF (.NOT. atom_pair_less_than(sorted_pairs(i - 1), sorted_pairs(i))) cycle
2596 nblocks = nblocks + 1
2599 starts(nblocks + 1) = npairs + 1
2600 ALLOCATE (block_starts(nblocks + 1))
2601 block_starts(:) = starts(:nblocks + 1)
2603 END SUBROUTINE rs_group_atom_pairs
2610 TYPE(
dbcsr_p_type),
DIMENSION(:),
INTENT(IN) :: src_matrices
2615 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rs_scatter_matrices'
2618 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: buffer_send
2620 CALL timeset(routinen, handle)
2622 IF (.NOT.
ASSOCIATED(task_list%atom_pair_send))
THEN
2624 CALL timestop(handle)
2627 ALLOCATE (buffer_send(task_list%buffer_size_send))
2630 cpassert(
ASSOCIATED(task_list%atom_pair_send))
2631 CALL rs_pack_buffer(src_matrices=src_matrices, &
2632 dest_buffer=buffer_send, &
2633 atom_pair=task_list%atom_pair_send, &
2634 pair_offsets=task_list%pair_offsets_send)
2637 CALL group%alltoall(buffer_send, task_list%rank_sizes_send, task_list%rank_offsets_send, &
2638 dest_buffer%host_buffer, &
2639 task_list%rank_sizes_recv, task_list%rank_offsets_recv)
2641 DEALLOCATE (buffer_send)
2642 CALL timestop(handle)
2652 TYPE(
dbcsr_p_type),
DIMENSION(:),
INTENT(INOUT) :: dest_matrices
2656 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rs_gather_matrices'
2659 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: buffer_send
2661 CALL timeset(routinen, handle)
2663 IF (.NOT.
ASSOCIATED(task_list%atom_pair_send))
THEN
2665 CALL timestop(handle)
2670 ALLOCATE (buffer_send(task_list%buffer_size_send))
2673 CALL group%alltoall(src_buffer%host_buffer, task_list%rank_sizes_recv, task_list%rank_offsets_recv, &
2674 buffer_send, task_list%rank_sizes_send, task_list%rank_offsets_send)
2677 cpassert(
ASSOCIATED(task_list%atom_pair_send))
2678 CALL rs_unpack_buffer(src_buffer=buffer_send, &
2679 dest_matrices=dest_matrices, &
2680 atom_pair=task_list%atom_pair_send, &
2681 pair_offsets=task_list%pair_offsets_send, &
2682 block_starts=task_list%unpack_block_starts, &
2683 pair_indices=task_list%unpack_pair_indices)
2685 DEALLOCATE (buffer_send)
2686 CALL timestop(handle)
2695 TYPE(
dbcsr_p_type),
DIMENSION(:),
INTENT(IN) :: src_matrices
2699 CALL rs_pack_buffer(src_matrices=src_matrices, &
2700 dest_buffer=dest_buffer%host_buffer, &
2701 atom_pair=task_list%atom_pair_recv, &
2702 pair_offsets=task_list%pair_offsets_recv)
2712 TYPE(
dbcsr_p_type),
DIMENSION(:),
INTENT(INOUT) :: dest_matrices
2715 CALL rs_unpack_buffer(src_buffer=src_buffer%host_buffer, &
2716 dest_matrices=dest_matrices, &
2717 atom_pair=task_list%atom_pair_recv, &
2718 pair_offsets=task_list%pair_offsets_recv, &
2719 block_starts=task_list%unpack_block_starts, &
2720 pair_indices=task_list%unpack_pair_indices)
2728 SUBROUTINE rs_pack_buffer(src_matrices, dest_buffer, atom_pair, pair_offsets)
2729 TYPE(
dbcsr_p_type),
DIMENSION(:),
INTENT(IN) :: src_matrices
2730 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: dest_buffer
2732 INTEGER,
DIMENSION(:),
INTENT(IN) :: pair_offsets
2734 INTEGER :: acol, arow, img, i, offset, block_size
2736 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
2742 DO i = 1,
SIZE(atom_pair)
2743 arow = atom_pair(i)%row
2744 acol = atom_pair(i)%col
2745 img = atom_pair(i)%image
2747 block=block, found=found)
2749 block_size =
SIZE(block)
2750 offset = pair_offsets(i)
2751 dest_buffer(offset + 1:offset + block_size) = reshape(block, shape=[block_size])
2756 END SUBROUTINE rs_pack_buffer
2762 SUBROUTINE rs_unpack_buffer(src_buffer, dest_matrices, atom_pair, pair_offsets, block_starts, pair_indices)
2763 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: src_buffer
2764 TYPE(
dbcsr_p_type),
DIMENSION(:),
INTENT(INOUT) :: dest_matrices
2766 INTEGER,
DIMENSION(:),
INTENT(IN) :: pair_offsets
2767 INTEGER,
DIMENSION(:),
INTENT(IN) :: block_starts, pair_indices
2769 INTEGER :: acol, arow, i, iblock, img, ipair, &
2770 j, ncols, nrows, offset, pair
2772 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
2779 DO iblock = 1,
SIZE(block_starts) - 1
2780 pair = pair_indices(block_starts(iblock))
2781 arow = atom_pair(pair)%row
2782 acol = atom_pair(pair)%col
2783 img = atom_pair(pair)%image
2785 block=block, found=found)
2787 nrows =
SIZE(block, 1)
2788 ncols =
SIZE(block, 2)
2789 DO ipair = block_starts(iblock), block_starts(iblock + 1) - 1
2790 offset = pair_offsets(pair_indices(ipair))
2793 block(i, j) = block(i, j) + src_buffer(offset + i + (j - 1)*nrows)
2801 END SUBROUTINE rs_unpack_buffer
2819 SUBROUTINE rs_find_node(rs_desc, igrid_level, n_levels, cube_center, ntasks, tasks, &
2820 lb_cube, ub_cube, added_tasks)
2823 INTEGER,
INTENT(IN) :: igrid_level, n_levels
2824 INTEGER,
DIMENSION(3),
INTENT(IN) :: cube_center
2825 INTEGER,
INTENT(INOUT) :: ntasks
2826 TYPE(
task_type),
DIMENSION(:),
POINTER :: tasks
2827 INTEGER,
DIMENSION(3),
INTENT(IN) :: lb_cube, ub_cube
2828 INTEGER,
INTENT(OUT) :: added_tasks
2830 INTEGER,
PARAMETER :: add_tasks = 1000
2831 REAL(kind=
dp),
PARAMETER :: mult_tasks = 2.0_dp
2833 INTEGER :: bit_index, coord(3), curr_tasks, dest, i, icoord(3), idest, itask, ix, iy, iz, &
2834 lb_coord(3), lb_domain(3), lbc(3), ub_coord(3), ub_domain(3), ubc(3)
2835 INTEGER :: bit_pattern
2836 LOGICAL :: dir_periodic(3)
2838 coord(1) = rs_desc%x2coord(cube_center(1))
2839 coord(2) = rs_desc%y2coord(cube_center(2))
2840 coord(3) = rs_desc%z2coord(cube_center(3))
2841 dest = rs_desc%coord2rank(coord(1), coord(2), coord(3))
2844 lbc = lb_cube + cube_center
2845 ubc = ub_cube + cube_center
2847 IF (all((rs_desc%lb_global(:, dest) - rs_desc%border) <= lbc) .AND. &
2848 all((rs_desc%ub_global(:, dest) + rs_desc%border) >= ubc))
THEN
2850 tasks(ntasks)%destination = encode_rank(dest, igrid_level, n_levels)
2851 tasks(ntasks)%dist_type = 1
2852 tasks(ntasks)%subpatch_pattern = 0
2871 IF (rs_desc%perd(i) == 1)
THEN
2872 bit_pattern = ibclr(bit_pattern, bit_index)
2873 bit_index = bit_index + 1
2874 bit_pattern = ibclr(bit_pattern, bit_index)
2875 bit_index = bit_index + 1
2878 IF (ubc(i) <= rs_desc%lb_global(i, dest) - 1 + rs_desc%border)
THEN
2879 bit_pattern = ibset(bit_pattern, bit_index)
2880 bit_index = bit_index + 1
2882 bit_pattern = ibclr(bit_pattern, bit_index)
2883 bit_index = bit_index + 1
2886 IF (lbc(i) >= rs_desc%ub_global(i, dest) + 1 - rs_desc%border)
THEN
2887 bit_pattern = ibset(bit_pattern, bit_index)
2888 bit_index = bit_index + 1
2890 bit_pattern = ibclr(bit_pattern, bit_index)
2891 bit_index = bit_index + 1
2895 tasks(ntasks)%subpatch_pattern = bit_pattern
2905 lb_domain = rs_desc%lb_global(:, dest) - rs_desc%border
2906 ub_domain = rs_desc%ub_global(:, dest) + rs_desc%border
2909 IF (rs_desc%perd(i) == 0)
THEN
2912 IF (lb_domain(i) > lbc(i))
THEN
2913 lb_coord(i) = lb_coord(i) - 1
2914 icoord =
modulo(lb_coord, rs_desc%group_dim)
2915 idest = rs_desc%coord2rank(icoord(1), icoord(2), icoord(3))
2916 lb_domain(i) = lb_domain(i) - (rs_desc%ub_global(i, idest) - rs_desc%lb_global(i, idest) + 1)
2923 IF (ub_domain(i) < ubc(i))
THEN
2924 ub_coord(i) = ub_coord(i) + 1
2925 icoord =
modulo(ub_coord, rs_desc%group_dim)
2926 idest = rs_desc%coord2rank(icoord(1), icoord(2), icoord(3))
2927 ub_domain(i) = ub_domain(i) + (rs_desc%ub_global(i, idest) - rs_desc%lb_global(i, idest) + 1)
2937 IF (ub_domain(i) - lb_domain(i) + 1 >= rs_desc%npts(i))
THEN
2938 dir_periodic(i) = .true.
2940 ub_coord(i) = rs_desc%group_dim(i) - 1
2942 dir_periodic(i) = .false.
2946 added_tasks = product(ub_coord - lb_coord + 1)
2948 ntasks = ntasks + added_tasks - 1
2949 IF (ntasks >
SIZE(tasks))
THEN
2950 curr_tasks = int((
SIZE(tasks) + add_tasks)*mult_tasks)
2953 DO iz = lb_coord(3), ub_coord(3)
2954 DO iy = lb_coord(2), ub_coord(2)
2955 DO ix = lb_coord(1), ub_coord(1)
2956 icoord =
modulo([ix, iy, iz], rs_desc%group_dim)
2957 idest = rs_desc%coord2rank(icoord(1), icoord(2), icoord(3))
2958 tasks(itask)%destination = encode_rank(idest, igrid_level, n_levels)
2959 tasks(itask)%dist_type = 2
2960 tasks(itask)%subpatch_pattern = 0
2963 IF (ix == lb_coord(1) .AND. .NOT. dir_periodic(1))
THEN
2964 tasks(itask)%subpatch_pattern = ibset(tasks(itask)%subpatch_pattern, 0)
2966 IF (ix == ub_coord(1) .AND. .NOT. dir_periodic(1))
THEN
2967 tasks(itask)%subpatch_pattern = ibset(tasks(itask)%subpatch_pattern, 1)
2969 IF (iy == lb_coord(2) .AND. .NOT. dir_periodic(2))
THEN
2970 tasks(itask)%subpatch_pattern = ibset(tasks(itask)%subpatch_pattern, 2)
2972 IF (iy == ub_coord(2) .AND. .NOT. dir_periodic(2))
THEN
2973 tasks(itask)%subpatch_pattern = ibset(tasks(itask)%subpatch_pattern, 3)
2975 IF (iz == lb_coord(3) .AND. .NOT. dir_periodic(3))
THEN
2976 tasks(itask)%subpatch_pattern = ibset(tasks(itask)%subpatch_pattern, 4)
2978 IF (iz == ub_coord(3) .AND. .NOT. dir_periodic(3))
THEN
2979 tasks(itask)%subpatch_pattern = ibset(tasks(itask)%subpatch_pattern, 5)
2987 END SUBROUTINE rs_find_node
3001 FUNCTION encode_rank(rank, grid_level, n_levels)
RESULT(encoded_int)
3003 INTEGER,
INTENT(IN) :: rank, grid_level, n_levels
3004 INTEGER :: encoded_int
3008 encoded_int = rank*n_levels + grid_level - 1
3010 END FUNCTION encode_rank
3018 FUNCTION decode_rank(encoded_int, n_levels)
RESULT(rank)
3020 INTEGER,
INTENT(IN) :: encoded_int
3021 INTEGER,
INTENT(IN) :: n_levels
3024 rank = int(encoded_int/n_levels)
3026 END FUNCTION decode_rank
3034 FUNCTION decode_level(encoded_int, n_levels)
RESULT(grid_level)
3036 INTEGER,
INTENT(IN) :: encoded_int
3037 INTEGER,
INTENT(IN) :: n_levels
3038 INTEGER :: grid_level
3040 grid_level = int(
modulo(encoded_int, n_levels)) + 1
3042 END FUNCTION decode_level
3058 PURE FUNCTION tasks_less_than(a, b)
RESULT(res)
3062 IF (a%grid_level /= b%grid_level)
THEN
3063 res = a%grid_level < b%grid_level
3065 ELSE IF (a%image /= b%image)
THEN
3066 res = a%image < b%image
3068 ELSE IF (a%iatom /= b%iatom)
THEN
3069 res = a%iatom < b%iatom
3071 ELSE IF (a%jatom /= b%jatom)
THEN
3072 res = a%jatom < b%jatom
3074 ELSE IF (a%iset /= b%iset)
THEN
3075 res = a%iset < b%iset
3077 ELSE IF (a%jset /= b%jset)
THEN
3078 res = a%jset < b%jset
3080 ELSE IF (a%ipgf /= b%ipgf)
THEN
3081 res = a%ipgf < b%ipgf
3084 res = a%jpgf < b%jpgf
3087 END FUNCTION tasks_less_than
3100 SUBROUTINE tasks_sort(arr, n, indices)
3101 INTEGER,
INTENT(IN) :: n
3102 TYPE(
task_type),
DIMENSION(1:n),
INTENT(INOUT) :: arr
3103 integer,
DIMENSION(1:n),
INTENT(INOUT) :: indices
3106 TYPE(
task_type),
ALLOCATABLE :: tmp_arr(:)
3107 INTEGER,
ALLOCATABLE :: tmp_idx(:)
3111 ALLOCATE (tmp_arr((n + 1)/2), tmp_idx((n + 1)/2))
3113 indices = [(i, i=1, n)]
3115 CALL tasks_sort_low(arr(1:n), indices, tmp_arr, tmp_idx)
3117 DEALLOCATE (tmp_arr, tmp_idx)
3118 ELSE IF (n > 0)
THEN
3122 END SUBROUTINE tasks_sort
3134 RECURSIVE SUBROUTINE tasks_sort_low(arr, indices, tmp_arr, tmp_idx)
3135 TYPE(
task_type),
DIMENSION(:),
INTENT(INOUT) :: arr
3136 INTEGER,
DIMENSION(size(arr)),
INTENT(INOUT) :: indices
3137 TYPE(
task_type),
DIMENSION((size(arr) + 1)/2),
INTENT(INOUT) :: tmp_arr
3138 INTEGER,
DIMENSION((size(arr) + 1)/2),
INTENT(INOUT) :: tmp_idx
3140 INTEGER :: t, m, i, j, k
3147 IF (
size(arr) <= 7)
THEN
3148 DO j =
size(arr) - 1, 1, -1
3151 IF (tasks_less_than(arr(i + 1), arr(i)))
THEN
3158 indices(i) = indices(i + 1)
3163 IF (.NOT. swapped)
EXIT
3169 m = (
size(arr) + 1)/2
3170 CALL tasks_sort_low(arr(1:m), indices(1:m), tmp_arr, tmp_idx)
3171 CALL tasks_sort_low(arr(m + 1:), indices(m + 1:), tmp_arr, tmp_idx)
3175 IF (tasks_less_than(arr(m + 1), arr(m)))
THEN
3178 tmp_arr(1:m) = arr(1:m)
3179 tmp_idx(1:m) = indices(1:m)
3184 DO WHILE (i <= m .and. j <=
size(arr) - m)
3185 IF (tasks_less_than(arr(m + j), tmp_arr(i)))
THEN
3187 indices(k) = indices(m + j)
3191 indices(k) = tmp_idx(i)
3201 indices(k) = tmp_idx(i)
3208 END SUBROUTINE tasks_sort_low
3218 PURE FUNCTION atom_pair_less_than(a, b)
RESULT(res)
3222 IF (a%rank /= b%rank)
THEN
3223 res = a%rank < b%rank
3225 ELSE IF (a%row /= b%row)
THEN
3228 ELSE IF (a%col /= b%col)
THEN
3232 res = a%image < b%image
3235 END FUNCTION atom_pair_less_than
3248 SUBROUTINE atom_pair_sort(arr, n, indices)
3249 INTEGER,
INTENT(IN) :: n
3251 integer,
DIMENSION(1:n),
INTENT(INOUT) :: indices
3255 INTEGER,
ALLOCATABLE :: tmp_idx(:)
3259 ALLOCATE (tmp_arr((n + 1)/2), tmp_idx((n + 1)/2))
3261 indices = [(i, i=1, n)]
3263 CALL atom_pair_sort_low(arr(1:n), indices, tmp_arr, tmp_idx)
3265 DEALLOCATE (tmp_arr, tmp_idx)
3266 ELSE IF (n > 0)
THEN
3270 END SUBROUTINE atom_pair_sort
3282 RECURSIVE SUBROUTINE atom_pair_sort_low(arr, indices, tmp_arr, tmp_idx)
3284 INTEGER,
DIMENSION(size(arr)),
INTENT(INOUT) :: indices
3285 TYPE(
atom_pair_type),
DIMENSION((size(arr) + 1)/2),
INTENT(INOUT) :: tmp_arr
3286 INTEGER,
DIMENSION((size(arr) + 1)/2),
INTENT(INOUT) :: tmp_idx
3288 INTEGER :: t, m, i, j, k
3295 IF (
size(arr) <= 7)
THEN
3296 DO j =
size(arr) - 1, 1, -1
3299 IF (atom_pair_less_than(arr(i + 1), arr(i)))
THEN
3306 indices(i) = indices(i + 1)
3311 IF (.NOT. swapped)
EXIT
3317 m = (
size(arr) + 1)/2
3318 CALL atom_pair_sort_low(arr(1:m), indices(1:m), tmp_arr, tmp_idx)
3319 CALL atom_pair_sort_low(arr(m + 1:), indices(m + 1:), tmp_arr, tmp_idx)
3323 IF (atom_pair_less_than(arr(m + 1), arr(m)))
THEN
3326 tmp_arr(1:m) = arr(1:m)
3327 tmp_idx(1:m) = indices(1:m)
3332 DO WHILE (i <= m .and. j <=
size(arr) - m)
3333 IF (atom_pair_less_than(arr(m + j), tmp_arr(i)))
THEN
3335 indices(k) = indices(m + j)
3339 indices(k) = tmp_idx(i)
3349 indices(k) = tmp_idx(i)
3356 END SUBROUTINE atom_pair_sort_low
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
All kind of helpful little routines.
real(kind=dp) function, public exp_radius_very_extended(la_min, la_max, lb_min, lb_max, pab, o1, o2, ra, rb, rp, zetp, eps, prefactor, cutoff, epsabs)
computes the radius of the Gaussian outside of which it is smaller than eps
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.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
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_work_create(matrix, nblks_guess, sizedata_guess, n, work_mutable)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_put_block(matrix, row, col, block, summation)
...
for a given dr()/dh(r) this will provide the bounds to be used if one wants to go over a sphere-subre...
subroutine, public compute_cube_center(cube_center, rs_desc, zeta, zetb, ra, rab)
unifies the computation of the cube center, so that differences in implementation,...
subroutine, public return_cube(info, radius, lb_cube, ub_cube, sphere_bounds)
...
subroutine, public return_cube_nonortho(info, radius, lb, ub, rp)
...
integer function, public gaussian_gridlevel(gridlevel_info, exponent)
...
Fortran API for the grid package, which is written in C.
subroutine, public grid_create_task_list(ntasks, natoms, nkinds, nblocks, block_offsets, atom_positions, atom_kinds, basis_sets, level_list, iatom_list, jatom_list, iset_list, jset_list, ipgf_list, jpgf_list, border_mask_list, block_num_list, radius_list, rab_list, rs_grids, task_list)
Allocates a task list which can be passed to grid_collocate_task_list.
subroutine, public grid_create_basis_set(nset, nsgf, maxco, maxpgf, lmin, lmax, npgf, nsgf_set, first_sgf, sphi, zet, basis_set)
Allocates a basis set which can be passed to grid_create_task_list.
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
integer, parameter, public default_string_length
Types and basic routines needed for a kpoint calculation.
subroutine, public get_kpoint_info(kpoint, kp_scheme, nkp_grid, kp_shift, symmetry, verbose, full_grid, use_real_wfn, eps_geo, parallel_group_size, kp_range, nkp, xkp, wkp, para_env, blacs_env_all, para_env_kp, para_env_inter_kp, blacs_env, kp_env, kp_aux_env, mpools, iogrp, nkp_groups, kp_dist, cell_to_index, index_to_cell, sab_nl, sab_nl_nosym, inversion_symmetry_only, symmetry_backend, symmetry_reduction_method, gamma_centered, lattice_fft)
Retrieve information from a kpoint environment.
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Utility routines for the memory handling.
Interface to the message passing library MPI.
Fortran API for the offload package, which is written in C.
subroutine, public offload_create_buffer(length, buffer)
Allocates a buffer of given length, ie. number of elements.
Define methods related to particle_type.
subroutine, public get_particle_set(particle_set, qs_kind_set, first_sgf, last_sgf, nsgf, nmao, basis, ncgf)
Get the components of a particle set.
Define the data structure for the particle information.
container for various plainwaves related things
subroutine, public pw_env_get(pw_env, pw_pools, cube_info, gridlevel_info, auxbas_pw_pool, auxbas_grid, auxbas_rs_desc, auxbas_rs_grid, rs_descs, rs_grids, xc_pw_pool, vdw_pw_pool, poisson_env, interp_section)
returns the various attributes of the pw env
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, cneo_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zatom, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, hund_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, proj_shell_charge, lr_atom, do_mtlr, u_j_loop, ao_coef, init_u_ramping_each_scf, reltmat, ghost, monovalent, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
subroutine, public get_ks_env(ks_env, v_hartree_rspace, s_mstruct_changed, rho_changed, exc_accint, potential_changed, forces_up_to_date, complex_ks, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, kinetic, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_ks_im_kp, rho, rho_xc, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, vee, neighbor_list_id, sab_orb, sab_all, sac_ae, sac_ppl, sac_lri, sap_ppnl, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_vdw, sab_scp, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, task_list, task_list_soft, kpoints, do_kpoints, atomic_kind_set, qs_kind_set, cell, cell_ref, use_ref_cell, particle_set, energy, force, local_particles, local_molecules, molecule_kind_set, molecule_set, subsys, cp_subsys, virial, results, atprop, nkind, natom, dft_control, dbcsr_dist, distribution_2d, pw_env, para_env, blacs_env, nelectron_total, nelectron_spin)
...
Define the neighbor list data types and the corresponding functionality.
subroutine, public rs_grid_create(rs, desc)
...
pure integer function, public rs_grid_locate_rank(rs_desc, rank_in, shift)
returns the 1D rank of the task which is a cartesian shift away from 1D rank rank_in only possible if...
pure subroutine, public rs_grid_reorder_ranks(desc, real2virtual)
Defines a new ordering of ranks on this realspace grid, recalculating the data bounds and reallocatin...
subroutine, public rs_grid_release(rs_grid)
releases the given rs grid (see doc/ReferenceCounting.html)
generate the tasks lists used by collocate and integrate routines
subroutine, public rs_copy_to_matrices(src_buffer, dest_matrices, task_list)
Copies from buffer into DBCSR matrics, replaces rs_gather_matrix for non-distributed grids.
subroutine, public rs_scatter_matrices(src_matrices, dest_buffer, task_list, group)
Scatters dbcsr matrix blocks and receives them into a buffer as needed before collocation.
subroutine, public rs_distribute_matrix(rs_descs, pmats, atom_pair_send, atom_pair_recv, nimages, scatter, hmats)
redistributes the matrix so that it can be used in realspace operations i.e. according to the task li...
subroutine, public distribute_tasks(rs_descs, ntasks, natoms, tasks, atom_pair_send, atom_pair_recv, symmetric, reorder_rs_grid_ranks, skip_load_balance_distributed, balance_replicated)
Assembles tasks to be performed on local grid.
subroutine, public rs_gather_matrices(src_buffer, dest_matrices, task_list, group)
Gather the dbcsr matrix blocks and receives them into a buffer as needed after integration.
subroutine, public task_list_inner_loop(tasks, ntasks, curr_tasks, rs_descs, dft_control, cube_info, gridlevel_info, cindex, iatom, jatom, rpgfa, rpgfb, zeta, zetb, kind_radius_b, set_radius_a, set_radius_b, ra, rab, la_max, la_min, lb_max, lb_min, npgfa, npgfb, nseta, nsetb)
...
subroutine, public generate_qs_task_list(ks_env, task_list, basis_type, reorder_rs_grid_ranks, skip_load_balance_distributed, pw_env_external, sab_orb_external, ext_kpoints)
...
subroutine, public rs_copy_to_buffer(src_matrices, dest_buffer, task_list)
Copies the DBCSR blocks into buffer, replaces rs_scatter_matrix for non-distributed grids.
subroutine, public serialize_task(task, serialized_task)
Serialize a task into an integer array. Used for MPI communication.
subroutine, public deserialize_task(task, serialized_task)
De-serialize a task from an integer array. Used for MPI communication.
subroutine, public reallocate_tasks(tasks, new_size)
Grow an array of tasks while preserving the existing entries.
integer, parameter, public task_size_in_int8
All kind of helpful little routines.
Type defining parameters related to the simulation cell.
Contains information about kpoints.
contained for different pw related things
Provides all information about a quickstep kind.
calculation environment to calculate the ks matrix, holds all the needed vars. assumes that the core ...