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: mpi_reduceall_max, mpi_mod_rotate_arrays_around_ring, mpi_xermsg
41 use precisn,
only: longint, wp
59 integer(longint),
allocatable :: electron_integral(:,:)
60 real(wp),
allocatable :: coeffs(:)
62 logical :: constructed = .false.
63 real(wp) :: threshold = 0.0
64 integer :: max_capacity = 0
65 integer :: expand_size = 10
114 integer,
intent(in) :: i, j
115 type(c_ptr),
optional,
intent(in) :: data
117 integer(longint) :: ii(2), jj(2)
118 integer(longint),
pointer :: kk(:)
121 if (
present(data))
call c_f_pointer(
data, kk, (/ 2 /))
124 if (i <= 0) then; ii = kk; else; ii = this % electron_integral(:,i);
end if
125 if (j <= 0) then; jj = kk; else; jj = this % electron_integral(:,j);
end if
128 if (ii(1) < jj(1))
then
130 else if (ii(1) > jj(1))
then
132 else if (ii(2) < jj(2))
then
134 else if (ii(2) > jj(2))
then
149 if (.not. this % constructed)
then
150 write (stdout,
"('Vector::constructed - Vector is not constructed')")
151 stop
"Vector::constructed - Vector is not constructed"
168 real(wp),
optional,
intent(in) :: threshold
169 integer,
optional,
intent(in) :: initial_size
172 if (
present(threshold))
then
173 this % threshold = threshold
178 this % expand_size = 100
179 this % max_capacity = this % expand_size
182 allocate(this % electron_integral(2, this % max_capacity), this % coeffs(this % max_capacity), stat = err)
183 call master_memory % track_memory(kind(this % electron_integral),
size(this % electron_integral), &
184 err,
'SYMBOLIC::ELECTRONINT')
185 call master_memory % track_memory(kind(this % coeffs),
size(this % coeffs), err,
'SYMBOLIC::ELECTRONCOEFF')
187 write (stdout,
"('SymbolicVector::construct- arrays not allocated')")
188 stop
"SymbolicVector arrays not allocated"
195 this % constructed = .true.
212 integer(longint),
target,
intent(in) :: integral(2)
213 integer,
intent(out) :: idx
215 call this % check_constructed
217 idx = this % locate(-1, c_loc(integral))
237 integer,
intent(in) :: i, j, k, l, m
238 real(wp),
intent(in) :: coeff
239 logical,
optional,
intent(in) :: check_same_
240 integer(longint) :: integral_label(2)
241 logical :: check_same
243 if (
present(check_same_))
then
244 check_same = check_same_
249 call pack8ints(i, j, k, l, m, 0, 0, 0, integral_label)
250 call this % insert_symbol(integral_label, coeff, check_same)
269 integer(longint),
intent(in) :: integral_label(2)
270 real(wp),
intent(in) :: coeff
271 logical,
optional,
intent(in) :: check_same_
272 integer :: idx = 0, check_idx
273 logical :: check_same
275 if (
present(check_same_))
then
276 check_same = check_same_
282 if (abs(coeff) < this % threshold)
return
284 if (.not.check_same)
then
286 this % n = this % n + 1
289 if (this % n > this % max_capacity)
then
290 call this % expand_array()
293 this % electron_integral(:,idx) = integral_label(:)
294 this % coeffs(idx) = 0.0_wp
295 call this % insert(idx)
298 else if (.not. this % check_same_integral(integral_label, idx))
then
300 this % n = this % n + 1
303 if (this % n > this % max_capacity)
then
304 call this % expand_array()
307 this % electron_integral(:,idx) = integral_label(:)
308 this % coeffs(idx) = 0.0_wp
309 call this % insert(idx)
313 this % coeffs(idx) = this % coeffs(idx) + coeff
328 integer(longint),
allocatable :: temp_integral(:,:)
329 real(wp),
allocatable :: temp_coeffs(:)
330 integer :: temp_capacity,ido,err
333 call this % check_constructed
336 temp_capacity = this % max_capacity
338 allocate(temp_integral(2, this % max_capacity), temp_coeffs(this % max_capacity))
341 do ido = 1, temp_capacity
342 temp_integral(1,ido) = this % electron_integral(1,ido)
343 temp_integral(2,ido) = this % electron_integral(2,ido)
346 temp_coeffs(1:temp_capacity) = this % coeffs(1:temp_capacity)
348 call master_memory % free_memory(kind(this % electron_integral),
size(this % electron_integral))
349 call master_memory % free_memory(kind(this % coeffs),
size(this % coeffs))
351 deallocate(this % electron_integral)
352 deallocate(this % coeffs)
355 this % max_capacity = this % max_capacity + this % expand_size
357 allocate(this % electron_integral(2, this % max_capacity), this % coeffs(this % max_capacity), stat = err)
358 call master_memory % track_memory(kind(this % electron_integral),
size(this % electron_integral), &
359 err,
'SYMBOLIC::EXP::ELECTRONINT')
360 call master_memory % track_memory(kind(this % coeffs),
size(this % coeffs), err,
'SYMBOLIC::EXP::ELECTRONCOEFF')
363 this % electron_integral(:,:) = -1
364 this % coeffs(:) = 0.0_wp
366 do ido = 1, temp_capacity
368 this % electron_integral(1,ido) = temp_integral(1,ido)
369 this % electron_integral(2,ido) = temp_integral(2,ido)
371 this % coeffs(1:temp_capacity) = temp_coeffs(1:temp_capacity)
372 deallocate(temp_integral, temp_coeffs)
388 real(wp),
optional,
intent(in) :: alpha_
392 if (
present(alpha_))
then
400 call this % insert_symbol(rhs % electron_integral(1:2,ido), rhs % coeffs(ido) * alpha)
407 real(wp),
allocatable :: coeffs(:)
408 integer(longint),
allocatable,
target :: labels(:,:)
409 integer(longint),
pointer :: label_ptr(:)
410 integer(longint) :: my_num_symbols, largest_num_symbols, procs_num_of_symbols
411 integer :: ido, proc_id, ierr
413 if (grid % gprocs <= 1)
then
417 my_num_symbols = this % get_size()
419 call mpi_reduceall_max(my_num_symbols, largest_num_symbols, grid % gcomm)
421 if (largest_num_symbols == 0)
return
423 call master_memory % track_memory(kind(labels), int(largest_num_symbols * 2), 0,
'SYMBOLIC::MPISYNCH::LABELS')
424 call master_memory % track_memory(kind(coeffs), int(largest_num_symbols), 0,
'SYMBOLIC::MPISYNCH::COEFFS')
425 allocate(labels(2,largest_num_symbols), coeffs(largest_num_symbols), stat = ierr)
427 label_ptr(1:largest_num_symbols*2) => labels(:,:)
431 if (my_num_symbols > 0)
then
432 labels(1,1:my_num_symbols) = this % electron_integral(1,1:my_num_symbols)
433 labels(2,1:my_num_symbols) = this % electron_integral(2,1:my_num_symbols)
434 coeffs(1:my_num_symbols) = this % coeffs(1:my_num_symbols)
437 procs_num_of_symbols = my_num_symbols
439 do proc_id = 1, grid % gprocs - 1
440 call mpi_mod_rotate_arrays_around_ring(procs_num_of_symbols, label_ptr, coeffs, largest_num_symbols, grid % gcomm)
441 do ido = 1, procs_num_of_symbols
442 call this % insert_symbol(labels(1:2,ido), coeffs(ido))
448 deallocate(labels, coeffs)
464 integer,
intent(in) :: i
466 if (i <= 0 .or. i > this % n)
then
467 write (stdout,
"('SymbolicVector::check_bounds - Out of Bounds access')")
468 stop
"SymbolicVector::check_bounds - Out of Bounds access"
485 integer,
intent(in) :: idx
488 if (this % check_bounds(idx))
then
489 do ido = idx + 1, this % n
490 this % electron_integral(1,ido-1) = this % electron_integral(1,ido)
491 this % electron_integral(2,ido-1) = this % electron_integral(2,ido)
492 this % coeffs(ido-1) = this % coeffs(ido)
494 this % electron_integral(:, this % n) = 0
495 this % coeffs(this % n) = 0
496 this % n = this % n - 1
530 call this % bstree % destroy
543 integer,
intent(in) :: idx
546 this % coeffs(idx) = this % coeffs(idx) + coeff
558 integer,
intent(in) :: idx
573 integer,
intent(in) :: idx
587 integer,
intent(in) :: idx
588 real(wp),
intent(out) :: coeff
589 integer(longint),
intent(out) :: label(2)
591 if (this % check_bounds(idx))
then
592 label(1:2) = this % electron_integral(1:2,idx)
593 coeff = this % coeffs(idx)
617 if (
allocated(this % electron_integral))
then
618 call master_memory % free_memory(kind(this % electron_integral),
size(this % electron_integral))
619 deallocate(this % electron_integral)
621 if (
allocated(this % coeffs))
then
622 call master_memory % free_memory(kind(this % coeffs),
size(this % coeffs))
623 deallocate(this % coeffs)
626 call this % bstree % destroy
628 this % constructed = .false.
639 integer :: labels(8), ido
642 if (.not. this % is_empty())
write (stdout,
"('Outputting symbolic elements....')")
644 call unpack8ints(this % electron_integral(1,ido), labels)
645 write (stdout,
"(5i4,' -- ',es14.3)") labels(1:5),this % coeffs(ido)