57 type,
extends(bstree) :: symbolicelementvector
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
68 procedure,
public :: compare => bstree_compare
71 procedure,
public :: construct
72 procedure,
public :: insert_ijklm_symbol
73 procedure,
public :: insert_symbol
74 procedure,
public :: remove_symbol_at
75 procedure,
public :: is_empty
76 procedure,
public :: clear
77 procedure,
public :: check_same_integral
78 procedure,
public :: get_integral_label
79 procedure,
public :: synchronize_symbols
80 procedure,
public :: modify_coeff
81 procedure,
public :: get_coefficient
82 procedure,
public :: get_coeff_and_integral
83 procedure,
public :: get_size
84 procedure,
public :: add_symbols
85 procedure,
public :: print => print_symbols
86 procedure,
private :: expand_array
87 procedure,
private :: check_bounds
88 procedure,
public :: destroy
89 procedure,
private :: check_constructed
90 end type symbolicelementvector
111 integer function bstree_compare (this, i, j, data)
result (verdict)
113 class(symbolicelementvector),
intent(in) :: this
114 integer,
intent(in) :: i, j
115 type(c_ptr),
optional,
intent(in) :: data
117 integer(longint) :: ii(
nidx), jj(
nidx)
118 integer(longint),
pointer :: kk(:)
121 if (
present(data))
call c_f_pointer(
data, kk, (/
nidx /))
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 verdict = lexicographical_compare(ii, jj)
156 subroutine construct (this, threshold, initial_size)
157 class(symbolicelementvector) :: this
158 real(wp),
optional,
intent(in) :: threshold
159 integer,
optional,
intent(in) :: initial_size
162 if (
present(threshold))
then
163 this % threshold = threshold
168 this % expand_size = 100
169 this % max_capacity = this % expand_size
172 allocate(this % electron_integral(
nidx, this % max_capacity), this % coeffs(this % max_capacity), stat = err)
173 call master_memory % track_memory(storage_size(this % electron_integral)/8,
size(this % electron_integral), &
174 err,
'SYMBOLIC::ELECTRONINT')
175 call master_memory % track_memory(storage_size(this % coeffs)/8,
size(this % coeffs), err,
'SYMBOLIC::ELECTRONCOEFF')
177 write (stdout,
"('SymbolicVector::construct- arrays not allocated')")
178 stop
"SymbolicVector arrays not allocated"
185 this % constructed = .true.
225 subroutine insert_ijklm_symbol (this, i, j, k, l, m, coeff, check_same_)
226 class(symbolicelementvector) :: this
227 integer,
intent(in) :: i, j, k, l, m
228 real(wp),
intent(in) :: coeff
229 logical,
optional,
intent(in) :: check_same_
230 integer(longint) :: integral_label(NIDX)
231 logical :: check_same
233 if (
present(check_same_))
then
234 check_same = check_same_
239 call pack_ints(i, j, k, l, m, 0, 0, 0, integral_label)
240 call this % insert_symbol(integral_label, coeff, check_same)
257 subroutine insert_symbol (this, integral_label, coeff, check_same_)
258 class(symbolicelementvector) :: this
259 integer(longint),
intent(in) :: integral_label(NIDX)
260 real(wp),
intent(in) :: coeff
261 logical,
optional,
intent(in) :: check_same_
262 integer :: idx = 0, check_idx
263 logical :: check_same
265 if (
present(check_same_))
then
266 check_same = check_same_
272 if (abs(coeff) < this % threshold)
return
274 if (.not.check_same)
then
276 this % n = this % n + 1
279 if (this % n > this % max_capacity)
then
280 call this % expand_array()
283 this % electron_integral(:,idx) = integral_label(:)
284 this % coeffs(idx) = 0.0_wp
285 call this % insert(idx)
288 else if (.not. this % check_same_integral(integral_label, idx))
then
290 this % n = this % n + 1
293 if (this % n > this % max_capacity)
then
294 call this % expand_array()
297 this % electron_integral(:,idx) = integral_label(:)
298 this % coeffs(idx) = 0.0_wp
299 call this % insert(idx)
303 this % coeffs(idx) = this % coeffs(idx) + coeff
316 subroutine expand_array(this)
317 class(symbolicelementvector) :: this
318 integer(longint),
allocatable :: temp_integral(:,:)
319 real(wp),
allocatable :: temp_coeffs(:)
320 integer :: temp_capacity,ido,err
323 call this % check_constructed
326 temp_capacity = this % max_capacity
328 allocate(temp_integral(
nidx, this % max_capacity), temp_coeffs(this % max_capacity))
331 do ido = 1, temp_capacity
332 temp_integral(:,ido) = this % electron_integral(:,ido)
335 temp_coeffs(1:temp_capacity) = this % coeffs(1:temp_capacity)
337 call master_memory % free_memory(storage_size(this % electron_integral)/8,
size(this % electron_integral))
338 call master_memory % free_memory(storage_size(this % coeffs)/8,
size(this % coeffs))
340 deallocate(this % electron_integral)
341 deallocate(this % coeffs)
344 this % max_capacity = this % max_capacity + this % expand_size
346 allocate(this % electron_integral(
nidx, this % max_capacity), this % coeffs(this % max_capacity), stat = err)
347 call master_memory % track_memory(storage_size(this % electron_integral)/8,
size(this % electron_integral), &
348 err,
'SYMBOLIC::EXP::ELECTRONINT')
349 call master_memory % track_memory(storage_size(this % coeffs)/8,
size(this % coeffs), err,
'SYMBOLIC::EXP::ELECTRONCOEFF')
352 this % electron_integral(:,:) = -1
353 this % coeffs(:) = 0.0_wp
355 do ido = 1, temp_capacity
357 this % electron_integral(:,ido) = temp_integral(:,ido)
359 this % coeffs(1:temp_capacity) = temp_coeffs(1:temp_capacity)
360 deallocate(temp_integral, temp_coeffs)
373 subroutine add_symbols (this, rhs, alpha_)
374 class(symbolicelementvector) :: this
375 class(symbolicelementvector),
intent(in) :: rhs
376 real(wp),
optional,
intent(in) :: alpha_
380 if (
present(alpha_))
then
388 call this % insert_symbol(rhs % electron_integral(:,ido), rhs % coeffs(ido) * alpha)
393 subroutine synchronize_symbols (this)
394 class(symbolicelementvector) :: this
395 real(wp),
allocatable :: coeffs(:)
396 integer(longint),
allocatable,
target :: labels(:,:)
397 integer(longint),
pointer :: label_ptr(:)
398 integer(longint) :: my_num_symbols, largest_num_symbols, procs_num_of_symbols
399 integer :: ido, proc_id, ierr
401 if (grid % gprocs <= 1)
then
405 my_num_symbols = this % get_size()
407 call mpi_reduceall_max(my_num_symbols, largest_num_symbols, grid % gcomm)
409 if (largest_num_symbols == 0)
return
411 call master_memory % track_memory(storage_size(labels)/8, int(largest_num_symbols *
nidx), 0,
'SYMBOLIC::MPISYNCH::LABELS')
412 call master_memory % track_memory(storage_size(coeffs)/8, int(largest_num_symbols), 0,
'SYMBOLIC::MPISYNCH::COEFFS')
413 allocate(labels(
nidx,largest_num_symbols), coeffs(largest_num_symbols), stat = ierr)
415 label_ptr(1:largest_num_symbols*
nidx) => labels(:,:)
419 if (my_num_symbols > 0)
then
420 labels(:,1:my_num_symbols) = this % electron_integral(:,1:my_num_symbols)
421 coeffs(1:my_num_symbols) = this % coeffs(1:my_num_symbols)
424 procs_num_of_symbols = my_num_symbols
426 do proc_id = 1, grid % gprocs - 1
427 call mpi_mod_rotate_arrays_around_ring(procs_num_of_symbols, label_ptr, coeffs, largest_num_symbols, grid % gcomm)
428 do ido = 1, procs_num_of_symbols
429 call this % insert_symbol(labels(:,ido), coeffs(ido))
433 call master_memory % free_memory(storage_size(labels)/8,
size(labels))
434 call master_memory % free_memory(storage_size(coeffs)/8,
size(coeffs))
435 deallocate(labels, coeffs)
470 subroutine remove_symbol_at (this, idx)
471 class(symbolicelementvector) :: this
472 integer,
intent(in) :: idx
475 if (this % check_bounds(idx))
then
476 do ido = idx + 1, this % n
477 this % electron_integral(:,ido-1) = this % electron_integral(:,ido)
478 this % coeffs(ido-1) = this % coeffs(ido)
480 this % electron_integral(:, this % n) = 0
481 this % coeffs(this % n) = 0
482 this % n = this % n - 1
571 subroutine get_coeff_and_integral (this, idx, coeff, label)
572 class(symbolicelementvector),
intent(in) :: this
573 integer,
intent(in) :: idx
574 real(wp),
intent(out) :: coeff
575 integer(longint),
intent(out) :: label(NIDX)
577 if (this % check_bounds(idx))
then
578 label = this % electron_integral(:,idx)
579 coeff = this % coeffs(idx)
600 subroutine destroy (this)
601 class(symbolicelementvector) :: this
603 if (
allocated(this % electron_integral))
then
604 call master_memory % free_memory(storage_size(this % electron_integral)/8,
size(this % electron_integral))
605 deallocate(this % electron_integral)
607 if (
allocated(this % coeffs))
then
608 call master_memory % free_memory(storage_size(this % coeffs)/8,
size(this % coeffs))
609 deallocate(this % coeffs)
612 call this % bstree % destroy
614 this % constructed = .false.
623 subroutine print_symbols (this)
624 class(symbolicelementvector) :: this
625 integer :: labels(8), ido
628 if (.not. this % is_empty())
write (stdout,
"('Outputting symbolic elements....')")
630 call unpack_ints(this % electron_integral(:,ido), labels)
631 write (stdout,
"(5i4,' -- ',es14.3)") labels(1:5),this % coeffs(ido)