34#include "./base/base_uses.f90"
43 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'hfx_load_balance_methods'
45 REAL(kind=
dp),
PARAMETER ::
p1_energy(12) = [2.9461408209700424_dp, 1.0624718662999657_dp, &
46 -1.91570128356921242e-002_dp, -1.6668495454436603_dp, &
47 1.7512639006523709_dp, -9.76074323945336081e-002_dp, &
48 2.6230786127311889_dp, -0.31870737623014189_dp, &
49 7.9588203912690973_dp, 1.8331423413134813_dp, &
50 -0.15427618665346299_dp, 0.19749436090711650_dp]
51 REAL(kind=
dp),
PARAMETER ::
p2_energy(12) = [2.3104682960662593_dp, 1.8744052737304417_dp, &
52 -9.36564055598656797e-002_dp, 0.64284973765086939_dp, &
53 1.0137565430060556_dp, -6.80088178288954567e-003_dp, &
54 1.1692629207374552_dp, -2.6314710080507573_dp, &
55 19.237814781880786_dp, 1.0505934173661349_dp, &
56 0.80382371955699250_dp, 0.49903401991818103_dp]
57 REAL(kind=
dp),
PARAMETER ::
p3_energy(2) = [7.82336287670072350e-002_dp, 0.38073304105744837_dp]
58 REAL(kind=
dp),
PARAMETER :: p1_forces(12) = [2.5746279948798874_dp, 1.3420575378609276_dp, &
59 -9.41673106447732111e-002_dp, 0.94568006899317825_dp, &
60 -1.4511897117448544_dp, 0.59178934677316952_dp, &
61 2.7291149361757236_dp, -0.50555512044800210_dp, &
62 8.3508180969609871_dp, 1.6829982496141809_dp, &
63 -0.74895370472152600_dp, 0.43801726744197500_dp]
64 REAL(kind=
dp),
PARAMETER :: p2_forces(12) = [2.6398568961569020_dp, 2.3024918834564101_dp, &
65 5.33216585432061581e-003_dp, 0.45572145697283628_dp, &
66 1.8119743851500618_dp, -0.12533918548421166_dp, &
67 -1.4040312084552751_dp, -4.5331650463917859_dp, &
68 12.593431549069477_dp, 1.1311978374487595_dp, &
69 1.4245996087624646_dp, 1.1425350529853495_dp]
70 REAL(kind=
dp),
PARAMETER :: p3_forces(2) = [0.12051930516830946_dp, 1.3828051586144336_dp]
124 coeffs_set, coeffs_kind, &
125 is_assoc_atomic_block_global, do_periodic, &
126 load_balance_parameter, kind_of, basis_parameter, pmax_set, &
127 pmax_atom, i_thread, n_threads, cell, &
128 do_p_screening, map_atom_to_kind_atom, nkind, eval_type, &
129 pmax_block, use_virial)
131 REAL(
dp),
INTENT(IN) :: eps_schwarz
133 INTEGER,
INTENT(IN) :: max_set
135 TYPE(hfx_screen_coeff_type), &
136 DIMENSION(:, :, :, :),
POINTER :: coeffs_set
137 TYPE(hfx_screen_coeff_type),
DIMENSION(:, :), &
138 POINTER :: coeffs_kind
139 INTEGER,
DIMENSION(:, :) :: is_assoc_atomic_block_global
140 LOGICAL :: do_periodic
142 INTEGER :: kind_of(*)
144 TYPE(
hfx_p_kind),
DIMENSION(:),
POINTER :: pmax_set
145 REAL(
dp),
DIMENSION(:, :),
POINTER :: pmax_atom
146 INTEGER,
INTENT(IN) :: i_thread, n_threads
148 LOGICAL,
INTENT(IN) :: do_p_screening
149 INTEGER,
DIMENSION(:),
POINTER :: map_atom_to_kind_atom
150 INTEGER,
INTENT(IN) :: nkind, eval_type
151 REAL(
dp),
DIMENSION(:, :),
POINTER :: pmax_block
152 LOGICAL,
INTENT(IN) :: use_virial
154 CHARACTER(LEN=*),
PARAMETER :: routinen =
'hfx_load_balance'
157 INTEGER(int_8),
PARAMETER :: max_cached_quartet_costs = 2000000_int_8
159 CHARACTER(LEN=512) :: error_msg
160 INTEGER :: block_size, current_block_id, data_from, dest, handle, handle_inner, &
161 handle_range, i, iatom_block, iatom_end, iatom_start, ibin, icpu, j, jatom_block, &
162 jatom_end, jatom_start, katom_block, katom_end, katom_start, latom_block, latom_end, &
163 latom_start, mepos, my_process_id, n_processes, natom, nbins, nblocks, ncpu, &
164 new_iatom_end, new_iatom_start, new_jatom_end, new_jatom_start, non_empty_blocks, &
165 objective_block_size, objective_nblocks, source, total_blocks
167 INTEGER(int_8) :: atom_block, block_cost_val, cost_per_bin, cost_per_core, current_cost, &
168 distribution_counter_end, distribution_counter_start, global_quartet_counter, &
169 local_quartet_counter, n_my_quartets, q_idx, &
170 self_cost_per_block, tmp_block, total_block_self_cost
171 INTEGER(int_8),
ALLOCATABLE,
DIMENSION(:) :: buffer_in, buffer_out, cached_block_cost
172 INTEGER(int_8),
DIMENSION(:),
POINTER :: local_cost_matrix, recbuffer, &
173 sendbuffer, swapbuffer
174 INTEGER(int_8),
DIMENSION(:),
POINTER,
SAVE :: cost_matrix
175 INTEGER(int_8),
SAVE :: shm_global_quartet_counter, &
176 shm_local_quartet_counter
177 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rcount, rdispl, tmp_index, tmp_pos, &
179 INTEGER,
DIMENSION(:),
POINTER,
SAVE :: shm_distribution_vector
180 INTEGER,
SAVE :: shm_nblocks
181 LOGICAL :: changed, last_bin_needs_to_be_filled, &
183 LOGICAL,
DIMENSION(:, :),
POINTER,
SAVE :: atomic_pair_list
184 REAL(
dp) :: coeffs_kind_max0, log10_eps_schwarz, &
188 POINTER,
SAVE :: shm_blocks
189 TYPE(
hfx_distribution),
DIMENSION(:),
POINTER :: binned_dist, ptr_to_tmp_dist, tmp_dist
194 DIMENSION(:) :: set_list_ij, set_list_kl
198 CALL timeset(routinen, handle)
202 log10_eps_schwarz = log10(eps_schwarz)
203 log_2 = log10(2.0_dp)
204 coeffs_kind_max0 = maxval(coeffs_kind(:, :)%x(2))
205 ncpu = para_env%num_pe
206 n_processes = ncpu*n_threads
207 natom =
SIZE(particle_set)
209 block_size = load_balance_parameter%block_size
210 ALLOCATE (set_list_ij((max_set*block_size)**2))
211 ALLOCATE (set_list_kl((max_set*block_size)**2))
213 IF (.NOT. load_balance_parameter%blocks_initialized)
THEN
216 CALL timeset(routinen//
"_range", handle_range)
218 nblocks = max((natom + block_size - 1)/block_size, 1)
219 ALLOCATE (blocks_guess(nblocks))
220 ALLOCATE (tmp_blocks(natom))
221 ALLOCATE (tmp_blocks2(natom))
224 SELECT CASE (eval_type)
226 atomic_pair_list => x_data%atomic_pair_list
228 atomic_pair_list => x_data%atomic_pair_list_forces
230 atomic_pair_list = .true.
231 CALL init_blocks(nkind, para_env, natom, block_size, nblocks, blocks_guess, &
232 list_ij, list_kl, set_list_ij, set_list_kl, &
234 coeffs_set, coeffs_kind, &
235 is_assoc_atomic_block_global, do_periodic, &
236 kind_of, basis_parameter, pmax_set, pmax_atom, &
238 do_p_screening, map_atom_to_kind_atom, eval_type, &
239 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
241 total_block_self_cost = 0
244 total_block_self_cost = total_block_self_cost + blocks_guess(i)%cost
247 CALL para_env%sum(total_block_self_cost)
249 objective_block_size = load_balance_parameter%block_size
250 objective_nblocks = max((natom + objective_block_size - 1)/objective_block_size, 1)
252 self_cost_per_block = (total_block_self_cost + objective_nblocks - 1)/(objective_nblocks)
255 tmp_blocks2(i) = blocks_guess(i)
260 DO WHILE (.NOT. optimized)
264 DO atom_block = 1, nblocks
265 current_block_id = current_block_id + 1
266 iatom_start = tmp_blocks2(atom_block)%istart
267 iatom_end = tmp_blocks2(atom_block)%iend
268 IF (tmp_blocks2(atom_block)%cost > 1.5_dp*self_cost_per_block .AND. iatom_end - iatom_start > 0)
THEN
270 new_iatom_start = iatom_start
271 new_iatom_end = (iatom_end - iatom_start + 1)/2 + iatom_start - 1
272 new_jatom_start = new_iatom_end + 1
273 new_jatom_end = iatom_end
274 tmp_blocks(current_block_id)%istart = new_iatom_start
275 tmp_blocks(current_block_id)%iend = new_iatom_end
276 tmp_blocks(current_block_id)%cost = estimate_block_cost( &
277 natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
278 new_iatom_start, new_iatom_end, new_iatom_start, new_iatom_end, &
279 new_iatom_start, new_iatom_end, new_iatom_start, new_iatom_end, &
281 coeffs_set, coeffs_kind, &
282 is_assoc_atomic_block_global, do_periodic, &
283 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
285 do_p_screening, map_atom_to_kind_atom, eval_type, &
286 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
287 current_block_id = current_block_id + 1
288 tmp_blocks(current_block_id)%istart = new_jatom_start
289 tmp_blocks(current_block_id)%iend = new_jatom_end
290 tmp_blocks(current_block_id)%cost = estimate_block_cost( &
291 natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
292 new_jatom_start, new_jatom_end, new_jatom_start, new_jatom_end, &
293 new_jatom_start, new_jatom_end, new_jatom_start, new_jatom_end, &
295 coeffs_set, coeffs_kind, &
296 is_assoc_atomic_block_global, do_periodic, &
297 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
299 do_p_screening, map_atom_to_kind_atom, eval_type, &
300 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
302 tmp_blocks(current_block_id)%istart = iatom_start
303 tmp_blocks(current_block_id)%iend = iatom_end
304 tmp_blocks(current_block_id)%cost = tmp_blocks2(atom_block)%cost
307 IF (.NOT. changed) optimized = .true.
308 IF (i > 20) optimized = .true.
309 nblocks = current_block_id
310 DO atom_block = 1, nblocks
311 tmp_blocks2(atom_block) = tmp_blocks(atom_block)
315 DEALLOCATE (tmp_blocks2)
319 DO atom_block = 1, nblocks
320 IF (tmp_blocks(atom_block)%istart == 0) cycle
321 non_empty_blocks = non_empty_blocks + 1
324 ALLOCATE (rcount(ncpu))
326 rcount(para_env%mepos + 1) = non_empty_blocks
327 CALL para_env%sum(rcount)
332 total_blocks = total_blocks + rcount(i)
336 ALLOCATE (rdispl(ncpu))
337 rcount(:) = rcount(:)*3
340 rdispl(i) = rdispl(i - 1) + rcount(i - 1)
343 ALLOCATE (buffer_in(3*non_empty_blocks))
346 DO atom_block = 1, nblocks
347 IF (tmp_blocks(atom_block)%istart == 0) cycle
348 buffer_in(non_empty_blocks*3 + 1) = tmp_blocks(atom_block)%istart
349 buffer_in(non_empty_blocks*3 + 2) = tmp_blocks(atom_block)%iend
350 buffer_in(non_empty_blocks*3 + 3) = tmp_blocks(atom_block)%cost
351 non_empty_blocks = non_empty_blocks + 1
354 nblocks = total_blocks
356 ALLOCATE (tmp_blocks2(nblocks))
358 ALLOCATE (buffer_out(3*nblocks))
361 CALL para_env%allgatherv(buffer_in, buffer_out, rcount, rdispl)
364 tmp_blocks2(i)%istart = int(buffer_out((i - 1)*3 + 1))
365 tmp_blocks2(i)%iend = int(buffer_out((i - 1)*3 + 2))
366 tmp_blocks2(i)%cost = buffer_out((i - 1)*3 + 3)
370 ALLOCATE (to_be_sorted(nblocks))
371 ALLOCATE (tmp_index(nblocks))
373 DO atom_block = 1, nblocks
374 to_be_sorted(atom_block) = tmp_blocks2(atom_block)%istart
377 CALL sort(to_be_sorted, nblocks, tmp_index)
379 ALLOCATE (x_data%blocks(nblocks))
381 DO atom_block = 1, nblocks
382 x_data%blocks(atom_block) = tmp_blocks2(tmp_index(atom_block))
385 shm_blocks => x_data%blocks
386 shm_nblocks = nblocks
389 load_balance_parameter%nblocks = nblocks
391 DEALLOCATE (blocks_guess, tmp_blocks, tmp_blocks2)
393 DEALLOCATE (rcount, rdispl, buffer_in, buffer_out, to_be_sorted, tmp_index)
395 load_balance_parameter%blocks_initialized = .true.
397 x_data%blocks = shm_blocks
398 load_balance_parameter%nblocks = shm_nblocks
399 load_balance_parameter%blocks_initialized = .true.
401 ALLOCATE (x_data%pmax_block(shm_nblocks, shm_nblocks))
402 x_data%pmax_block = 0.0_dp
403 pmax_block => x_data%pmax_block
404 CALL timestop(handle_range)
408 IF (.NOT. load_balance_parameter%blocks_initialized)
THEN
409 ALLOCATE (x_data%blocks(shm_nblocks))
410 x_data%blocks = shm_blocks
411 load_balance_parameter%nblocks = shm_nblocks
412 load_balance_parameter%blocks_initialized = .true.
420 pmax_block => x_data%pmax_block
422 IF (do_p_screening)
THEN
423 DO iatom_block = 1, shm_nblocks
424 iatom_start = x_data%blocks(iatom_block)%istart
425 iatom_end = x_data%blocks(iatom_block)%iend
426 DO jatom_block = 1, shm_nblocks
427 jatom_start = x_data%blocks(jatom_block)%istart
428 jatom_end = x_data%blocks(jatom_block)%iend
429 pmax_block(iatom_block, jatom_block) = maxval(pmax_atom(iatom_start:iatom_end, jatom_start:jatom_end))
434 SELECT CASE (eval_type)
436 atomic_pair_list => x_data%atomic_pair_list
438 atomic_pair_list => x_data%atomic_pair_list_forces
441 do_periodic, coeffs_kind, coeffs_kind_max0, log10_eps_schwarz, cell, &
448 IF (n_processes == 1)
THEN
449 ALLOCATE (tmp_dist(1))
450 tmp_dist(1)%number_of_atom_quartets = huge(tmp_dist(1)%number_of_atom_quartets)
451 tmp_dist(1)%istart = 0_int_8
452 ptr_to_tmp_dist => tmp_dist(:)
453 SELECT CASE (eval_type)
459 DEALLOCATE (tmp_dist)
464 CALL timeset(routinen//
"_count", handle_inner)
468 cost_per_core = 0_int_8
469 my_process_id = para_env%mepos*n_threads + i_thread
470 nblocks = load_balance_parameter%nblocks
471 n_my_quartets = 0_int_8
472 DO atom_block = my_process_id, int(nblocks, kind=
int_8)**4 - 1_int_8, n_processes
473 latom_block = int(
modulo(atom_block, int(nblocks, kind=
int_8))) + 1
474 tmp_block = atom_block/nblocks
475 katom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
476 IF (latom_block < katom_block) cycle
477 tmp_block = tmp_block/nblocks
478 jatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
479 tmp_block = tmp_block/nblocks
480 iatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
481 IF (jatom_block < iatom_block) cycle
482 n_my_quartets = n_my_quartets + 1_int_8
483 IF (n_my_quartets == max_cached_quartet_costs)
EXIT
485 IF (n_my_quartets > 0_int_8)
THEN
486 ALLOCATE (cached_block_cost(n_my_quartets))
490 DO atom_block = my_process_id, int(nblocks, kind=
int_8)**4 - 1, n_processes
492 latom_block = int(
modulo(atom_block, int(nblocks, kind=
int_8))) + 1
493 tmp_block = atom_block/nblocks
494 katom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
495 IF (latom_block < katom_block) cycle
496 tmp_block = tmp_block/nblocks
497 jatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
498 tmp_block = tmp_block/nblocks
499 iatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
500 IF (jatom_block < iatom_block) cycle
502 q_idx = q_idx + 1_int_8
504 iatom_start = x_data%blocks(iatom_block)%istart
505 iatom_end = x_data%blocks(iatom_block)%iend
506 jatom_start = x_data%blocks(jatom_block)%istart
507 jatom_end = x_data%blocks(jatom_block)%iend
508 katom_start = x_data%blocks(katom_block)%istart
509 katom_end = x_data%blocks(katom_block)%iend
510 latom_start = x_data%blocks(latom_block)%istart
511 latom_end = x_data%blocks(latom_block)%iend
513 SELECT CASE (eval_type)
515 pmax_blocks = max(pmax_block(katom_block, iatom_block), &
516 pmax_block(latom_block, jatom_block), &
517 pmax_block(latom_block, iatom_block), &
518 pmax_block(katom_block, jatom_block))
520 pmax_blocks = max(pmax_block(katom_block, iatom_block) + &
521 pmax_block(latom_block, jatom_block), &
522 pmax_block(latom_block, iatom_block) + &
523 pmax_block(katom_block, jatom_block))
526 IF (2.0_dp*coeffs_kind_max0 + pmax_blocks < log10_eps_schwarz)
THEN
527 IF (q_idx <= n_my_quartets) cached_block_cost(q_idx) = -1_int_8
531 block_cost_val = estimate_block_cost(natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
532 iatom_start, iatom_end, jatom_start, jatom_end, &
533 katom_start, katom_end, latom_start, latom_end, &
535 coeffs_set, coeffs_kind, &
536 is_assoc_atomic_block_global, do_periodic, &
537 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
539 do_p_screening, map_atom_to_kind_atom, eval_type, &
540 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
541 IF (q_idx <= n_my_quartets) cached_block_cost(q_idx) = block_cost_val
542 cost_per_core = cost_per_core + block_cost_val
546 nbins = load_balance_parameter%nbins
547 cost_per_bin = (cost_per_core + nbins - 1)/(nbins)
551 CALL timestop(handle_inner)
557 CALL hfx_recursive_load_balance(n_processes, my_process_id, nblocks, &
558 natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
560 coeffs_set, coeffs_kind, &
561 is_assoc_atomic_block_global, do_periodic, &
562 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
563 cell, x_data, para_env, pmax_block, &
564 do_p_screening, map_atom_to_kind_atom, eval_type, &
565 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
570 CALL timeset(routinen//
"_bin", handle_inner)
574 ALLOCATE (binned_dist(nbins))
575 binned_dist(:)%istart = -1_int_8
576 binned_dist(:)%number_of_atom_quartets = 0_int_8
577 binned_dist(:)%cost = 0_int_8
578 binned_dist(:)%time_first_scf = 0.0_dp
579 binned_dist(:)%time_other_scf = 0.0_dp
580 binned_dist(:)%time_forces = 0.0_dp
584 distribution_counter_start = 1
585 distribution_counter_end = 0
588 global_quartet_counter = 0
589 local_quartet_counter = 0
590 last_bin_needs_to_be_filled = .false.
591 DO atom_block = my_process_id, int(nblocks, kind=
int_8)**4 - 1, n_processes
592 latom_block = int(
modulo(atom_block, int(nblocks, kind=
int_8))) + 1
593 tmp_block = atom_block/nblocks
594 katom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
595 IF (latom_block < katom_block) cycle
596 tmp_block = tmp_block/nblocks
597 jatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
598 tmp_block = tmp_block/nblocks
599 iatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
600 IF (jatom_block < iatom_block) cycle
602 distribution_counter_end = distribution_counter_end + 1
603 global_quartet_counter = global_quartet_counter + 1
604 last_bin_needs_to_be_filled = .true.
606 IF (binned_dist(ibin)%istart == -1_int_8) binned_dist(ibin)%istart = atom_block
608 IF (distribution_counter_end <= n_my_quartets)
THEN
609 block_cost_val = cached_block_cost(distribution_counter_end)
610 IF (block_cost_val < 0_int_8) cycle
611 current_cost = current_cost + block_cost_val
613 iatom_start = x_data%blocks(iatom_block)%istart
614 iatom_end = x_data%blocks(iatom_block)%iend
615 jatom_start = x_data%blocks(jatom_block)%istart
616 jatom_end = x_data%blocks(jatom_block)%iend
617 katom_start = x_data%blocks(katom_block)%istart
618 katom_end = x_data%blocks(katom_block)%iend
619 latom_start = x_data%blocks(latom_block)%istart
620 latom_end = x_data%blocks(latom_block)%iend
622 SELECT CASE (eval_type)
624 pmax_blocks = max(pmax_block(katom_block, iatom_block), &
625 pmax_block(latom_block, jatom_block), &
626 pmax_block(latom_block, iatom_block), &
627 pmax_block(katom_block, jatom_block))
629 pmax_blocks = max(pmax_block(katom_block, iatom_block) + &
630 pmax_block(latom_block, jatom_block), &
631 pmax_block(latom_block, iatom_block) + &
632 pmax_block(katom_block, jatom_block))
635 IF (2.0_dp*coeffs_kind_max0 + pmax_blocks < log10_eps_schwarz) cycle
637 current_cost = current_cost &
638 + estimate_block_cost(natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
639 iatom_start, iatom_end, jatom_start, jatom_end, &
640 katom_start, katom_end, latom_start, latom_end, &
642 coeffs_set, coeffs_kind, &
643 is_assoc_atomic_block_global, do_periodic, &
644 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
646 do_p_screening, map_atom_to_kind_atom, eval_type, &
647 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
650 IF (current_cost >= cost_per_bin)
THEN
651 IF (ibin == nbins)
THEN
652 binned_dist(ibin)%number_of_atom_quartets = binned_dist(ibin)%number_of_atom_quartets + &
653 distribution_counter_end - distribution_counter_start + 1
655 binned_dist(ibin)%number_of_atom_quartets = distribution_counter_end - distribution_counter_start + 1
657 binned_dist(ibin)%cost = binned_dist(ibin)%cost + current_cost
658 ibin = min(ibin + 1, nbins)
659 distribution_counter_start = distribution_counter_end + 1
661 last_bin_needs_to_be_filled = .false.
664 IF (
ALLOCATED(cached_block_cost))
DEALLOCATE (cached_block_cost)
668 CALL timestop(handle_inner)
669 CALL timeset(routinen//
"_dist", handle_inner)
673 IF (last_bin_needs_to_be_filled)
THEN
674 binned_dist(ibin)%cost = binned_dist(ibin)%cost + current_cost
675 IF (ibin == nbins)
THEN
676 binned_dist(ibin)%number_of_atom_quartets = binned_dist(ibin)%number_of_atom_quartets + &
677 distribution_counter_end - distribution_counter_start + 1
679 binned_dist(ibin)%number_of_atom_quartets = distribution_counter_end - distribution_counter_start + 1
685 local_quartet_counter = local_quartet_counter + binned_dist(ibin)%number_of_atom_quartets
689 shm_local_quartet_counter = 0
690 shm_global_quartet_counter = 0
694 shm_local_quartet_counter = shm_local_quartet_counter + local_quartet_counter
696 shm_global_quartet_counter = shm_global_quartet_counter + global_quartet_counter
700 CALL para_env%sum(shm_local_quartet_counter)
701 CALL para_env%sum(shm_global_quartet_counter)
702 IF (para_env%is_source())
THEN
703 IF (shm_local_quartet_counter /= shm_global_quartet_counter)
THEN
704 WRITE (error_msg,
'(A,I0,A,I0,A)')
"HFX Sanity check for parallel distribution failed. "// &
705 "Number of local quartets (", shm_local_quartet_counter, &
706 ") and number of global quartets (", shm_global_quartet_counter, &
707 ") are different. Please send in a bug report."
715 ALLOCATE (cost_matrix(ncpu*nbins*n_threads))
719 icpu = para_env%mepos + 1
721 cost_matrix((icpu - 1)*nbins*n_threads + i_thread*nbins + i) = binned_dist(i)%cost
723 mepos = para_env%mepos
730 ALLOCATE (sendbuffer(nbins*n_threads))
731 ALLOCATE (recbuffer(nbins*n_threads))
733 sendbuffer = cost_matrix(mepos*nbins*n_threads + 1:mepos*nbins*n_threads + nbins*n_threads)
735 dest =
modulo(mepos + 1, ncpu)
736 source =
modulo(mepos - 1, ncpu)
737 DO icpu = 0, ncpu - 1
738 IF (icpu /= ncpu - 1)
THEN
739 CALL para_env%isendrecv(sendbuffer, dest, recbuffer, source, &
742 data_from =
modulo(mepos - icpu, ncpu)
743 cost_matrix(data_from*nbins*n_threads + 1:data_from*nbins*n_threads + nbins*n_threads) = sendbuffer
744 IF (icpu /= ncpu - 1)
THEN
747 swapbuffer => sendbuffer
748 sendbuffer => recbuffer
749 recbuffer => swapbuffer
751 DEALLOCATE (recbuffer, sendbuffer)
757 CALL timestop(handle_inner)
758 CALL timeset(routinen//
"_opt", handle_inner)
764 ALLOCATE (local_cost_matrix(
SIZE(cost_matrix, 1)))
765 local_cost_matrix = cost_matrix
767 ALLOCATE (shm_distribution_vector(ncpu*nbins*n_threads))
769 CALL optimize_distribution(ncpu*nbins*n_threads, ncpu*n_threads, local_cost_matrix, &
770 shm_distribution_vector, x_data%load_balance_parameter%do_randomize)
772 CALL timestop(handle_inner)
773 CALL timeset(routinen//
"_redist", handle_inner)
775 ALLOCATE (full_dist(ncpu*n_threads, nbins))
777 full_dist(:, :)%istart = 0_int_8
778 full_dist(:, :)%number_of_atom_quartets = 0_int_8
779 full_dist(:, :)%cost = 0_int_8
780 full_dist(:, :)%time_first_scf = 0.0_dp
781 full_dist(:, :)%time_other_scf = 0.0_dp
782 full_dist(:, :)%time_forces = 0.0_dp
785 mepos = para_env%mepos + 1
786 full_dist((mepos - 1)*n_threads + i_thread + 1, :) = binned_dist(:)
790 ALLOCATE (sendbuffer(3*nbins*n_threads))
791 ALLOCATE (recbuffer(3*nbins*n_threads))
792 mepos = para_env%mepos
795 sendbuffer((j - 1)*3*nbins + (i - 1)*3 + 1) = full_dist(mepos*n_threads + j, i)%istart
796 sendbuffer((j - 1)*3*nbins + (i - 1)*3 + 2) = full_dist(mepos*n_threads + j, i)%number_of_atom_quartets
797 sendbuffer((j - 1)*3*nbins + (i - 1)*3 + 3) = full_dist(mepos*n_threads + j, i)%cost
803 dest =
modulo(mepos + 1, ncpu)
804 source =
modulo(mepos - 1, ncpu)
805 DO icpu = 0, ncpu - 1
806 IF (icpu /= ncpu - 1)
THEN
807 CALL para_env%isendrecv(sendbuffer, dest, recbuffer, source, &
810 data_from =
modulo(mepos - icpu, ncpu)
813 full_dist(data_from*n_threads + j, i)%istart = sendbuffer((j - 1)*3*nbins + (i - 1)*3 + 1)
814 full_dist(data_from*n_threads + j, i)%number_of_atom_quartets = sendbuffer((j - 1)*3*nbins + (i - 1)*3 + 2)
815 full_dist(data_from*n_threads + j, i)%cost = sendbuffer((j - 1)*3*nbins + (i - 1)*3 + 3)
819 IF (icpu /= ncpu - 1)
THEN
822 swapbuffer => sendbuffer
823 sendbuffer => recbuffer
824 recbuffer => swapbuffer
826 DEALLOCATE (recbuffer, sendbuffer)
833 ALLOCATE (tmp_pos(ncpu*n_threads))
835 ALLOCATE (tmp_dist(nbins*ncpu*n_threads))
837 tmp_dist(:)%istart = 0_int_8
838 tmp_dist(:)%number_of_atom_quartets = 0_int_8
839 tmp_dist(:)%cost = 0_int_8
840 tmp_dist(:)%time_first_scf = 0.0_dp
841 tmp_dist(:)%time_other_scf = 0.0_dp
842 tmp_dist(:)%time_forces = 0.0_dp
844 DO icpu = 1, n_processes
846 mepos = my_process_id + 1
847 IF (shm_distribution_vector((icpu - 1)*nbins + i) == mepos)
THEN
848 tmp_dist(tmp_pos(mepos)) = full_dist(icpu, i)
849 tmp_pos(mepos) = tmp_pos(mepos) + 1
855 NULLIFY (ptr_to_tmp_dist)
856 mepos = my_process_id + 1
857 ptr_to_tmp_dist => tmp_dist(1:tmp_pos(mepos) - 1)
858 SELECT CASE (eval_type)
867 DEALLOCATE (full_dist, cost_matrix, shm_distribution_vector)
870 DEALLOCATE (tmp_dist, tmp_pos)
871 DEALLOCATE (binned_dist, local_cost_matrix)
872 DEALLOCATE (set_list_ij, set_list_kl)
876 CALL timestop(handle_inner)
882 CALL timestop(handle)
930 SUBROUTINE hfx_recursive_load_balance(n_processes, my_process_id, nblocks, &
931 natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
933 coeffs_set, coeffs_kind, &
934 is_assoc_atomic_block_global, do_periodic, &
935 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
936 cell, x_data, para_env, pmax_block, &
937 do_p_screening, map_atom_to_kind_atom, eval_type, &
938 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
941 INTEGER,
INTENT(IN) :: n_processes, my_process_id, nblocks, &
945 DIMENSION(:),
INTENT(IN) :: set_list_ij, set_list_kl
947 POINTER :: particle_set
948 TYPE(hfx_screen_coeff_type), &
949 DIMENSION(:, :, :, :),
INTENT(IN),
POINTER :: coeffs_set
950 TYPE(hfx_screen_coeff_type),
DIMENSION(:, :), &
951 INTENT(IN),
POINTER :: coeffs_kind
952 INTEGER,
DIMENSION(:, :),
INTENT(IN) :: is_assoc_atomic_block_global
953 LOGICAL,
INTENT(IN) :: do_periodic
954 INTEGER,
INTENT(IN) :: kind_of(*)
956 POINTER :: basis_parameter
959 REAL(
dp),
DIMENSION(:, :),
INTENT(IN),
POINTER :: pmax_atom
960 REAL(
dp) :: pmax_blocks
961 TYPE(
cell_type),
INTENT(IN),
POINTER :: cell
962 TYPE(
hfx_type),
INTENT(IN),
POINTER :: x_data
964 REAL(
dp),
DIMENSION(:, :),
INTENT(IN),
POINTER :: pmax_block
965 LOGICAL,
INTENT(IN) :: do_p_screening
966 INTEGER,
DIMENSION(:),
INTENT(IN),
POINTER :: map_atom_to_kind_atom
967 INTEGER,
INTENT(IN) :: eval_type
968 REAL(
dp),
INTENT(IN) :: log10_eps_schwarz, log_2, &
970 LOGICAL,
INTENT(IN) :: use_virial
971 LOGICAL,
DIMENSION(:, :),
INTENT(IN),
POINTER :: atomic_pair_list
973 CHARACTER(LEN=*),
PARAMETER :: routinen =
'hfx_recursive_load_balance'
975 INTEGER :: handle, i, iatom_block, iatom_end, iatom_start, j, jatom_block, jatom_end, &
976 jatom_start, katom_block, katom_end, katom_start, latom_block, latom_end, latom_start, &
977 np, nq, numbins, p, q, sizep, sizeq, unit_nr
978 INTEGER(int_8) :: local_cost, pidx, qidx, sump, sumq
979 INTEGER(int_8),
ALLOCATABLE,
DIMENSION(:) :: local_cost_vector
980 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: blocksize, p_atom_blocks, permute, &
982 REAL(
dp) :: maximum, mean
988 CALL timeset(routinen, handle)
993 CALL hfx_calculate_pq(p, q, numbins, n_processes)
995 ALLOCATE (blocksize(numbins))
996 ALLOCATE (permute(nblocks**2))
1005 CALL hfx_recursive_permute(blocksize, 1, nblocks**2, numbins, &
1007 my_process_id, n_processes, nblocks, &
1008 natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
1010 coeffs_set, coeffs_kind, &
1011 is_assoc_atomic_block_global, do_periodic, &
1012 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
1013 cell, x_data, para_env, pmax_block, &
1014 do_p_screening, map_atom_to_kind_atom, eval_type, &
1015 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
1023 pidx =
modulo(int(my_process_id), int(p)) + 1
1024 qidx = my_process_id/p + 1
1026 sizep = sum(blocksize((np*(pidx - 1) + 1):(np*pidx)))
1027 sizeq = sum(blocksize((nq*(qidx - 1) + 1):(nq*qidx)))
1029 sump = sum(blocksize(1:(np*(pidx - 1))))
1030 sumq = sum(blocksize(1:(nq*(qidx - 1))))
1032 ALLOCATE (p_atom_blocks(sizep))
1033 ALLOCATE (q_atom_blocks(sizeq))
1035 p_atom_blocks(:) = permute((sump + 1):(sump + sizep))
1036 q_atom_blocks(:) = permute((sumq + 1):(sumq + sizeq))
1050 latom_block =
modulo(q_atom_blocks(j), nblocks)
1051 iatom_block = q_atom_blocks(j)/nblocks + 1
1052 jatom_block =
modulo(p_atom_blocks(i), nblocks)
1053 katom_block = p_atom_blocks(i)/nblocks + 1
1056 IF (latom_block < katom_block) cycle
1057 IF (jatom_block < iatom_block) cycle
1059 iatom_start = x_data%blocks(iatom_block)%istart
1060 iatom_end = x_data%blocks(iatom_block)%iend
1061 jatom_start = x_data%blocks(jatom_block)%istart
1062 jatom_end = x_data%blocks(jatom_block)%iend
1063 katom_start = x_data%blocks(katom_block)%istart
1064 katom_end = x_data%blocks(katom_block)%iend
1065 latom_start = x_data%blocks(latom_block)%istart
1066 latom_end = x_data%blocks(latom_block)%iend
1069 SELECT CASE (eval_type)
1071 pmax_blocks = max(pmax_block(katom_block, iatom_block), &
1072 pmax_block(latom_block, jatom_block), &
1073 pmax_block(latom_block, iatom_block), &
1074 pmax_block(katom_block, jatom_block))
1076 pmax_blocks = max(pmax_block(katom_block, iatom_block) + &
1077 pmax_block(latom_block, jatom_block), &
1078 pmax_block(latom_block, iatom_block) + &
1079 pmax_block(katom_block, jatom_block))
1083 IF (2.0_dp*coeffs_kind_max0 + pmax_blocks < log10_eps_schwarz) cycle
1086 local_cost = local_cost + estimate_block_cost(natom, nkind, list_ij, list_kl, set_list_ij, &
1088 iatom_start, iatom_end, jatom_start, jatom_end, &
1089 katom_start, katom_end, latom_start, latom_end, &
1091 coeffs_set, coeffs_kind, &
1092 is_assoc_atomic_block_global, do_periodic, &
1093 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
1095 do_p_screening, map_atom_to_kind_atom, eval_type, &
1096 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
1100 ALLOCATE (local_cost_vector(n_processes))
1101 local_cost_vector = 0
1102 local_cost_vector(my_process_id + 1) = local_cost
1103 CALL para_env%sum(local_cost_vector)
1105 mean = sum(local_cost_vector)/n_processes
1106 maximum = maxval(local_cost_vector)
1111 IF (my_process_id == 0)
THEN
1112 CALL open_file(unit_number=unit_nr, file_name=
"loads.dat")
1113 WRITE (unit_nr, *)
'maximum cost:', maximum
1114 WRITE (unit_nr, *)
'mean cost:', mean
1115 WRITE (unit_nr, *)
'load balance ratio max/mean: ', maximum/mean
1116 WRITE (unit_nr, *)
'-------- detailed per-process costs ---------'
1117 DO i = 1, n_processes
1118 WRITE (unit_nr, *) local_cost_vector(i)
1125 DEALLOCATE (local_cost_vector)
1126 DEALLOCATE (p_atom_blocks, q_atom_blocks)
1127 DEALLOCATE (blocksize, permute)
1131 CALL timestop(handle)
1135 END SUBROUTINE hfx_recursive_load_balance
1149 SUBROUTINE hfx_calculate_pq(p, q, nBins, N)
1151 INTEGER,
INTENT(OUT) :: p, q, nbins
1152 INTEGER,
INTENT(IN) :: n
1158 sqn = sqrt(real(n, kind=
dp))
1161 DO WHILE (real(k, kind=
dp) <= sqn)
1162 IF (
modulo(n, k) == 0)
THEN
1186 END SUBROUTINE hfx_calculate_pq
1237 RECURSIVE SUBROUTINE hfx_recursive_permute(blocksize, blockstart, blockend, nProc_in, &
1239 my_process_id, n_processes, nblocks, &
1240 natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
1242 coeffs_set, coeffs_kind, &
1243 is_assoc_atomic_block_global, do_periodic, &
1244 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
1245 cell, x_data, para_env, pmax_block, &
1246 do_p_screening, map_atom_to_kind_atom, eval_type, &
1247 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
1249 INTEGER :: nproc_in, blockend, blockstart
1250 INTEGER,
DIMENSION(nProc_in) :: blocksize
1251 INTEGER :: nblocks, n_processes, my_process_id
1252 INTEGER,
INTENT(IN) :: step
1253 INTEGER,
DIMENSION(nblocks*nblocks) :: permute
1255 INTEGER,
INTENT(IN) :: nkind
1258 DIMENSION(:) :: set_list_ij, set_list_kl
1260 TYPE(hfx_screen_coeff_type), &
1261 DIMENSION(:, :, :, :),
POINTER :: coeffs_set
1262 TYPE(hfx_screen_coeff_type),
DIMENSION(:, :), &
1263 POINTER :: coeffs_kind
1264 INTEGER,
DIMENSION(:, :) :: is_assoc_atomic_block_global
1265 LOGICAL :: do_periodic
1266 INTEGER :: kind_of(*)
1268 TYPE(
hfx_p_kind),
DIMENSION(:),
POINTER :: pmax_set
1269 REAL(
dp),
DIMENSION(:, :),
POINTER :: pmax_atom
1270 REAL(
dp) :: pmax_blocks
1274 REAL(
dp),
DIMENSION(:, :),
POINTER :: pmax_block
1275 LOGICAL,
INTENT(IN) :: do_p_screening
1276 INTEGER,
DIMENSION(:),
POINTER :: map_atom_to_kind_atom
1277 INTEGER,
INTENT(IN) :: eval_type
1278 REAL(
dp) :: log10_eps_schwarz, log_2, &
1280 LOGICAL,
INTENT(IN) :: use_virial
1281 LOGICAL,
DIMENSION(:, :),
POINTER :: atomic_pair_list
1283 INTEGER :: col, endoffset, i, iatom_block, iatom_end, iatom_start,
idx, inv_perm, &
1284 jatom_block, jatom_end, jatom_start, katom_block, katom_end, katom_start, latom_block, &
1285 latom_end, latom_start, nbins, nproc, row, startoffset
1286 INTEGER(int_8) :: atom_block, tmp_block
1287 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ithblocksize, localblocksize
1288 INTEGER,
DIMENSION(blockend - blockstart + 1) :: bin_perm, tmp_perm
1289 REAL(
dp) :: partialcost
1290 REAL(
dp),
DIMENSION(nblocks*nblocks) :: cost_vector
1293 cost_vector = 0.0_dp
1296 DO atom_block = my_process_id, int(nblocks, kind=
int_8)**4 - 1, n_processes
1299 latom_block = int(
modulo(atom_block, int(nblocks, kind=
int_8))) + 1
1300 tmp_block = atom_block/nblocks
1301 katom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
1302 IF (latom_block < katom_block) cycle
1303 tmp_block = tmp_block/nblocks
1304 jatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
1305 tmp_block = tmp_block/nblocks
1306 iatom_block = int(
modulo(tmp_block, int(nblocks, kind=
int_8))) + 1
1307 IF (jatom_block < iatom_block) cycle
1313 row = (katom_block - 1)*nblocks + jatom_block
1315 DO WHILE (permute(inv_perm) /= row)
1316 inv_perm = inv_perm + 1
1320 col = (iatom_block - 1)*nblocks + latom_block
1322 DO WHILE (permute(inv_perm) /= col)
1323 inv_perm = inv_perm + 1
1328 IF (col < blockstart .OR. col > blockend) cycle
1329 IF (row < blockstart .OR. row > blockend) cycle
1331 iatom_start = x_data%blocks(iatom_block)%istart
1332 iatom_end = x_data%blocks(iatom_block)%iend
1333 jatom_start = x_data%blocks(jatom_block)%istart
1334 jatom_end = x_data%blocks(jatom_block)%iend
1335 katom_start = x_data%blocks(katom_block)%istart
1336 katom_end = x_data%blocks(katom_block)%iend
1337 latom_start = x_data%blocks(latom_block)%istart
1338 latom_end = x_data%blocks(latom_block)%iend
1341 SELECT CASE (eval_type)
1343 pmax_blocks = max(pmax_block(katom_block, iatom_block), &
1344 pmax_block(latom_block, jatom_block), &
1345 pmax_block(latom_block, iatom_block), &
1346 pmax_block(katom_block, jatom_block))
1348 pmax_blocks = max(pmax_block(katom_block, iatom_block) + &
1349 pmax_block(latom_block, jatom_block), &
1350 pmax_block(latom_block, iatom_block) + &
1351 pmax_block(katom_block, jatom_block))
1355 IF (2.0_dp*coeffs_kind_max0 + pmax_blocks < log10_eps_schwarz) cycle
1359 IF (
modulo(step, 2) == 0)
THEN
1366 partialcost = estimate_block_cost(natom, nkind, list_ij, list_kl, set_list_ij, &
1368 iatom_start, iatom_end, jatom_start, jatom_end, &
1369 katom_start, katom_end, latom_start, latom_end, &
1371 coeffs_set, coeffs_kind, &
1372 is_assoc_atomic_block_global, do_periodic, &
1373 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
1375 do_p_screening, map_atom_to_kind_atom, eval_type, &
1376 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
1378 cost_vector(
idx) = cost_vector(
idx) + partialcost
1382 CALL para_env%sum(cost_vector)
1386 DO WHILE (
modulo(int(nproc), int(nbins)) /= 0)
1394 ALLOCATE (localblocksize(nbins))
1395 CALL hfx_permute_binning(nbins, cost_vector(blockstart:blockend), blockend - blockstart + 1, bin_perm, localblocksize)
1399 tmp_perm = permute(blockstart:blockend)
1400 permute(blockstart:blockend) = tmp_perm(bin_perm)
1404 ALLOCATE (ithblocksize(nproc))
1406 startoffset = sum(localblocksize(1:(i - 1)))
1407 endoffset = sum(localblocksize(1:i)) - 1
1409 CALL hfx_recursive_permute(ithblocksize, blockstart + startoffset, blockstart + endoffset, nproc, &
1410 permute, step + 1, &
1411 my_process_id, n_processes, nblocks, &
1412 natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
1414 coeffs_set, coeffs_kind, &
1415 is_assoc_atomic_block_global, do_periodic, &
1416 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
1417 cell, x_data, para_env, pmax_block, &
1418 do_p_screening, map_atom_to_kind_atom, eval_type, &
1419 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
1420 blocksize(((i - 1)*nproc + 1):(i*nproc)) = ithblocksize
1422 DEALLOCATE (ithblocksize)
1425 blocksize(i) = localblocksize(i)
1429 DEALLOCATE (localblocksize)
1431 END SUBROUTINE hfx_recursive_permute
1445 SUBROUTINE hfx_permute_binning(nBins, costvector, maxbinsize, perm, block_count)
1447 INTEGER,
INTENT(IN) :: nbins, maxbinsize
1448 REAL(
dp),
DIMENSION(maxbinsize),
INTENT(IN) :: costvector
1449 INTEGER,
DIMENSION(maxbinsize),
INTENT(OUT) :: perm
1450 INTEGER,
DIMENSION(nBins),
INTENT(OUT) :: block_count
1452 INTEGER :: i, j, mod_idx, offset
1453 INTEGER,
DIMENSION(nBins, maxbinsize) :: bin
1454 INTEGER,
DIMENSION(nBins) :: bin_idx
1455 INTEGER,
DIMENSION(maxbinsize) ::
idx
1456 REAL(
dp),
DIMENSION(maxbinsize) :: vec
1457 REAL(
dp),
DIMENSION(nBins) :: bincosts
1466 CALL sort(vec, maxbinsize,
idx)
1469 DO i = maxbinsize, 1, -1
1470 IF (vec(i) == 0)
THEN
1472 mod_idx =
modulo(i, nbins) + 1
1473 block_count(mod_idx) = block_count(mod_idx) + 1
1474 bin(mod_idx, block_count(mod_idx)) =
idx(i)
1478 CALL sort(bincosts, nbins, bin_idx)
1479 block_count = block_count(bin_idx)
1480 bin = bin(bin_idx, :)
1482 bincosts(1) = bincosts(1) + vec(i)
1483 block_count(1) = block_count(1) + 1
1484 bin(1, block_count(1)) =
idx(i)
1491 DO j = 1, block_count(i)
1492 perm(offset + j) = bin(i, j)
1494 offset = offset + block_count(i)
1497 END SUBROUTINE hfx_permute_binning
1516 load_balance_parameter, &
1517 i_thread, n_threads, eval_type)
1522 INTEGER,
INTENT(IN) :: i_thread, n_threads, eval_type
1524 CHARACTER(LEN=*),
PARAMETER :: routinen =
'hfx_update_load_balance'
1526 INTEGER :: data_from, dest, end_idx, handle, i, ibin, icpu, iprocess, j, mepos, my_bin_size, &
1527 my_global_start_idx, my_process_id, n_processes, nbins, ncpu, source, start_idx
1529 INTEGER(int_8),
DIMENSION(:),
POINTER :: local_cost_matrix, recbuffer, &
1530 sendbuffer, swapbuffer
1531 INTEGER(int_8),
DIMENSION(:),
POINTER,
SAVE :: cost_matrix
1532 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: tmp_pos
1533 INTEGER,
ALLOCATABLE,
DIMENSION(:),
SAVE :: bins_per_rank
1534 INTEGER,
ALLOCATABLE,
DIMENSION(:, :),
SAVE :: bin_histogram
1535 INTEGER,
DIMENSION(:),
POINTER,
SAVE :: shm_distribution_vector
1536 INTEGER,
SAVE :: max_bin_size
1537 TYPE(
hfx_distribution),
DIMENSION(:),
POINTER :: binned_dist, ptr_to_tmp_dist, tmp_dist
1543 CALL timeset(routinen, handle)
1547 ncpu = para_env%num_pe
1548 n_processes = ncpu*n_threads
1550 IF (n_processes == 1)
THEN
1551 ALLOCATE (tmp_dist(1))
1552 tmp_dist(1)%number_of_atom_quartets = huge(tmp_dist(1)%number_of_atom_quartets)
1553 tmp_dist(1)%istart = 0_int_8
1554 ptr_to_tmp_dist => tmp_dist(:)
1555 SELECT CASE (eval_type)
1561 DEALLOCATE (tmp_dist)
1563 mepos = para_env%mepos
1564 my_process_id = para_env%mepos*n_threads + i_thread
1565 nbins = load_balance_parameter%nbins
1567 ALLOCATE (bin_histogram(n_processes, 2))
1571 SELECT CASE (eval_type)
1573 my_bin_size =
SIZE(x_data%distribution_energy)
1575 my_bin_size =
SIZE(x_data%distribution_forces)
1577 bin_histogram(my_process_id + 1, 1) = my_bin_size
1580 CALL para_env%sum(bin_histogram(:, 1))
1581 bin_histogram(1, 2) = bin_histogram(1, 1)
1582 DO iprocess = 2, n_processes
1583 bin_histogram(iprocess, 2) = bin_histogram(iprocess - 1, 2) + bin_histogram(iprocess, 1)
1586 max_bin_size = maxval(bin_histogram(para_env%mepos*n_threads + 1:para_env%mepos*n_threads + n_threads, 1))
1587 CALL para_env%max(max_bin_size)
1590 ALLOCATE (binned_dist(my_bin_size))
1592 SELECT CASE (eval_type)
1594 binned_dist = x_data%distribution_energy
1596 binned_dist = x_data%distribution_forces
1599 DO ibin = 1, my_bin_size
1600 IF (binned_dist(ibin)%number_of_atom_quartets == 0)
THEN
1601 binned_dist(ibin)%cost = 0
1603 SELECT CASE (eval_type)
1605 IF (.NOT. load_balance_parameter%rtp_redistribute)
THEN
1606 binned_dist(ibin)%cost = int((binned_dist(ibin)%time_first_scf + &
1607 binned_dist(ibin)%time_other_scf)*10000.0_dp,
int_8)
1609 binned_dist(ibin)%cost = int((binned_dist(ibin)%time_other_scf)*10000.0_dp,
int_8)
1612 binned_dist(ibin)%cost = int((binned_dist(ibin)%time_forces)*10000.0_dp,
int_8)
1619 ALLOCATE (cost_matrix(ncpu*nbins*n_threads))
1621 ALLOCATE (sendbuffer(max_bin_size*n_threads))
1622 ALLOCATE (recbuffer(max_bin_size*n_threads))
1625 my_global_start_idx = bin_histogram(my_process_id + 1, 2) - my_bin_size
1626 icpu = para_env%mepos + 1
1627 DO i = 1, my_bin_size
1628 cost_matrix(my_global_start_idx + i) = binned_dist(i)%cost
1631 mepos = para_env%mepos
1634 ALLOCATE (bins_per_rank(ncpu))
1637 bins_per_rank(icpu) = sum(bin_histogram((icpu - 1)*n_threads + 1:(icpu - 1)*n_threads + n_threads, 1))
1639 sendbuffer(1:bins_per_rank(para_env%mepos + 1)) = &
1640 cost_matrix(my_global_start_idx + 1:my_global_start_idx + bins_per_rank(para_env%mepos + 1))
1642 dest =
modulo(mepos + 1, ncpu)
1643 source =
modulo(mepos - 1, ncpu)
1645 CALL para_env%sync()
1646 DO icpu = 0, ncpu - 1
1647 IF (icpu /= ncpu - 1)
THEN
1648 CALL para_env%isendrecv(sendbuffer, dest, recbuffer, source, &
1651 data_from =
modulo(mepos - icpu, ncpu)
1652 start_idx = sum(bins_per_rank(1:data_from + 1)) - bins_per_rank(data_from + 1) + 1
1653 end_idx = start_idx + bins_per_rank(data_from + 1) - 1
1654 cost_matrix(start_idx:end_idx) = sendbuffer(1:end_idx - start_idx + 1)
1656 IF (icpu /= ncpu - 1)
THEN
1659 swapbuffer => sendbuffer
1660 sendbuffer => recbuffer
1661 recbuffer => swapbuffer
1663 DEALLOCATE (recbuffer, sendbuffer)
1665 CALL para_env%sync()
1668 ALLOCATE (local_cost_matrix(
SIZE(cost_matrix, 1)))
1669 local_cost_matrix = cost_matrix
1671 ALLOCATE (shm_distribution_vector(ncpu*nbins*n_threads))
1672 CALL optimize_distribution(ncpu*nbins*n_threads, ncpu*n_threads, local_cost_matrix, &
1673 shm_distribution_vector, x_data%load_balance_parameter%do_randomize)
1675 ALLOCATE (full_dist(ncpu*n_threads, max_bin_size))
1677 full_dist(:, :)%istart = 0_int_8
1678 full_dist(:, :)%number_of_atom_quartets = 0_int_8
1679 full_dist(:, :)%cost = 0_int_8
1680 full_dist(:, :)%time_first_scf = 0.0_dp
1681 full_dist(:, :)%time_other_scf = 0.0_dp
1682 full_dist(:, :)%time_forces = 0.0_dp
1686 mepos = para_env%mepos + 1
1687 full_dist((mepos - 1)*n_threads + i_thread + 1, 1:my_bin_size) = binned_dist(1:my_bin_size)
1690 ALLOCATE (sendbuffer(3*max_bin_size*n_threads))
1691 ALLOCATE (recbuffer(3*max_bin_size*n_threads))
1692 mepos = para_env%mepos
1694 DO i = 1, max_bin_size
1695 sendbuffer((j - 1)*3*max_bin_size + (i - 1)*3 + 1) = full_dist(mepos*n_threads + j, i)%istart
1696 sendbuffer((j - 1)*3*max_bin_size + (i - 1)*3 + 2) = full_dist(mepos*n_threads + j, i)%number_of_atom_quartets
1697 sendbuffer((j - 1)*3*max_bin_size + (i - 1)*3 + 3) = full_dist(mepos*n_threads + j, i)%cost
1700 dest =
modulo(mepos + 1, ncpu)
1701 source =
modulo(mepos - 1, ncpu)
1703 CALL para_env%sync()
1704 DO icpu = 0, ncpu - 1
1705 IF (icpu /= ncpu - 1)
THEN
1706 CALL para_env%isendrecv(sendbuffer, dest, recbuffer, source, &
1709 data_from =
modulo(mepos - icpu, ncpu)
1711 DO i = 1, max_bin_size
1712 full_dist(data_from*n_threads + j, i)%istart = sendbuffer((j - 1)*3*max_bin_size + (i - 1)*3 + 1)
1713 full_dist(data_from*n_threads + j, i)%number_of_atom_quartets = sendbuffer((j - 1)*3*max_bin_size + (i - 1)*3 + 2)
1714 full_dist(data_from*n_threads + j, i)%cost = sendbuffer((j - 1)*3*max_bin_size + (i - 1)*3 + 3)
1718 IF (icpu /= ncpu - 1)
THEN
1721 swapbuffer => sendbuffer
1722 sendbuffer => recbuffer
1723 recbuffer => swapbuffer
1726 DEALLOCATE (recbuffer, sendbuffer)
1727 CALL para_env%sync()
1731 ALLOCATE (tmp_pos(ncpu*n_threads))
1733 ALLOCATE (tmp_dist(nbins*ncpu*n_threads))
1735 tmp_dist(:)%istart = 0_int_8
1736 tmp_dist(:)%number_of_atom_quartets = 0_int_8
1737 tmp_dist(:)%cost = 0_int_8
1738 tmp_dist(:)%time_first_scf = 0.0_dp
1739 tmp_dist(:)%time_other_scf = 0.0_dp
1740 tmp_dist(:)%time_forces = 0.0_dp
1742 mepos = my_process_id + 1
1743 DO icpu = 1, n_processes
1744 DO i = 1, bin_histogram(icpu, 1)
1745 IF (shm_distribution_vector(bin_histogram(icpu, 2) - bin_histogram(icpu, 1) + i) == mepos)
THEN
1746 tmp_dist(tmp_pos(mepos)) = full_dist(icpu, i)
1747 tmp_pos(mepos) = tmp_pos(mepos) + 1
1753 NULLIFY (ptr_to_tmp_dist)
1754 mepos = my_process_id + 1
1755 ptr_to_tmp_dist => tmp_dist(1:tmp_pos(mepos) - 1)
1756 SELECT CASE (eval_type)
1765 DEALLOCATE (full_dist, cost_matrix, shm_distribution_vector)
1766 DEALLOCATE (bins_per_rank, bin_histogram)
1769 DEALLOCATE (tmp_dist, tmp_pos)
1770 DEALLOCATE (binned_dist, local_cost_matrix)
1774 CALL timestop(handle)
1800 FUNCTION cost_model(nsa, nsb, nsc, nsd, npgfa, npgfb, npgfc, npgfd, ratio, p1, p2, p3)
RESULT(res)
1801 REAL(kind=
dp) :: estimate1, estimate2, estimate, ratio, switch, mu, sigma
1802 INTEGER(KIND=int_8) :: res
1803 REAL(kind=
dp),
INTENT(IN) :: p1(12), p2(12), p3(2)
1805 INTEGER :: nsa, nsb, nsc, nsd, npgfa, npgfb, npgfc, npgfd
1807 estimate1 = estimate_basic(p1)
1808 estimate2 = estimate_basic(p2)
1809 mu = log(abs(1.0e6_dp*p3(1)) + 1)
1810 sigma = p3(2)*0.1_dp*mu
1811 switch = 1.0_dp/(1.0_dp + exp((log(estimate1) - mu)/sigma))
1812 estimate = estimate1*(1.0_dp - switch) + estimate2*switch
1813 res = int(estimate*0.001_dp, kind=
int_8) + 1
1822 REAL(kind=
dp)
FUNCTION estimate_basic(p)
RESULT(res)
1823 REAL(kind=
dp) :: p(12)
1825 REAL(kind=
dp) :: p1, p10, p11, p12, p2, p3, p4, p5, p6, &
1828 p1 = p(1); p2 = p(2); p3 = p(3); p4 = p(4)
1829 p5 = p(5); p6 = p(6); p7 = p(7); p8 = p(8)
1830 p9 = p(9); p10 = p(10); p11 = p(11); p12 = p(12)
1831 res = poly2(nsa, p1, p2, p3)*poly2(nsb, p1, p2, p3)*poly2(nsc, p1, p2, p3)*poly2(nsd, p1, p2, p3)* &
1832 poly2(npgfa, p4, p5, p6)*poly2(npgfb, p4, p5, p6)*poly2(npgfc, p4, p5, p6)* &
1833 poly2(npgfd, p4, p5, p6)*exp(-p7*ratio + p8*ratio**2) + &
1834 1000.0_dp*p9 + poly2(nsa, p10, p11, p12)*poly2(nsb, p10, p11, p12)*poly2(nsc, p10, p11, p12)*poly2(nsd, p10, p11, p12)
1836 END FUNCTION estimate_basic
1846 REAL(kind=
dp)
FUNCTION poly2(x, a0, a1, a2)
1847 INTEGER,
INTENT(IN) :: x
1848 REAL(kind=
dp),
INTENT(IN) :: a0, a1, a2
1851 r = real(x, kind=
dp)
1852 poly2 = a0 + (a1 + a2*r)*r
1867 SUBROUTINE optimize_distribution(total_number_of_bins, number_of_processes, bin_costs, &
1868 distribution_vector, do_randomize)
1869 INTEGER :: total_number_of_bins, number_of_processes
1870 INTEGER(int_8),
DIMENSION(:),
POINTER :: bin_costs
1871 INTEGER,
DIMENSION(:),
POINTER :: distribution_vector
1872 LOGICAL,
INTENT(IN) :: do_randomize
1874 INTEGER :: i, itmp, j, nstep
1875 INTEGER(int_8),
DIMENSION(:),
POINTER :: my_cost_cpu, tmp_cost, tmp_cpu_cost
1876 INTEGER,
DIMENSION(:),
POINTER :: tmp_cpu_index, tmp_index
1879 nstep = max(1, int(number_of_processes)/2)
1881 ALLOCATE (tmp_cost(total_number_of_bins))
1882 ALLOCATE (tmp_index(total_number_of_bins))
1883 ALLOCATE (tmp_cpu_cost(number_of_processes))
1884 ALLOCATE (tmp_cpu_index(number_of_processes))
1885 ALLOCATE (my_cost_cpu(number_of_processes))
1886 tmp_cost = bin_costs
1888 CALL sort(tmp_cost, total_number_of_bins, tmp_index)
1898 IF (do_randomize)
THEN
1903 DO i = total_number_of_bins, 1, -nstep
1904 tmp_cpu_cost = my_cost_cpu
1905 CALL sort(tmp_cpu_cost, int(number_of_processes), tmp_cpu_index)
1906 IF (do_randomize)
THEN
1907 CALL rng_stream%shuffle(tmp_cpu_index(1:min(i, nstep)))
1909 DO j = 1, min(i, nstep)
1910 itmp = tmp_cpu_index(j)
1911 distribution_vector(tmp_index(i - j + 1)) = itmp
1912 my_cost_cpu(itmp) = my_cost_cpu(itmp) + bin_costs(tmp_index(i - j + 1))
1916 DEALLOCATE (tmp_cost, tmp_index, tmp_cpu_cost)
1917 DEALLOCATE (tmp_cpu_index, my_cost_cpu)
1918 END SUBROUTINE optimize_distribution
1933 PURE FUNCTION get_1d_idx(i, j, N)
1934 INTEGER,
INTENT(IN) :: i, j
1935 INTEGER(int_8),
INTENT(IN) :: n
1936 INTEGER(int_8) :: get_1d_idx
1938 INTEGER(int_8) :: min_ij
1941 get_1d_idx = min_ij*n + max(i, j) - (min_ij - 1)*min_ij/2 - n
1943 END FUNCTION get_1d_idx
1982 FUNCTION estimate_block_cost(natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
1983 iatom_start, iatom_end, jatom_start, jatom_end, &
1984 katom_start, katom_end, latom_start, latom_end, &
1986 coeffs_set, coeffs_kind, &
1987 is_assoc_atomic_block_global, do_periodic, &
1988 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
1990 do_p_screening, map_atom_to_kind_atom, eval_type, &
1991 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, &
1994 INTEGER,
INTENT(IN) :: natom, nkind
1997 INTEGER,
INTENT(IN) :: iatom_start, iatom_end, jatom_start, &
1998 jatom_end, katom_start, katom_end, &
1999 latom_start, latom_end
2001 TYPE(hfx_screen_coeff_type), &
2002 DIMENSION(:, :, :, :),
POINTER :: coeffs_set
2003 TYPE(hfx_screen_coeff_type), &
2004 DIMENSION(nkind, nkind) :: coeffs_kind
2005 INTEGER,
DIMENSION(:, :) :: is_assoc_atomic_block_global
2006 LOGICAL :: do_periodic
2007 INTEGER :: kind_of(*)
2009 TYPE(
hfx_p_kind),
DIMENSION(:),
POINTER :: pmax_set
2010 REAL(
dp),
DIMENSION(:, :),
POINTER :: pmax_atom
2011 REAL(
dp) :: pmax_blocks
2013 LOGICAL,
INTENT(IN) :: do_p_screening
2014 INTEGER,
DIMENSION(:),
POINTER :: map_atom_to_kind_atom
2015 INTEGER,
INTENT(IN) :: eval_type
2016 REAL(
dp) :: log10_eps_schwarz, log_2, &
2018 LOGICAL,
INTENT(IN) :: use_virial
2019 LOGICAL,
DIMENSION(natom, natom) :: atomic_pair_list
2020 INTEGER(int_8) :: estimate_block_cost
2022 INTEGER :: i_list_ij, i_list_kl, i_set_list_ij, i_set_list_ij_start, i_set_list_ij_stop, &
2023 i_set_list_kl, i_set_list_kl_start, i_set_list_kl_stop, iatom, ikind, iset, jatom, jkind, &
2024 jset, katom, kind_kind_idx, kkind, kset, latom, lkind, lset, swap_id
2025 INTEGER,
DIMENSION(:),
POINTER :: npgfa, npgfb, npgfc, npgfd, nsgfa, &
2027 REAL(
dp) :: actual_pmax_atom, cost_tmp, max_val1, &
2028 max_val2, pmax_entry, rab2, rcd2, &
2029 screen_kind_ij, screen_kind_kl
2030 REAL(
dp),
DIMENSION(:, :),
POINTER :: ptr_p_1, ptr_p_2, ptr_p_3, ptr_p_4
2032 estimate_block_cost = 0_int_8
2034 CALL build_pair_list(natom, list_ij, set_list_ij, iatom_start, iatom_end, jatom_start, jatom_end, &
2035 kind_of, basis_parameter, particle_set, &
2036 do_periodic, coeffs_set, coeffs_kind, coeffs_kind_max0, &
2037 log10_eps_schwarz, cell, pmax_blocks, atomic_pair_list)
2039 CALL build_pair_list(natom, list_kl, set_list_kl, katom_start, katom_end, latom_start, latom_end, &
2040 kind_of, basis_parameter, particle_set, &
2041 do_periodic, coeffs_set, coeffs_kind, coeffs_kind_max0, &
2042 log10_eps_schwarz, cell, pmax_blocks, atomic_pair_list)
2044 DO i_list_ij = 1, list_ij%n_element
2045 iatom = list_ij%elements(i_list_ij)%pair(1)
2046 jatom = list_ij%elements(i_list_ij)%pair(2)
2047 i_set_list_ij_start = list_ij%elements(i_list_ij)%set_bounds(1)
2048 i_set_list_ij_stop = list_ij%elements(i_list_ij)%set_bounds(2)
2049 ikind = list_ij%elements(i_list_ij)%kind_pair(1)
2050 jkind = list_ij%elements(i_list_ij)%kind_pair(2)
2051 rab2 = list_ij%elements(i_list_ij)%dist2
2053 nsgfa => basis_parameter(ikind)%nsgf
2054 nsgfb => basis_parameter(jkind)%nsgf
2055 npgfa => basis_parameter(ikind)%npgf
2056 npgfb => basis_parameter(jkind)%npgf
2058 DO i_list_kl = 1, list_kl%n_element
2060 katom = list_kl%elements(i_list_kl)%pair(1)
2061 latom = list_kl%elements(i_list_kl)%pair(2)
2063 IF (.NOT. (katom + latom <= iatom + jatom)) cycle
2064 IF (((iatom + jatom) == (katom + latom)) .AND. (katom < iatom)) cycle
2067 IF (.NOT. use_virial)
THEN
2068 IF ((iatom == jatom .AND. iatom == katom .AND. iatom == latom)) cycle
2072 i_set_list_kl_start = list_kl%elements(i_list_kl)%set_bounds(1)
2073 i_set_list_kl_stop = list_kl%elements(i_list_kl)%set_bounds(2)
2074 kkind = list_kl%elements(i_list_kl)%kind_pair(1)
2075 lkind = list_kl%elements(i_list_kl)%kind_pair(2)
2076 rcd2 = list_kl%elements(i_list_kl)%dist2
2078 nsgfc => basis_parameter(kkind)%nsgf
2079 nsgfd => basis_parameter(lkind)%nsgf
2080 npgfc => basis_parameter(kkind)%npgf
2081 npgfd => basis_parameter(lkind)%npgf
2083 IF (do_p_screening)
THEN
2084 actual_pmax_atom = max(pmax_atom(katom, iatom), &
2085 pmax_atom(latom, jatom), &
2086 pmax_atom(latom, iatom), &
2087 pmax_atom(katom, jatom))
2089 actual_pmax_atom = 0.0_dp
2092 screen_kind_ij = coeffs_kind(jkind, ikind)%x(1)*rab2 + &
2093 coeffs_kind(jkind, ikind)%x(2)
2094 screen_kind_kl = coeffs_kind(lkind, kkind)%x(1)*rcd2 + &
2095 coeffs_kind(lkind, kkind)%x(2)
2096 IF (screen_kind_ij + screen_kind_kl + actual_pmax_atom < log10_eps_schwarz) cycle
2098 IF (.NOT. (is_assoc_atomic_block_global(latom, iatom) >= 1 .AND. &
2099 is_assoc_atomic_block_global(katom, iatom) >= 1 .AND. &
2100 is_assoc_atomic_block_global(katom, jatom) >= 1 .AND. &
2101 is_assoc_atomic_block_global(latom, jatom) >= 1)) cycle
2103 IF (do_p_screening)
THEN
2104 SELECT CASE (eval_type)
2107 kind_kind_idx = int(get_1d_idx(kkind, ikind, int(nkind,
int_8)))
2108 IF (ikind >= kkind)
THEN
2109 ptr_p_1 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2110 map_atom_to_kind_atom(katom), &
2111 map_atom_to_kind_atom(iatom))
2113 ptr_p_1 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2114 map_atom_to_kind_atom(iatom), &
2115 map_atom_to_kind_atom(katom))
2116 swap_id = swap_id + 1
2118 kind_kind_idx = int(get_1d_idx(lkind, jkind, int(nkind,
int_8)))
2119 IF (jkind >= lkind)
THEN
2120 ptr_p_2 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2121 map_atom_to_kind_atom(latom), &
2122 map_atom_to_kind_atom(jatom))
2124 ptr_p_2 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2125 map_atom_to_kind_atom(jatom), &
2126 map_atom_to_kind_atom(latom))
2127 swap_id = swap_id + 2
2129 kind_kind_idx = int(get_1d_idx(lkind, ikind, int(nkind,
int_8)))
2130 IF (ikind >= lkind)
THEN
2131 ptr_p_3 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2132 map_atom_to_kind_atom(latom), &
2133 map_atom_to_kind_atom(iatom))
2135 ptr_p_3 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2136 map_atom_to_kind_atom(iatom), &
2137 map_atom_to_kind_atom(latom))
2138 swap_id = swap_id + 4
2140 kind_kind_idx = int(get_1d_idx(kkind, jkind, int(nkind,
int_8)))
2141 IF (jkind >= kkind)
THEN
2142 ptr_p_4 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2143 map_atom_to_kind_atom(katom), &
2144 map_atom_to_kind_atom(jatom))
2146 ptr_p_4 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2147 map_atom_to_kind_atom(jatom), &
2148 map_atom_to_kind_atom(katom))
2149 swap_id = swap_id + 8
2153 kind_kind_idx = int(get_1d_idx(kkind, ikind, int(nkind,
int_8)))
2154 IF (ikind >= kkind)
THEN
2155 ptr_p_1 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2156 map_atom_to_kind_atom(katom), &
2157 map_atom_to_kind_atom(iatom))
2159 ptr_p_1 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2160 map_atom_to_kind_atom(iatom), &
2161 map_atom_to_kind_atom(katom))
2162 swap_id = swap_id + 1
2164 kind_kind_idx = int(get_1d_idx(lkind, jkind, int(nkind,
int_8)))
2165 IF (jkind >= lkind)
THEN
2166 ptr_p_2 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2167 map_atom_to_kind_atom(latom), &
2168 map_atom_to_kind_atom(jatom))
2170 ptr_p_2 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2171 map_atom_to_kind_atom(jatom), &
2172 map_atom_to_kind_atom(latom))
2173 swap_id = swap_id + 2
2175 kind_kind_idx = int(get_1d_idx(lkind, ikind, int(nkind,
int_8)))
2176 IF (ikind >= lkind)
THEN
2177 ptr_p_3 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2178 map_atom_to_kind_atom(latom), &
2179 map_atom_to_kind_atom(iatom))
2181 ptr_p_3 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2182 map_atom_to_kind_atom(iatom), &
2183 map_atom_to_kind_atom(latom))
2184 swap_id = swap_id + 4
2186 kind_kind_idx = int(get_1d_idx(kkind, jkind, int(nkind,
int_8)))
2187 IF (jkind >= kkind)
THEN
2188 ptr_p_4 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2189 map_atom_to_kind_atom(katom), &
2190 map_atom_to_kind_atom(jatom))
2192 ptr_p_4 => pmax_set(kind_kind_idx)%p_kind(:, :, &
2193 map_atom_to_kind_atom(jatom), &
2194 map_atom_to_kind_atom(katom))
2195 swap_id = swap_id + 8
2200 DO i_set_list_ij = i_set_list_ij_start, i_set_list_ij_stop
2201 iset = set_list_ij(i_set_list_ij)%pair(1)
2202 jset = set_list_ij(i_set_list_ij)%pair(2)
2204 max_val1 = coeffs_set(jset, iset, jkind, ikind)%x(1)*rab2 + &
2205 coeffs_set(jset, iset, jkind, ikind)%x(2)
2207 IF (max_val1 + screen_kind_kl + actual_pmax_atom < log10_eps_schwarz) cycle
2208 DO i_set_list_kl = i_set_list_kl_start, i_set_list_kl_stop
2209 kset = set_list_kl(i_set_list_kl)%pair(1)
2210 lset = set_list_kl(i_set_list_kl)%pair(2)
2212 max_val2 = max_val1 + (coeffs_set(lset, kset, lkind, kkind)%x(1)*rcd2 + &
2213 coeffs_set(lset, kset, lkind, kkind)%x(2))
2215 IF (max_val2 + actual_pmax_atom < log10_eps_schwarz) cycle
2216 IF (do_p_screening)
THEN
2217 CALL get_pmax_val(ptr_p_1, ptr_p_2, ptr_p_3, ptr_p_4, &
2218 iset, jset, kset, lset, &
2219 pmax_entry, swap_id)
2221 pmax_entry = log_2 + pmax_entry
2226 max_val2 = max_val2 + pmax_entry
2227 IF (max_val2 < log10_eps_schwarz) cycle
2228 SELECT CASE (eval_type)
2230 cost_tmp =
cost_model(nsgfa(iset), nsgfb(jset), nsgfc(kset), nsgfd(lset), &
2231 npgfa(iset), npgfb(jset), npgfc(kset), npgfd(lset), &
2232 max_val2/log10_eps_schwarz, &
2234 estimate_block_cost = estimate_block_cost + int(cost_tmp, kind=
int_8)
2236 cost_tmp =
cost_model(nsgfa(iset), nsgfb(jset), nsgfc(kset), nsgfd(lset), &
2237 npgfa(iset), npgfb(jset), npgfc(kset), npgfd(lset), &
2238 max_val2/log10_eps_schwarz, &
2239 p1_forces, p2_forces, p3_forces)
2240 estimate_block_cost = estimate_block_cost + int(cost_tmp, kind=
int_8)
2247 END FUNCTION estimate_block_cost
2281 SUBROUTINE init_blocks(nkind, para_env, natom, block_size, nblock, blocks, &
2282 list_ij, list_kl, set_list_ij, set_list_kl, &
2284 coeffs_set, coeffs_kind, &
2285 is_assoc_atomic_block_global, do_periodic, &
2286 kind_of, basis_parameter, pmax_set, pmax_atom, &
2287 pmax_blocks, cell, &
2288 do_p_screening, map_atom_to_kind_atom, eval_type, &
2289 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, &
2292 INTEGER,
INTENT(IN) :: nkind
2294 INTEGER :: natom, block_size, nblock
2299 TYPE(hfx_screen_coeff_type), &
2300 DIMENSION(:, :, :, :),
POINTER :: coeffs_set
2301 TYPE(hfx_screen_coeff_type),
DIMENSION(:, :), &
2302 POINTER :: coeffs_kind
2303 INTEGER,
DIMENSION(:, :) :: is_assoc_atomic_block_global
2304 LOGICAL :: do_periodic
2305 INTEGER :: kind_of(*)
2307 TYPE(
hfx_p_kind),
DIMENSION(:),
POINTER :: pmax_set
2308 REAL(
dp),
DIMENSION(:, :),
POINTER :: pmax_atom
2309 REAL(
dp) :: pmax_blocks
2311 LOGICAL,
INTENT(IN) :: do_p_screening
2312 INTEGER,
DIMENSION(:),
POINTER :: map_atom_to_kind_atom
2313 INTEGER,
INTENT(IN) :: eval_type
2314 REAL(
dp) :: log10_eps_schwarz, log_2, &
2316 LOGICAL,
INTENT(IN) :: use_virial
2317 LOGICAL,
DIMENSION(natom, natom) :: atomic_pair_list
2319 INTEGER :: atom_block, i, iatom_block, iatom_end, &
2320 iatom_start, my_cpu_rank, ncpus
2322 DO atom_block = 0, nblock - 1
2323 iatom_block =
modulo(atom_block, nblock) + 1
2324 iatom_start = (iatom_block - 1)*block_size + 1
2325 iatom_end = min(iatom_block*block_size, natom)
2326 blocks(atom_block + 1)%istart = iatom_start
2327 blocks(atom_block + 1)%iend = iatom_end
2328 blocks(atom_block + 1)%cost = 0_int_8
2331 ncpus = para_env%num_pe
2332 my_cpu_rank = para_env%mepos
2334 IF (
modulo(i, ncpus) /= my_cpu_rank)
THEN
2335 blocks(i)%istart = 0
2339 iatom_start = blocks(i)%istart
2340 iatom_end = blocks(i)%iend
2341 blocks(i)%cost = estimate_block_cost(natom, nkind, list_ij, list_kl, set_list_ij, set_list_kl, &
2342 iatom_start, iatom_end, iatom_start, iatom_end, &
2343 iatom_start, iatom_end, iatom_start, iatom_end, &
2345 coeffs_set, coeffs_kind, &
2346 is_assoc_atomic_block_global, do_periodic, &
2347 kind_of, basis_parameter, pmax_set, pmax_atom, pmax_blocks, &
2349 do_p_screening, map_atom_to_kind_atom, eval_type, &
2350 log10_eps_schwarz, log_2, coeffs_kind_max0, use_virial, atomic_pair_list)
2353 END SUBROUTINE init_blocks
2369 INTEGER,
INTENT(IN) :: iw, n_threads, i_thread, eval_type
2371 INTEGER :: i, j, k, my_rank, nbins, nranks, &
2373 INTEGER(int_8) :: avg_bin, avg_rank, max_bin, max_rank, &
2374 min_bin, min_rank, sum_bin, sum_rank
2375 INTEGER(int_8),
ALLOCATABLE,
DIMENSION(:) :: buffer, buffer_in, buffer_out, summary
2376 INTEGER(int_8),
ALLOCATABLE,
DIMENSION(:),
SAVE :: shm_cost_vector
2377 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: bins_per_rank, rdispl, sort_idx
2378 INTEGER,
ALLOCATABLE,
DIMENSION(:),
SAVE :: shm_bins_per_rank, shm_displ
2380 SELECT CASE (eval_type)
2382 nbins =
SIZE(x_data%distribution_energy)
2384 nbins =
SIZE(x_data%distribution_forces)
2388 ALLOCATE (shm_bins_per_rank(n_threads))
2389 ALLOCATE (shm_displ(n_threads + 1))
2393 shm_bins_per_rank(i_thread + 1) = nbins
2397 nbins = nbins + shm_bins_per_rank(i)
2399 my_rank = para_env%mepos
2400 nranks = para_env%num_pe
2404 ALLOCATE (bins_per_rank(nranks))
2407 bins_per_rank(my_rank + 1) = nbins
2409 CALL para_env%sum(bins_per_rank)
2413 total_bins = total_bins + bins_per_rank(i)
2416 ALLOCATE (shm_cost_vector(2*total_bins))
2417 shm_cost_vector = -1_int_8
2420 shm_displ(i) = shm_displ(i - 1) + shm_bins_per_rank(i - 1)
2422 shm_displ(n_threads + 1) = nbins + 1
2426 SELECT CASE (eval_type)
2428 DO i = shm_displ(i_thread + 1), shm_displ(i_thread + 2) - 1
2430 shm_cost_vector(2*(i - 1) + 1) = x_data%distribution_energy(j)%cost
2431 shm_cost_vector(2*i) = int(x_data%distribution_energy(j)%time_first_scf*10000.0_dp, kind=
int_8)
2434 DO i = shm_displ(i_thread + 1), shm_displ(i_thread + 2) - 1
2436 shm_cost_vector(2*(i - 1) + 1) = x_data%distribution_forces(j)%cost
2437 shm_cost_vector(2*i) = int(x_data%distribution_forces(j)%time_forces*10000.0_dp, kind=
int_8)
2443 ALLOCATE (rdispl(nranks))
2444 bins_per_rank(:) = bins_per_rank(:)*2
2447 rdispl(i) = rdispl(i - 1) + bins_per_rank(i - 1)
2450 ALLOCATE (buffer_in(2*nbins))
2451 ALLOCATE (buffer_out(2*total_bins))
2454 buffer_in(2*(i - 1) + 1) = shm_cost_vector(2*(i - 1) + 1)
2455 buffer_in(2*i) = shm_cost_vector(2*i)
2458 CALL para_env%gatherv(buffer_in, buffer_out, bins_per_rank, rdispl)
2462 ALLOCATE (summary(2*nranks))
2465 WRITE (iw,
'( /, 1X, 79("-") )')
2466 WRITE (iw,
'( " -", 77X, "-" )')
2467 SELECT CASE (eval_type)
2469 WRITE (iw,
'( " -", 20X, A, 19X, "-" )')
' HFX LOAD BALANCE INFORMATION - ENERGY '
2471 WRITE (iw,
'( " -", 20X, A, 19X, "-" )')
' HFX LOAD BALANCE INFORMATION - FORCES '
2473 WRITE (iw,
'( " -", 77X, "-" )')
2474 WRITE (iw,
'( 1X, 79("-") )')
2476 WRITE (iw, fmt=
"(T3,A,T15,A,T35,A,T55,A)")
"MPI RANK",
"BIN #",
"EST cost",
"Processing time [s]"
2477 WRITE (iw,
'( 1X, 79("-"), / )')
2480 DO j = 1, bins_per_rank(i)/2
2482 WRITE (iw, fmt=
"(T6,I5,T15,I5,T27,I16,T55,F19.8)") &
2483 i - 1, j, buffer_out(2*(k - 1) + 1), real(buffer_out(2*k),
dp)/10000.0_dp
2484 summary(2*(i - 1) + 1) = summary(2*(i - 1) + 1) + buffer_out(2*(k - 1) + 1)
2485 summary(2*i) = summary(2*i) + buffer_out(2*k)
2491 min_bin = huge(min_bin)
2493 DO i = 1, total_bins
2494 sum_bin = sum_bin + buffer_out(2*i)
2495 max_bin = max(max_bin, buffer_out(2*i))
2496 min_bin = min(min_bin, buffer_out(2*i))
2498 avg_bin = sum_bin/total_bins
2501 min_rank = huge(min_rank)
2504 sum_rank = sum_rank + summary(2*i)
2505 max_rank = max(max_rank, summary(2*i))
2506 min_rank = min(min_rank, summary(2*i))
2508 avg_rank = sum_rank/nranks
2510 WRITE (iw, fmt=
'(/,T3,A,/)')
"SUMMARY:"
2511 WRITE (iw, fmt=
"(T3,A,T35,F19.8)")
"Max bin", real(max_bin,
dp)/10000.0_dp
2512 WRITE (iw, fmt=
"(T3,A,T35,F19.8)")
"Min bin", real(min_bin,
dp)/10000.0_dp
2513 WRITE (iw, fmt=
"(T3,A,T35,F19.8)")
"Sum bin", real(sum_bin,
dp)/10000.0_dp
2514 WRITE (iw, fmt=
"(T3,A,T35,F19.8,/)")
"Avg bin", real(avg_bin,
dp)/10000.0_dp
2515 WRITE (iw, fmt=
"(T3,A,T35,F19.8)")
"Max rank", real(max_rank,
dp)/10000.0_dp
2516 WRITE (iw, fmt=
"(T3,A,T35,F19.8)")
"Min rank", real(min_rank,
dp)/10000.0_dp
2517 WRITE (iw, fmt=
"(T3,A,T35,F19.8)")
"Sum rank", real(sum_rank,
dp)/10000.0_dp
2518 WRITE (iw, fmt=
"(T3,A,T35,F19.8,/)")
"Avg rank", real(avg_rank,
dp)/10000.0_dp
2520 ALLOCATE (buffer(nranks))
2521 ALLOCATE (sort_idx(nranks))
2524 buffer(i) = summary(2*i)
2527 CALL sort(buffer, nranks, sort_idx)
2529 WRITE (iw, fmt=
"(T3,A,T35,A,T55,A,/)")
"MPI RANK",
"EST cost",
"Processing time [s]"
2530 DO i = nranks, 1, -1
2531 WRITE (iw, fmt=
"(T6,I5,T27,I16,T55,F19.8)") sort_idx(i) - 1, summary(2*(sort_idx(i) - 1) + 1), real(buffer(i),
dp)/10000.0_dp
2534 DEALLOCATE (summary, buffer, sort_idx)
2538 DEALLOCATE (buffer_in, buffer_out, rdispl)
2540 CALL para_env%sync()
2542 DEALLOCATE (shm_bins_per_rank, shm_displ, shm_cost_vector)
2569PURE SUBROUTINE get_pmax_val(ptr_p_1, ptr_p_2, ptr_p_3, ptr_p_4, iset, jset, kset, lset, pmax_val, swap_id)
2571 REAL(
dp),
DIMENSION(:, :),
POINTER :: ptr_p_1, ptr_p_2, ptr_p_3, ptr_p_4
2572 INTEGER,
INTENT(IN) :: iset, jset, kset, lset
2574 REAL(
dp),
INTENT(OUT) :: pmax_val
2575 INTEGER,
INTENT(IN) :: swap_id
2577 REAL(
dp) :: pmax_1, pmax_2, pmax_3, pmax_4
2579 SELECT CASE (swap_id)
2581 pmax_1 = ptr_p_1(kset, iset)
2582 pmax_2 = ptr_p_2(lset, jset)
2583 pmax_3 = ptr_p_3(lset, iset)
2584 pmax_4 = ptr_p_4(kset, jset)
2585 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2587 pmax_1 = ptr_p_1(iset, kset)
2588 pmax_2 = ptr_p_2(lset, jset)
2589 pmax_3 = ptr_p_3(lset, iset)
2590 pmax_4 = ptr_p_4(kset, jset)
2591 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2593 pmax_1 = ptr_p_1(kset, iset)
2594 pmax_2 = ptr_p_2(jset, lset)
2595 pmax_3 = ptr_p_3(lset, iset)
2596 pmax_4 = ptr_p_4(kset, jset)
2597 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2599 pmax_1 = ptr_p_1(iset, kset)
2600 pmax_2 = ptr_p_2(jset, lset)
2601 pmax_3 = ptr_p_3(lset, iset)
2602 pmax_4 = ptr_p_4(kset, jset)
2603 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2605 pmax_1 = ptr_p_1(kset, iset)
2606 pmax_2 = ptr_p_2(lset, jset)
2607 pmax_3 = ptr_p_3(iset, lset)
2608 pmax_4 = ptr_p_4(kset, jset)
2609 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2611 pmax_1 = ptr_p_1(iset, kset)
2612 pmax_2 = ptr_p_2(lset, jset)
2613 pmax_3 = ptr_p_3(iset, lset)
2614 pmax_4 = ptr_p_4(kset, jset)
2615 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2617 pmax_1 = ptr_p_1(kset, iset)
2618 pmax_2 = ptr_p_2(jset, lset)
2619 pmax_3 = ptr_p_3(iset, lset)
2620 pmax_4 = ptr_p_4(kset, jset)
2621 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2623 pmax_1 = ptr_p_1(iset, kset)
2624 pmax_2 = ptr_p_2(jset, lset)
2625 pmax_3 = ptr_p_3(iset, lset)
2626 pmax_4 = ptr_p_4(kset, jset)
2627 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2629 pmax_1 = ptr_p_1(kset, iset)
2630 pmax_2 = ptr_p_2(lset, jset)
2631 pmax_3 = ptr_p_3(lset, iset)
2632 pmax_4 = ptr_p_4(jset, kset)
2633 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2635 pmax_1 = ptr_p_1(iset, kset)
2636 pmax_2 = ptr_p_2(lset, jset)
2637 pmax_3 = ptr_p_3(lset, iset)
2638 pmax_4 = ptr_p_4(jset, kset)
2639 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2641 pmax_1 = ptr_p_1(kset, iset)
2642 pmax_2 = ptr_p_2(jset, lset)
2643 pmax_3 = ptr_p_3(lset, iset)
2644 pmax_4 = ptr_p_4(jset, kset)
2645 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2647 pmax_1 = ptr_p_1(iset, kset)
2648 pmax_2 = ptr_p_2(jset, lset)
2649 pmax_3 = ptr_p_3(lset, iset)
2650 pmax_4 = ptr_p_4(jset, kset)
2651 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2653 pmax_1 = ptr_p_1(kset, iset)
2654 pmax_2 = ptr_p_2(lset, jset)
2655 pmax_3 = ptr_p_3(iset, lset)
2656 pmax_4 = ptr_p_4(jset, kset)
2657 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2659 pmax_1 = ptr_p_1(iset, kset)
2660 pmax_2 = ptr_p_2(lset, jset)
2661 pmax_3 = ptr_p_3(iset, lset)
2662 pmax_4 = ptr_p_4(jset, kset)
2663 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2665 pmax_1 = ptr_p_1(kset, iset)
2666 pmax_2 = ptr_p_2(jset, lset)
2667 pmax_3 = ptr_p_3(iset, lset)
2668 pmax_4 = ptr_p_4(jset, kset)
2669 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2671 pmax_1 = ptr_p_1(iset, kset)
2672 pmax_2 = ptr_p_2(jset, lset)
2673 pmax_3 = ptr_p_3(iset, lset)
2674 pmax_4 = ptr_p_4(jset, kset)
2675 pmax_val = max(pmax_1, pmax_2, pmax_3, pmax_4)
2677 pmax_1 = ptr_p_1(kset, iset)
2678 pmax_2 = ptr_p_2(lset, jset)
2679 pmax_3 = ptr_p_3(lset, iset)
2680 pmax_4 = ptr_p_4(kset, jset)
2681 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2683 pmax_1 = ptr_p_1(iset, kset)
2684 pmax_2 = ptr_p_2(lset, jset)
2685 pmax_3 = ptr_p_3(lset, iset)
2686 pmax_4 = ptr_p_4(kset, jset)
2687 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2689 pmax_1 = ptr_p_1(kset, iset)
2690 pmax_2 = ptr_p_2(jset, lset)
2691 pmax_3 = ptr_p_3(lset, iset)
2692 pmax_4 = ptr_p_4(kset, jset)
2693 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2695 pmax_1 = ptr_p_1(iset, kset)
2696 pmax_2 = ptr_p_2(jset, lset)
2697 pmax_3 = ptr_p_3(lset, iset)
2698 pmax_4 = ptr_p_4(kset, jset)
2699 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2701 pmax_1 = ptr_p_1(kset, iset)
2702 pmax_2 = ptr_p_2(lset, jset)
2703 pmax_3 = ptr_p_3(iset, lset)
2704 pmax_4 = ptr_p_4(kset, jset)
2705 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2707 pmax_1 = ptr_p_1(iset, kset)
2708 pmax_2 = ptr_p_2(lset, jset)
2709 pmax_3 = ptr_p_3(iset, lset)
2710 pmax_4 = ptr_p_4(kset, jset)
2711 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2713 pmax_1 = ptr_p_1(kset, iset)
2714 pmax_2 = ptr_p_2(jset, lset)
2715 pmax_3 = ptr_p_3(iset, lset)
2716 pmax_4 = ptr_p_4(kset, jset)
2717 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2719 pmax_1 = ptr_p_1(iset, kset)
2720 pmax_2 = ptr_p_2(jset, lset)
2721 pmax_3 = ptr_p_3(iset, lset)
2722 pmax_4 = ptr_p_4(kset, jset)
2723 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2725 pmax_1 = ptr_p_1(kset, iset)
2726 pmax_2 = ptr_p_2(lset, jset)
2727 pmax_3 = ptr_p_3(lset, iset)
2728 pmax_4 = ptr_p_4(jset, kset)
2729 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2731 pmax_1 = ptr_p_1(iset, kset)
2732 pmax_2 = ptr_p_2(lset, jset)
2733 pmax_3 = ptr_p_3(lset, iset)
2734 pmax_4 = ptr_p_4(jset, kset)
2735 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2737 pmax_1 = ptr_p_1(kset, iset)
2738 pmax_2 = ptr_p_2(jset, lset)
2739 pmax_3 = ptr_p_3(lset, iset)
2740 pmax_4 = ptr_p_4(jset, kset)
2741 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2743 pmax_1 = ptr_p_1(iset, kset)
2744 pmax_2 = ptr_p_2(jset, lset)
2745 pmax_3 = ptr_p_3(lset, iset)
2746 pmax_4 = ptr_p_4(jset, kset)
2747 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2749 pmax_1 = ptr_p_1(kset, iset)
2750 pmax_2 = ptr_p_2(lset, jset)
2751 pmax_3 = ptr_p_3(iset, lset)
2752 pmax_4 = ptr_p_4(jset, kset)
2753 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2755 pmax_1 = ptr_p_1(iset, kset)
2756 pmax_2 = ptr_p_2(lset, jset)
2757 pmax_3 = ptr_p_3(iset, lset)
2758 pmax_4 = ptr_p_4(jset, kset)
2759 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2761 pmax_1 = ptr_p_1(kset, iset)
2762 pmax_2 = ptr_p_2(jset, lset)
2763 pmax_3 = ptr_p_3(iset, lset)
2764 pmax_4 = ptr_p_4(jset, kset)
2765 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2767 pmax_1 = ptr_p_1(iset, kset)
2768 pmax_2 = ptr_p_2(jset, lset)
2769 pmax_3 = ptr_p_3(iset, lset)
2770 pmax_4 = ptr_p_4(jset, kset)
2771 pmax_val = max(pmax_1 + pmax_2, pmax_3 + pmax_4)
2774END SUBROUTINE get_pmax_val
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
Handles all functions related to the CELL.
Utility routines to open and close files.
subroutine, public open_file(file_name, unit_number, file_status, file_form, file_action, file_position, file_pad, file_access, debug)
Opens a file and returns its logical unit number.
subroutine, public close_file(unit_number, file_status)
Closes an open file given by its logical unit number.
Routines for optimizing load balance between processes in HFX calculations.
real(kind=dp), dimension(12), parameter, public p1_energy
real(kind=dp), dimension(2), parameter, public p3_energy
real(kind=dp), dimension(12), parameter, public p2_energy
subroutine, public collect_load_balance_info(para_env, x_data, iw, n_threads, i_thread, eval_type)
...
subroutine, public hfx_load_balance(x_data, eps_schwarz, particle_set, max_set, para_env, coeffs_set, coeffs_kind, is_assoc_atomic_block_global, do_periodic, load_balance_parameter, kind_of, basis_parameter, pmax_set, pmax_atom, i_thread, n_threads, cell, do_p_screening, map_atom_to_kind_atom, nkind, eval_type, pmax_block, use_virial)
Distributes the computation of eri's to all available processes.
integer(kind=int_8) function, public cost_model(nsa, nsb, nsc, nsd, npgfa, npgfb, npgfc, npgfd, ratio, p1, p2, p3)
estimates the cost of a set quartet with info available at load balance time i.e. without much info o...
subroutine, public hfx_update_load_balance(x_data, para_env, load_balance_parameter, i_thread, n_threads, eval_type)
Cheap way of redistributing the eri's.
Routines for optimizing load balance between processes in HFX calculations.
subroutine, public build_atomic_pair_list(natom, atomic_pair_list, kind_of, basis_parameter, particle_set, do_periodic, coeffs_kind, coeffs_kind_max0, log10_eps_schwarz, cell, blocks)
...
subroutine, public build_pair_list(natom, list, set_list, i_start, i_end, j_start, j_end, kind_of, basis_parameter, particle_set, do_periodic, coeffs_set, coeffs_kind, coeffs_kind_max0, log10_eps_schwarz, cell, pmax_blocks, atomic_pair_list)
...
Types and set/get functions for HFX.
subroutine, public hfx_set_distr_energy(ptr_to_distr, x_data)
This routine stores the data obtained from the load balance routine for the energy
subroutine, public hfx_set_distr_forces(ptr_to_distr, x_data)
This routine stores the data obtained from the load balance routine for the forces
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
Interface to the message passing library MPI.
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
integer, parameter, public uniform
Define the data structure for the particle information.
All kind of helpful little routines.
Type defining parameters related to the simulation cell.
stores some data used in construction of Kohn-Sham matrix
stores all the informations relevant to an mpi environment