35 use integer_packing,
only: unpack8ints
36 use precisn,
only: longint, wp
64 integer :: diagonal_flag
65 integer :: positron_flag
67 logical :: constructed = .false.
68 logical :: initialized = .false.
70 integer :: number_of_integrals = 0
71 real(wp) :: element_one = 0.0
105 class(
basematrix),
intent(inout) :: matrix_elements
123 class(
options),
target,
intent(in) :: option
124 class(
csfobject),
target,
intent(in) :: csfs(:)
129 this % options => option
131 this % orbitals => orbitals
132 this % integral => integral
133 this % phase_flag = this % options % phase_correction_flag
134 this % positron_flag = this % options % positron_flag
137 this % diagonal_flag = min(this % options % matrix_eval, 2)
138 this % constructed = .true.
161 class(
csfobject),
intent(in) :: csf_a, csf_b
163 integer,
intent(in) :: flag
164 logical,
optional,
intent(in) :: job_
166 integer :: diag, num_differences, dtr_diff(4), dtr_diff_fast(4), dtr_idx_a, dtr_idx_b
170 if (
present(job_))
then
177 call sym_elements % clear()
182 if (.not. this % my_job())
return
186 if (csf_a % id /= csf_b % id)
then
188 if (csf_a % check_slater(csf_b) > 4)
return
193 do dtr_idx_a = 1, csf_a % num_orbitals
195 do dtr_idx_b = 1, csf_b % num_orbitals
198 call csf_a % orbital(dtr_idx_a) % compare_excitations_fast(csf_b % orbital(dtr_idx_b), &
199 this % options % num_electrons, &
205 select case (num_differences)
209 call this % handle_two_pair(dtr_diff, coeff, sym_elements, flag)
211 call this % handle_one_pair(dtr_diff, coeff, sym_elements, csf_a % orbital(dtr_idx_a), flag)
213 call this % handle_same(dtr_diff, coeff, sym_elements, csf_a % orbital(dtr_idx_a), flag)
235 integer,
intent(in) :: dtrs(4)
236 real(wp),
intent(in) :: coeff
237 integer,
intent(in) :: flag
239 if (this % diagonal_flag> 1 .and. this % orbitals % get_minimum_mcon(dtrs) > 0)
return
242 call this % orbitals % evaluate_IJKL_and_coeffs(dtrs, coeff, 0, sym_element, flag)
262 integer,
intent(inout) :: dtrs(4)
263 real(wp),
intent(in) :: coeff
264 integer,
intent(in) :: flag
268 integer :: ref_dtrs(this % options % num_electrons)
269 integer :: num_electrons, N, M, ido, ia1, ia2, lnadd
276 num_electrons = this % options % num_electrons
288 call csf % get_determinants(ref_dtrs, num_electrons)
291 if (this % diagonal_flag > 1 .and. this % orbitals % get_two_minimum_mcon(dtrs(3), dtrs(4)) > 0)
then
298 do ido = 1, num_electrons
300 if (ref_dtrs(ido) == dtrs(3)) cycle
302 if (nchk == 1 .and. this % orbitals % get_mcon(ref_dtrs(ido)) > 0) cycle
304 dtrs(1) = ref_dtrs(ido)
305 dtrs(2) = ref_dtrs(ido)
307 call this % orbitals % evaluate_IJKL_and_coeffs(dtrs, coeff, 0, sym_element, flag)
311 if (this % positron_flag /= 0) lnadd = this % orbitals % add_positron(dtrs, 3, 4)
312 if (nchk == 1)
return
315 so1 = this % orbitals % spin_orbitals(dtrs(3))
316 so2 = this % orbitals % spin_orbitals(dtrs(4))
319 if (so1 % m_quanta /= so2 % m_quanta .or. so1 % spin /= so2 % spin)
return
320 if (so1 % orbital_number < so2 % orbital_number)
then
321 ia1 = so2 % orbital_number
322 ia2 = so1 % orbital_number
324 ia1 = so1 % orbital_number
325 ia2 = so2 % orbital_number
329 call sym_element % insert_ijklm_symbol(0, ia1, 0, ia2, lnadd, coeff)
345 subroutine handle_same (this, dtrs, coeff, sym_element, csf, flag)
349 integer,
intent(inout) :: dtrs(4)
350 real(wp),
intent(in) :: coeff
351 integer,
intent(in) :: flag
355 integer :: ref_dtrs(this % options % num_electrons)
356 integer :: num_electrons, N, M, ido, jdo, ia1, ia2, lnadd
363 num_electrons = this % options % num_electrons
375 call csf % get_determinants(ref_dtrs, num_electrons)
377 do ido = 2, num_electrons
378 dtrs(1) = ref_dtrs(ido)
381 dtrs(3) = ref_dtrs(jdo)
383 if (this % diagonal_flag > 1 .and. this % orbitals % get_two_minimum_mcon(dtrs(1), dtrs(3)) > 0) cycle
385 call this % orbitals % evaluate_IJKL_and_coeffs(dtrs, coeff, 0, sym_element, flag)
389 if (this % NFLG /= 0) this % NFLG = 2
390 do ido = 1, num_electrons
392 if (this % diagonal_flag > 1 .and. this % orbitals%get_mcon(n) /= 0) cycle
394 m = this % orbitals % get_orbital_number(n)
395 if (this % positron_flag /= 0) lnadd = this % orbitals % add_positron(dtrs, 1, 2)
396 call sym_element % insert_ijklm_symbol(0, m, 0, m, lnadd, coeff)
415 integer,
intent(in) :: dummy_orb
416 real(wp),
intent(in) :: coeff
417 integer(longint),
intent(in) :: label(2)
419 integer :: ido, jdo, num_elements, lwd(8)
423 if (coeff == 0.0_wp)
return
426 if (this % phase_flag > 0)
then
427 call unpack8ints(label, lwd)
429 if (lwd(jdo) == this % phase_flag)
return
431 else if (this % phase_flag == 0)
then
432 call unpack8ints(label, lwd)
434 if (lwd(jdo) <= 0) cycle
435 if (this % orbitals % mcorb(lwd(jdo)) == 0)
return
442 this % number_of_integrals = this % number_of_integrals + 1
459 class(symbolicelementvector),
intent(in) :: symbolic_elements
460 integer,
intent(in) :: dummy_orb
462 integer :: ido, num_elements
463 integer(longint) :: label(2)
466 num_elements = symbolic_elements % get_size()
469 if (num_elements == 0)
return
470 do ido = 1, num_elements
471 call symbolic_elements % get_coeff_and_integral(ido, coeff, label)
484 if (grid % gprocs == 1 .or. grid % grank == -1)
return
486 if (this % job_id /= grid % grank)
then
490 this % job_id = this % job_id + 1
491 if (this % job_id == grid % gprocs)
then
504 integer function fast_slat (rep1, rep2, fin1, fin2, num_rep1, num_rep2, spin_orbs, tot_num_spin_orbs)
505 integer,
intent(in) :: num_rep1, rep1(num_rep1), fin1(num_rep1)
506 integer,
intent(in) :: num_rep2, rep2(num_rep2), fin2(num_rep2), tot_num_spin_orbs
507 integer,
intent(inout) :: spin_orbs(tot_num_spin_orbs)
511 integer :: i_spin_orbital
513 integer :: orb_remove
515 do i_dtrs = 1, num_rep1
516 orb_remove = (rep1(i_dtrs) + 1) / 2
517 orb_add = (fin1(i_dtrs) + 1) / 2
518 spin_orbs(orb_remove) = spin_orbs(orb_remove) - 1
519 spin_orbs(orb_add) = spin_orbs(orb_add) + 1
522 do i_dtrs = 1, num_rep2
523 orb_remove = (rep2(i_dtrs) + 1) / 2
524 orb_add = (fin2(i_dtrs) + 1) / 2
525 spin_orbs(orb_remove) = spin_orbs(orb_remove) + 1
526 spin_orbs(orb_add) = spin_orbs(orb_add) - 1
531 do i_dtrs = 1, num_rep1
532 orb_remove = (rep1(i_dtrs) + 1) / 2
533 orb_add = (fin1(i_dtrs) + 1) / 2
535 spin_orbs(orb_remove) = 0
537 spin_orbs(orb_add) = 0
540 do i_dtrs = 1, num_rep2
541 orb_remove = (rep2(i_dtrs) + 1) / 2
542 orb_add = (fin2(i_dtrs) + 1) / 2
544 spin_orbs(orb_remove) = 0
546 spin_orbs(orb_add) = 0