39 use mpi_gbl,
only: myrank, mpiint, mpi_mod_allgather, mpi_mod_rotate_cfp_arrays_around_ring, &
62 type,
extends(bstree) :: contractedsymbolicelementvector
65 integer(longint),
allocatable :: electron_integral(:,:)
66 real(wp),
allocatable :: coeffs(:,:,:)
69 logical :: constructed = .false.
70 real(wp) :: threshold = 0.0
71 integer :: num_states_1 = 0
72 integer :: num_states_2 = 0
73 integer :: max_capacity = 0
74 integer :: expand_size = 100
77 procedure,
public :: compare => bstree_compare
80 procedure,
public :: construct
81 procedure,
public :: insert_ijklm_symbol
82 procedure,
public :: insert_symbol
83 procedure,
public :: remove_symbol_at
84 procedure,
public :: is_empty
85 procedure,
public :: clear
86 procedure,
public :: check_same_integral
87 procedure,
public :: get_integral_label
88 procedure,
public :: synchronize_symbols
89 procedure,
public :: estimate_synchronize_cost
90 procedure,
public :: modify_coeff
91 procedure,
public :: get_coefficient
92 procedure,
public :: get_coeff_and_integral
93 procedure,
public :: get_size
94 procedure,
public :: get_num_targets_sym1
95 procedure,
public :: get_num_targets_sym2
96 procedure,
public :: add_symbols
97 procedure,
public :: reduce_symbols
98 procedure,
public :: print => print_symbols
101 procedure,
private :: expand_array
102 procedure,
private :: check_bounds
103 procedure,
public :: destroy
104 procedure,
private :: check_constructed
105 procedure,
private :: synchronize_symbols_ii
108 end type contractedsymbolicelementvector
132 integer function bstree_compare (this, i, j, data)
result (verdict)
134 class(contractedsymbolicelementvector),
intent(in) :: this
135 integer,
intent(in) :: i, j
136 type(c_ptr),
optional,
intent(in) :: data
138 integer(longint) :: ii(
nidx), jj(
nidx)
139 integer(longint),
pointer :: kk(:)
142 if (
present(data))
call c_f_pointer(
data, kk, (/
nidx /))
145 if (i <= 0) then; ii = kk; else; ii = this % electron_integral(:,i);
end if
146 if (j <= 0) then; jj = kk; else; jj = this % electron_integral(:,j);
end if
149 verdict = lexicographical_compare(ii, jj)
178 subroutine construct (this, n1, n2, threshold, initial_size)
179 class(contractedsymbolicelementvector) :: this
180 real(wp),
optional,
intent(in) :: threshold
181 integer,
optional,
intent(in) :: initial_size
183 integer :: err, n1, n2
185 if (
present(threshold))
then
186 this % threshold = threshold
191 this % expand_size = 100
192 this % max_capacity = this % expand_size
193 this % num_states_1 = n1
194 this % num_states_2 = n2
197 allocate(this % electron_integral(
nidx, this % max_capacity), this % coeffs(n1, n2, this % max_capacity), stat = err)
198 call master_memory % track_memory (storage_size(this % electron_integral)/8, &
199 size(this % electron_integral), err,
'CONSYMBOLIC::ELECTRONINT')
200 call master_memory % track_memory(storage_size(this % coeffs)/8, &
201 size(this % coeffs), err,
'CONSYMBOLIC::ELECTRONCOEFF')
203 call mpi_xermsg(
'Contracted_Symbolic_module',
'construct',
'SymbolicVector arrays not allocated', 1, 1)
210 this % constructed = .true.
251 subroutine insert_ijklm_symbol (this, i, j, k, l, m, coeffs, check_same_)
252 class(contractedsymbolicelementvector) :: this
253 integer,
intent(in) :: i, j, k, l, m
254 real(wp),
intent(in) :: coeffs(this % num_states_1, this % num_states_2)
255 logical,
intent(in),
optional :: check_same_
257 integer(longint) :: integral_label(NIDX)
258 logical :: check_same
260 if (
present(check_same_))
then
261 check_same = check_same_
266 call pack_ints(i, j, k, l, m, 0, 0, 0, integral_label)
267 call this%insert_symbol(integral_label, coeffs, check_same)
285 subroutine insert_symbol (this, integral_label, coeffs, check_same_)
286 class(contractedsymbolicelementvector) :: this
287 integer(longint),
intent(in) :: integral_label(NIDX)
288 real(wp),
intent(in) :: coeffs(this % num_states_1, this % num_states_2)
289 logical,
intent(in),
optional :: check_same_
291 integer :: idx = 0, check_idx
292 logical :: check_same
294 if (
present(check_same_))
then
295 check_same = check_same_
303 if (.not. this % check_same_integral(integral_label, idx))
then
305 this % n = this % n + 1
309 if (this % n > this % max_capacity)
then
310 call this % expand_array()
313 this % electron_integral(:,idx) = integral_label(:)
315 this % coeffs(:,:,idx) = 0.0_wp
317 call this % insert(idx)
321 this % coeffs(:,:,idx) = this % coeffs(:,:,idx) + coeffs(:,:)
333 subroutine expand_array (this)
334 class(contractedsymbolicelementvector) :: this
335 integer(longint),
allocatable :: temp_integral(:,:)
336 real(wp),
allocatable :: temp_coeffs(:,:,:)
337 integer :: temp_capacity, ido, err
342 call this % check_constructed
345 temp_capacity = this % max_capacity
347 allocate(temp_integral(
nidx, this % max_capacity), &
348 temp_coeffs(this % num_states_1, this % num_states_2, this % max_capacity), stat = err)
349 call master_memory % track_memory(storage_size(temp_integral)/8,
size(temp_integral), err,
'CONSYMBOLIC::EXP::TEMPINT')
350 call master_memory % track_memory(storage_size(temp_coeffs)/8,
size(temp_coeffs), err,
'CONSYMBOLIC::EXP::TEMPCOEFF')
353 do ido = 1, temp_capacity
354 temp_integral(:,ido) = this % electron_integral(:,ido)
355 temp_coeffs(:,:,ido) = this % coeffs(:,:,ido)
358 call master_memory % free_memory(storage_size(this % electron_integral)/8,
size(this % electron_integral))
359 call master_memory % free_memory(storage_size(this % coeffs)/8,
size(this % coeffs))
362 deallocate(this % electron_integral)
363 deallocate(this % coeffs)
366 this % max_capacity = this % max_capacity + this % expand_size
369 allocate(this % electron_integral(
nidx, this % max_capacity), &
370 this % coeffs(this % num_states_1, this % num_states_2, this % max_capacity), stat = err)
371 call master_memory % track_memory (storage_size(this % electron_integral)/8, &
372 size(this % electron_integral), err,
'CONSYMBOLIC::EXP::ELECTRONINT_EXP')
373 call master_memory % track_memory(storage_size(this % coeffs)/8, &
374 size(this % coeffs), err,
'CONSYMBOLIC::EXP::ELECTRONCOEFF_EXP')
376 this % electron_integral = -1
377 this % coeffs = 0.0_wp
379 do ido = 1, temp_capacity
381 this % electron_integral(:,ido) = temp_integral(:,ido)
382 this % coeffs(:,:,ido) = temp_coeffs(:,:,ido)
385 call master_memory % free_memory(storage_size(temp_integral)/8,
size(temp_integral))
386 call master_memory % free_memory(storage_size(temp_coeffs)/8,
size(temp_coeffs))
388 deallocate(temp_integral, temp_coeffs)
401 subroutine add_symbols (this, rhs, alpha)
402 class(contractedsymbolicelementvector) :: this
403 class(symbolicelementvector),
intent(in) :: rhs
404 real(wp) :: alpha(this % num_states_1, this % num_states_2), int_coeff
405 real(wp) :: coeffs(this % num_states_1, this % num_states_2)
407 integer(longint) :: label(NIDX)
412 do ido = 1, rhs % get_size()
413 call rhs % get_coeff_and_integral(ido, int_coeff, label)
414 coeffs = int_coeff * alpha
415 call this % insert_symbol(label, coeffs)
421 subroutine reduce_symbols (this, rhs)
422 class(contractedsymbolicelementvector) :: this
423 class(contractedsymbolicelementvector),
intent(in) :: rhs
427 do ido = 1, rhs % get_size()
428 call this % insert_symbol(rhs % electron_integral(:,ido), rhs % coeffs(:,:,ido))
434 subroutine synchronize_symbols (this)
435 class(contractedsymbolicelementvector) :: this
437 integer :: my_num_symbols, largest_num_symbols, ierr
438 integer :: ido, proc_id, jdo
440 integer(longint),
allocatable,
target :: labels(:,:)
441 integer(longint),
pointer :: label_ptr(:)
442 integer(longint) :: procs_num_of_symbols_int, procs_num_of_symbols_coeff, size_labels, size_coeffs
444 real(wp),
allocatable,
target :: coeffs(:,:,:)
445 real(wp),
pointer :: coeffs_ptr(:)
447 if (grid % gprocs <= 1)
then
451 call master_timer % start_timer(
"Symbol Synchronize")
453 my_num_symbols = this % get_size()
454 call mpi_reduceall_max(my_num_symbols, largest_num_symbols, grid % lcomm)
456 if (largest_num_symbols == 0)
then
457 call master_timer % stop_timer(
"Symbol Synchronize")
461 call master_memory % track_memory (storage_size(labels)/8, largest_num_symbols *
nidx, 0,
'CONSYMBOLIC::MPISYNCH::LABELS')
462 call master_memory % track_memory (storage_size(coeffs)/8, largest_num_symbols * this % num_states_1 * this % num_states_2,&
463 0,
'CONSYMBOLIC::MPISYNCH::COEFFS')
465 allocate(labels(
nidx, largest_num_symbols), &
466 coeffs(this % num_states_1, this % num_states_2, largest_num_symbols), &
469 size_labels =
size(labels, kind = longint)
470 size_coeffs =
size(coeffs, kind = longint)
472 label_ptr(1:size_labels) => labels(:,:)
473 coeffs_ptr(1:size_coeffs) => coeffs(:,:,:)
478 if (my_num_symbols > 0)
then
479 labels(:,1:my_num_symbols) = this % electron_integral(:,1:my_num_symbols)
480 do ido = 1, my_num_symbols
481 coeffs(1:this%num_states_1,1:this%num_states_2,ido) = this % coeffs(1:this%num_states_1,1:this%num_states_2,ido)
485 procs_num_of_symbols_int = my_num_symbols *
nidx
486 procs_num_of_symbols_coeff = my_num_symbols * this % num_states_1 * this % num_states_2
487 do proc_id = 1, grid % lprocs - 1
488 call mpi_mod_rotate_int_arrays_around_ring(procs_num_of_symbols_int, label_ptr, size_labels, grid % lcomm)
489 call mpi_mod_rotate_cfp_arrays_around_ring(procs_num_of_symbols_coeff, coeffs_ptr, size_coeffs, grid % lcomm)
491 do ido = 1, procs_num_of_symbols_int /
nidx
492 call this % insert_symbol(labels(:,ido), coeffs(1:this%num_states_1,1:this%num_states_2,ido))
496 call master_timer % stop_timer(
"Symbol Synchronize")
497 call master_memory % free_memory(storage_size(labels)/8,
size(labels))
498 call master_memory % free_memory(storage_size(coeffs)/8,
size(coeffs))
500 deallocate(labels, coeffs)
505 subroutine synchronize_symbols_ii (this)
506 class(contractedsymbolicelementvector),
target :: this
508 integer(longint),
allocatable,
target :: labels(:,:)
509 integer(longint),
pointer :: label_ptr(:)
511 real(wp),
allocatable,
target :: coeffs(:,:,:)
512 real(wp),
pointer :: coeffs_ptr(:)
514 integer :: my_num_symbols, largest_num_symbols, procs_num_of_symbols_int, procs_num_of_symbols_coeff, ido, proc_id, jdo
515 integer :: ierr, local_communicator, global_communicator, odd_even
517 integer(kind=mpiint) :: master_comm, global_rank, global_nprocs, error, proc, tag = 1
519 if (grid % gprocs <= 1)
then
552 subroutine remove_symbol_at (this, idx)
553 class(contractedsymbolicelementvector) :: this
554 integer,
intent(in) :: idx
557 if (this % check_bounds(idx))
then
558 do ido = idx + 1, this % n
559 this % electron_integral(:, ido - 1) = this % electron_integral(:, ido)
562 this % electron_integral(:, this % n) = 0
564 this % n = this % n - 1
639 subroutine get_coeff_and_integral (this, idx, coeff, label)
640 class(contractedsymbolicelementvector),
intent(in) :: this
641 integer,
intent(in) :: idx
642 real(wp),
intent(out) :: coeff(this % num_states_1, this % num_states_2)
643 integer(longint),
intent(out) :: label(:)
645 if (this % check_bounds(idx))
then
646 label = this % electron_integral(:,idx)
647 coeff = this % coeffs(:,:,idx)
679 subroutine destroy (this)
680 class(contractedsymbolicelementvector) :: this
682 if (
allocated(this % electron_integral))
then
683 call master_memory % free_memory(storage_size(this % electron_integral)/8,
size(this % electron_integral))
684 deallocate(this % electron_integral)
686 if(
allocated(this % coeffs))
then
687 call master_memory % free_memory(storage_size(this % coeffs)/8,
size(this % coeffs))
688 deallocate(this % coeffs)
691 call this % bstree % destroy
693 this % constructed = .false.
702 subroutine print_symbols (this)
703 class(contractedsymbolicelementvector) :: this
704 integer :: labels(8), ido
707 if (.not. this % is_empty())
write (stdout,
"('Outputting symbolic elements....')")
710 call unpack_ints(this % electron_integral(:,ido), labels)
711 write (1923 + myrank,
"(5i4,' -- ',5es14.3)") labels(1:5), this % coeffs(:,:,ido)
717 logical function estimate_synchronize_cost (this)
718 class(contractedsymbolicelementvector) :: this
719 integer(longint) :: memory_cost
720 integer :: my_num_symbols, largest_num_symbols
721 integer :: gathered_bool, global_bool(grid % gprocs)
723 if (grid % gprocs <= 1)
then
724 estimate_synchronize_cost = .true.
728 my_num_symbols = this % get_size()
730 estimate_synchronize_cost = .true.
732 call mpi_reduceall_max(my_num_symbols, largest_num_symbols, grid % gcomm)
734 memory_cost = 2 * largest_num_symbols * (2 + this % num_states_1 * this % num_states_2) * 8
736 if (memory_cost >= master_memory % get_scaled_available_memory(0.75_wp)) gathered_bool = 1
740 call mpi_mod_allgather(gathered_bool, global_bool, grid % gcomm)
742 if (sum(global_bool) /= 0)
then
743 estimate_synchronize_cost = .false.