SetupNatOrbLabels Subroutine

public subroutine SetupNatOrbLabels()

Arguments

None

Contents

Source Code


Source Code

    subroutine SetupNatOrbLabels()

        use MemoryManager, only: TagIntType

        integer :: x, i, j, ierr, NoOcc
        integer :: StartFill01, StartFill02, Symi, SymCurr, Prev, EndFill01, EndFill02
        character(len=*), parameter :: t_r = 'SetupNatOrbLabels'
        integer, allocatable :: LabVirtOrbs(:), LabOccOrbs(:), SymVirtOrbs(:), SymOccOrbs(:)
        integer(TagIntType) :: LabVirtOrbsTag, LabOccOrbsTag, SymVirtOrbsTag, SymOccOrbsTag
        integer :: lo, hi

        ! The earlier test should pick this up, if it crashes here, will want
        ! to put in an earlier test so that we don't get all the way to this
        ! stage.
        if ((LMS /= 0) .and. (.not. tStoreSpinOrbs)) then
            call stop_all("FindNatOrbs", "Open shell system, and UMAT is not being stored as spin orbitals.")
        end if

        ! We now need two slightly different sets of orbital labels for the
        ! case of spin orbitals and spatial orbitals. When using spin orbitals
        ! we want all the beta spin followed by all the alpha spin. Then we
        ! want two values for the number of occupied orbitals to allow for high
        ! spin cases. With spatial, it is equivalent to just keeping the beta
        ! spin.
        if (tStoreSpinOrbs) then
            NoSpinCyc = 2
        else
            NoSpinCyc = 1
        end if

        do x = 1, NoSpinCyc
            if (.not. tSeparateOccVirt) then
                NoOcc = 0
            else
                if (x == 1) then
                    if (tStoreSpinOrbs) then
                        NoOcc = nOccBeta
                    else
                        NoOcc = NEl / 2
                    end if
                end if
                if (x == 2) NoOcc = nOccAlpha
            end if

            if (tSeparateOccVirt) then
                allocate(LabOccOrbs(NoOcc), stat=ierr)
                call LogMemAlloc('LabOccOrbs', (NoOcc), 4, t_r, LabOccOrbsTag, ierr)
                if (ierr /= 0) call stop_all(t_r, "Mem allocation for LabOccOrbs failed.")
                LabOccOrbs(:) = 0
                allocate(SymOccOrbs(NoOcc), stat=ierr)
                call LogMemAlloc('SymOccOrbs', (NoOcc), 4, t_r, SymOccOrbsTag, ierr)
                if (ierr /= 0) call stop_all(t_r, "Mem allocation for SymOccOrbs failed.")
                SymOccOrbs(:) = 0
            end if

            allocate(LabVirtOrbs(SpatOrbs - NoOcc), stat=ierr)
            call LogMemAlloc('LabVirtOrbs', (SpatOrbs - NoOcc), 4, t_r, LabVirtOrbsTag, ierr)
            if (ierr /= 0) call stop_all(t_r, "Mem allocation for LabVirtOrbs failed.")
            LabVirtOrbs(:) = 0
            allocate(SymVirtOrbs(SpatOrbs - NoOcc), stat=ierr)
            call LogMemAlloc('SymVirtOrbs', (SpatOrbs - NoOcc), 4, t_r, SymVirtOrbsTag, ierr)
            if (ierr /= 0) call stop_all(t_r, "Mem allocation for SymVirtOrbs failed.")
            SymVirtOrbs(:) = 0

            ! First fill SymLabelList2_rot.

            ! Brr has the orbital numbers in order of energy...
            ! i.e Brr(2) = the orbital index with the second lowest energy.

            ! This picks out the NoOcc lowest energy orbitals from BRR as these
            ! will be the occupied. These are then ordered according to
            ! symmetry, and the same done to the virtual.
            do i = 1, NoOcc
                if (x == 1) then
                    if (tStoreSpinOrbs) then
                        LabOccOrbs(i) = BRR(2 * i) - 1
                        SymOccOrbs(i) = int(G1(LabOccOrbs(i))%sym%S, 4)
                    else
                        LabOccOrbs(i) = BRR(2 * i) / 2
                        SymOccOrbs(i) = int(G1(LabOccOrbs(i) * 2)%sym%S, 4)
                    end if
                else if (x == 2) then
                    LabOccOrbs(i) = BRR(2 * i)
                    SymOccOrbs(i) = int(G1(LabOccOrbs(i))%sym%S, 4)
                end if
            end do

            ! Sorts LabOrbs according to the order of SymOccOrbs (i.e. in
            ! terms of symmetry).
            if (tSeparateOccVirt) call sort(SymOccOrbs, LabOccOrbs)

            ! Same for the virtual.
            do i = 1, SpatOrbs - NoOcc
                if (x == 1) then
                    if (tStoreSpinOrbs) then
                        if (tSeparateOccVirt) then
                            LabVirtOrbs(i) = BRR((2 * i) + (NoOcc * 2)) - 1
                            SymVirtOrbs(i) = int(G1(LabVirtOrbs(i))%sym%S, 4)
                        else
                            LabVirtOrbs(i) = BRR((2 * i)) - 1
                            SymVirtOrbs(i) = int(G1(LabVirtOrbs(i))%sym%S, 4)
                        end if
                    else
                        if (tSeparateOccVirt) then
                            LabVirtOrbs(i) = BRR((2 * i) + (NoOcc * 2)) / 2
                            SymVirtOrbs(i) = int(G1(LabVirtOrbs(i) * 2)%sym%S, 4)
                        else
                            LabVirtOrbs(i) = BRR((2 * i)) / 2
                            SymVirtOrbs(i) = int(G1(LabVirtOrbs(i) * 2)%sym%S, 4)
                        end if
                    end if
                else if (x == 2) then
                    if (tSeparateOccVirt) then
                        LabVirtOrbs(i) = BRR((2 * i) + (NoOcc * 2))
                        SymVirtOrbs(i) = int(G1(LabVirtOrbs(i))%sym%S, 4)
                    else
                        LabVirtOrbs(i) = BRR((2 * i))
                        SymVirtOrbs(i) = int(G1(LabVirtOrbs(i))%sym%S, 4)
                    end if
                end if
            end do

            ! Sorts LabOrbs according to the order of SymOccOrbs (i.e. in
            ! terms of symmetry).
            call sort(SymVirtOrbs, LabVirtOrbs)

            ! SymLabelList2_rot is then filled with the symmetry ordered
            ! occupied then virtual arrays for each spin.
            if (x == 1) then
                StartFill01 = 1
                StartFill02 = NoOcc + 1
                EndFill01 = NoOcc
                EndFill02 = SpatOrbs
            else if (x == 2) then
                StartFill01 = SpatOrbs + 1
                StartFill02 = SpatOrbs + NoOcc + 1
                EndFill01 = SpatOrbs + NoOcc
                EndFill02 = NoOrbs
            end if

            j = 0
            do i = StartFill01, EndFill01
                j = j + 1
                SymLabelList2_rot(i) = LabOccOrbs(j)
            end do
            j = 0
            do i = StartFill02, EndFill02
                j = j + 1
                SymLabelList2_rot(i) = LabVirtOrbs(j)
            end do

            ! Second fill SymLabelCounts2_rot.
            ! - the first 8 places of SymLabelCounts2_rot(1,:) and
            !     SymLabelCounts2_rot(2,:) refer to the occupied orbitals
            ! - and the second 8 to the virtuals.

            if (lNoSymmetry) then
                ! If we are ignoring symmetry, all orbitals essentially have
                ! symmetry 0.
                if (x == 1) then
                    SymLabelCounts2_rot(1, 1) = 1
                    SymLabelCounts2_rot(1, 9) = NoOcc + 1
                    SymLabelCounts2_rot(2, 1) = NoOcc
                    SymLabelCounts2_rot(2, 9) = SpatOrbs - NoOcc
                else if (x == 2) then
                    SymLabelCounts2_rot(1, 17) = 1
                    SymLabelCounts2_rot(1, 25) = NoOcc + 1
                    SymLabelCounts2_rot(2, 17) = NoOcc
                    SymLabelCounts2_rot(2, 25) = SpatOrbs - NoOcc
                end if

            else
                ! Otherwise we run through the occupied orbitals, counting the
                ! number with each symmetry and noting where in
                ! SymLabelList2_rot each symmetry block starts.
                if (x == 1) then
                    StartFill01 = 1
                    StartFill02 = 9
                    Prev = 0
                else if (x == 2) then
                    StartFill01 = 17
                    StartFill02 = 25
                    Prev = SpatOrbs
                end if
                SymCurr = 0
                SymLabelCounts2_rot(1, StartFill01) = 1 + Prev
                do i = 1, NoOcc
                    if (tStoreSpinOrbs) then
                        Symi = int(G1(SymLabelList2_rot(i + Prev))%sym%S, 4)
                    else
                        Symi = int(G1((SymLabelList2_rot(i + Prev) * 2))%sym%S, 4)
                    end if
                    SymLabelCounts2_rot(2, (Symi + StartFill01)) = SymLabelCounts2_rot(2, (Symi + StartFill01)) + 1
                    if (Symi /= SymCurr) then
                        SymLabelCounts2_rot(1, (Symi + StartFill01)) = i + Prev
                        SymCurr = Symi
                    end if
                end do
                ! The same is then done for the virtuals.
                SymCurr = 0
                SymLabelCounts2_rot(1, StartFill02) = NoOcc + 1 + Prev
                do i = NoOcc + 1, SpatOrbs
                    if (tStoreSpinOrbs) then
                        Symi = int(G1(SymLabelList2_rot(i + Prev))%sym%S, 4)
                    else
                        Symi = int(G1((SymLabelList2_rot(i + Prev) * 2))%sym%S, 4)
                    end if
                    SymLabelCounts2_rot(2, (Symi + StartFill02)) = SymLabelCounts2_rot(2, (Symi + StartFill02)) + 1
                    if (Symi /= SymCurr) then
                        SymLabelCounts2_rot(1, (Symi + StartFill02)) = i + Prev
                        SymCurr = Symi
                    end if
                end do
            end if

            ! Go through each symmetry group, making sure the orbital pairs
            ! are ordered lowest to highest.
            if (x == 1) then
                do i = 1, 16
                    if (SymLabelCounts2_rot(2, i) /= 0) then
                        lo = SymLabelCounts2_rot(1, i)
                        hi = lo + SymLabelCounts2_rot(2, i) - 1
                        call sort(SymLabelList2_rot(lo:hi))
                    end if
                end do
            else if (x == 2) then
                do i = 17, 32
                    if (SymLabelCounts2_rot(2, i) /= 0) then
                        lo = SymLabelCounts2_rot(1, i)
                        hi = lo + SymLabelCounts2_rot(2, i) - 1
                        call sort(SymLabelList2_rot(lo:hi))
                    end if
                end do
            end if

            ! Deallocate the arrays just used in this routine.
            if (tSeparateOccVirt) then
                deallocate(SymOccOrbs)
                call LogMemDealloc(t_r, SymOccOrbsTag)

                deallocate(LabOccOrbs)
                call LogMemDealloc(t_r, LabOccOrbsTag)
            end if

            deallocate(SymVirtOrbs)
            call LogMemDealloc(t_r, SymVirtOrbsTag)

            deallocate(LabVirtOrbs)
            call LogMemDealloc(t_r, LabVirtOrbsTag)

        end do

        do i = 1, NoOrbs
            SymLabelListInv_rot(SymLabelList2_rot(i)) = i
        end do

        do i = 1, NoOrbs
            SymLabelList3_rot(i) = SymLabelList2_rot(i)
        end do

        if (.not. tSeparateOccVirt) then
            ! Basically we treat all the orbitals as virtuals and set NoOcc
            ! to zero in each routine.
            tRotateVirtOnly = .true.
        end if

    end subroutine SetupNatOrbLabels