48 type,
extends(baseintegral) :: swedenintegral
52 real(wp),
pointer :: one_electron_integral(:)
53 real(wp),
pointer :: two_electron_integral(:)
55 real(wp),
allocatable :: one_electron_integral(:)
56 real(wp),
allocatable :: two_electron_integral(:)
59 integer :: one_electron_window
60 integer :: two_electron_window
62 integer :: num_one_electron_integrals
63 integer :: num_two_electron_integrals
65 real(wp),
allocatable :: xnuc(:),ynuc(:),znuc(:),charge(:)
66 character(len=8),
allocatable :: cname(:)
68 integer :: num_unique_pairs
69 integer(longint),
allocatable :: pair_labels(:,:)
70 integer,
allocatable :: num_orbitals_sym(:)
72 integer :: max_number_pair_sets
73 integer :: num_two_electron_blocks
74 integer,
allocatable :: one_electron_pointer(:)
75 integer,
allocatable :: two_electron_pointer(:)
77 integer :: num_pq, num_rs
78 integer :: num_pair_idx
81 integer,
allocatable :: pair_idx(:)
82 integer,
allocatable :: orbital_idx(:)
83 integer,
allocatable :: symmetry_idx(:)
87 procedure,
public :: initialize_self => initialize_sweden
88 procedure,
public :: finalize_self => finalize_sweden
89 procedure,
public :: load_integrals => load_integrals_sweden
90 procedure,
public :: get_integral_ijklm => get_integral_sweden
91 procedure,
public :: write_geometries => write_geometries_sweden
92 procedure,
public :: destroy_integrals => destroy_integral_sweden
93 procedure,
private :: count_num_pairs
94 procedure,
private :: generate_pairs
95 procedure,
private :: generate_pointer_table
96 procedure,
private :: generate_pair_index
97 procedure,
private :: generate_orbital_index
100 procedure,
private :: get_one_electron_index
101 procedure,
private :: get_two_electron_index
103 end type swedenintegral
107 integer function count_num_pairs (this)
108 use global_utils,
only: mprod
110 class(swedenintegral) :: this
111 integer :: i, j, k, l
112 integer :: jend, lend
113 integer :: ij, kl, ijkltest
117 do i = 1, this % num_symmetries
118 count_num_pairs = count_num_pairs + 1
121 if (this % num_symmetries == 1)
return
124 do i = 2, this % num_symmetries
128 count_num_pairs = count_num_pairs + 1
133 do i = 2, this % num_symmetries
137 count_num_pairs = count_num_pairs + 1
141 if (this % num_symmetries < 4)
return
143 do i = 2, this % num_symmetries
150 if (i == k .and. j == l) cycle
151 ij = mprod(i, j, 0, stdout)
152 kl = mprod(k, l, 0, stdout)
153 ijkltest = mprod(ij, kl, 0, stdout)
154 if (ijkltest /= 1) cycle
155 count_num_pairs = count_num_pairs + 1
164 subroutine generate_pairs (this)
165 class(swedenintegral) :: this
166 integer :: i, j, k, l
167 integer :: jend, lend
168 integer :: ij, kl, ijkltest
169 integer :: pair_number
173 write (stdout, *)
'All IIII blocks of integrals'
175 do i = 1, this % num_symmetries
177 pair_number = pair_number + 1
178 call pack_ints(j, j, j, j, 0, 0, 0, 0, this % pair_labels(:, pair_number))
179 write (stdout, *) pair_number, j, j, j, j
182 if (this % num_symmetries == 1)
return
185 write (stdout, *)
'All IJIJ blocks'
186 do i = 2, this % num_symmetries
190 pair_number = pair_number + 1
191 call pack_ints(jend, lend, jend, lend, 0, 0, 0, 0, this % pair_labels(:, pair_number))
192 write (stdout, *) pair_number, jend, lend, jend, lend
197 write (stdout, *)
'All IIJJ blocks'
198 do i = 2, this % num_symmetries
202 pair_number = pair_number + 1
203 call pack_ints(jend, jend, lend, lend, 0, 0, 0, 0, this % pair_labels(:, pair_number))
204 write (stdout, *) pair_number, jend, jend, lend, lend
208 if (this % num_symmetries < 4)
return
209 write (stdout, *)
'All IJKL blocks'
210 do i = 2, this % num_symmetries
217 if (i == k .and. j == l) cycle
218 ij = mprod(i, j, 0, stdout)
219 kl = mprod(k, l, 0, stdout)
220 ijkltest = mprod(ij, kl, 0, stdout)
221 if (ijkltest /=1 ) cycle
222 pair_number = pair_number + 1
223 call pack_ints(i - 1, j - 1, k - 1, l - 1, 0, 0, 0, 0, this % pair_labels(:, pair_number))
224 write (stdout, *) pair_number, i - 1, j - 1, k - 1, l - 1
233 subroutine generate_pointer_table (this)
234 class(swedenintegral) :: this
236 integer :: label(8), num_orbs(4)
237 integer :: ido, jdo, nam1, nam2, num_pq, num_rs, num_pr
238 integer :: block_number, err
240 this % num_two_electron_blocks = indfunc(this % num_symmetries + 1, 0)
241 this % num_two_electron_blocks = indfunc(this % num_two_electron_blocks + 1, 0)
242 this % num_two_electron_integrals = 1
244 allocate(this % one_electron_pointer(this % num_symmetries + 1), stat = err)
246 call master_memory % track_memory(storage_size(this % one_electron_pointer)/8, &
247 size(this % one_electron_pointer), err,
'SWEDEN::One electron pointer')
249 this % one_electron_pointer(1) = 1
251 do ido = 1, this % num_symmetries
252 this % one_electron_pointer(ido + 1) = this % one_electron_pointer(ido) + indfunc(this % num_orbitals_sym(ido) + 1, 0)
255 this % num_one_electron_integrals = this % one_electron_pointer(this % num_symmetries + 1) - 1
257 allocate(this % two_electron_pointer(this % num_two_electron_blocks), stat = err)
259 call master_memory % track_memory(storage_size(this % two_electron_pointer)/8, &
260 size(this % two_electron_pointer), err,
'SWEDEN::Two electron pointer')
262 this % two_electron_pointer(:) = 0
264 write (stdout,
"(//,5X,'Integral Storage Table follows : ',/)")
266 do ido = 1, this % num_unique_pairs
268 call unpack_ints(this % pair_labels(:, ido), label)
271 label(jdo) = label(jdo) + 1
272 num_orbs(jdo) = this % num_orbitals_sym(label(jdo))
276 if (label(1) == label(2))
then
277 num_pq = indfunc(num_orbs(1) + 1, 0)
279 num_pq = num_orbs(1) * num_orbs(2)
281 nam1 = indfunc(max(label(1), label(2)) + 1, 0) - abs(label(1) - label(2))
284 if (label(3) == label(4))
then
285 num_rs = indfunc(num_orbs(3) + 1, 0)
287 num_rs = num_orbs(3) * num_orbs(4)
290 nam2 = indfunc(max(label(3), label(4)) + 1, 0) - abs(label(3)-label(4))
291 block_number = indfunc(max(nam1, nam2) + 1, 0) - abs(nam1 - nam2)
292 this % two_electron_pointer(block_number) = this % num_two_electron_integrals
294 write (stdout,
"(3X,4I3,1X,I5,1X,I10)") label(1), label(2), label(3), label(4), &
295 block_number, this % num_two_electron_integrals
297 if (nam1 == nam2)
then
298 num_pr = indfunc(num_pq + 1, 0)
300 num_pr = num_pq * num_rs
303 this % max_number_pair_sets = max(this % max_number_pair_sets, num_pq, num_rs)
304 if (num_pr > 0) this % num_two_electron_integrals = this % num_two_electron_integrals + num_pr + 1
308 this % num_two_electron_integrals = this % num_two_electron_integrals - 1
310 write (stdout,
"('No of 1 electron integrals = ',i8)") this % num_one_electron_integrals
311 write (stdout,
"('No of 2 electron integrals = ',i8)") this % num_two_electron_integrals
316 subroutine generate_orbital_index (this)
317 class(swedenintegral) :: this
318 integer :: total_num_orbitals, orbital, iorb, isym, max_orbitals, ifail
320 total_num_orbitals = sum(this % num_orbitals_sym(:))
322 allocate(this % orbital_idx(total_num_orbitals), this % symmetry_idx(total_num_orbitals), stat = ifail)
324 call master_memory % track_memory(storage_size(this%orbital_idx)/8,
size(this % orbital_idx), ifail,
'SWEDEN::pair_idx')
325 call master_memory % track_memory(storage_size(this%symmetry_idx)/8,
size(this % symmetry_idx), ifail, &
326 'SWEDEN::symmetry_idx')
328 this % orbital_idx(:) = 0
329 this % symmetry_idx(:) = 0
334 do isym = 1, this % num_symmetries
335 max_orbitals = max(max_orbitals, this % num_orbitals_sym(isym)**2)
336 do iorb = 1, this % num_orbitals_sym(isym)
337 orbital = orbital + 1
338 this % orbital_idx(orbital) = iorb
339 this % symmetry_idx(orbital) = isym - 1
343 this % num_pair_idx = max((this % num_symmetries**2 + this % num_symmetries) / 2 + 1, &
344 this % max_number_pair_sets, &
368 subroutine initialize_sweden (this, option)
369 class(swedenintegral) :: this
370 class(options),
intent(in) :: option
371 integer :: ido, jdo, ifail
373 write (stdout,
"('Using SWEDEN integral')")
375 this % num_unique_pairs = 0
376 this % num_symmetries = option % num_syms
378 allocate(this % num_orbitals_sym(this % num_symmetries), stat = ifail)
379 call master_memory % track_memory(storage_size(this % num_orbitals_sym)/8, &
380 size(this % num_orbitals_sym), ifail,
'SWEDEN::num_orbitals_sym')
382 this % num_orbitals_sym(:) = option % num_electronic_orbitals_sym(:)
383 this % num_unique_pairs = this % count_num_pairs()
385 allocate(this % pair_labels(
nidx, this % num_unique_pairs), stat = ifail)
386 call master_memory % track_memory(storage_size(this % pair_labels)/8, &
387 size(this % pair_labels), ifail,
'SWEDEN::Pair labels')
389 write (stdout, *)
'SWEDEN Integral -- Generating pairs'
392 call this % generate_pairs
393 call this % generate_orbital_index
394 call this % generate_pair_index
396 write (stdout,
"('1',/,10x,'D2h Two Electron Integral Box ','Information')")
397 write (stdout,
"( /,10x,'No. of Boxes = ',i4,/)") this % num_unique_pairs
398 write (stdout,
"( 10x,'Box Descripti ons: ',/)")
399 write (stdout, *)
'SWEDEN Integral -- Generating block pointers'
401 call this % generate_pointer_table
412 subroutine load_integrals_sweden (this, iounit)
413 use params,
only: ctrans1, cpoly
414 use global_utils,
only: intape
415 use scatci_routines,
only: search, chn2e
417 class(swedenintegral) :: this
418 integer,
intent(in) :: iounit
421 character(len=4),
dimension(4) :: LABEL
422 character(len=4),
dimension(33) :: NAM1
423 integer(longint),
dimension(8) :: NAO, NCORE
424 integer(longint),
dimension(20) :: NHE, NOB
425 real(wp),
allocatable :: xtempe(:), xtempp(:)
427 integer(longint) :: I, NSYM, IONEIN
428 integer :: ifail, k, l, ind, ii
431 call master_timer % start_timer(
'SWEDEN load')
433 write (stdout, *)
' Loading SWEDEN Integrals into core'
438 this % one_electron_window = mpi_memory_allocate_real(this % one_electron_integral, 2 * this % num_one_electron_integrals)
443 this % two_electron_window = mpi_memory_allocate_real(this % two_electron_integral, this % num_two_electron_integrals)
445 call mpi_memory_synchronize(this % one_electron_window)
446 call mpi_memory_synchronize(this % two_electron_window)
451 read (iounit) (label(i), i = 1, 4)
453 write (stdout, fmt=
'(/,5X,''Label on Sweden tape = '',4A)') (label(i), i = 1, 4)
455 read (iounit) nsym, en, (nao(i), nob(i), ncore(i), i = 1, nsym)
457 write (stdout,
"(' NSYM =',I5,3X,'NOB =',20I5)") nsym, (nob(i), i = 1, nsym)
458 write (stdout,
"(/,10x,'Nuclear repulsion energy = ',f15.7)") en
459 write (stdout,
"(/10x,' NAO NMO NCORE',/,(10x,2I5,i7))") (nao(i), nob(i), ncore(i), i = 1, nsym)
461 this % core_energy = en
464 if (ncore(i) /= 0)
then
465 write (stdout,
"(10X,'Non-zero CORE in Sweden. Sym no. = ',i5,' Ncore = ',I5,/)") i, ncore(i)
466 write (stdout,
"(10X,'Core Energy = ',F15.7,' Hartrees ',/)") en
474 ionein = ionein + (nob(i) * (nob(i) + 1)) / 2
477 if ((this % two_electron_window == -1 .and. this % one_electron_window == -1) .or. grid % lrank == local_master)
then
478 call search(iounit, ctrans1, ifail)
480 call intape(iounit, this % one_electron_integral, this % num_one_electron_integrals)
483 if (this % positron_flag /= 0)
then
484 allocate(xtempe(this % num_one_electron_integrals), stat = ifail)
485 call master_memory % track_memory(storage_size(xtempe)/8,
size(xtempe), ifail,
'SWEDEN::xtempe')
487 allocate(xtempp(this % num_one_electron_integrals), stat = ifail)
488 call master_memory % track_memory(storage_size(xtempp)/8,
size(xtempp), ifail,
'SWEDEN::xtempp')
490 xtempe(1:this % num_one_electron_integrals) = this % one_electron_integral(1:this % num_one_electron_integrals)
491 call intape(iounit, xtempp, this % num_one_electron_integrals)
494 if (this % quantamoln_flag)
then
499 write (413,
"(i6,3x,i6,3x,i6,5x,f12.7)") k - 1, l, l, xtempp(ind)
504 do i = 1, this % num_one_electron_integrals
505 this % one_electron_integral(i + this % num_one_electron_integrals) = 2.0_wp * xtempp(i) - xtempe(i)
508 call master_memory % free_memory(storage_size(xtempp)/8,
size(xtempp))
510 call master_memory % free_memory(storage_size(xtempe)/8,
size(xtempe))
514 call chn2e(iounit, stdout, this % two_electron_integral, this % num_two_electron_integrals)
517 1600
format(
' Integrals read successfully:', /, &
518 ' 1-electron integrals, NINT1e =',i10, /, &
519 ' 2-electron integrals, NINT2e =',i10)
521 write (stdout, 1600) this % num_one_electron_integrals, this % num_two_electron_integrals
523 this % nhe(:) = nhe(:)
527 this % nhe(:) = nob(:)
528 this % dtnuc(22:41) = 0
529 this % dtnuc(2:21) = 0
533 call search(iounit, cpoly, ifail)
534 read (iounit) this % nnuc
536 allocate(this % xnuc(this % nnuc), this % ynuc(this % nnuc), this % znuc(this % nnuc), &
537 this % charge(this % nnuc), this % CNAME(this % nnuc))
539 do i = 1, this % nnuc
540 read (iounit) this % cname(i), ii, this % xnuc(i), this % ynuc(i), this % znuc(i), this % charge(i)
543 call master_timer % stop_timer(
'SWEDEN load')
547 call mpi_memory_synchronize(this % one_electron_window)
548 call mpi_memory_synchronize(this % two_electron_window)
553 function get_integral_sweden (this, i, j, k, l, m)
result(coeff)
554 class(swedenintegral) :: this
555 integer,
intent(in) :: i, j, k, l, m
557 integer :: ia, ib, integral_idx
563 integral_idx = this % get_one_electron_index(j, l, m)
564 coeff = this % one_electron_integral(integral_idx)
566 integral_idx = this % get_two_electron_index(i, j, k, l, m)
567 coeff = this % two_electron_integral(integral_idx)
573 integer function get_one_electron_index (this, i, j, pos)
574 class(swedenintegral),
intent(in) :: this
575 integer,
intent(in) :: i, j, pos
576 integer :: m, p, q, ii, jj
578 ii = this % orbital_mapping(i)
579 jj = this % orbital_mapping(j)
581 p = this % orbital_idx(ii)
582 q = this % orbital_idx(jj)
584 m = this % symmetry_idx(ii)
587 get_one_electron_index = this % pair_idx(q) + p + this % one_electron_pointer(m + 1) - 1
589 get_one_electron_index = this % pair_idx(p) + q + this % one_electron_pointer(m + 1) - 1
592 if (pos /= 0) get_one_electron_index = get_one_electron_index + this % num_one_electron_integrals
598 integer function get_two_electron_index (this, i, j, k, l, m)
599 class(swedenintegral),
intent(in) :: this
600 integer,
intent(in) :: i, j, k, l, m
602 integer,
dimension(4) :: orb_num_sym, orb_sym, num_orb_sym
605 integer :: mpq, mrs, mpr, aaa, block_pointer, nobrs, nobpq, ipqrs
607 mapped(1) = this % orbital_mapping(i)
608 mapped(2) = this % orbital_mapping(j)
609 mapped(3) = this % orbital_mapping(k)
610 mapped(4) = this % orbital_mapping(l)
613 orb_num_sym(ido) = this % orbital_idx(mapped(ido))
614 symmetry = this % symmetry_idx(mapped(ido)) + 1
615 orb_sym(ido) = symmetry
616 num_orb_sym(ido) = this % num_orbitals_sym(symmetry)
621 mpq = this % pair_idx(orb_sym(1)) + orb_sym(2)
622 mrs = this % pair_idx(orb_sym(3)) + orb_sym(4)
623 mpr = this % pair_idx(mpq) + mrs
625 if (mpq == mrs .and. &
626 ( orb_num_sym(1) < orb_num_sym(3) .or. &
627 (orb_num_sym(1) == orb_num_sym(3) .and. orb_num_sym(2) < orb_num_sym(4)) .or. &
628 (orb_num_sym(1) < orb_num_sym(3) .and. orb_num_sym(2) < orb_num_sym(4)) ))
then
629 aaa = orb_num_sym(1) ; orb_num_sym(1) = orb_num_sym(3) ; orb_num_sym(3) = aaa
630 aaa = orb_sym(1) ; orb_sym(1) = orb_sym(3) ; orb_sym(3) = aaa
631 aaa = orb_num_sym(2) ; orb_num_sym(2) = orb_num_sym(4) ; orb_num_sym(4) = aaa
632 aaa = orb_sym(2) ; orb_sym(2) = orb_sym(4) ; orb_sym(4) = aaa
635 block_pointer = this % two_electron_pointer(mpr) - 1
637 if (orb_sym(1) == orb_sym(2) .and. orb_sym(3) == orb_sym(4) .and. orb_sym(1) == orb_sym(3))
then
638 ipqrs = this % pair_idx(orb_num_sym(1)) + orb_num_sym(2)
640 ipqrs = this % pair_idx(ipqrs - 1) + ipqrs - 1 + this % pair_idx(orb_num_sym(3)) + orb_num_sym(4)
641 else if (orb_sym(1) == orb_sym(3) .and. orb_sym(2) == orb_sym(4))
then
642 ipqrs = (orb_num_sym(1) - 1) * num_orb_sym(2) + orb_num_sym(2) - 1
644 ipqrs = this % pair_idx(ipqrs) + ipqrs + (orb_num_sym(3) - 1) * num_orb_sym(4) + orb_num_sym(4)
645 else if (orb_sym(1) == orb_sym(2) .and. orb_sym(3) == orb_sym(4))
then
646 nobrs = this % pair_idx(num_orb_sym(3)) + num_orb_sym(3)
647 ipqrs = (this % pair_idx(orb_num_sym(1)) + orb_num_sym(2) - 1)*nobrs + this % pair_idx(orb_num_sym(3)) + orb_num_sym(4)
649 nobrs = num_orb_sym(3) * num_orb_sym(4)
650 ipqrs = ((orb_num_sym(1) - 1) * num_orb_sym(2) + orb_num_sym(2) - 1) * nobrs + (orb_num_sym(3) - 1) * num_orb_sym(4) &
654 get_two_electron_index = ipqrs + block_pointer + 1
679 subroutine destroy_integral_sweden (this)
680 class(swedenintegral) :: this
686 call mpi_memory_deallocate_real(this % one_electron_integral, &
687 size(this % one_electron_integral), this % one_electron_window)
688 call mpi_memory_deallocate_real(this % two_electron_integral, &
689 size(this % two_electron_integral), this % two_electron_window)
695 if (
allocated(this % pair_labels))
then
696 call master_memory % free_memory(storage_size(this % pair_labels)/8,
size(this % pair_labels))
697 deallocate(this % pair_labels)
701 if (
allocated(this % num_orbitals_sym))
then
702 call master_memory % free_memory(storage_size(this % num_orbitals_sym)/8,
size(this % num_orbitals_sym))
703 deallocate(this % num_orbitals_sym)
706 if (
allocated(this % one_electron_pointer))
then
707 call master_memory % free_memory(storage_size(this % one_electron_pointer)/8,
size(this % one_electron_pointer))
708 deallocate(this % one_electron_pointer)
711 if (
allocated(this % two_electron_pointer))
then
712 call master_memory % free_memory(storage_size(this % two_electron_pointer)/8,
size(this % two_electron_pointer))
713 deallocate(this % two_electron_pointer)
716 if (
allocated(this % pair_idx))
then
717 call master_memory % free_memory(storage_size(this % pair_idx)/8,
size(this % pair_idx))
718 deallocate(this % pair_idx)
721 if (
allocated(this%orbital_idx))
then
722 call master_memory % free_memory(storage_size(this % orbital_idx)/8,
size(this % orbital_idx))
723 deallocate(this %orbital_idx)
726 if (
allocated(this % symmetry_idx))
then
727 call master_memory % free_memory(storage_size(this % symmetry_idx)/8,
size(this % symmetry_idx))
728 deallocate(this % symmetry_idx)