gndts_blk.F90 Source File


Contents

Source Code


Source Code

#include "macros.h"
module gndts_blk_mod
    use SystemData, only: BasisFN, Symmetry, NullBasisFn, BasisFNSize
    use constants, only: dp
    use sort_mod, only: sort
    use sym_mod, only: GENNEXTSYM, SETUPSYM, GETSYMDEGEN, &
        GETSYM, LCHKSYM, WRITEALLSYM, getsym, ROUNDSYM, LCHKSYM
    use util_mod, only: NECI_ICOPY
    use calcrho_mod, only: igetexcitlevel
    use determinants, only: calcT
    use error_handling_neci, only: stop_all
    better_implicit_none
    private
    public :: gndts_blk, gensymdetss

contains

    SUBROUTINE GNDTS_BLK(NEL, NBASIS, BRR, NBASISMAX, NMRKS, TCOUNT, &
                         NDET, G1, II, NBLOCKSTARTS, NBLOCKS, TSPN, LMS, &
                         TPARITY, SymRestrict, IFDET, TGENFDET, NDETTOT, BLOCKSYM)
        INTEGER NEL, NBASIS, BRR(NBASIS), nBasisMax(5, *), NDET
        INTEGER NMRKS(NEL, NDET)
        INTEGER II, NLMAX
        INTEGER NBLOCKS, NBLOCKSTARTS(NBLOCKS + 1), OII
        TYPE(BASISFN) G1(NBASIS), ISYM, KJ, BLOCKSYM(NBLOCKS), IMAX(2)
        TYPE(BasisFN) SymRestrict
        LOGICAL TCOUNT
        INTEGER I, NI(NEL), NJ(NEL)
        LOGICAL TSPN, TPARITY, TDONE
        INTEGER LMS
        LOGICAL TGENFDET
        INTEGER IFDET, NDETTOT, IDEG
        real(dp) DETSC, TDETSC
#ifdef CMPLX_
        routine_name("GNDTS_BLK")
#endif
        DETSC = 1D200
        II = 0
        IF (TCOUNT) THEN
            NLMAX = 0
            NBLOCKS = 0
        ELSE
            NLMAX = NDET
        END IF
        I = 0
        OII = 0
        NDETTOT = 0
!.. set the comparison det to an invalid one, so all dets are counted
        NI(1) = 0
        IF (TCOUNT) OPEN(14, FILE="BLOCKS", STATUS="UNKNOWN")
        CALL GENNEXTSYM(NEL, NBASISMAX, TSPN, LMS, TPARITY, SymRestrict, .TRUE., TDONE, IMAX, ISYM)
        DO WHILE (.NOT. TDONE)
            CALL SETUPSYM(KJ)
            CALL GENSYMDETS_R(NI, ISYM, NEL, G1, BRR, NBASIS, NMRKS, II, NLMAX, NJ, KJ, 1, 1, NBASISMAX)
            IF (II /= OII) THEN
!.. we've found an occupied block
                I = I + 1
                CALL GETSYMDEGEN(ISYM, NBASISMAX, IDEG)
                NDETTOT = NDETTOT + (II - OII) * IDEG
                IF (TCOUNT) THEN
                    WRITE(14, "(I5)", advance='no') I
                    CALL WRITEALLSYM(14, ISYM, .FALSE.)
                    WRITE(14, "(2I10)") II - OII,(II - OII) * IDEG
                ELSE
                    NBLOCKSTARTS(I) = OII + 1
                    BLOCKSYM(I) = ISYM
                    IF (TGENFDET) THEN
#ifdef CMPLX_
                        call stop_all(this_routine, "not implemented for complex")
#else
                        TDETSC = CALCT(NMRKS(1:NEL, OII + 1), NEL)
#endif
                        IF (TDETSC < DETSC) THEN
                            IFDET = OII + 1
                            DETSC = TDETSC
                        END IF
                    END IF
                END IF
            END IF
            OII = II
            CALL GENNEXTSYM(NEL, NBASISMAX, TSPN, LMS, TPARITY, SymRestrict, .FALSE., TDONE, IMAX, ISYM)
        END DO
        NBLOCKS = I
        IF (.NOT. TCOUNT) NBLOCKSTARTS(I + 1) = II + 1
        IF (TCOUNT) CLOSE(14)
        IF (.NOT. TGENFDET) IFDET = 1
        RETURN
    END

    RECURSIVE SUBROUTINE GENSYMDETSSD_R(NI, KI, NEL, G1, BRR, NBASIS, LSTE, NLIST, NLMAX, NJ, KJ, NELEC, NBF, NBASISMAX)
        INTEGER NEL, NI(NEL), NBASIS, NLMAX, NLIST
        TYPE(BASISFN) G1(NBASIS), KI, KJ, KJ2
        INTEGER LSTE(NEL, NLMAX), NJ(NEL), NELEC, NBF
        INTEGER I, BRR(NBASIS), NN(NEL), nBasisMax(5, *)
        INTEGER ICE
        DO I = NBF, NBASIS
            NJ(NELEC) = BRR(I)
            KJ2 = KJ
!.. Check if we've filled all the electrons
            IF (NELEC == NEL) THEN
                CALL GETSYM(NJ, NEL, G1, NBASISMAX, KJ2)
                CALL ROUNDSYM(KJ2, NBASISMAX)
                IF (LCHKSYM(KJ2, KI)) THEN
                    CALL NECI_ICOPY(NEL, NJ, 1, NN, 1)
                    call sort(nN)
                    ICE = IGETEXCITLEVEL(NI, NN, NEL)
                    IF (ICE > 0 .AND. ICE <= 2) THEN
!.. we've found a det with the right sym.
                        NLIST = NLIST + 1
                        IF (NLIST <= NLMAX) THEN
!.. if there's space, we save it
                            CALL NECI_ICOPY(NEL, NN, 1, LSTE(1, NLIST), 1)
                        END IF
                    END IF
                END IF
            ELSE
!.. otherwise we need to add more electrons:
                CALL GENSYMDETSSD_R(NI, KI, NEL, G1, BRR, NBASIS, LSTE, NLIST, NLMAX, NJ, KJ2, NELEC + 1, I + 1, NBASISMAX)
            END IF
        END DO
        RETURN
    END

    RECURSIVE SUBROUTINE GENSYMDETS_R(NI, KI, NEL, G1, BRR, NBASIS, LSTE, NLIST, NLMAX, NJ, KJ, NELEC, NBF, NBASISMAX)
        INTEGER NEL, NI(NEL), NBASIS, NLMAX, NLIST
        INTEGER LSTE(NEL, NLMAX), NJ(NEL), NELEC, NBF
        INTEGER I, J, BRR(NBASIS), NN(NEL), nBasisMax(5, *)
        LOGICAL LCMP
        TYPE(BASISFN) G1(NBASIS), KI, KJ, KJ2
        DO I = NBF, NBASIS
            NJ(NELEC) = BRR(I)
            KJ2 = KJ
!.. Check if we've filled all the electrons
            IF (NELEC == NEL) THEN
                CALL GETSYM(NJ, NEL, G1, NBASISMAX, KJ2)
                IF (LCHKSYM(KJ2, KI)) THEN
!                  CALL ROUNDSYM(KJ3,NBASISMAX)
!.. we've found a det with the right sym.
                    NLIST = NLIST + 1
                    CALL NECI_ICOPY(NEL, NJ, 1, NN, 1)
                    call sort(nN)
!.. Just check to see if it's our original det
                    LCMP = .TRUE.
                    DO J = 1, NEL
                        IF (NN(J) /= NI(J)) LCMP = .FALSE.
                    END DO
                    IF (LCMP) THEN
!.. Roll back NLIST
                        NLIST = NLIST - 1
                    ELSEIF (NLIST <= NLMAX) THEN
!.. if there's space, we save it
                        CALL NECI_ICOPY(NEL, NN, 1, LSTE(1, NLIST), 1)
                    END IF
                END IF
            ELSE
!.. otherwise we need to add more electrons:
                CALL GENSYMDETS_R(NI, KI, NEL, G1, BRR, NBASIS, LSTE, NLIST, NLMAX, NJ, KJ2, NELEC + 1, I + 1, NBASISMAX)
            END IF
        END DO
        RETURN
    END

!.. Generate determinants with a given symmetry, given by KI, as GENSYMDETS
    SUBROUTINE GENSYMDETSS(KI, NEL, G1, BRR, NBASIS, LSTE, NLIST, NBASISMAX)
        INTEGER NEL, NI(NEL), NBASIS, BRR(NBASIS)
        INTEGER NLIST, LSTE(NEL, NLIST)
        TYPE(BASISFN) G1(NBASIS), KI, KJ
        INTEGER NJ(NEL), nBasisMax(5, *)
        INTEGER NLMAX
        KJ = NullBasisFn
        NI(1:NEL) = 0
        NLMAX = NLIST
        NLIST = 0
        CALL GENSYMDETS_R(NI, KI, NEL, G1, BRR, NBASIS, LSTE, NLIST, NLMAX, NJ, KJ, 1, 1, NBASISMAX)
        RETURN
    END

end module gndts_blk_mod