MPI-SCATCI 2.0
An MPI version of SCATCI
Loading...
Searching...
No Matches
Hamiltonian_module.f90
Go to the documentation of this file.
1! Copyright 2019
2!
3! For a comprehensive list of the developers that contributed to these codes
4! see the UK-AMOR website.
5!
6! This file is part of UKRmol-in (UKRmol+ suite).
7!
8! UKRmol-in is free software: you can redistribute it and/or modify
9! it under the terms of the GNU General Public License as published by
10! the Free Software Foundation, either version 3 of the License, or
11! (at your option) any later version.
12!
13! UKRmol-in is distributed in the hope that it will be useful,
14! but WITHOUT ANY WARRANTY; without even the implied warranty of
15! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16! GNU General Public License for more details.
17!
18! You should have received a copy of the GNU General Public License
19! along with UKRmol-in (in source/COPYING). Alternatively, you can also visit
20! <https://www.gnu.org/licenses/>.
21
22!> \brief Base Hamiltonian module
23!> \authors A Al-Refaie
24!> \date 2017
25!>
26!> Provides an abstract hamiltonian class that has built in functionalities for all inherited hamiltonians.
27!>
28!> \todo Rewrite the idiag = 0 matrix evaluation into a more easily handled form and chenge variable naming to be less confusing.
29!>
30!> \note 30/01/2017 - Ahmed Al-Refaie: Initial documentation version
31!> \note 16/01/2019 - Jakub Benda: Unifom coding style and expanded documentation.
32!>
33module hamiltonian_module
34
35 use precisn, only: longint, wp
36 use baseintegral_module, only: baseintegral
37 use consts_mpi_ci, only: nidx
38 use csf_module, only: csfobject, csforbital
39 use options_module, only: options
40 use orbital_module, only: orbitaltable, spinorbital
41 use parallelization_module, only: grid => process_grid
42 use symbolic_module, only: symbolicelementvector
43 use utility_module, only: unpack_ints
44
45 implicit none
46
47 public basehamiltonian
48
49 !> \brief This is an abstract class that contains the majority of functionality required to construct hamiltonians
50 !> \authors A Al-Refaie
51 !> \date 2017
52 !>
53 !> This class provides an abstraction of a lot of the components required to build the hamiltonian.
54 !> For example, the user does not need to worry about the specific implementation of Slaters rules or evaluating integrals
55 !> this class wraps these features for you and should allow one to implement hamiltonians closer to those described in papers.
56 !> This is not a Matrix class. BaseHamiltonain deals with building the matrix whilst BaseMatrix deals with storing the matrix.
57 !>
58 type, abstract :: basehamiltonian
59 class(orbitaltable), pointer :: orbitals !< Our orbitals required to generate symblic elements
60 class(options), pointer :: options !< Scatci program settings
61 class(baseintegral), pointer :: integral !< The integrals we are using
62 class(csfobject), pointer :: csfs(:) !< Our configuration state functions
63
64 integer :: nflg = 0
65 integer :: diagonal_flag
66 integer :: positron_flag !< Positron aware flag
67 integer :: phase_flag !< whether to evaluate integrals whilst dealing with phase
68 logical :: constructed = .false. !< Has the hamiltonain been constructed
69 logical :: initialized = .false. !< Has the hamiltonian been initialized
70 integer :: job_id = 0 !< Whose job it is to (soon to be deprecated)
71 integer :: number_of_integrals = 0 !< How many integrals have been evaluated?
72 real(wp) :: element_one = 0.0 !< First element for idiag = 0
73 real(wp) :: enh_factor !< Enhancement factor set in options
74 integer :: enh_factor_type !< Enhancement factor type set in options
75
76 type(symbolicelementvector) :: reference_symbol !< Symbols for idiag = 0
77 contains
78 !Constructor
79 procedure, public :: construct => construct_base_hamiltonian
80 procedure(generic_build), deferred :: build_hamiltonian
81
82 !-----------------------Private procedures-----------------!
83 procedure, public :: slater_rules
84 !procedure, public :: obey_slater_rules
85 procedure, public :: evaluate_integrals
86 procedure, public :: evaluate_integrals_singular
87 !procedure, public :: store_first_element
88
89 !-------Slater rule functions------------------!
90 procedure, private :: handle_two_pair
91 procedure, private :: handle_one_pair
92 procedure, private :: handle_same
93 procedure, public :: my_job
94 end type basehamiltonian
95
96 abstract interface
97 !> \brief Main build routine of the hamiltonian
98 !> \authors A Al-Refaie
99 !> \date 2017
100 !>
101 !> All build must be done within this routine in order to be used by MPI-SCATCI.
102 !> \param[out] matrix_elements Resulting matrix elements from the build.
103 !>
104 subroutine generic_build(this,matrix_elements)
105 use basematrix_module, only: basematrix
106 import :: basehamiltonian
107 class(basehamiltonian) :: this
108 class(basematrix), intent(inout) :: matrix_elements
109 end subroutine generic_build
110 end interface
111
112contains
113
114 !> \brief Constructs the hamiltonain object and provides all the various componenets required for building
115 !> \authors A Al-Refaie
116 !> \date 2017
117 !>
118 !> \param[inout] this Hamiltonian object to update.
119 !> \param[in] option An Options class containing run constants
120 !> \param[in] csfs An array of configuration state functions
121 !> \param[in] orbitals An initialized Orbitals class
122 !> \param[in] integral A BaseIntegral class for evaluating symbols
123 !>
124 subroutine construct_base_hamiltonian (this, option, csfs, orbitals, integral)
125 class(basehamiltonian), intent(inout) :: this
126 class(options), target, intent(in) :: option
127 class(csfobject), target, intent(in) :: csfs(:)
128 class(orbitaltable), target, intent(in) :: orbitals
129 class(baseintegral), target, intent(in) :: integral
130
131 !Assign our member pointers for each class
132 this % options => option
133 this % csfs => csfs
134 this % orbitals => orbitals
135 this % integral => integral
136 this % phase_flag = this % options % phase_correction_flag
137 this % positron_flag = this % options % positron_flag
138 this % enh_factor = this % options % enh_factor
139 this % enh_factor_type = this % options % enh_factor_type
140
141 this % job_id = 0
142 this % diagonal_flag = min(this % options % matrix_eval, 2)
143 this % constructed = .true.
144
145 end subroutine construct_base_hamiltonian
146
147
148 !> \brief Performs Slater rules and returns symbolic elements
149 !> \authors A Al-Refaie
150 !> \date 2017
151 !>
152 !> Computes the Slater rules and adds them to the symbolic elements class that is provided.
153 !> Additionaly has an automatic MPI mode by usage of the job_ = .true. keyword.
154 !> Whilst not faster than manually unrolling a loop, it provides a quick and easy way to fairly
155 !> effectively parallelize the loop. However this is not OpenMP compatible
156 !>
157 !> \param[inout] this Hamiltonian object to query.
158 !> \param[in] csf_a First configuration state function to slater
159 !> \param[in] csf_b Second configuration state function to slater
160 !> \param[out] sym_elements Resulting smbolic elements
161 !> \param[in] flag Whether we are doing the diagonal or not
162 !> \param[in] job_ Whether to use the 'easy' MPI split method
163 !>
164 subroutine slater_rules (this, csf_a, csf_b, sym_elements, flag, job_)
165 class(basehamiltonian), intent(in) :: this
166 class(csfobject), intent(in) :: csf_a, csf_b
167 class(symbolicelementvector), intent(inout) :: sym_elements
168 integer, intent(in) :: flag
169 logical, optional, intent(in) :: job_
170 logical :: job
171 integer :: diag, num_differences, dtr_diff(4), dtr_diff_fast(4), dtr_idx_a, dtr_idx_b
172 real(wp) :: coeff
173
174 !Check for job parameter
175 if (present(job_)) then
176 job = job_
177 else
178 job = .true.
179 end if
180
181 !Clear the symbolic elements ahead of time
182 call sym_elements % clear()
183
184 !Check if we should be doing this
185 if (job) then
186 !If not then return
187 if (.not. this % my_job()) return
188 end if
189
190 !Check if we are not the same
191 if (csf_a % id /= csf_b % id) then
192 !If we are not then quickly check if we need to do a slater calculation
193 if (csf_a % check_slater(csf_b) > 4) return
194 !if(this%obey_slater_rules(csf_a,csf_b) > 4) return
195 end if
196
197 !Loop through the first set of determinants
198 do dtr_idx_a = 1, csf_a % num_orbitals
199 !Loop through the second set of determinants
200 do dtr_idx_b = 1, csf_b % num_orbitals
201
202 !Use the fast slater rules method to check the number of differences and get the differing determinants
203 call csf_a % orbital(dtr_idx_a) % compare_excitations_fast(csf_b % orbital(dtr_idx_b), &
204 this % options % num_electrons, &
205 coeff, &
206 num_differences, &
207 dtr_diff)
208
209 !Depending on the number of differences, we handle it appropriately
210 select case (num_differences)
211 case(3:)
212 cycle
213 case(2)
214 call this % handle_two_pair(dtr_diff, coeff, sym_elements, flag)
215 case(1)
216 call this % handle_one_pair(dtr_diff, coeff, sym_elements, csf_a % orbital(dtr_idx_a), flag)
217 case(0)
218 call this % handle_same(dtr_diff, coeff, sym_elements, csf_a % orbital(dtr_idx_a), flag)
219 end select
220
221 end do
222 end do
223
224 end subroutine slater_rules
225
226
227 !> \brief Handles if there are two pairs of spin orbitals that differ
228 !> \authors A Al-Refaie
229 !> \date 2017
230 !>
231 !> \param[inout] this Hamiltonian object to query.
232 !> \param[in] dtrs A 4 element array of slater determinants that differ.
233 !> \param[in] coeff The computed coefficients from the Slater rules.
234 !> \param[out] sym_element Resulting symbolic elements.
235 !> \param[in] flag Whether we are doing the diagonal or not.
236 !>
237 subroutine handle_two_pair (this, dtrs, coeff, sym_element, flag)
238 class(basehamiltonian) :: this
239 class(symbolicelementvector) :: sym_element
240 integer, intent(in) :: dtrs(4)
241 real(wp), intent(in) :: coeff
242 integer, intent(in) :: flag
243
244 if (this % diagonal_flag> 1 .and. this % orbitals % get_minimum_mcon(dtrs) > 0) return
245
246 !Evaluate for symbolic elements
247 call this % orbitals % evaluate_IJKL_and_coeffs(dtrs, coeff, 0, sym_element, flag)
248
249 end subroutine handle_two_pair
250
251
252 !> \brief Handles if there are one pair of spin orbitals that differ
253 !> \authors A Al-Refaie
254 !> \date 2017
255 !>
256 !> \param[inout] this Hamiltonian object to query.
257 !> \param[in] dtrs A 4 element array of slater determinants
258 !> \param[in] coeff The computed coefficients from the Slater rules
259 !> \param[in] csf The first CSFs determinant
260 !> \param[out] sym_element Resulting symbolic elements
261 !> \param[in] flag Whether we are doing the diagonal or not
262 !>
263 subroutine handle_one_pair (this, dtrs, coeff, sym_element, csf, flag)
264 class(basehamiltonian) :: this
265 class(symbolicelementvector) :: sym_element
266 class(csforbital), intent(in) :: csf
267 integer, intent(inout) :: dtrs(4)
268 real(wp), intent(in) :: coeff
269 integer, intent(in) :: flag
270
271 type(spinorbital) :: so1, so2
272
273 integer :: ref_dtrs(this % options % num_electrons)
274 integer :: num_electrons, N, M, ido, ia1, ia2, lnadd
275 integer :: nchk !Whether its continuum maybe?
276
277 !Reset the positron flag
278 lnadd = 0
279
280 !Get number of electrons
281 num_electrons = this % options % num_electrons
282
283 !Copt the reference determinant to a seperate array
284 !ref_dtrs(:) = this%options%reference_dtrs(:)
285
286 !Loop through the reference and replace the spin orbitals with ones from the CSF
287 !do ido=1,csf%num_replaced_dtrs
288 ! N = csf%replacing(ido)
289 ! M = this%orbitals%get_electron_number(N)
290 ! ref_dtrs(M) = csf%replaced(ido)
291 !enddo
292
293 call csf % get_determinants(ref_dtrs, num_electrons)
294
295 !Not sure what this does exactly
296 if (this % diagonal_flag > 1 .and. this % orbitals % get_two_minimum_mcon(dtrs(3), dtrs(4)) > 0) then
297 nchk = 1
298 else
299 nchk = 0
300 end if
301
302 !Loop through all the spin orbitals
303 do ido = 1, num_electrons
304 !If we have the same spin orbitals then skip
305 if (ref_dtrs(ido) == dtrs(3)) cycle
306 !Again not quite sure what this does
307 if (nchk == 1 .and. this % orbitals % get_mcon(ref_dtrs(ido)) > 0) cycle
308 !Place the reference into our determinant array
309 dtrs(1) = ref_dtrs(ido)
310 dtrs(2) = ref_dtrs(ido)
311 !Now evaluate for symbols
312 call this % orbitals % evaluate_IJKL_and_coeffs(dtrs, coeff, 0, sym_element, flag)
313 end do
314
315 !If this run contains positrons, then add them in if necessary
316 if (this % positron_flag /= 0) lnadd = this % orbitals % add_positron(dtrs, 3, 4)
317 if (nchk == 1) return
318
319 !Get our original slater replacements
320 so1 = this % orbitals % spin_orbitals(dtrs(3))
321 so2 = this % orbitals % spin_orbitals(dtrs(4))
322
323 !Check if they posses the same spin and m quanta
324 if (so1 % m_quanta /= so2 % m_quanta .or. so1 % spin /= so2 % spin) return
325 if (so1 % orbital_number < so2 % orbital_number) then
326 ia1 = so2 % orbital_number
327 ia2 = so1 % orbital_number
328 else
329 ia1 = so1 % orbital_number
330 ia2 = so2 % orbital_number
331 end if
332
333 !if they do then add a 0I0J + P symbol
334 call sym_element % insert_ijklm_symbol(0, ia1, 0, ia2, lnadd, coeff)
335
336 end subroutine handle_one_pair
337
338
339 !> \brief Handles if there are no differences between spin orbitals
340 !> \authors A Al-Refaie
341 !> \date 2017
342 !>
343 !> \param[inout] this Hamiltonian object to query.
344 !> \param[in] dtrs A 4 element array of slater determinants
345 !> \param[in] coeff The computed coefficients from the Slater rules
346 !> \param[in] csf The first CSFs determinant
347 !> \param[out] sym_element Resulting symbolic elements
348 !> \param[in] flag Whether we are doing the diagonal or not
349 !>
350 subroutine handle_same (this, dtrs, coeff, sym_element, csf, flag)
351 class(basehamiltonian) :: this
352 class(symbolicelementvector) :: sym_element
353 class(csforbital), intent(in) :: csf
354 integer, intent(inout) :: dtrs(4)
355 integer :: pdtrs(4)
356 real(wp), intent(in) :: coeff
357 integer, intent(in) :: flag
358
359 type(spinorbital) :: so1, so2
360
361 integer :: ref_dtrs(this % options % num_electrons)
362 integer :: num_electrons, N, M, ido, jdo, ia1, ia2, lnadd
363 integer :: nchk !Whether its continuum maybe?
364
365 !Reset the positron flag
366 lnadd = 0
367
368 !Get number of electrons
369 num_electrons = this % options % num_electrons
370
371 !Copt the reference determinant to a seperate array
372 !ref_dtrs(:) = this%options%reference_dtrs(:)
373
374 !Loop through the reference and replace the spin orbitals with ones from the CSF
375 !do ido=1,csf%num_replaced_dtrs
376 ! N = csf%replacing(ido)
377 ! M = this%orbitals%get_electron_number(N)
378 ! ref_dtrs(M) = csf%replaced(ido)
379 !enddo
380
381 call csf % get_determinants(ref_dtrs, num_electrons)
382
383 do ido = 2, num_electrons
384 dtrs(1) = ref_dtrs(ido)
385 dtrs(2) = dtrs(1)
386 do jdo = 1, ido - 1
387 dtrs(3) = ref_dtrs(jdo)
388 dtrs(4) = dtrs(3)
389 if (this % diagonal_flag > 1 .and. this % orbitals % get_two_minimum_mcon(dtrs(1), dtrs(3)) > 0) cycle
390 !Now evaluate for symbols
391 call this % orbitals % evaluate_IJKL_and_coeffs(dtrs, coeff, 0, sym_element, flag)
392 end do
393 end do
394
395 if (this % NFLG /= 0) this % NFLG = 2
396 do ido = 1, num_electrons
397 n = ref_dtrs(ido)
398 if (this % diagonal_flag > 1 .and. this % orbitals%get_mcon(n) /= 0) cycle
399
400 m = this % orbitals % get_orbital_number(n)
401 if (this % positron_flag /= 0) then
402 pdtrs(1) = n
403 pdtrs(2) = n
404 lnadd = this % orbitals % add_positron(pdtrs, 1, 2)
405 endif
406 call sym_element % insert_ijklm_symbol(0, m, 0, m, lnadd, coeff)
407 end do
408
409 end subroutine handle_same
410
411
412 !> \brief Evaluates a single integral from labels and also checks for dummy orbitals
413 !> \authors A Al-Refaie
414 !> \date 2017
415 !>
416 !> \param[inout] this Hamiltonian object to update.
417 !> \param[in] label A packed integral label
418 !> \param[in] coeff The computed coefficients from the Slater rules
419 !> \param[in] dummy_orb Check wheter to ignore the integral if it contains a dummy orbital of this value
420 !>
421 !> \return Evaluated integral
422 !>
423 real(wp) function evaluate_integrals_singular (this, label, coeff, dummy_orb)
424 USE ukrmol_interface_gbl, ONLY : get_orb_energy
425
426 class(basehamiltonian), intent(inout) :: this
427 integer, intent(in) :: dummy_orb
428 real(wp), intent(in) :: coeff
429 integer(longint), intent(in) :: label(nidx)
430
431 integer :: ido, jdo, num_elements, lwd(8), i, orb_n, orb_num, &
432 belec_orb, velec_orb, posi_orb, enh_factor_type
433
434 real(wp):: integralf, orb_diff, oe, mp2_corr, x1
435
436 real(kind=wp), dimension(4) :: occu_orbe, virt_orbe
437 logical :: with_pos
438
439
440 evaluate_integrals_singular = 0.0
441
442 if (coeff == 0.0_wp) return
443
444 !Search for the dummy orbital
445 if (this % phase_flag > 0) then
446 call unpack_ints(label, lwd)
447 do jdo = 1, 4
448 if (lwd(jdo) == this % phase_flag) return
449 end do
450 else if (this % phase_flag == 0) then
451 call unpack_ints(label, lwd)
452 do jdo = 1, 4
453 if (lwd(jdo) <= 0) cycle
454 if (this % orbitals % mcorb(lwd(jdo)) == 0) return
455 end do
456 end if
457
458 integralf = this % integral % get_integralf(label)
459 call unpack_ints(label,lwd)
460
461 !~~~~~~~~~~~ENHANCEMENT FACTOR BIT ~~~~~~~~~~~~~~~~
462 with_pos=.false.
463 if (lwd(1) > 0) then
464 do i=1, 4
465 if (this % orbitals % mcorb(lwd(i)) .ne. lwd(i)) then
466 with_pos=.true.
467 endif
468 enddo
469 end if
470
471 if (this%enh_factor_type .gt. 1) then
472 if (with_pos) then
473 belec_orb = 0
474 velec_orb = 0
475 posi_orb = 0
476
477 do orb_n=1, 4
478 virt_orbe(orb_n) = 0.0
479 occu_orbe(orb_n) = 0.0
480
481 orb_num = this % orbitals % mcorb(lwd(orb_n)) !orb index
482
483 oe = get_orb_energy(orb_num)
484 if (oe .gt. 0.0) then !virtual or continuum orbital
485 virt_orbe(orb_n) = oe
486 if (this % orbitals % mcorb(lwd(orb_n)) .ne. lwd(orb_n)) then
487 velec_orb = velec_orb + 1
488 else
489 posi_orb = posi_orb + 1
490 endif
491 else !bound orbital
492 occu_orbe(orb_n) = oe
493 if (this % orbitals % mcorb(lwd(orb_n)) .ne. lwd(orb_n)) then
494 belec_orb = belec_orb + 1
495 else
496 posi_orb = posi_orb + 1
497 endif
498 endif
499 enddo
500 orb_diff = 0.0
501 if (belec_orb .eq. 1 .and. velec_orb .eq. 1) then
502 !Energy diff between bound and virtual/continuum
503 !orbitals
504 orb_diff = sum(occu_orbe(1:4)) - sum(virt_orbe(1:4))!Will always be negative
505 x1 = integralf
506 elseif (this % orbitals % mcorb(lwd(1)) .eq. this % orbitals % mcorb(lwd(2)) .and. &
507 this % orbitals % mcorb(lwd(3)) .eq. this % orbitals % mcorb(lwd(4)) .and. &
508 this % orbitals % mcorb(lwd(1)) .eq. this % orbitals % mcorb(lwd(3)) .and. &
509 velec_orb .ne. 0) then
510 !Electron and positron occupying the same orbital -
511 !virtual Ps
512 orb_diff= 1.0 !Orbital energy that all particles are in.
513 x1 = 1
514 endif
515
516 if (orb_diff .ne. 0.0) then !include MP2 correction
517 if (integralf .ge. 0) then
518 mp2_corr = ( (integralf*x1) / orb_diff) * this%enh_factor
519 else
520 mp2_corr = (-(integralf*x1) / orb_diff) * this%enh_factor
521 endif
522 integralf = integralf + mp2_corr
523 endif
524 endif
525 else
526 if (with_pos) then
527 integralf = integralf * this%enh_factor !use provided average enhancement factor. Apply to all (positron) 2-particle integrals
528 endif
529 endif
530 !~~~~~~~~~~~~~END ENHANCEMENT FACTOR BIT~~~~~~~~~~~~~~~~~~~~
531
532 evaluate_integrals_singular = coeff * integralf
533
534 !$OMP ATOMIC
535 this % number_of_integrals = this % number_of_integrals + 1
536
537 end function evaluate_integrals_singular
538
539
540 !> \brief Evaluates all integrals from a list of symbolic elements
541 !> \authors A Al-Refaie
542 !> \date 2017
543 !>
544 !> \param[inout] this Hamiltonian object to update.
545 !> \param[in] symbolic_elements Symbolic elements to be evaluated.
546 !> \param[in] dummy_orb Check wheter to ignore the integral if it contains a dummy orbital of this value.
547 !>
548 !> \return Total evaluated integrals from symbols.
549 !>
550 real(wp) function evaluate_integrals (this, symbolic_elements, dummy_orb)
551 class(basehamiltonian), intent(inout) :: this
552 class(symbolicelementvector), intent(in) :: symbolic_elements
553 integer, intent(in) :: dummy_orb
554
555 integer :: ido, num_elements
556 integer(longint) :: label(nidx)
557 real(wp) :: coeff
558
559 num_elements = symbolic_elements % get_size()
560
561 evaluate_integrals = 0.0_wp
562 if (num_elements == 0) return
563 do ido = 1, num_elements
564 call symbolic_elements % get_coeff_and_integral(ido, coeff, label)
565 evaluate_integrals = evaluate_integrals + this % evaluate_integrals_singular(label, coeff, dummy_orb)
566 end do
567
568 end function evaluate_integrals
569
570
571 !> \brief Used by the easy MPI parallelization of slater loops
572 logical function my_job (this)
573 class(basehamiltonian) :: this
574
575 my_job = .true.
576
577 if (grid % gprocs == 1 .or. grid % grank == -1) return
578
579 if (this % job_id /= grid % grank) then
580 my_job = .false.
581 end if
582
583 this % job_id = this % job_id + 1
584 if (this % job_id == grid % gprocs) then
585 this % job_id = 0
586 end if
587
588 end function my_job
589
590
591 !> \brief ?
592 !> \authors A Al-Refaie
593 !> \date 2017
594 !>
595 !> \deprecated No longer used.
596 !>
597 integer function fast_slat (rep1, rep2, fin1, fin2, num_rep1, num_rep2, spin_orbs, tot_num_spin_orbs)
598 integer, intent(in) :: num_rep1, rep1(num_rep1), fin1(num_rep1)
599 integer, intent(in) :: num_rep2, rep2(num_rep2), fin2(num_rep2), tot_num_spin_orbs
600 integer, intent(inout) :: spin_orbs(tot_num_spin_orbs)
601
602 integer :: i_orbital
603 integer :: i_dtrs
604 integer :: i_spin_orbital
605 integer :: orb_add
606 integer :: orb_remove
607
608 do i_dtrs = 1, num_rep1
609 orb_remove = (rep1(i_dtrs) + 1) / 2
610 orb_add = (fin1(i_dtrs) + 1) / 2
611 spin_orbs(orb_remove) = spin_orbs(orb_remove) - 1
612 spin_orbs(orb_add) = spin_orbs(orb_add) + 1
613 end do
614
615 do i_dtrs = 1, num_rep2
616 orb_remove = (rep2(i_dtrs) + 1) / 2
617 orb_add = (fin2(i_dtrs) + 1) / 2
618 spin_orbs(orb_remove) = spin_orbs(orb_remove) + 1
619 spin_orbs(orb_add) = spin_orbs(orb_add) - 1
620 end do
621
622 fast_slat = 0
623
624 do i_dtrs = 1, num_rep1
625 orb_remove = (rep1(i_dtrs) + 1) / 2
626 orb_add = (fin1(i_dtrs) + 1) / 2
627 fast_slat = fast_slat + spin_orbs(orb_remove)
628 spin_orbs(orb_remove) = 0
629 fast_slat = fast_slat + spin_orbs(orb_add)
630 spin_orbs(orb_add) = 0
631 end do
632
633 do i_dtrs = 1, num_rep2
634 orb_remove = (rep2(i_dtrs) + 1) / 2
635 orb_add = (fin2(i_dtrs) + 1) / 2
636 fast_slat = fast_slat + spin_orbs(orb_remove)
637 spin_orbs(orb_remove) = 0
638 fast_slat = fast_slat + spin_orbs(orb_add)
639 spin_orbs(orb_add) = 0
640 end do
641
642 end function fast_slat
643
644end module hamiltonian_module
MPI SCATCI Constants module.
integer, parameter nidx
Number of long integers used to store up to 8 (packed) integral indices.