35 use const_gbl,
only: stdout
37 use containers,
only: bstree
38 use integer_packing,
only: pack8ints, unpack8ints
39 use iso_c_binding,
only: c_loc, c_ptr, c_f_pointer
40 use mpi_gbl,
only: myrank, mpiint, mpi_mod_allgather, mpi_mod_rotate_cfp_arrays_around_ring, &
41 mpi_mod_rotate_int_arrays_around_ring, mpi_xermsg, mpi_reduceall_max
42 use precisn,
only: longint, wp
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
135 integer,
intent(in) :: i, j
136 type(c_ptr),
optional,
intent(in) :: data
138 integer(longint) :: ii(2), jj(2)
139 integer(longint),
pointer :: kk(:)
142 if (
present(data))
call c_f_pointer(
data, kk, (/ 2 /))
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 if (ii(1) < jj(1))
then
151 else if (ii(1) > jj(1))
then
153 else if (ii(2) < jj(2))
then
155 else if (ii(2) > jj(2))
then
170 if (.not. this % constructed)
then
171 write (stdout,
"('Vector::constructed - Vector is not constructed')")
172 stop
"Vector::constructed - Vector is not constructed"
188 subroutine construct (this, n1, n2, threshold, initial_size)
190 real(wp),
optional,
intent(in) :: threshold
191 integer,
optional,
intent(in) :: initial_size
193 integer :: err, n1, n2
195 if (
present(threshold))
then
196 this % threshold = threshold
201 this % expand_size = 100
202 this % max_capacity = this % expand_size
203 this % num_states_1 = n1
204 this % num_states_2 = n2
207 allocate(this % electron_integral(2, this % max_capacity), this % coeffs(n1, n2, this % max_capacity), stat = err)
208 call master_memory % track_memory (kind(this % electron_integral), &
209 size(this % electron_integral), err,
'CONSYMBOLIC::ELECTRONINT')
211 size(this % coeffs), err,
'CONSYMBOLIC::ELECTRONCOEFF')
213 call mpi_xermsg(
'Contracted_Symbolic_module',
'construct',
'SymbolicVector arrays not allocated', 1, 1)
220 this % constructed = .true.
238 integer(longint),
target,
intent(in) :: integral(2)
239 integer,
intent(out) :: idx
241 call this % check_constructed
243 idx = this % locate(-1, c_loc(integral))
263 integer,
intent(in) :: i, j, k, l, m
264 real(wp),
intent(in) :: coeffs(this % num_states_1, this % num_states_2)
265 logical,
intent(in),
optional :: check_same_
267 integer(longint) :: integral_label(2)
268 logical :: check_same
270 if (
present(check_same_))
then
271 check_same = check_same_
276 call pack8ints(i, j, k, l, m, 0, 0, 0, integral_label)
277 call this%insert_symbol(integral_label, coeffs, check_same)
297 integer(longint),
intent(in) :: integral_label(2)
298 real(wp),
intent(in) :: coeffs(this % num_states_1, this % num_states_2)
299 logical,
intent(in),
optional :: check_same_
301 integer :: idx = 0, check_idx
302 logical :: check_same
304 if (
present(check_same_))
then
305 check_same = check_same_
313 if (.not. this % check_same_integral(integral_label, idx))
then
315 this % n = this % n + 1
319 if (this % n > this % max_capacity)
then
320 call this % expand_array()
323 this % electron_integral(:,idx) = integral_label(:)
325 this % coeffs(:,:,idx) = 0.0_wp
327 call this % insert(idx)
331 this % coeffs(:,:,idx) = this % coeffs(:,:,idx) + coeffs(:,:)
345 integer(longint),
allocatable :: temp_integral(:,:)
346 real(wp),
allocatable :: temp_coeffs(:,:,:)
347 integer :: temp_capacity, ido, err
352 call this % check_constructed
355 temp_capacity = this % max_capacity
357 allocate(temp_integral(2, this % max_capacity), &
358 temp_coeffs(this % num_states_1, this % num_states_2, this % max_capacity), stat = err)
359 call master_memory % track_memory(kind(temp_integral),
size(temp_integral), err,
'CONSYMBOLIC::EXP::TEMPINT')
360 call master_memory % track_memory(kind(temp_coeffs),
size(temp_coeffs), err,
'CONSYMBOLIC::EXP::TEMPCOEFF')
363 do ido = 1, temp_capacity
364 temp_integral(1,ido) = this % electron_integral(1,ido)
365 temp_integral(2,ido) = this % electron_integral(2,ido)
366 temp_coeffs(:,:,ido) = this % coeffs(:,:,ido)
369 call master_memory % free_memory(kind(this % electron_integral),
size(this % electron_integral))
370 call master_memory % free_memory(kind(this % coeffs),
size(this % coeffs))
373 deallocate(this % electron_integral)
374 deallocate(this % coeffs)
377 this % max_capacity = this % max_capacity + this % expand_size
380 allocate(this % electron_integral(2, this % max_capacity), &
381 this % coeffs(this % num_states_1, this % num_states_2, this % max_capacity), stat = err)
382 call master_memory % track_memory (kind(this % electron_integral), &
383 size(this % electron_integral), err,
'CONSYMBOLIC::EXP::ELECTRONINT_EXP')
385 size(this % coeffs), err,
'CONSYMBOLIC::EXP::ELECTRONCOEFF_EXP')
387 this % electron_integral = -1
388 this % coeffs = 0.0_wp
390 do ido = 1, temp_capacity
392 this % electron_integral(1,ido) = temp_integral(1,ido)
393 this % electron_integral(2,ido) = temp_integral(2,ido)
394 this % coeffs(:,:,ido) = temp_coeffs(:,:,ido)
397 call master_memory % free_memory(kind(temp_integral),
size(temp_integral))
398 call master_memory % free_memory(kind(temp_coeffs),
size(temp_coeffs))
400 deallocate(temp_integral, temp_coeffs)
416 real(wp) :: alpha(this % num_states_1, this % num_states_2), int_coeff
418 integer(longint) :: label(2)
421 do ido = 1, rhs % get_size()
422 call rhs % get_coeff_and_integral(ido, int_coeff, label)
423 call this % insert_symbol(label, int_coeff * alpha)
433 integer(longint) :: label(2)
436 do ido = 1, rhs % get_size()
437 call this % insert_symbol(rhs % electron_integral(:,ido), rhs % coeffs(:,:,ido))
446 integer :: my_num_symbols, largest_num_symbols, ierr
447 integer :: ido, proc_id, jdo
449 integer(longint),
allocatable,
target :: labels(:,:)
450 integer(longint),
pointer :: label_ptr(:)
451 integer(longint) :: procs_num_of_symbols_int, procs_num_of_symbols_coeff, size_labels, size_coeffs
453 real(wp),
allocatable,
target :: coeffs(:,:,:)
454 real(wp),
pointer :: coeffs_ptr(:)
456 if (grid % gprocs <= 1)
then
462 my_num_symbols = this % get_size()
463 call mpi_reduceall_max(my_num_symbols, largest_num_symbols, grid % lcomm)
465 if (largest_num_symbols == 0)
then
470 call master_memory % track_memory (kind(labels), largest_num_symbols * 2, 0,
'CONSYMBOLIC::MPISYNCH::LABELS')
471 call master_memory % track_memory (kind(coeffs), largest_num_symbols * this % num_states_1 * this % num_states_2, &
472 0,
'CONSYMBOLIC::MPISYNCH::COEFFS')
474 allocate(labels(2, largest_num_symbols), coeffs(this % num_states_1, this % num_states_2, largest_num_symbols), stat = ierr)
476 size_labels =
size(labels, kind = longint)
477 size_coeffs =
size(coeffs, kind = longint)
479 label_ptr(1:size_labels) => labels(:,:)
480 coeffs_ptr(1:size_coeffs) => coeffs(:,:,:)
485 if (my_num_symbols > 0)
then
486 labels(1,1:my_num_symbols) = this % electron_integral(1,1:my_num_symbols)
487 labels(2,1:my_num_symbols) = this % electron_integral(2,1:my_num_symbols)
488 do ido = 1, my_num_symbols
489 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)
493 procs_num_of_symbols_int = my_num_symbols * 2
494 procs_num_of_symbols_coeff = my_num_symbols * this % num_states_1 * this % num_states_2
495 do proc_id = 1, grid % lprocs - 1
496 call mpi_mod_rotate_int_arrays_around_ring(procs_num_of_symbols_int, label_ptr, size_labels, grid % lcomm)
497 call mpi_mod_rotate_cfp_arrays_around_ring(procs_num_of_symbols_coeff, coeffs_ptr, size_coeffs, grid % lcomm)
499 do ido = 1, procs_num_of_symbols_int / 2
500 call this % insert_symbol(labels(1:2,ido), coeffs(1:this%num_states_1,1:this%num_states_2,ido))
508 deallocate(labels, coeffs)
516 integer(longint),
allocatable,
target :: labels(:,:)
517 integer(longint),
pointer :: label_ptr(:)
519 real(wp),
allocatable,
target :: coeffs(:,:,:)
520 real(wp),
pointer :: coeffs_ptr(:)
522 integer :: my_num_symbols, largest_num_symbols, procs_num_of_symbols_int, procs_num_of_symbols_coeff, ido, proc_id, jdo
523 integer :: ierr, local_communicator, global_communicator, odd_even
525 integer(kind=mpiint) :: master_comm, global_rank, global_nprocs, error, proc, tag = 1
527 if (grid % gprocs <= 1)
then
543 integer,
intent(in) :: i
545 if (i <= 0 .or. i > this % n)
then
546 write (stdout,
"('SymbolicVector::check_bounds - Out of Bounds access')")
547 stop
"SymbolicVector::check_bounds - Out of Bounds access"
562 integer,
intent(in) :: idx
565 if (this % check_bounds(idx))
then
566 do ido = idx + 1, this % n
567 this % electron_integral(1, ido - 1) = this % electron_integral(1, ido)
568 this % electron_integral(2, ido - 1) = this % electron_integral(2, ido)
571 this % electron_integral(:, this % n) = 0
573 this % n = this % n - 1
603 call this % bstree % destroy
610 integer,
intent(in) :: idx
622 integer,
intent(in) :: idx
636 integer,
intent(in) :: idx, n1, n2
650 integer,
intent(in) :: idx
651 real(wp),
intent(out) :: coeff(this % num_states_1, this % num_states_2)
652 integer(longint),
intent(out) :: label(2)
654 if (this % check_bounds(idx))
then
655 label(1:2) = this % electron_integral(1:2,idx)
656 coeff(:,:) = this % coeffs(:,:,idx)
691 if (
allocated(this % electron_integral))
then
692 call master_memory % free_memory(kind(this % electron_integral),
size(this % electron_integral))
693 deallocate(this % electron_integral)
695 if(
allocated(this % coeffs))
then
696 call master_memory % free_memory(kind(this % coeffs),
size(this % coeffs))
697 deallocate(this % coeffs)
700 call this % bstree % destroy
702 this % constructed = .false.
713 integer :: labels(8), ido
716 if (.not. this % is_empty())
write (stdout,
"('Outputting symbolic elements....')")
719 call unpack8ints(this % electron_integral(1,ido), labels)
720 write (1923 + myrank,
"(5i4,' -- ',5es14.3)") labels(1:5), this % coeffs(:,:,ido)
728 integer(longint) :: memory_cost
729 integer :: my_num_symbols, largest_num_symbols
730 integer :: gathered_bool, global_bool(grid % gprocs)
732 if (grid % gprocs <= 1)
then
737 my_num_symbols = this % get_size()
741 call mpi_reduceall_max(my_num_symbols, largest_num_symbols, grid % gcomm)
743 memory_cost = 2 * largest_num_symbols * (2 + this % num_states_1 * this % num_states_2) * 8
745 if (memory_cost >= master_memory % get_scaled_available_memory(0.75_wp)) gathered_bool = 1
749 call mpi_mod_allgather(gathered_bool, global_bool, grid % gcomm)
751 if (sum(global_bool) /= 0)
then