CalcFOCKMatrix_RDM Subroutine

public subroutine CalcFOCKMatrix_RDM(rdm)

Arguments

Type IntentOptional Attributes Name
type(one_rdm_t), intent(in) :: rdm

Contents

Source Code


Source Code

    subroutine CalcFOCKMatrix_RDM(rdm)

        ! Calculate the fock matrix in the natural orbital basis.

        use MemoryManager, only: LogMemAlloc, LogMemDealloc
        use rdm_data, only: one_rdm_t
        use SystemData, only: nbasis, ARR, BRR

        type(one_rdm_t), intent(in) :: rdm

        integer :: i, j, k, l, a, b, ierr, ArrDiagNewTag
        real(dp) :: FOCKDiagSumHF, FOCKDiagSumNew
        character(len=*), parameter :: t_r = 'CalcFOCKMatrix_RDM'
        real(dp), allocatable :: ArrDiagNew(:)

        ! This subroutine calculates and writes out the fock matrix for the
        ! transformed orbitals.
        ! ARR is originally the fock matrix in the HF basis.
        ! ARR(:,1) - ordered by energy, ARR(:,2) - ordered by spin-orbital index.

        ! When transforming the orbitals into approximate natural orbitals, we
        ! want to save memory, so don't bother calculating the whole matrix,
        ! just the diagonal elements that we actually need.

        allocate(ArrDiagNew(nBasis), stat=ierr)
        if (ierr /= 0) call Stop_All(t_r, 'Problem allocating ArrDiagNew array,')
        call LogMemAlloc('ArrDiagNew', nBasis, 8, t_r, ArrDiagNewTag, ierr)
        ArrDiagNew(:) = 0.0_dp

        ! First calculate the sum of the diagonal elements, ARR.
        ! Check if this is already being done.
        FOCKDiagSumHF = 0.0_dp
        do a = 1, nBasis
            FOCKDiagSumHF = FOCKDiagSumHF + Arr(a, 2)
        end do

        ! Then calculate the fock matrix in the transformed basis, and the sum
        ! of the new diagonal elements.

        FOCKDiagSumNew = 0.0_dp
        do j = 1, NoOrbs
            l = rdm%sym_list_no(j)
            if (tOpenShell) then
                ArrDiagNew(l) = 0.0_dp
            else
                ArrDiagNew(2 * l) = 0.0_dp
                ArrDiagNew((2 * l) - 1) = 0.0_dp
            end if
            do a = 1, NoOrbs
                b = rdm%sym_list_no(a)
                if (tOpenShell) then
                    ArrDiagNew(l) = ArrDiagNew(l) + (rdm%matrix(a, j) * ARR(b, 2) * rdm%matrix(a, j))
                else
                    ArrDiagNew(2 * l) = ArrDiagNew(2 * l) + (rdm%matrix(a, j) * ARR(2 * b, 2) * rdm%matrix(a, j))
                    ArrDiagNew((2 * l) - 1) = ArrDiagNew((2 * l) - 1) + (rdm%matrix(a, j) * ARR((2 * b) - 1, 2) * rdm%matrix(a, j))
                end if
            end do
            if (tOpenShell) then
                FOCKDiagSumNew = FOCKDiagSumNew + (ArrDiagNew(l))
            else
                FOCKDiagSumNew = FOCKDiagSumNew + (ArrDiagNew(2 * l))
                FOCKDiagSumNew = FOCKDiagSumNew + (ArrDiagNew((2 * l) - 1))
            end if
        end do
        ! If we are truncation the virtual space, only the unfrozen entries will
        ! be transformed.

        ! Refill ARR(:,1) (ordered in terms of energies), and ARR(:,2)
        ! (ordered in terms of orbital number).
        ! ARR(:,2) needs to be ordered in terms of symmetry and then energy
        ! (like SymLabelList), so currently this ordering will not be correct
        ! when reading in qchem INTDUMPs as the orbital number ordering is by energy.

        do j = 1, nBasis
            ARR(j, 2) = ArrDiagNew(j)
            ARR(j, 1) = ArrDiagNew(BRR(j))
        end do

        deallocate(ArrDiagNew)
        call LogMemDealloc(t_r, ArrDiagNewTag)

    end subroutine CalcFOCKMatrix_RDM