<commit_before>module determinants

! Generation, inspection and manipulation of Slater determinants. 

use const
use system
use basis
use parallel

implicit none

! Bit masks to reveal the list of alpha basis functions and beta functions
! occupied in a Slater determinant.
! If separate_strings is false, then:
!     Alpha basis functions are in the even bits.  alpha_mask = 01010101...
!     Beta basis functions are in the odd bits.    beta_mask  = 10101010...
! otherwise:
!     Alpha basis functions are stored in the first basis_length/2 integers
!     followed by the beta orbitals in the next basis_length/2 integers.
integer(i0) :: alpha_mask, beta_mask

! If true the determinant bit string is formed from concatenating the strings
! for the alpha and beta orbitals rather than interleaving them.
! Note that this in general uses more memory due to padding at the end of the
! alpha and beta strings.
! Whilst some memory could be saved by having no padding between the end of the
! alpha string and the start of the beta string (ie not have the beta string
! start on a new integer) this would make certain operations (eg finding
! <D|U|D> in the real space Hubbard model) much harder and slower.
! WARNING: the vast majority of procedures assume this to be false.  It is the
! developer's responsibility to ensure required procedures can handle the case
! when it is true.
! Further, decoding the bit string does not produce an ordered list of
! orbitals but several procedures assume that the list *is* ordered.  It is
! therefore not sufficient to only check the procedures which operate directly
! upon bit strings.
logical :: separate_strings = .false.

!--- Info for FCI calculations ---

type det
    ! Bit string representation of the Slater determinant.
    ! f is used throughout to indicate a Slater determinant
    ! represented as a bit string.
    ! The *even* bits contain the alpha (spin up) functions.  This is in
    ! contrast to the list of basis functions, basis_fns, where the *odd*
    ! indices refer to alpha (spin up) functions.  This difference arises because 
    ! fortran numbers bits from 0...
    ! If separate_strings is turned on, then the first basis_length/2 integers
    ! represent the alpha orbitals and the second half of the bit array the beta
    ! orbitals.
    integer(i0), pointer :: f(:)  => NULL()  ! (basis_length)
    ! Total spin of the determinant in units of electron spin (1/2).   
    integer, pointer :: Ms => NULL()
    ! Sum of wavevectors of the occupied orbitals in the Slater determinant.
    ! Refers to the wavevector of the i-th alpha spin-orbitals.
    integer, pointer :: ksum => NULL() 
end type det

! Store of determinant information.
! This will quickly become a memory issue, but for dealing with the FCI of small
! systems it is ok.

! Rather than creating an array of type(det), which leads to a serious
! memory overhead due to the need for pointers/allocatable arrays in the
! derived type, we instead create 3 separate variables.  A variable of type det
! can be used to point to the appropriate information, if needed.

! Bit list of the Slater determinant.  See note for f in det type.
! We only store determinants of the same Ms and (for momentum space
! calculations) same ksum at a time.
integer(i0), allocatable, target :: dets_list(:,:) ! (basis_length,ndets)

! Total spin of each Slater determinant stored in dets_list in units of electron spin (1/2).
integer, target :: dets_Ms 

! Sum of wavevectors of the occupied orbitals in each Slater determinant stored
! in det_list.  Sum is to within a reciprocal lattice vector.
! Refers to the wavevector of the i-th alpha spin-orbitals.
integer(i0), target :: dets_ksum

! Number of determinants stored in dets.
! This is the number of determinants enumerated in enumerate_determinants with
! the desired spin and momentum symmetry.
integer :: ndets

! Total (exact) size of determinant space.
! Only used in FCI calculations, where we can be certain that we have fewer
! determinants than 2**31-1 (ie no overflow).
! Whilst it's set (and frequently overflows) in FCIQMC calculations, we never
! actually use it then.  See the estimate_hilbert_space option to obtain an
! estimate estimate (or, in real-space systems, exact to a certain precision)
! for the size of the Hilbert space for a given symmetry which avoids overflows.
integer :: tot_ndets

! Number of determinants of each symmetry.
integer, allocatable :: sym_space_size(:) ! (nsym)

! If true then the determinant list is written to determinant_file.
logical :: write_determinants = .false.
character(255) :: determinant_file = 'DETS'
integer :: det_unit

! --- FCIQMC info ---

! A handy type for containing a lot of information about a determinant.
! This is convenient for passing around different amounts of info when
! we need consistent interfaces.
! Not all compenents are necessarily allocated: only those needed at the time.
type det_info
    ! bit representation of determinant.
    integer(i0), pointer :: f(:)  => NULL()  ! (basis_length)
    ! List of occupied spin-orbitals.
    integer, pointer :: occ_list(:)  => NULL()  ! (nel)
    ! List of occupied alpha/beta spin-orbitals
    integer, pointer :: occ_list_alpha(:), occ_list_beta(:)
    ! List of unoccupied alpha/beta spin-orbitals
    integer, pointer :: unocc_list_alpha(:), unocc_list_beta(:)
    ! is the determinant an initiator determinant or not? (used only in
    ! i-FCIQMC).
    integer :: initiator_flag
end type det_info

interface operator(.detgt.)
    module procedure det_gt
end interface

contains

    subroutine init_determinants()

        ! Initialise determinant information: number of determinants, how
        ! they are stored as bit strings, lookup arrays for converting from
        ! integer list of orbitals to bit strings and vice versa.

        use checking, only: check_allocate
        use utils, only: binom_i
        use utils, only: get_free_unit, int_fmt
        use calc, only: doing_calc, exact_diag, lanczos_diag

        integer :: i, bit_pos, bit_element, ierr
        character(4) :: fmt1(5)

        tot_ndets = binom_i(nbasis, nel)

        ! See note in basis.
        if (separate_strings) then
            basis_length = 2*ceiling(real(nbasis)/(2*i0_length))
            last_basis_ind = nbasis/2 - i0_length*(basis_length/2-1) - 1
        else
            basis_length = ceiling(real(nbasis)/i0_length)
            last_basis_ind = nbasis - i0_length*(basis_length-1) - 1
        end if

        if (parent) then
            fmt1 = int_fmt((/nel, nbasis, tot_ndets, i0_length, basis_length/), padding=1)
            write (6,'(1X,a20,'//fmt1(1)//')') 'Number of electrons:', nel
            write (6,'(1X,a26,'//fmt1(2)//')') 'Number of basis functions:', nbasis
            if (doing_calc(exact_diag+lanczos_diag)) &
                write (6,'(1X,a32,'//fmt1(3)//')') 'Total size of determinant space:', tot_ndets
            write (6,'(1X,a61,'//fmt1(4)//',/)') 'Bit-length of integers used to store determinant bit-strings:', i0_length
            write (6,'(1X,a57,'//fmt1(5)//',/)') 'Number of integers used to store determinant bit-strings:', basis_length
        end if<commit_msg>Minor formatting change to output of det bit string info.<commit_after>module determinants

! Generation, inspection and manipulation of Slater determinants. 

use const
use system
use basis
use parallel

implicit none

! Bit masks to reveal the list of alpha basis functions and beta functions
! occupied in a Slater determinant.
! If separate_strings is false, then:
!     Alpha basis functions are in the even bits.  alpha_mask = 01010101...
!     Beta basis functions are in the odd bits.    beta_mask  = 10101010...
! otherwise:
!     Alpha basis functions are stored in the first basis_length/2 integers
!     followed by the beta orbitals in the next basis_length/2 integers.
integer(i0) :: alpha_mask, beta_mask

! If true the determinant bit string is formed from concatenating the strings
! for the alpha and beta orbitals rather than interleaving them.
! Note that this in general uses more memory due to padding at the end of the
! alpha and beta strings.
! Whilst some memory could be saved by having no padding between the end of the
! alpha string and the start of the beta string (ie not have the beta string
! start on a new integer) this would make certain operations (eg finding
! <D|U|D> in the real space Hubbard model) much harder and slower.
! WARNING: the vast majority of procedures assume this to be false.  It is the
! developer's responsibility to ensure required procedures can handle the case
! when it is true.
! Further, decoding the bit string does not produce an ordered list of
! orbitals but several procedures assume that the list *is* ordered.  It is
! therefore not sufficient to only check the procedures which operate directly
! upon bit strings.
logical :: separate_strings = .false.

!--- Info for FCI calculations ---

type det
    ! Bit string representation of the Slater determinant.
    ! f is used throughout to indicate a Slater determinant
    ! represented as a bit string.
    ! The *even* bits contain the alpha (spin up) functions.  This is in
    ! contrast to the list of basis functions, basis_fns, where the *odd*
    ! indices refer to alpha (spin up) functions.  This difference arises because 
    ! fortran numbers bits from 0...
    ! If separate_strings is turned on, then the first basis_length/2 integers
    ! represent the alpha orbitals and the second half of the bit array the beta
    ! orbitals.
    integer(i0), pointer :: f(:)  => NULL()  ! (basis_length)
    ! Total spin of the determinant in units of electron spin (1/2).   
    integer, pointer :: Ms => NULL()
    ! Sum of wavevectors of the occupied orbitals in the Slater determinant.
    ! Refers to the wavevector of the i-th alpha spin-orbitals.
    integer, pointer :: ksum => NULL() 
end type det

! Store of determinant information.
! This will quickly become a memory issue, but for dealing with the FCI of small
! systems it is ok.

! Rather than creating an array of type(det), which leads to a serious
! memory overhead due to the need for pointers/allocatable arrays in the
! derived type, we instead create 3 separate variables.  A variable of type det
! can be used to point to the appropriate information, if needed.

! Bit list of the Slater determinant.  See note for f in det type.
! We only store determinants of the same Ms and (for momentum space
! calculations) same ksum at a time.
integer(i0), allocatable, target :: dets_list(:,:) ! (basis_length,ndets)

! Total spin of each Slater determinant stored in dets_list in units of electron spin (1/2).
integer, target :: dets_Ms 

! Sum of wavevectors of the occupied orbitals in each Slater determinant stored
! in det_list.  Sum is to within a reciprocal lattice vector.
! Refers to the wavevector of the i-th alpha spin-orbitals.
integer(i0), target :: dets_ksum

! Number of determinants stored in dets.
! This is the number of determinants enumerated in enumerate_determinants with
! the desired spin and momentum symmetry.
integer :: ndets

! Total (exact) size of determinant space.
! Only used in FCI calculations, where we can be certain that we have fewer
! determinants than 2**31-1 (ie no overflow).
! Whilst it's set (and frequently overflows) in FCIQMC calculations, we never
! actually use it then.  See the estimate_hilbert_space option to obtain an
! estimate estimate (or, in real-space systems, exact to a certain precision)
! for the size of the Hilbert space for a given symmetry which avoids overflows.
integer :: tot_ndets

! Number of determinants of each symmetry.
integer, allocatable :: sym_space_size(:) ! (nsym)

! If true then the determinant list is written to determinant_file.
logical :: write_determinants = .false.
character(255) :: determinant_file = 'DETS'
integer :: det_unit

! --- FCIQMC info ---

! A handy type for containing a lot of information about a determinant.
! This is convenient for passing around different amounts of info when
! we need consistent interfaces.
! Not all compenents are necessarily allocated: only those needed at the time.
type det_info
    ! bit representation of determinant.
    integer(i0), pointer :: f(:)  => NULL()  ! (basis_length)
    ! List of occupied spin-orbitals.
    integer, pointer :: occ_list(:)  => NULL()  ! (nel)
    ! List of occupied alpha/beta spin-orbitals
    integer, pointer :: occ_list_alpha(:), occ_list_beta(:)
    ! List of unoccupied alpha/beta spin-orbitals
    integer, pointer :: unocc_list_alpha(:), unocc_list_beta(:)
    ! is the determinant an initiator determinant or not? (used only in
    ! i-FCIQMC).
    integer :: initiator_flag
end type det_info

interface operator(.detgt.)
    module procedure det_gt
end interface

contains

    subroutine init_determinants()

        ! Initialise determinant information: number of determinants, how
        ! they are stored as bit strings, lookup arrays for converting from
        ! integer list of orbitals to bit strings and vice versa.

        use checking, only: check_allocate
        use utils, only: binom_i
        use utils, only: get_free_unit, int_fmt
        use calc, only: doing_calc, exact_diag, lanczos_diag

        integer :: i, bit_pos, bit_element, ierr
        character(4) :: fmt1(5)

        tot_ndets = binom_i(nbasis, nel)

        ! See note in basis.
        if (separate_strings) then
            basis_length = 2*ceiling(real(nbasis)/(2*i0_length))
            last_basis_ind = nbasis/2 - i0_length*(basis_length/2-1) - 1
        else
            basis_length = ceiling(real(nbasis)/i0_length)
            last_basis_ind = nbasis - i0_length*(basis_length-1) - 1
        end if

        if (parent) then
            fmt1 = int_fmt((/nel, nbasis, tot_ndets, i0_length, basis_length/), padding=1)
            write (6,'(/,1X,a20,'//fmt1(1)//')') 'Number of electrons:', nel
            write (6,'(1X,a26,'//fmt1(2)//')') 'Number of basis functions:', nbasis
            if (doing_calc(exact_diag+lanczos_diag)) &
                write (6,'(1X,a32,'//fmt1(3)//')') 'Total size of determinant space:', tot_ndets
            write (6,'(/,1X,a61,'//fmt1(4)//')') 'Bit-length of integers used to store determinant bit-strings:', i0_length
            write (6,'(1X,a57,'//fmt1(5)//',/)') 'Number of integers used to store determinant bit-strings:', basis_length
        end if
{'fraction_non_alphanumeric': 0.07898009950248756, 'fraction_numerical': 0.011885019347705915, 'mean_word_length': 3.4477566072526122, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '618523', 'n_tokens_mistral': 4223, 'n_tokens_neox': 3949, 'n_words': 1838}