MPI-SCATCI  2.0
An MPI version of SCATCI
CSF_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 
34 module csf_module
35 
36  use const_gbl, only: stdout
37  use mpi_memory_gbl, only: mpi_memory_allocate_integer_2dim, mpi_memory_allocate_real, mpi_memory_synchronize, &
38  mpi_memory_deallocate_integer_2dim, mpi_memory_deallocate_real, local_master
39  use mpi_gbl, only: mpi_mod_barrier, shared_enabled
40  use precisn, only: longint, wp
41  use scatci_routines, only: rdnfto, rdwf, setposwf
43  use options_module, only: options
44  use orbital_module, only: orbitaltable
45  use parallelization_module, only: grid => process_grid
46 
47  implicit none
48 
49  private
50 
52 
63  type :: csfmanager
64 #ifdef mpithree
65  integer(longint), pointer :: int64dtrs(:,:)
66  real(wp), pointer :: coeffdtrs(:)
67 #else
68  integer(longint), allocatable :: int64dtrs(:,:)
69  real(wp), allocatable :: coeffdtrs(:)
70 #endif
71 
72  integer :: int64_win = -1
73  integer :: coeffs_win = -1
74 
75  integer :: megul
76  integer :: num_csfs
77  integer :: length_coeff
78  integer :: length_dtrs
79  integer, pointer :: num_dtr_csf_out(:)
80 
81  !---------CSF body------------------------------!
82  integer, allocatable :: index_dtrs(:)
83  integer, allocatable :: index_coeffs(:)
84  integer, allocatable :: packed_dtrs(:)
85  real(wp), allocatable :: coeffs(:)
86 
87  class(options), pointer :: option_ptr
88  integer :: largest_num_configs
89 
90  !This is for the fast slater rules
91  integer :: num_mo
92  integer :: num_so
93  integer :: num_electrons
94  integer :: nints
95 
96  integer, allocatable :: orbitals(:)
97  integer, allocatable :: spin(:)
98  integer, allocatable :: reference_dtrs(:)
99  integer(longint), allocatable :: ref_int64dtrs(:)
100  class(orbitaltable), pointer :: pt_orb
101  contains
102  procedure, public :: initialize => read_csf_body
103  procedure, public :: print => print_all_csfs
104  procedure, public :: create_csfs
105  procedure, public :: toggle_determinant
106  procedure, public :: finalize => finalize_manager
107  end type csfmanager
108 
109 
119  type(csfobject), pointer :: csf
120  integer :: id_dtr
121  contains
122  procedure, public :: compare_excitations_fast
123  procedure, public :: get_determinants
125  end type csforbital
126 
127 
136  type(csfmanager), pointer :: manager
137  type(csforbital), allocatable :: orbital(:)
138  integer :: num_orbitals
139  integer :: id
140  integer :: orbital_sequence_number
141  logical :: is_continuum
142  integer :: target_symmetry
143  integer :: continuum_symmetry
144  integer :: continuum_orbital_idx
145  integer :: target_configuration
146  contains
147  procedure, public :: print => print_csf
148  procedure, public :: check_slater => does_it_obey_slater
149  end type csfobject
150 
151 contains
152 
161  subroutine read_csf_body (this, option, orbital)
162  class(csfmanager), intent(inout) :: this
163  class(options), intent(in) :: option
164  class(orbitaltable), intent(in), target :: orbital
165 
166  integer :: ido, ifail, size_mem
167 
168  ! Store important values for the CSF generation
169  this % num_csfs = option % num_csfs
170  this % length_dtrs = option % length_dtrs
171  this % length_coeff = option % length_coeff
172  this % megul = option % megul
173 
174  allocate(this % num_dtr_csf_out(this % num_csfs), stat = ifail)
175 
176  call master_memory % track_memory(kind(this % num_dtr_csf_out), &
177  size(this % num_dtr_csf_out), ifail, 'CSFMANAGER::num_dtr_csr_out')
178 
179  this % num_dtr_csf_out = option % num_dtr_csf_out
180  this % num_electrons = option % num_electrons
181 
182  this % num_MO = orbital % total_num_orbitals
183  this % num_SO = orbital % total_num_spin_orbitals
184 
185  allocate(this % orbitals(this % num_SO), &
186  this % reference_dtrs(this % num_electrons), &
187  this % spin(this % num_SO), stat = ifail)
188 
189  call master_memory % track_memory(kind(this % orbitals), &
190  size(this % orbitals), ifail, 'CSFMANAGER::orbitals')
191  call master_memory % track_memory(kind(this % reference_dtrs), &
192  size(this % reference_dtrs), ifail, 'CSFMANAGER::reference_dtrs')
193  call master_memory % track_memory(kind(this % spin), &
194  size(this % spin), ifail, 'CSFMANAGER::spin')
195 
196  do ido = 1, this % num_SO
197  this % orbitals(ido) = orbital % get_orbital_number(ido)
198  this % spin(ido) = orbital % get_spin(ido)
199  end do
200 
201  this % reference_dtrs(:) = option % reference_dtrs(:)
202  this % Nints = this % num_SO / 64 + 1
203 
204  allocate(this % ref_int64dtrs(this % Nints), stat = ifail)
205 
206  call master_memory % track_memory(kind(this % ref_int64dtrs), &
207  size(this % ref_int64dtrs), ifail, 'CSFMANAGER::ref_int64dtrs')
208 
209  this % ref_int64dtrs(:) = 0
210  write (stdout, "('Nints = ',i4)") this % Nints
211  this % pt_orb => orbital
212 
213  do ido = 1, this % num_electrons
214  call this % toggle_determinant(this % reference_dtrs(ido), this % ref_int64dtrs, this % Nints)
215  end do
216 
217  if ((shared_enabled .and. grid % lrank == local_master) .or. .not. shared_enabled) then
218  ! Allocate arrays for reading from congen output
219  allocate(this % index_dtrs(this % num_csfs + 1), &
220  this % index_coeffs(this % num_csfs + 1), &
221  this % packed_dtrs(this % length_dtrs), &
222  this % coeffs(this % length_coeff), stat = ifail)
223 
224  ! Rewind and reposition CONGEN file to the beginning of the wavefunction data
225  call setposwf(option % positron_flag, &
226  option % num_continuum, &
227  option % num_target_sym, &
228  this % megul)
229 
230  ! Read from congen
231  call rdwf(this % num_csfs + 1, &
232  this % index_coeffs, &
233  this % index_dtrs, &
234  this % packed_dtrs, &
235  this % length_dtrs, &
236  this % coeffs, &
237  this % length_coeff, &
238  this % megul)
239  end if
240 
241  end subroutine read_csf_body
242 
243 
250  subroutine finalize_manager (this)
251  class(csfmanager), intent(inout), target :: this
252 
253  call master_memory % free_memory(kind(this % num_dtr_csf_out), size(this % num_dtr_csf_out))
254  call master_memory % free_memory(kind(this % orbitals), size(this % orbitals))
255  call master_memory % free_memory(kind(this % reference_dtrs), size(this % reference_dtrs))
256  call master_memory % free_memory(kind(this % spin), size(this % spin))
257  call master_memory % free_memory(kind(this % ref_int64dtrs), size(this % ref_int64dtrs))
258 
259  if (associated(this % num_dtr_csf_out)) deallocate (this % num_dtr_csf_out)
260  if (allocated(this % orbitals)) deallocate (this % orbitals)
261  if (allocated(this % reference_dtrs)) deallocate (this % reference_dtrs)
262  if (allocated(this % spin)) deallocate (this % spin)
263  if (allocated(this % ref_int64dtrs)) deallocate (this % ref_int64dtrs)
264 
265  if (allocated(this % index_dtrs)) deallocate (this % index_dtrs)
266  if (allocated(this % index_coeffs)) deallocate (this % index_coeffs)
267  if (allocated(this % packed_dtrs)) deallocate (this % packed_dtrs)
268  if (allocated(this % coeffs)) deallocate (this % coeffs)
269 
270  call mpi_memory_deallocate_integer_2dim(this % int64dtrs, size(this % int64dtrs), this % int64_win, grid % lcomm)
271  call mpi_memory_deallocate_real(this % coeffdtrs, size(this % coeffdtrs), this % coeffs_win, grid % lcomm)
272 
273  end subroutine finalize_manager
274 
275 
292  subroutine create_csfs (this, CSF, orbital_sequence, num_ci_target_sym, continuum_projection)
293 
294  class(csfmanager), intent(inout), target :: this
295  type(csfobject), intent(inout), allocatable, target :: CSF(:)
296  integer, intent(in) :: num_ci_target_sym(:), continuum_projection(:)
297 
298  integer :: orbital_sequence(this % num_csfs)
299  integer :: csf_det(this % num_electrons)
300 
301  real(wp) :: phase_fold
302  integer :: ido, jdo, kdo, ifail, num_orbs, start_index_dtr, start_index_coeff, num_spin_orb
303  integer :: dtr_size, elec_idx, total_number_orbs, orb_counter, count_number, symmetry_idx
304 
305  symmetry_idx = 1
306  count_number = 1
307  this % largest_num_configs = 0
308 
309  write (stdout, "('Creating our CSFs.........')", advance = "no")
310 
311  total_number_orbs = 0
312  orb_counter = 0
313  do ido = 1, this % num_csfs
314  total_number_orbs = total_number_orbs + this % num_dtr_csf_out(ido)
315  end do
316 
317  write (stdout, "('Total number of determinants = ',i12)") total_number_orbs
318 
319  allocate(csf(this % num_csfs))
320 
321  this % int64_win = mpi_memory_allocate_integer_2dim(this % int64dtrs, this % Nints, total_number_orbs, grid % lcomm)
322  this % coeffs_win = mpi_memory_allocate_real(this % coeffdtrs, total_number_orbs, grid % lcomm)
323 
324  call mpi_mod_barrier(ifail, grid % gcomm)
325  call mpi_memory_synchronize(this % int64_win, grid % lcomm)
326  call mpi_memory_synchronize(this % coeffs_win, grid % lcomm)
327 
328  do ido = 1, this % num_csfs
329  num_orbs = this % num_dtr_csf_out(ido)
330 
331  csf(ido) % id = ido
332  csf(ido) % manager => this
333  csf(ido) % num_orbitals = num_orbs
334 
335  ! Store the orbital number from mkpt
336  csf(ido) % orbital_sequence_number = orbital_sequence(ido)
337 
338  this % largest_num_configs = max(this % largest_num_configs, num_orbs)
339 
340  if (csf(ido) % orbital_sequence_number > 0) then
341 
342  csf(ido) % is_continuum = .true.
343  csf(ido) % continuum_orbital_idx = mod(ido - 1, 2)
344  csf(ido) % target_symmetry = symmetry_idx
345  csf(ido) % target_configuration = ((count_number - 1) / 2) + 1
346  csf(ido) % continuum_symmetry = continuum_projection(symmetry_idx) + 1
347 
348  count_number = count_number + 1
349 
350  if (count_number > num_ci_target_sym(symmetry_idx) * 2) then
351  symmetry_idx = symmetry_idx + 1
352  count_number = 1
353  end if
354 
355  else
356 
357  csf(ido) % is_continuum = .false.
358 
359  end if
360 
361  orb_counter = orb_counter + 1
362  allocate(csf(ido) % orbital(num_orbs), stat = ifail) ! Allocate our orbitals
363 
364  csf(ido) % orbital(1) % id_dtr = orb_counter
365  csf(ido) % orbital(1) % csf => csf(ido)
366 
367  if ((shared_enabled .and. grid % lrank == local_master) .or. .not. shared_enabled) then
368  !Assign the coefficient to the first
369  start_index_dtr = this % index_dtrs(ido)
370  start_index_coeff = this % index_coeffs(ido) - 1
371  num_spin_orb = this % packed_dtrs(start_index_dtr)
372  this % int64dtrs(:,orb_counter) = this % ref_int64dtrs(:)
373  csf_det(:) = this % reference_dtrs(:)
374 
375  do kdo = 1, num_spin_orb
376  call this % toggle_determinant(this % packed_dtrs(start_index_dtr + kdo), &
377  this % int64dtrs(:,orb_counter), this % Nints)
378  call this % toggle_determinant(this % packed_dtrs(start_index_dtr + num_spin_orb + kdo), &
379  this % int64dtrs(:,orb_counter), this % Nints)
380  elec_idx = this % pt_orb % get_electron_number(this % packed_dtrs(start_index_dtr + kdo))
381  csf_det(elec_idx) = this % packed_dtrs(start_index_dtr + num_spin_orb + kdo)
382  end do
383 
384  phase_fold = 1_wp
385  call qsortdets(csf_det, phase_fold)
386  this % coeffdtrs(orb_counter) = this % coeffs(start_index_coeff + 1) * phase_fold
387  start_index_dtr = start_index_dtr + 2 * num_spin_orb + 1
388  end if
389 
390  !Move to the next orbital
391 
392  !Do for the rest
393  do jdo = 2, num_orbs
394  orb_counter = orb_counter + 1
395  csf(ido) % orbital(jdo) % id_dtr = orb_counter
396  csf(ido) % orbital(jdo) % csf => csf(ido)
397 
398  if ((shared_enabled .and. grid % lrank == local_master) .or. .not. shared_enabled) then
399  num_spin_orb = this % packed_dtrs(start_index_dtr)
400  this % int64dtrs(:,orb_counter) = this % ref_int64dtrs(:)
401  csf_det(:) = this % reference_dtrs(:)
402 
403  do kdo = 1, num_spin_orb
404  call this % toggle_determinant(this % packed_dtrs(start_index_dtr + kdo), &
405  this % int64dtrs(:,orb_counter), this % Nints)
406  call this % toggle_determinant(this % packed_dtrs(start_index_dtr + num_spin_orb + kdo), &
407  this % int64dtrs(:,orb_counter), this % Nints)
408  elec_idx = this % pt_orb % get_electron_number(this % packed_dtrs(start_index_dtr + kdo))
409  csf_det(elec_idx) = this % packed_dtrs(start_index_dtr + num_spin_orb + kdo)
410  end do
411 
412  phase_fold = 1_wp
413  call qsortdets(csf_det, phase_fold)
414  this % coeffdtrs(orb_counter) = this % coeffs(start_index_coeff + jdo) * phase_fold
415  start_index_dtr = start_index_dtr + 2 * num_spin_orb + 1
416  end if
417  end do
418  end do
419 
420  write (stdout, "('success!')")
421  write (stdout, "('Largest number of configurations in a single CSF is ',i10)") this % largest_num_configs
422 
423  call mpi_mod_barrier(ifail, grid % gcomm)
424  call mpi_memory_synchronize(this % int64_win, grid % lcomm)
425  call mpi_memory_synchronize(this % coeffs_win, grid % lcomm)
426  !call master_memory % free_memory(kind(this % index_dtrs), size(this % index_dtrs))
427  !call master_memory % free_memory(kind(this % index_coeffs), size(this % index_coeffs))
428  !call master_memory % free_memory(kind(this % packed_dtrs), size(this % packed_dtrs))
429  call master_memory % free_memory(kind(this % num_dtr_csf_out),size(this % num_dtr_csf_out))
430 
431  ! We don't need them anymore
432  if ((shared_enabled .and. grid % lrank == local_master) .or. .not. shared_enabled) then
433  deallocate(this % index_dtrs, this % index_coeffs, this % packed_dtrs, this % coeffs)
434  end if
435  deallocate(this % num_dtr_csf_out)
436 
437  end subroutine create_csfs
438 
439 
440  subroutine print_csf (this)
441  class(csfobject), intent(in) :: this
442  end subroutine print_csf
443 
444 
445  subroutine print_all_csfs (this, csf)
446  class(csfmanager), intent(in) :: this
447  class(csfobject), intent(in) :: csf(:)
448  integer :: ido
449 
450  do ido = 1, this % num_csfs
451  call csf(ido) % print
452  end do
453 
454  end subroutine print_all_csfs
455 
456 
457  subroutine destroy_orbitals (this)
458  type(csforbital) :: this
459  end subroutine destroy_orbitals
460 
461 
462  subroutine compare_excitations_fast (this, that, num_electrons, coeff, num_excitations, output_dtrs)
463  class(csforbital), intent(in) :: this, that
464  class(csfmanager), pointer :: manager
465  integer, intent(in) :: num_electrons
466  integer, intent(out) :: num_excitations
467  integer, intent(out) :: output_dtrs(4)
468  real(wp), intent(out) :: coeff
469  real(wp) :: phase
470 
471  phase = 1
472  coeff = 0.0_wp
473  output_dtrs = 0
474 
475  manager => this % csf % manager
476 
477  !DIR$ FORCEINLINE
478  call get_excitation(manager % int64dtrs(:, this % id_dtr), &
479  manager % int64dtrs(:, that % id_dtr), &
480  output_dtrs, num_excitations, phase, manager % Nints)
481 
482  coeff = phase * manager % coeffdtrs(this % id_dtr) &
483  * manager % coeffdtrs(that % id_dtr)
484 
485  end subroutine compare_excitations_fast
486 
487 
488  integer function does_it_obey_slater (this, that)
489  class(csfobject), intent(in) :: this, that
490  class(csfmanager), pointer :: manager
491  integer :: min_num_excitation, ido
492 
493  manager => this % manager
494 
495  does_it_obey_slater = pzero(manager % int64dtrs(:, this % orbital(1) % id_dtr), &
496  manager % int64dtrs(:, that % orbital(1) % id_dtr), &
497  manager % Nints)
498 
499  end function does_it_obey_slater
500 
501 
502  subroutine toggle_determinant (this, det0, det1, Nints)
503  class(csfmanager), intent(in) :: this
504  integer, intent(in) :: Nints
505  integer :: det0
506  integer(longint) :: det1(Nints)
507  integer(longint) :: bit_set
508  integer :: spin_position, array_position, local_orbital
509 
510  bit_set = 0
511  array_position = (det0 - 1) / 64 + 1
512  ! odd is alpha even is beta
513 
514  local_orbital = det0 - (array_position - 1) * 64 - 1
515  bit_set = ibset(bit_set, local_orbital)
516 
517  det1(array_position) = ieor(det1(array_position), bit_set)
518 
519  end subroutine toggle_determinant
520 
521 
522  integer function pzero (det1, det2, Nint)
523  integer, intent(in) :: nint
524  integer(longint), intent(in) :: det1(nint), det2(nint)
525  integer(longint) :: xor1
526  integer :: l, nexcitations = 0
527 
528  xor1 = ieor(det1(1), det2(1))
529  pzero = popcnt(ieor(get_beta(xor1), get_alpha(xor1)))
530 
531  do l = 2, nint
532  xor1 = ieor(det1(l), det2(l))
533  pzero = pzero + popcnt(ieor(get_beta(xor1), get_alpha(xor1)))
534  end do
535 
536  end function pzero
537 
538 
539  ! \brief Select only beta orbitals
540  ! \date 2017 - 2020
541  ! \author A Al-Refaie, J Benda
542  !
543  ! Given a section of a bit array representing the population of spin-orbitals, mask out the the alpha
544  ! orbitals (odd bits), keeping only the even bits. On return, the even bits are shifted one bit back,
545  ! to odd positions.
546  !
547  ! Note that rather than masking out odd bits and then shifting the result, we do it the other way round (first
548  ! shift, then mask out *even* bits). This is because in some circumstances the leading non-zero bit is reserved
549  ! for sign and constructing a mask that explicitly sets it may result in "Arithmetic Overflow" errors.
550  !
551  elemental integer function get_beta (det)
552  integer(longint), intent(in) :: det
553  integer(longint), parameter :: mask = int(z'5555555555555555', longint) ! = 0101...0101
554 
555  get_beta = iand(ishft(det, -1), mask)
556 
557  end function get_beta
558 
559 
560  ! \brief Select only alpha orbitals
561  ! \date 2017 - 2020
562  ! \author A Al-Refaie, J Benda
563  !
564  ! Given a section of a bit array representing the population of spin-orbitals, mask out the the beta
565  ! orbitals (even bits), keeping only the odd bits.
566  !
567  elemental integer function get_alpha (det)
568  integer(longint), intent(in) :: det
569  integer(longint), parameter :: mask = int(z'5555555555555555', longint) ! = 0101...0101
570 
571  get_alpha = iand(det, mask)
572 
573  end function get_alpha
574 
575 
576  integer function n_excitations (det1, det2, Nint)
577  integer, intent(in) :: nint
578  integer(longint), intent(in) :: det1(nint), det2(nint)
579 
580  integer :: l
581 
582  n_excitations = popcnt(ieor(det1(1), det2(1)))
583 
584  do l = 2, nint
585  n_excitations = n_excitations + popcnt(ieor(det1(l), det2(l)))
586  end do
587 
588  n_excitations = ishft(n_excitations, -1)
589 
590  end function n_excitations
591 
592 
593  subroutine get_excitation (det1, det2, exc, degree, phase, Nint)
594  integer, intent(in) :: Nint
595  integer(longint), intent(in) :: det1(Nint,2), det2(Nint,2)
596  integer, intent(out) :: exc(4)
597  integer, intent(out) :: degree
598  double precision, intent(inout) :: phase
599 
600  degree = n_excitations(det1, det2, nint)
601 
602  select case (degree)
603  case (3:)
604  return
605  case (2)
606  call get_double_excitation(det1, det2, exc, phase, nint)
607  return
608  case (1)
609  call get_single_excitation(det1, det2, exc(3:4), phase, nint)
610  return
611  case (0)
612  return
613  end select
614 
615  end subroutine get_excitation
616 
617 
618  subroutine get_single_excitation (det1, det2, exc, phase, Nint)
619  integer, intent(in) :: Nint
620  integer(longint), intent(in) :: det1(Nint)
621  integer(longint), intent(in) :: det2(Nint)
622  integer, intent(inout) :: exc(2)
623  double precision, intent(out) :: phase
624 
625  integer :: tz, l, ispin, ishift, nperm, i, j, k, m, n, high, low
626  integer :: holes(1)
627  integer :: particles(1)
628  integer(longint) :: hole, particle, tmp, masklow, maskhigh
629  double precision, parameter :: phase_dble(0:1) = (/ 1.d0, -1.d0 /)
630 
631  nperm = 0
632  exc(:) = 0
633  ishift = -63
634  do l = 1, nint
635  ishift = ishift + 64
636  if (det1(l) == det2(l)) cycle
637  tmp = ieor(det1(l), det2(l))
638  particle = iand(tmp, det2(l))
639  hole = iand(tmp, det1(l))
640  if (particle /= 0_8) then
641  tz = trailz(particle)
642  exc(2) = tz + ishift
643  end if
644  if (hole /= 0_8) then
645  tz = trailz(hole)
646  !exc(0,1,ispin) = 1
647  exc(1) = tz + ishift
648  end if
649  if (exc(1) /= 0 .and. exc(2) /=0 ) then
650  low = min(exc(1), exc(2))
651  high = max(exc(1), exc(2))
652  j = ishft(low - 1, -6) + 1
653  n = iand(low - 1, 63)
654  k = ishft(high - 1, -6) + 1
655  m = iand(high - 1, 63)
656  ! masklow = not(ishft(1_8,n+1))+1
657  ! maskhigh = ishft(1_8,m)-1
658  if (j == k) then
659  nperm = nperm + popcnt(iand(det1(j), iand(not(ishft(1_8, n + 1)) + 1, ishft(1_8, m) - 1)))
660  else
661  nperm = nperm + popcnt(iand(det1(k), ishft(1_8, m) - 1)) &
662  + popcnt(iand(det1(j), not(ishft(1_8, n + 1)) + 1))
663  do i = j + 1, k - 1
664  nperm = nperm + popcnt(det1(i))
665  end do
666  end if
667  phase = phase_dble(iand(nperm, 1))
668  return
669  end if
670  end do
671 
672  end subroutine get_single_excitation
673 
674 
675  subroutine get_double_excitation (det1, det2, exc, phase, Nint)
676  integer, intent(in) :: Nint
677  integer(longint), intent(in) :: det1(Nint), det2(Nint)
678  integer, intent(out) :: exc(4)
679  double precision, intent(out) :: phase
680  integer :: l, ispin, idx_hole, idx_particle, ishift
681  integer :: i, j, k, m, n, high, low, a, b, c, d, nperm, tz, nexc, num_holes
682  integer(longint) :: hole, particle, tmp, spin_total, masklow, maskhigh
683  integer :: holes(2), particles(2), comp(2)
684  double precision, parameter :: phase_dble(0:1) = (/ 1.d0, -1.d0 /)
685 
686  exc(:) = 0
687  nexc = 0
688  nperm = 0
689  idx_particle = 0
690  idx_hole = 0
691  ishift = -63
692  num_holes = 0
693  do l = 1, nint
694  ishift = ishift + 64
695  if (det1(l) == det2(l)) cycle
696  tmp = ieor(det1(l), det2(l))
697  particle = iand(tmp, det2(l))
698  hole = iand(tmp, det1(l))
699  do while (particle /= 0_8)
700  tz = trailz(particle)
701  nexc = nexc + 1
702  idx_particle = idx_particle + 1
703  !exc(2*idx_particle) = tz+ishift
704  particles(idx_particle) = tz + ishift
705  particle = iand(particle, particle - 1_8)
706  end do
707  do while (hole /= 0_8)
708  tz = trailz(hole)
709  nexc = nexc + 1
710  idx_hole = idx_hole + 1
711  holes(idx_hole) = tz + ishift
712  num_holes = num_holes + 1
713  !exc( idx_hole*2 -1) = tz+ishift
714  hole = iand(hole, hole - 1_8)
715  end do
716  if (nexc == 4) exit
717  end do
718 
719  !if(exc(4) < exc(2)) then
720  ! tmp = exc(4)
721  ! exc(4) = exc(2)
722  ! exc(2) = tmp
723  ! endif
724  ! if(exc(3) < exc(1)) then
725  ! tmp = exc(3)
726  ! exc(1) = exc(3)
727  ! exc(3) = tmp
728  ! endif
729  !if(holes(2) < holes(1)) then
730  ! tmp = holes(1)
731  ! holes(1) = holes(2)
732  ! holes(2) = tmp
733  !endif
734 
735  !write(stdout,*) particles
736 
737  !if(particles(2) < particles(1)) then
738  ! tmp = particles(1)
739  ! particles(1) = particles(2)
740  ! particles(2) = tmp
741  !endif
742  ! write(stdout,*) particles
743 
744  do i = 1, num_holes
745  low = min(particles(i), holes(i))
746  high = max(particles(i), holes(i))
747  j = ishft(low - 1, -6) + 1
748  n = iand(low - 1, 63)
749  k = ishft(high - 1, -6) + 1
750  m = iand(high - 1, 63)
751 
752  if (j == k) then
753  nperm = nperm + popcnt(iand(det1(j), iand(not(ishft(1_8, n + 1)) + 1, ishft(1_8, m) - 1)))
754  else
755  nperm = nperm + popcnt(iand(det1(k), ishft(1_8, m) - 1)) &
756  + popcnt(iand(det1(j), not(ishft(1_8, n + 1)) + 1))
757  do l = j + 1, k - 1
758  nperm = nperm + popcnt(det1(l))
759  end do
760  end if
761  end do
762 
763  ! spin_total = iand(particles(1),1) + iand(particles(2),1) + iand(holes(1),1) + iand(holes(2),1)
764  ! if (spin_total == 0 .or. spin_total == 4) then
765 
766  if (num_holes == 2) then
767  a = min(holes(1), particles(1))
768  b = max(holes(1), particles(1))
769  c = min(holes(2), particles(2))
770  d = max(holes(2), particles(2))
771  if (c > a .and. c < b .and. d > b) nperm = nperm + 1
772  end if
773 
774  ! end do
775  !exc(1) = holes(1)
776  !exc(2) = particles(1)
777  !exc(3) = holes(2)
778  !exc(4) = particles(2)
779  !if(holes(1) > holes(2)) then
780  ! comp(1) = particles(1)
781  ! comp(2) = particles(2)
782  ! else
783  ! comp(1) = particles(2)
784  ! comp(2) = particles(1)
785  ! endif
786  ! if(comp(1) > comp(2)) nperm = nperm + 1
787  ! exit
788  ! end if
789  ! end do
790  exc(1) = holes(1)
791  exc(2) = particles(1)
792  exc(3) = holes(2)
793  exc(4) = particles(2)
794 
795  phase = phase_dble(iand(nperm, 1))
796 
797  end subroutine get_double_excitation
798 
799 
800  subroutine assign_pointer (targ, point, Nints)
801  integer, intent(in) :: Nints
802  integer(longint), target, intent(in) :: targ(Nints)
803  integer(longint), pointer, intent(out) :: point(:)
804 
805  point(1:nints) => targ(1:nints)
806 
807  end subroutine assign_pointer
808 
809 
810  subroutine get_determinants (this, dtrs, nelec)
811  integer, intent(in) :: nelec
812  class(csforbital), intent(in) :: this
813  integer, intent(out) :: dtrs(nelec)
814  integer(longint) :: current_so
815  integer :: tz, ishift = -63, ints, idx_dtr, nexec
816 
817  idx_dtr = 0
818  dtrs = 0
819  ishift = -63
820 
821  do ints = 1, this % csf % manager % Nints
822  ishift = ishift + 64
823  current_so = this % csf % manager % int64dtrs(ints, this % id_dtr)
824  do while (current_so /= 0)
825  tz = trailz(current_so)
826  idx_dtr = idx_dtr + 1
827  dtrs(idx_dtr) = tz + ishift
828  current_so = iand(current_so, current_so - 1)
829  end do
830  end do
831 
832  end subroutine get_determinants
833 
834 
835  recursive subroutine qsortdets(A,phase)
836  integer, intent(inout), dimension(:) :: a
837  real(wp), intent(inout) :: phase
838  integer :: iq
839 
840  if (size(a) > 1) then
841  call partition(a, iq, phase)
842  call qsortdets(a(:iq-1), phase)
843  call qsortdets(a(iq:), phase)
844  end if
845 
846  end subroutine qsortdets
847 
848 
849  subroutine partition (A, marker, phase)
850  integer, intent(inout) :: A(:)
851  integer, intent(out) :: marker
852  real(wp), intent(inout) :: phase
853  integer :: i, j
854  integer :: temp
855  integer :: x ! pivot point
856 
857  x = a(1)
858  i = 0
859  j = size(a) + 1
860 
861  do
862  j = j - 1
863  do
864  if (a(j) <= x) exit
865  j = j-1
866  end do
867  i = i + 1
868  do
869  if (a(i) >= x) exit
870  i = i + 1
871  end do
872  if (i < j) then
873  ! exchange A(i) and A(j)
874  temp = a(i)
875  a(i) = a(j)
876  a(j) = temp
877  phase = -phase
878  elseif (i == j) then
879  marker = i + 1
880  return
881  else
882  marker = i
883  return
884  end if
885  end do
886 
887  end subroutine partition
888 
889 end module csf_module
csf_module
CSF module.
Definition: CSF_module.F90:34
memorymanager_module
Memory manager module.
Definition: MemoryManager_module.f90:31
csf_module::compare_excitations_fast
subroutine compare_excitations_fast(this, that, num_electrons, coeff, num_excitations, output_dtrs)
Definition: CSF_module.F90:463
csf_module::get_alpha
elemental integer function get_alpha(det)
Definition: CSF_module.F90:568
csf_module::partition
subroutine partition(A, marker, phase)
Definition: CSF_module.F90:850
csf_module::get_determinants
subroutine get_determinants(this, dtrs, nelec)
Definition: CSF_module.F90:811
options_module::options
Calculation setup for a single Hamiltonian diagonalization.
Definition: Options_module.f90:74
csf_module::assign_pointer
subroutine assign_pointer(targ, point, Nints)
Definition: CSF_module.F90:801
csf_module::destroy_orbitals
subroutine destroy_orbitals(this)
Definition: CSF_module.F90:458
csf_module::does_it_obey_slater
integer function does_it_obey_slater(this, that)
Definition: CSF_module.F90:489
csf_module::csfobject
Single configuration state function.
Definition: CSF_module.F90:135
csf_module::pzero
integer function pzero(det1, det2, Nint)
Definition: CSF_module.F90:523
csf_module::print_csf
subroutine print_csf(this)
Definition: CSF_module.F90:441
csf_module::print_all_csfs
subroutine print_all_csfs(this, csf)
Definition: CSF_module.F90:446
parallelization_module::process_grid
type(processgrid) process_grid
Definition: Parallelization_module.F90:80
csf_module::toggle_determinant
subroutine toggle_determinant(this, det0, det1, Nints)
Definition: CSF_module.F90:503
orbital_module
Target CI Hamiltonian module.
Definition: Orbital_module.f90:31
csf_module::qsortdets
recursive subroutine qsortdets(A, phase)
Definition: CSF_module.F90:836
parallelization_module
Distribution of processes into a grid.
Definition: Parallelization_module.F90:29
csf_module::create_csfs
subroutine create_csfs(this, CSF, orbital_sequence, num_ci_target_sym, continuum_projection)
This subroutine seperates out the CSFs and creates individual objects out of them.
Definition: CSF_module.F90:293
csf_module::get_beta
elemental integer function get_beta(det)
Definition: CSF_module.F90:552
options_module::phase
?
Definition: Options_module.f90:61
csf_module::csforbital
Single determinant.
Definition: CSF_module.F90:118
csf_module::get_single_excitation
subroutine get_single_excitation(det1, det2, exc, phase, Nint)
Definition: CSF_module.F90:619
csf_module::n_excitations
integer function n_excitations(det1, det2, Nint)
Definition: CSF_module.F90:577
csf_module::get_excitation
subroutine get_excitation(det1, det2, exc, degree, phase, Nint)
Definition: CSF_module.F90:594
csf_module::read_csf_body
subroutine read_csf_body(this, option, orbital)
Reads the CSFs.
Definition: CSF_module.F90:162
csf_module::get_double_excitation
subroutine get_double_excitation(det1, det2, exc, phase, Nint)
Definition: CSF_module.F90:676
options_module
Options module.
Definition: Options_module.f90:41
orbital_module::orbitaltable
This class generates the molecular and spin orbitals, stores them and generates symblic elements from...
Definition: Orbital_module.f90:69
csf_module::csfmanager
Configuration state function factory.
Definition: CSF_module.F90:63
memorymanager_module::master_memory
type(memorymanager), public master_memory
This is the global memory manager.
Definition: MemoryManager_module.f90:69
csf_module::finalize_manager
subroutine finalize_manager(this)
Release all memory used by the instance.
Definition: CSF_module.F90:251