! A wrapper routine to allow symsetupexcit3_worker to be called ! with incorrect arguments --> Allows Alex's hacking!! SUBROUTINE SYMSETUPEXCITS3(NI, NEL, G1, NBASIS, STORE, SPIin, ETin, & NAPin, OPin, TCOUNT, ICOUNT, CLASSES, ILUT, SYMPRODS, & ILEVEL, iMinElec1, iMaxElec1) use systemdata, only: Basisfn, Symmetry use SymData, only: SymClass use SymExcit2, only: symsetupexcits3_worker integer :: nel, nI(nel), nBasis, store(6), iCount, iLevel integer :: ilut(0:nBasis / 32), iMinElec1, iMaxElec1 type(basisfn) G1(nBasis) logical :: tCount type(symclass) :: classes(*) type(symmetry) :: symprods(0:nel * nel) !This nel*nel is the maximum it could possibly be integer :: SPIin(1:2, 1:3, 1:*), ETin(1:5, *), NAPin(1:3, *) integer :: OPin(1:2, *) call symsetupexcits3_worker(nI, nel, g1, nbasis, store, & SPIin, ETin, NAPin, OPin, tCount, iCount, classes, & ilut, symprods, iLevel, iMinElec1, iMaxElec1) end subroutine !.. List the symmetry classes in NI. !.. For each orb, just see if its class is in the list, and if not add it !.. Each state's symmetry falls into a class SymClasses(ISTATE). !.. We divide the occupied electrons into classes. A class correpsonds to a unique value of SymClasses(iState) for state (i.e. spatial orbital) iState. !.. The CLASSCOUNT arrays contain the number of electrons of each class. !.. We keep three lists: CLASSCOUNT which takes into account all electrons. !.. THISCLASSCOUNT which takes into account electrons allocated to this processor !.. and PREVCLASSCOUNT which takes into account electrons allocated to the previous processor. !.. These both have the format (Spn,iCl), where Spin=1,2 corresponding to alpha and beta and !.. iCl is the index of the Class. !.. CLASSES(iCl)%SymLab is the symmetry label (i.e. entry in SymClasses) of this class (NB not a symmetry itself) Subroutine SymSetupExcits_CreateClassList(nI, nEl, Classes, iMinElec1, iMaxElec1, ThisClassCount, PrevClassCount, ClassCount, G1, nCl) use SystemData, only: BasisFN use SystemData, only: Symmetry use SymData, only: SymClass, SymClasses, SymLabels use SymData, only: tAbelianFastExcitgen use sym_mod, only: SYMPROD, TotSymRep, SYMCONJ, SYMEQ use sym_mod, only: FindSymLabel IMPLICIT NONE INTEGER nEl, nI(nEl) Type(BasisFN) G1(*) TYPE(SymClass) CLASSES(*) ! Data about each class INTEGER nCl ! Will be the number of classes INTEGER CLASSCOUNT(2, nEl) ! Number of alpha and beta electrons in each class INTEGER THISCLASSCOUNT(2, nEl) ! ThisClassCount is used to list only electrons which this processor deals with INTEGER PREVCLASSCOUNT(2, nEl) ! PrevClassCount is used to list electrons which lower indexed processors deal with INTEGER iMinElec1, iMaxElec1 LOGICAL tNew INTEGER I, J, K, L INTEGER iSpn Type(Symmetry) Pr NCL = 0 !This is our running count of how many symmetry classes we have DO I = 1, NEL TNEW = .TRUE. ! WRITE(stdout,*) I,SymClasses((NI(I)+1)/2) DO J = 1, NCL IF (SymClasses((NI(I) + 1) / 2) == CLASSES(J)%SymLab) THEN ISPN = (G1(NI(I))%Ms + 3) / 2 CLASSCOUNT(ISPN, J) = CLASSCOUNT(ISPN, J) + 1 IF (I >= iMinElec1 .AND. i <= iMaxElec1) THEN THISCLASSCOUNT(ISPN, J) = THISCLASSCOUNT(ISPN, J) + 1 END IF IF (I < iMinElec1) THEN PREVCLASSCOUNT(ISPN, J) = PREVCLASSCOUNT(ISPN, J) + 1 END IF TNEW = .FALSE. EXIT END IF END DO IF (TNEW) THEN !.. add the new class !.. ISPN=1 is beta, ISPN=2 is alpha ISPN = (G1(NI(I))%Ms + 3) / 2 NCL = NCL + 1 CLASSES(NCL)%SymLab = SymClasses((NI(I) + 1) / 2) CLASSCOUNT(ISPN, NCL) = 1 CLASSCOUNT(3 - ISPN, NCL) = 0 IF (I >= iMinElec1 .AND. i <= iMaxElec1) THEN THISCLASSCOUNT(ISPN, NCL) = 1 THISCLASSCOUNT(3 - ISPN, NCL) = 0 ELSE THISCLASSCOUNT(1:2, NCL) = 0 END IF IF (I < iMinElec1) THEN PREVCLASSCOUNT(ISPN, NCL) = 1 PREVCLASSCOUNT(3 - ISPN, NCL) = 0 ELSE PREVCLASSCOUNT(1:2, NCL) = 0 END IF END IF END DO IF (.not. tAbelianFastExcitgen) THEN !This is not needed for abelian symmetry, since orb i and a must be the same symmetry class !.. Now calculate the resultant symmetry from removing one of each of the classes (for singles) !.. i.e. if we remove j, what's the symmetry of SYMCONJ(<ikl... |) (X) SYM( |ikl...>) !.. NB to cope with non-abelians, this actually takes the prod sym of the classes of each orb, !.. rather than the orb itself, so may end up classifying a single as allowed when it's not. !.. we'll use this in the future to determine the allowed j->a !.. This is stored in CLASSES(iCl)%SymRem DO I = 1, NCL PR = TotSymRep() DO J = 1, NCL L = CLASSCOUNT(1, I) + CLASSCOUNT(2, I) IF (J == I) L = L - 1 DO K = 1, L PR = SYMPROD(PR, SymConj(SymLabels(CLASSES(J)%SymLab))) PR = SYMPROD(PR, SymLabels(CLASSES(J)%SymLab)) END DO END DO CLASSES(I)%SymRem = PR ! WRITE(stdout,"(A,I4,2Z4,I)") "CLASS ",NCL,CLASSES(I)%SymLab, ! & CLASSES(I)%SymRem,I END DO ! WRITE(stdout,*) NCL," Symmetry Classes" END IF End Subroutine !.. Now determine all possible symmetry products of pairs of orbs, and classify them. !.. SYMPRODS(iPr) is the a symmetry product. !.. SymProdCount(iType,iPr) is the number of prods of a given type. iType=0 (beta/beta), 1 (alpha/beta), 2 (alpha/alpha) !.. NPairs totals all SymProdCounts. !.. For each pair of symmetry classes, determine its symmetry product. !.. We list them and then sort them Subroutine SymSetupExcits_CreateCSProds(nPr, nPairs, nCl, SymProds, ThisClassCount, PrevClassCount, ClassCount, Classes, SymProdCount) use SystemData, only: Symmetry, SymmetrySize, nel use SymData, only: SymClass, SymClasses, SymLabels use sort_mod use sym_mod, only: SymProd, symeq IMPLICIT NONE INTEGER nPr, nPairs, nCl TYPE(Symmetry) SymProds(0:*) INTEGER CLASSCOUNT(2, nCl) ! Number of alpha and beta electrons in each class INTEGER THISCLASSCOUNT(2, nCl) ! ThisClassCount is used to list only electrons which this processor deals with INTEGER PREVCLASSCOUNT(2, nCl) ! PrevClassCount is used to list electrons which lower indexed processors deal with INTEGER SYMPRODCOUNT(3, 0:*) TYPE(SymClass) CLASSES(*) INTEGER I, J, K LOGICAL tNew INTEGER ICC1, ICC2, ICC3 Type(Symmetry) Pr NPR = 0 NPAIRS = 0 DO I = 1, NCL DO J = I, NCL !.. The symmetry bit string, decomposing the sym label into its component irreps is in !.. SymLabels(ISYMLABEL) PR = SYMPROD(SymLabels(CLASSES(I)%SymLab), SymLabels(CLASSES(J)%SymLab)) TNEW = .TRUE. DO K = 1, NPR IF (SYMEQ(SYMPRODS(K), PR)) THEN TNEW = .FALSE. EXIT END IF END DO IF (TNEW) THEN NPR = NPR + 1 !K will then give the index for the unique symmetry product. K = NPR SYMPRODS(NPR) = PR !Add the new symmetry product label to SymProds END IF !.. 1 corresponds to beta beta, 2 to alpha/beta and beta/alpha, and 3 to alpha, alpha ! The number of pairs is somewhat more complex when we split electron 1 between processors ! For systems where we require the upper-triangle (excluding diagonal) we have ! NThis*(NAll+(NAll-NThis)-1)/2 pairs ! For cases where we allow all pairs, it's just NThis*NAll IF (I == J) THEN ICC1 = THISCLASSCOUNT(1, I) * (2 * CLASSCOUNT(1, I) - THISCLASSCOUNT(1, I) - 2 * PREVCLASSCOUNT(1, I) - 1) / 2 !If we have all electrons being considered here then the alpha beta lot is simple, and just Nalpha*Nbeta ! ICC2=CLASSCOUNT(1,I)*CLASSCOUNT(2,I) ! However, if we are splitting electron 1 between processors, alpha electrons here can only interact with beta ! electrons with higher index, and the same witb beta on alpha ! Therefore we have NThisA*(NAllB-NPrevB)+ NThisB*(NAllA-NPrevA-NThisA) ICC2 = THISCLASSCOUNT(1, I) & * (CLASSCOUNT(2, I) - PREVCLASSCOUNT(2, I)) & + THISCLASSCOUNT(2, I) & * (CLASSCOUNT(1, I) - PREVCLASSCOUNT(1, I) - THISCLASSCOUNT(1, I)) ICC3 = THISCLASSCOUNT(2, I) * (2 * CLASSCOUNT(2, I) - THISCLASSCOUNT(2, I) - 2 * PREVCLASSCOUNT(2, I) - 1) / 2 ELSE ICC1 = THISCLASSCOUNT(1, I) * CLASSCOUNT(1, J) ICC2 = THISCLASSCOUNT(1, I) * CLASSCOUNT(2, J) + THISCLASSCOUNT(2, I) * CLASSCOUNT(1, J) ICC3 = THISCLASSCOUNT(2, I) * CLASSCOUNT(2, J) END IF SYMPRODCOUNT(1, K) = SYMPRODCOUNT(1, K) + ICC1 SYMPRODCOUNT(2, K) = SYMPRODCOUNT(2, K) + ICC2 SYMPRODCOUNT(3, K) = SYMPRODCOUNT(3, K) + ICC3 !Find total number of spin-orbital pairs of all spin-combos NPAIRS = NPAIRS + ICC1 + ICC2 + ICC3 ! WRITE(stdout,"(6I6)") CLASSCOUNT(1:2,I), ! & THISCLASSCOUNT(1:2,I), PREVCLASSCOUNT(1:2,I) ! WRITE(stdout,"(6I6)") CLASSCOUNT(1:2,J), ! & THISCLASSCOUNT(1:2,J), PREVCLASSCOUNT(1:2,J) ! WRITE(stdout,"(A,I6,Z4,5I6)") "SYMPROD ",K,SYMPRODS(K),I,J, ! & ICC1,ICC2,ICC3 END DO END DO SYMPRODS(0)%s = 0 ! For historical reasons. Should never be needed. SYMPRODCOUNT(1, 0) = 0 SYMPRODCOUNT(2, 0) = 0 SYMPRODCOUNT(3, 0) = 0 ! DO I=1,NPR ! WRITE(stdout,"(Z4,3I4)") SYMPRODS(I),SYMPRODCOUNT(1,I), ! & SYMPRODCOUNT(2,I),SYMPRODCOUNT(3,I) ! ENDDO !. We sort the array of Symmetry products (and its associated SymProdCount info), into ascending order of product, for easy searching later. call sort(symProds(1:npr), symProdCount(:, 1:npr)) ! WRITE(stdout,*) NPR," Symmetry Products" ! WRITE(stdout,*) NPAIRS," Orbital Pairs" !.. Create a cumulative sum. DO I = 1, NPR SYMPRODCOUNT(1, I) = SYMPRODCOUNT(3, I - 1) + SYMPRODCOUNT(1, I) SYMPRODCOUNT(2, I) = SYMPRODCOUNT(1, I) + SYMPRODCOUNT(2, I) SYMPRODCOUNT(3, I) = SYMPRODCOUNT(2, I) + SYMPRODCOUNT(3, I) ! WRITE(stdout,*) SYMPRODS(I),SYMPRODCOUNT(1,I), ! & SYMPRODCOUNT(2,I),SYMPRODCOUNT(3,I) END DO End Subroutine !.. Classify and store each possible pair of orbitals under its symmetry product. !.. With each symmetry product (denoted []), calculate []'' which is the !.. remainder after having removed the orbitals. !.. Now classify each pair of orbs under its sym prod !.. SYMPRODS(I) specifies a sym prod. Orbitals for this are stored in !.. ORBPAIRS starting at index SYMPRODIND(1,ISPN,I)+1. !.. The first free space is at SYMPRODIND(1,ISPN,I)+SYMPRODIND(2,ISPN,I)+1. Subroutine SymSetupExcits_StoreOccPairs(OrbPairs, nPairs, nPr, iMinElec1, iMaxElec1, G1, SymProdInd, SymProds, nI, nEl) use SystemData, only: Symmetry, BasisFN, SymmetrySize use constants, only: int64, stdout use sym_mod, only: symprod, BINARYSEARCHSYM, WRITESYM use util_mod, only: stop_all IMPLICIT NONE INTEGER, intent(out) :: ORBPAIRS(2, nPairs) INTEGER, intent(in) :: nPairs INTEGER, intent(in) :: nPr INTEGER, intent(in) :: iMinElec1, iMaxElec1 TYPE(BasisFN), intent(in) :: G1(*) INTEGER, intent(inout) :: SYMPRODIND(1:2, 1:3, 1:nPr) TYPE(Symmetry), intent(in) :: SymProds(0:*) INTEGER, intent(in) :: nEl, nI(nEl) integer(int64) :: l Type(Symmetry) Pr INTEGER :: iSpn, iCC, I, J, K character(*), parameter :: t_r = 'SymSetupExcits_StoreOccPairs' ORBPAIRS(:, :) = 0 L = 0 DO I = iMinElec1, iMaxElec1 DO J = I + 1, NEL L = L + 1 PR = SYMPROD(G1(NI(I))%Sym, G1(NI(J))%Sym) !.. Find the product in the sorted symprod list CALL BINARYSEARCHSYM(PR, SYMPRODS(1), int(NPR), K) IF (K == 0) THEN WRITE(stdout, *) "Occupied Symmetry Products" DO L = 0, NPR WRITE(stdout, "(I4)", advance='no') L CALL writesym(stdout, SYMPRODS(L), .TRUE.) END DO WRITE(stdout, "(A)", advance='no') "Illegal Symmetry" CALL writesym(stdout, PR, .TRUE.) call stop_all(t_r, 'Illegal Symmetry Found') END IF ISPN = (G1(NI(I))%Ms + G1(NI(J))%Ms) / 2 + 2 !.. Increment the offset for the next one SYMPRODIND(2, ISPN, K) = SYMPRODIND(2, ISPN, K) + 1 ICC = SYMPRODIND(1, ISPN, K) + SYMPRODIND(2, ISPN, K) !.. The index + offset of the element ORBPAIRS(1, ICC) = NI(I) ORBPAIRS(2, ICC) = NI(J) ! WRITE(stdout,"(A,2I4,2Z4,2I4)") ! & "SP",ICC,ISPN,PR,SYMPRODS(K),NI(I),NI(J) ! WRITE(stdout,*) L,NI(I),NI(J),PR,K END DO END DO End Subroutine !.. With each of the symmetry products, calculate []' such that []x[]' !.. contains the totally symmetric rep. !.. We do this by checking whether any of the []' in the !.. global symprods table multiplied by [] give the sym rep. Subroutine SymSetupExcits_CountVirtProds(nDoub, nExcitTypes, nPr, SymProdInd, SymProds, nAllowPPS, iLUT) use SystemData, only: Symmetry, BasisFN use SymData, only: SymPairProds, SymStatePairs, nSymPairProds use sym_mod, only: LSYMSYM, SYMPROD, SymConj IMPLICIT NONE INTEGER nDoub INTEGER nExcitTypes INTEGER nPr INTEGER nAllowPPS(3, *) INTEGER iLUT(0:*) INTEGER SYMPRODIND(2, 3, 1:*) TYPE(Symmetry) SYMPRODS(0:*) INTEGER I, J, K, L Type(Symmetry) SPP INTEGER ICC1, ICC2, ICC3, ICC4 LOGICAL L1B, L1A, L2B, L2A INTEGER ICC, iSpn !.. SYMPRODIND(1,ISPN,I)+1 contains the index of the first element of spin ISPN of sym !.. SYMPRODS(I) in ORBPAIRS !.. SYMPRODIND(2,ISPN,I) contains the number of such elements !.. SYMPAIRPRODS(1:NSYMPAIRPRODS) is a global list of all SYMPRODs available, the number of pairs of !.. symlabels (listed in SymStatePairs), and the index of the start of this list !.. For a given (unique) SymPairProds(J)%Sym, I=SymPairProds(J)%Index. !.. [ SymStatePairs(1,I) , SymStatePairs(2,I) ] is the pair of symlabels whose prod is of that symmetry. NDOUB = 0 DO I = 1, NPR DO J = 1, NSYMPAIRPRODS !.. If it's the first time around, we flag NALLOWPPS as invalid IF (I == 1) THEN NALLOWPPS(1, J) = -1 NALLOWPPS(2, J) = -1 NALLOWPPS(3, J) = -1 END IF !.. [] is the SymProd(I). For each sympairprod, check if [] x []' contains the sym rep ! WRITE(stdout,*) SYMPRODS(I),SYMPAIRPRODS(J) SPP = SymPairProds(J)%Sym IF (LSYMSYM(SYMPROD(SymConj(SYMPRODS(I)), SPP))) THEN !.. Check if we've worked out the allowed number of excitation pairs, otherwise work it out IF (NALLOWPPS(1, J) == -1) THEN !.. Zero the counters NALLOWPPS(1, J) = 0 NALLOWPPS(2, J) = 0 NALLOWPPS(3, J) = 0 DO K = SymPairProds(J)%nIndex, SymPairProds(J)%nIndex + SymPairProds(J)%nPairs - 1 !.. Now check according to ISPN !.. ICC1 is the beta orbital corresponding to the first state, and ICC2 the alpha !.. ICC3 is the beta orbital corresponding to the state, and ICC4 the alpha ICC1 = SymStatePairs(1, K) * 2 - 1 ICC2 = ICC1 + 1 ICC3 = SymStatePairs(2, K) * 2 - 1 ICC4 = ICC3 + 1 L1B = .NOT. BTEST(ILUT((ICC1 - 1) / 32), MOD(ICC1 - 1, 32)) L1A = .NOT. BTEST(ILUT((ICC2 - 1) / 32), MOD(ICC2 - 1, 32)) L2B = .NOT. BTEST(ILUT((ICC3 - 1) / 32), MOD(ICC3 - 1, 32)) L2A = .NOT. BTEST(ILUT((ICC4 - 1) / 32), MOD(ICC4 - 1, 32)) !.. L1B is set if the beta of the first virtual is not in NI, i.e. is allowed ! NALLOWPPS is the number of ALLOWED virtuals IF (ICC1 == ICC3) THEN ! NALLOWPPS(1,J)=NALLOWPPS(1,J)+1 ! NALLOWPPS(3,J)=NALLOWPPS(3,J)+1 !.. The virtuals we are exciting to are the same state. We're only allowed an AB excitation IF (L1B .AND. L2A) NALLOWPPS(2, J) = NALLOWPPS(2, J) + 1 ELSE IF (L1B .AND. L2B) NALLOWPPS(1, J) = NALLOWPPS(1, J) + 1 IF (L1B .AND. L2A) NALLOWPPS(2, J) = NALLOWPPS(2, J) + 1 IF (L1A .AND. L2B) NALLOWPPS(2, J) = NALLOWPPS(2, J) + 1 IF (L1A .AND. L2A) NALLOWPPS(3, J) = NALLOWPPS(3, J) + 1 END IF ! WRITE(stdout,*) SPP,SymStatePairs(1,K)*2-1, ! & SymStatePairs(2,K)*2-1 ! & ,L1B,L1A,L2B,L2A END DO END IF !.. Now count all the excitations allowed for this set of []->[]' DO ISPN = 1, 3 L = NALLOWPPS(ISPN, J) K = SYMPRODIND(2, ISPN, I) ICC = L * K ! WRITE(stdout,*) "ET",NEXCITTYPES ! WRITE(stdout,"(14I5)") I,J,SYMPRODS(I), ! & SYMPAIRPRODS(J),ISPN,L,K,ICC NDOUB = NDOUB + ICC IF (ICC > 0) NEXCITTYPES = NEXCITTYPES + 1 END DO END IF END DO END DO ! WRITE(stdout,*) "Number of double excitations: ",NDOUB End Subroutine Subroutine SymSetupExcitsAb_CountVProds(nDoub, nExcitTypes, nCl, nPr, SymProds, SymProdInd, Classes, ClassCount, nAllowPPS) ! Calculated not enumerated use SymData, only: SymPairProds, nSymPairProds, SymmetrySize use SymData, only: Symmetry, SymLabelCounts, SymLabels, SymClass use sym_mod, only: SymConj, SymProd, FindSymLabel use sym_mod, only: BINARYSEARCHSYM use constants, only: stdout IMPLICIT NONE Type(Symmetry) SymProds(0:*) INTEGER nPr, nCl INTEGER ClassCount(2, *) Type(SymClass) Classes(nCl) INTEGER nAllowPPS(1:3, nSymPairProds) !.. SYMPRODIND(1,ISPN,I)+1 contains the index of the first element of spin ISPN of sym !.. SYMPRODS(I) in ORBPAIRS !.. SYMPRODIND(2,ISPN,I) contains the number of such elements INTEGER SymProdInd(1:2, 1:3, 1:nPr) INTEGER nDoub INTEGER nExcitTypes INTEGER I, L, K, KK, ICC, ISPN, lab, iOccs, iVirts, iClass, inCl Type(Symmetry) s Logical tDebugPrint tDebugPrint = .false. nDoub = 0 nAllowPPS = 0 ! For each Symmetry product count the number of allowed doubles. ! Loop over the complete list of pair types ! Each pair prod in the full list can only interact with prods of the same sym in the list of occ pairs. DO I = 1, nSymPairProds ! Now search for that symmetry within our occupied pair counts CALL BINARYSEARCHSYM(SymPairProds(I)%Sym, SYMPRODS(1), NPR, K) !K now has the index of that sym in the occ sym prod list. IF (tDebugPrint) WRITE(stdout, *) "Sym:", SymPairProds(I)%Sym IF (K /= 0) THEN !.. Now count all the excitations allowed for this set of []->[]' DO ISPN = 1, 3 ! First get the virts If (iSpn == 2) THEN L = SymPairProds(I)%nPairsStateOS else L = SymPairProds(I)%nPairsStateSS END IF ! L now contains total number (including occ and single excits) of double excits of this sym. ! We must remove the single excitations. ! The number of pairs of doubles in the total list with sym prod SymProds(K) ! which contain just one of the occupied orbitals can be worked out by ! multiplying SymProds(K) by the inverse of the symmetry of each occupied class. ! This will give the sym of the virtual which would make up the pair. ! Since we know how many occ there are in each occ class, and can calculated ! How many virts there are in its complement, that gives us the number of ! 'single excitations' masquerading as doubles. ! First loop over occupied classes DO iClass = 1, nCl ! SymLabels(Classes(iClass)%SymLab) is the sym of the class ! WARNING - here we use SymConj to mean 'inverse'. ! This seems right, although it would be nice to have it really proven. if (tDebugPrint) WRITE(stdout, *) "Occ Class,sym:", iClass, SymLabels(Classes(iClass)%SymLab) s = SymProd(SymConj(SymLabels(Classes(iClass)%SymLab)), SymPairProds(I)%Sym) lab = FindSymLabel(s) ! SymLabelCounts(2,lab) is the total number of states with the inverse sym. iVirts = SymLabelCounts(2, lab) if (tDebugPrint) Write(stdout, *) "Virts,lab", iVirts, lab do iNCl = 1, nCl if (Classes(iNCl)%SymLab == lab) exit end do if (tDebugPrint) WRITE(stdout, *) "Virt Class,sym:", iNCl, s if (iSpn == 2) then !The mixed spin case if (tDebugPrint) WRITE(stdout, *) "OS Tot:", L if (iNCL <= nCl) then ! We've found the class corresponding to the inverse, so we know how many occs it has iOccs = ClassCount(1, iClass) L = L - iOccs * (iVirts - ClassCount(2, iNCL)) if (tDebugPrint) WRITE(stdout, *) "Aocc Bvirt removed:", iOccs * (iVirts - ClassCount(2, iNCL)), ClassCount(2, iNCL) iOccs = ClassCount(2, iClass) L = L - iOccs * (iVirts - ClassCount(1, iNCL)) if (tDebugPrint) WRITE(stdout, *) "Bocc Avirt removed:", iOccs * (iVirts - ClassCount(1, iNCL)), ClassCount(1, iNCL) else iOccs = ClassCount(1, iClass) L = L - iOccs * iVirts if (tDebugPrint) WRITE(stdout, *) "Aocc Bvirt removed:", iOccs * iVirts iOccs = ClassCount(2, iClass) L = L - iOccs * iVirts if (tDebugPrint) WRITE(stdout, *) "Bocc Avirt removed:", iOccs * iVirts end if else ! same spin case iOccs = ClassCount((iSpn + 1) / 2, iClass) if (tDebugPrint) WRITE(stdout, *) "SS Tot:", L if (iNCL <= nCl) then L = L - iOccs * (iVirts - ClassCount((iSpn + 1) / 2, iNCL)) else L = L - iOccs * iVirts end if if (tDebugPrint) WRITE(stdout, *) "SS singles removed:", L end if end do ! The number of occupied pairs with sym prod SymProds(K) KK = SymProdInd(2, iSpn, K) if (tDebugPrint) WRITE(stdout, *) "Occ pairs", KK ! Also remove the occupied pairs from the count of virtuals L = L - KK ! Save this for later nAllowPPS(iSpn, I) = L ICC = L * KK if (tDebugPrint) WRITE(stdout, *) "Occ removed", L if (tDebugPrint) WRITE(stdout, *) "ET", NEXCITTYPES ! if(tDebugPrint) ! & WRITE(stdout,"(14I5)") K,I, ! & SYMPAIRPRODS(I),ISPN,L,KK,ICC NDOUB = NDOUB + ICC IF (ICC > 0) NEXCITTYPES = NEXCITTYPES + 1 END DO END IF END DO End Subroutine Subroutine SymSetupExcits_CountSingles(nSing, nCl, nExcitTypes, ThisClassCount, ClassCount, Classes) use SystemData, only: Symmetry use SymData, only: SymClass, SymLabelCounts, nSymLabels, SymLabels use sym_mod, only: LSYMSYM, SYMPROD, SymConj IMPLICIT NONE INTEGER nSing INTEGER nCl INTEGER nExcitTypes INTEGER ThisClassCount(2, *) INTEGER ClassCount(2, *) Type(SymClass) Classes(nCl) INTEGER I, J, K INTEGER iSpn INTEGER iCC NSING = 0 DO I = 1, NCL !.. For each class, see what sym prods it can interact with DO J = 1, NSYMLABELS IF (LSYMSYM(SYMPROD(CLASSES(I)%SymRem, SYMPROD(SymConj(SymLabels(J)), SymLabels(CLASSES(I)%SymLab))))) THEN DO ISPN = 1, 2 ICC = 0 ! Work out which virtuals are available DO K = 1, NCL IF (CLASSES(K)%SymLab == J) ICC = CLASSCOUNT(ISPN, K) END DO ICC = THISCLASSCOUNT(ISPN, I) * (SYMLABELCOUNTS(2, J) - ICC) NSING = NSING + ICC IF (ICC /= 0) NEXCITTYPES = NEXCITTYPES + 1 ! WRITE(stdout,"(2Z4,4I)") SymLabels(CLASSES(I)), ! & SymLabels(J),ISPN,ICC, ! & CLASSCOUNT(ISPN,I), ! & (SYMLABELCOUNTS(2,J)-CLASSCOUNT(ISPN,I)) END DO END IF END DO END DO ! WRITE(stdout,*) "Number of single excitations: ",NSING End Subroutine !A simple routine for counting the number of single excitations in abelian systems. !orbital 'a' must have the same symmetry and spin as orbital 'b' !Simply run through symmetry classes in NI to count these. !NExcitTypes counts the number of different ways of getting an excitation, i.e. Different spin or symmetry Subroutine SymSetupExcitsAb_CountSing(nSing, nCl, nExcitTypes, ThisClassCount, Classes) use SystemData, only: Symmetry use SymData, only: SymClass, SymLabelCounts, nSymLabels, SymLabels IMPLICIT NONE INTEGER nSing INTEGER nCl INTEGER nExcitTypes INTEGER ThisClassCount(2, *) Type(SymClass) Classes(nCl) INTEGER I, ICC nSing = 0 !Loop over all symmetry classes of your electrons DO I = 1, nCl !First deal with alpha spins - there are ThisClassCount(1,I) alpha spins in this determinant. !We need to know how many unoccupied alpha spins with the same symmetry there are. !There are SymLabelCounts(1,Classes(I)%SymLab) total alpha spin-orbitals with the same symmetry. !SymLabelCounts(2,Classes(I)%SymLab)-ThisClassCount(1,I) indicates the number of unoccupied alpha orbitals with the required symmetry. !Each electron can excite to each unoccupied orbital, giving us the number of single excitations for this symmetry and spin IF (ThisClassCount(1, I) /= 0) THEN !Aren't going to be any singles if there are no electrons of that spin in the symmetry... ICC = (SymLabelCounts(2, Classes(I)%SymLab) - ThisClassCount(1, I)) * ThisClassCount(1, I) IF (ICC /= 0) THEN !We have found some alpha->alpha single excitations nSing = nSing + ICC nExcitTypes = nExcitTypes + 1 END IF END IF !Now do the same for beta spins IF (ThisClassCount(2, I) /= 0) THEN ICC = (SymLabelCounts(2, Classes(I)%SymLab) - ThisClassCount(2, I)) * ThisClassCount(2, I) IF (ICC /= 0) THEN !We have found some single excitations nSing = nSing + ICC nExcitTypes = nExcitTypes + 1 END IF END IF END DO End Subroutine SymSetupExcitsAb_CountSing !Based on the Count singles analogue, this fills the ExcitTypes array with !symmetry and excitation type information. Subroutine SymSetupExcitsAb_StoreSing(nExcitTypes, nCl, Classes, ThisClassCount, ExcitTypes) use SystemData, only: Symmetry use SymData, only: SymClass, SymLabelCounts, nSymLabels, SymLabels IMPLICIT NONE INTEGER nCl INTEGER nExcitTypes INTEGER ThisClassCount(2, *) Type(SymClass) Classes(nCl) INTEGER I, ICC INTEGER ExcitTypes(5, *) !nExcitTypes is reset to zero before this routine - the nExcitTypes will be incremented for doubles later. !Loop over all symmetry classes of your electrons DO I = 1, nCl !First deal with alpha spins - there are ThisClassCount(1,I) alpha spins in this determinant. !We need to know how many unoccupied alpha spins with the same symmetry there are. !There are SymLabelCounts(1,Classes(I)%SymLab) total alpha spin-orbitals with the same symmetry. !SymLabelCounts(2,Classes(I)%SymLab)-ThisClassCount(1,I) indicates the number of unoccupied alpha orbitals with the required symmetry. !Each electron can excite to each unoccupied orbital, giving us the number of single excitations for this symmetry and spin IF (ThisClassCount(1, I) /= 0) THEN !Aren't going to be any singles if there are no electrons of that spin in the symmetry... ICC = (SymLabelCounts(2, Classes(I)%SymLab) - ThisClassCount(1, I)) * ThisClassCount(1, I) IF (ICC /= 0) THEN !We have found some alpha->alpha single excitations of a new 'type' nExcitTypes = nExcitTypes + 1 !Put information on these type of excitation into the excittypes array ExcitTypes(1, nExcitTypes) = 1 !Its a single ExcitTypes(2, nExcitTypes) = 1 !Its an alpha->alpha excitation ExcitTypes(3, nExcitTypes) = I !Symmetry class of occupied orbital ExcitTypes(4, nExcitTypes) = Classes(I)%SymLab !Symmetry class of virtual orbital (the same!) !However, it wants to be the symmetry class from all !symmetry classes ExcitTypes(5, nExcitTypes) = ICC !Number of this type of excitation END IF END IF !Now do the same for beta spins IF (ThisClassCount(2, I) /= 0) THEN ICC = (SymLabelCounts(2, Classes(I)%SymLab) - ThisClassCount(2, I)) * ThisClassCount(2, I) IF (ICC /= 0) THEN !We have found some beta single excitations of a new 'type' nExcitTypes = nExcitTypes + 1 !Put information on these type of excitation into the excittypes array ExcitTypes(1, nExcitTypes) = 1 !Its a single ExcitTypes(2, nExcitTypes) = 2 !Its an beta->beta excitation ExcitTypes(3, nExcitTypes) = I !Symmetry class of occupied orbital ExcitTypes(4, nExcitTypes) = Classes(I)%SymLab !Symmetry class of virtual orbital (the same!) !However, it wants to be the symmetry class from all !symmetry classes ExcitTypes(5, nExcitTypes) = ICC !Number of this type of excitation END IF END IF END DO End Subroutine SymSetupExcitsAb_StoreSing Subroutine SymSetupExcits_StoreSingles(nExcitTypes, nCl, Classes, ThisClassCount, ExcitTypes) Use SystemData, only: Symmetry use SymData, only: SymClass, SymPairProds, nSymLabels, SymLabels use SymData, only: SymLabelCounts use sym_mod, only: SYMPROD, SymConj, LSYMSYM IMPLICIT NONE INTEGER nExcitTypes INTEGER nCl Type(SymClass) Classes(*) INTEGER ThisClassCount(2, *) INTEGER ExcitTypes(5, *) INTEGER I, J, K Type(Symmetry) Pr, Pr2 INTEGER iSpn INTEGER iCC !.. Now store the singles: NEXCITTYPES = 0 ! CALL WRITEDET(6,NI,NEL,.TRUE.) DO I = 1, NCL !.. For each class, see what sym prods it can interact with DO J = 1, NSYMLABELS PR = SYMPROD(SymConj(SymLabels(J)), SymLabels(CLASSES(I)%SymLab)) PR2 = SYMPROD(PR, Classes(I)%SymRem) ! WRITE(stdout,"(2I4,5Z4)") I,J, ! & CLASSES(I)%SymRem, ! & SymLabels(J), ! & SymLabels(CLASSES(I)%SymLab), ! & PR,PR2 IF (LSYMSYM(PR2)) THEN DO ISPN = 1, 2 ICC = 0 DO K = 1, NCL IF (CLASSES(K)%SymLab == J) ICC = THISCLASSCOUNT(ISPN, K) END DO ICC = THISCLASSCOUNT(ISPN, I) * (SYMLABELCOUNTS(2, J) - ICC) IF (ICC /= 0) THEN NEXCITTYPES = NEXCITTYPES + 1 EXCITTYPES(1, NEXCITTYPES) = 1 EXCITTYPES(2, NEXCITTYPES) = ISPN EXCITTYPES(3, NEXCITTYPES) = I EXCITTYPES(4, NEXCITTYPES) = J EXCITTYPES(5, NEXCITTYPES) = ICC ! WRITE(stdout,"(A,I,Z4,A,Z4,A,Z4)") "SINGLE", ! & NEXCITTYPES, ! & SymLabels(2,Classes(I)%SymLab),"(", ! & Classes(I)%SymRem, ! & ")->",SymLabels(2,J) END IF END DO END IF END DO END DO End Subroutine Subroutine SymSetupExcits_StoreDoubles(nPr, nSymPairProds, nAllowPPS, ExcitTypes, nExcitTypes, SymProds, SymProdInd) Use SystemData, only: Symmetry Use SymData, only: SymPairProds use sym_mod, only: LSYMSYM, SYMPROD, SymConj IMPLICIT NONE INTEGER nPr INTEGER nSymPairProds INTEGER nAllowPPS(3, *) INTEGER ExcitTypes(5, *) INTEGER nExcitTypes TYPE(Symmetry) SYMPRODS(0:*) INTEGER SYMPRODIND(2, 3, 1:*) INTEGER I, J, K, L INTEGER ICC INTEGER iSpn Type(Symmetry) SPP !.. And the doubles DO I = 1, NPR DO J = 1, nSymPairProds SPP = SymPairProds(J)%Sym IF (LSYMSYM(SYMPROD(SymConj(SYMPRODS(I)), SPP))) THEN DO ISPN = 1, 3 K = NALLOWPPS(ISPN, J) L = SYMPRODIND(2, ISPN, I) ICC = L * K IF (ICC /= 0) THEN NEXCITTYPES = NEXCITTYPES + 1 EXCITTYPES(1, NEXCITTYPES) = 2 EXCITTYPES(2, NEXCITTYPES) = ISPN EXCITTYPES(3, NEXCITTYPES) = I EXCITTYPES(4, NEXCITTYPES) = J EXCITTYPES(5, NEXCITTYPES) = ICC ! WRITE(stdout,"(A,3I5,4I5)") "SD",NEXCITTYPES,I,J, ! & ISPN,L,K,ICC END IF END DO END IF END DO END DO End Subroutine SUBROUTINE SYMGENALLEXCITS(NI, NEL, EXCITTYPES, NEXCITTYPES, CLASSES, SYMPRODIND, ILUT, ORBPAIRS, LSTE, ICLIST, ICOUNT) use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds use SymData, only: tAbelianFastExcitGen use constants, only: maxExcit use util_mod, only: stop_all use excit_mod, only: FindExcitDet IMPLICIT NONE INTEGER NEXCITTYPES INTEGER NEL, NI(NEL), EXCITTYPES(5, NEXCITTYPES) INTEGER I, J, K, L INTEGER NK(NEL) TYPE(SymClass) CLASSES(*) INTEGER IEXCIT INTEGER IFROM, ITO, ISPN INTEGER IFROMSL, ITOSL INTEGER ExcitMat(2, maxExcit) TYPE(Symmetry) SPP LOGICAL L1, L2 INTEGER ICC1, ICC2, ICC3, ICC4 LOGICAL L1B, L1A, L2B, L2A, TParity INTEGER ORBPAIRS(2, *) INTEGER ILUT(0:*) INTEGER SYMPRODIND(2, 3, 1:*) INTEGER LSTE(NEL, *), ICLIST(*), ICOUNT character(66) error_msg character(*), parameter :: this_routine = 'SYMGENALLEXCITS' ICOUNT = 0 if (tAbelianFastExcitGen) then error_msg = 'Fast Abelian excitation generators do not work '//'for SymGenAllExcits' call stop_all(this_routine, "Wrong excitation generator") end if !.. Now work out all the excitations DO IEXCIT = 1, NEXCITTYPES IF (EXCITTYPES(1, IEXCIT) == 1) THEN !.. a single excitation !.. We store each excitation type as: !.. 1 TYPE (single=1, double=2) !.. 2 SPIN (for single, 1=beta, 2=alpha. For double, 1=beta/beta; 2=alpha/beta; 3=alpha/alpha;) !.. 3 FROM (for single, I in CLASSES(I); for double, I in SYMPRODS(I) ) !.. 4 TO (for single, J in SymLabels(J); for double, J in SYMPAIRPRODS(J) ) !.. 5 COUNT (Total number of excitations in this category) ISPN = EXCITTYPES(2, IEXCIT) - 2 IFROM = CLASSES(EXCITTYPES(3, IEXCIT))%SymLab ITO = EXCITTYPES(4, IEXCIT) J = 0 I = 1 ! WRITE(stdout,*) ISPN,IFROM,ITO,EXCITTYPES(5,IEXCIT) !.. SYMLABELCOUNTS(1,I) is the index within SYMLABELLIST of the first state of symlabel I !.. SYMLABELCOUNTS(2,I) is the number of states with symlabel I DO WHILE (I <= NEL) L1 = J < SYMLABELCOUNTS(2, IFROM) DO WHILE (L1) IFROMSL = (SYMLABELLIST(SYMLABELCOUNTS(1, IFROM) + J) * 2 + ISPN) ! WRITE(stdout,*) I,NI(I),J,IFROM,IFROMSL IF (IFROMSL < NI(I)) J = J + 1 L1 = IFROMSL < NI(I) .AND. J < SYMLABELCOUNTS(2, IFROM) END DO ! WRITE(stdout,*) I,J,SYMLABELCOUNTS(2,IFROM) IF (J < SYMLABELCOUNTS(2, IFROM) .AND. IFROMSL == NI(I)) THEN !.. We've found an orb in NI with the correct sym. Now go through the list of possible excitations of it K = 0 L = 0 DO WHILE (K < SYMLABELCOUNTS(2, ITO)) L2 = .TRUE. ITOSL = 2 * SYMLABELLIST(SYMLABELCOUNTS(1, ITO) + K) + ISPN DO WHILE (L2) L = L + 1 L2 = L <= NEL .AND. NI(L) < ITOSL END DO IF (L > NEL .OR. NI(L) /= ITOSL) THEN !.. We've found a virtual into which we can excite our occupied orb. ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(:) = NI(:) !Find the ordered excited determinant ExcitMat(1, 1) = I !This is the position of the orbital to excite ExcitMat(2, 1) = ITOSL CALL FindExcitDet(ExcitMat, NK, 1, TParity) ! NK(I)=ITOSL ! CALL NECI_SORTI(NEL,NK) ICOUNT = ICOUNT + 1 ICLIST(ICOUNT) = 1 ! CALL NECI_ICOPY(NEL,NK,1,LSTE(1,ICOUNT),1) LSTE(1:NEL, ICOUNT) = NK(:) ! CALL WRITEDET(26,NK,NEL,.FALSE.) ! CALL GETSYM(NK,NEL,G1,NBASISMAX,ISYM) ! WRITE(26,'(Z6)') ISYM END IF L = L - 1 K = K + 1 END DO END IF I = I + 1 END DO ELSE !.. a double excitation !.. We store each excitation type as: !.. 1 TYPE (single=1, double=2) !.. 2 SPIN (for single, 1=beta, 2=alpha. For double, 1=beta/beta; 2=alpha/beta; 3=alpha/alpha;) !.. 3 FROM (for single, I in CLASSES(I); for double, I in SYMPRODS(I) ) !.. 4 TO (for single, J in SymLabels(J); for double, J in SYMPAIRPRODS(J) ) !.. 5 COUNT (Total number of excitations in this category) ISPN = EXCITTYPES(2, IEXCIT) IFROM = EXCITTYPES(3, IEXCIT) ITO = EXCITTYPES(4, IEXCIT) ! WRITE(stdout,*) "EXC",IEXCIT,ISPN,IFROM,ITO,SYMPRODIND(2,ISPN, ! & IFROM) !.. Go through the list of pairs with a given symprod. !.. SYMPRODIND(1,ISPN,I)+1 contains the index of the first element of spin ISPN of sym !.. SYMPRODS(I) in ORBPAIRS !.. SYMPRODIND(2,ISPN,I) contains the number of such elements DO I = 1, SYMPRODIND(2, ISPN, IFROM) !.. Now go through the list of virtual pairs, excluding those with orbitals in NI SPP = SymPairProds(ITO)%Sym ! WRITE(stdout,*) "SPP:", SPP !.. SYMPAIRPRODS(1:NSYMPAIRPRODS) contains the list of all SYMPRODs available, the number of pairs of !.. states (listed in SymStatePairs), and the index of the start of this list !.. For a given (unique) SymPairProds(J)%Sym, I=SymPairProds(J)%Index. !.. [ SymStatePairs(1,I) , SymStatePairs(2,I) ] is the pair of states whose prod is of that symmetry. DO K = SymPairProds(ITO)%nIndex, SymPairProds(ITO)%nIndex + SymPairProds(ITO)%nPairs - 1 !.. Now check according to ISPN !.. ICC1 is the beta orbital corresponding to the first state, and ICC2 the alpha !.. ICC3 is the beta orbital corresponding to the state, and ICC4 the alpha ICC1 = SymStatePairs(1, K) * 2 - 1 ICC2 = ICC1 + 1 ICC3 = SymStatePairs(2, K) * 2 - 1 ICC4 = ICC3 + 1 ! WRITE(stdout,*) ORBPAIRS(1,SYMPRODIND(1,ISPN,IFROM)+I), ! & ORBPAIRS(2,SYMPRODIND(1,ISPN,IFROM)+I) ! WRITE(stdout,*) ISPN,ICC1,ICC3 L1B = BTEST(ILUT((ICC1 - 1) / 32), MOD(ICC1 - 1, 32)) L1A = BTEST(ILUT((ICC2 - 1) / 32), MOD(ICC2 - 1, 32)) L2B = BTEST(ILUT((ICC3 - 1) / 32), MOD(ICC3 - 1, 32)) L2A = BTEST(ILUT((ICC4 - 1) / 32), MOD(ICC4 - 1, 32)) ! WRITE(stdout,*) L1B,L1A,L2B,L2A !.. L1B is set if the beta of the first virtual is in NI, i.e. is disallowed IF (ISPN == 1) THEN !.. If both virtuals aren't the samem and neither are in NI, then allow IF (ICC1 /= ICC3 .AND. .NOT.(L1B .OR. L2B)) THEN ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC1 ! NK(J)=ICC1 END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(2, 1) = J ExcitMat(2, 2) = ICC3 ! NK(J)=ICC3 END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) CALL FindExcitDet(ExcitMat, NK, 2, TParity) ! CALL NECI_SORTI(NEL,NK) ICOUNT = ICOUNT + 1 ICLIST(ICOUNT) = 2 ! CALL NECI_ICOPY(NEL,NK,1,LSTE(1,ICOUNT),1) LSTE(1:NEL, ICOUNT) = NK(1:NEL) ! CALL WRITEDET(26,NK,NEL,.FALSE.) ! CALL GETSYM(NK,NEL,G1,NBASISMAX,ISYM) ! WRITE(26,'(Z6)') ISYM ! CALL WRITEDET(6,NK,NEL,.TRUE.) END IF ELSEIF (ISPN == 2) THEN !.. If neither virtuals are in NI, then allow IF (.NOT.(L1B .OR. L2A)) THEN ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC1 ! NK(J)=ICC1 END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(1, 2) = J ExcitMat(2, 2) = ICC4 ! NK(J)=ICC4 END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) CALL FindExcitDet(ExcitMat, NK, 2, TParity) ! CALL NECI_SORTI(NEL,NK) ICOUNT = ICOUNT + 1 ICLIST(ICOUNT) = 2 ! CALL NECI_ICOPY(NEL,NK,1,LSTE(1,ICOUNT),1) LSTE(1:NEL, ICOUNT) = NK(1:NEL) ! CALL WRITEDET(26,NK,NEL,.FALSE.) ! CALL GETSYM(NK,NEL,G1,NBASISMAX,ISYM) ! WRITE(26,'(Z6)') ISYM ! CALL WRITEDET(6,NK,NEL,.TRUE.) END IF !.. If neither virtuals are in NI, and they're not the same(which would give !.. us the same excitation as previously), then allow IF (.NOT.(L1A .OR. L2B) .AND. ICC1 /= ICC3) THEN ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC2 ! NK(J)=ICC2 END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(1, 2) = J ExcitMat(2, 2) = ICC3 ! NK(J)=ICC3 END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) ! CALL NECI_SORTI(NEL,NK) CALL FindExcitDet(ExcitMat, NK, 2, TParity) ICOUNT = ICOUNT + 1 ICLIST(ICOUNT) = 2 ! CALL NECI_ICOPY(NEL,NK,1,LSTE(1,ICOUNT),1) LSTE(1:NEL, ICOUNT) = NK(1:NEL) ! CALL WRITEDET(26,NK,NEL,.FALSE.) ! CALL GETSYM(NK,NEL,G1,NBASISMAX,ISYM) ! WRITE(26,'(Z6)') ISYM ! CALL WRITEDET(6,NK,NEL,.TRUE.) END IF ELSEIF (ISPN == 3) THEN !.. If both virtuals aren't the samem and neither are in NI, then allow IF (ICC1 /= ICC3 .AND. .NOT.(L1A .OR. L2A)) THEN ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC2 ! NK(J)=ICC2 END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN ExcitMat(1, 2) = J ExcitMat(2, 2) = ICC4 ! NK(J)=ICC4 END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) ! CALL NECI_SORTI(NEL,NK) CALL FindExcitDet(ExcitMat, NK, 2, TParity) ICOUNT = ICOUNT + 1 ICLIST(ICOUNT) = 2 ! CALL NECI_ICOPY(NEL,NK,1,LSTE(1,ICOUNT),1) LSTE(1:NEL, ICOUNT) = NK(1:NEL) ! CALL WRITEDET(26,NK,NEL,.FALSE.) ! CALL GETSYM(NK,NEL,G1,NBASISMAX,ISYM) ! WRITE(26,'(Z6)') ISYM ! CALL WRITEDET(6,NK,NEL,.TRUE.) END IF END IF END DO END DO END IF END DO ! WRITE(stdout,*) "COUNT:",ICOUNT END ! For a symmetry excitation generator stored in NMEM, return the total number of excitations from it in iCount. SUBROUTINE GetSymExcitCount(NMEM, iCount) use SystemData, only: tAssumeSizeExcitgen IMPLICIT NONE INTEGER NMEM(*) INTEGER iCount IF (tAssumeSizeExcitgen) THEN iCount = NMEM(1) ELSE iCount = NMEM(23) END IF RETURN END SUBROUTINE GetSymExcitCount SUBROUTINE GENSYMEXCITIT3Par(NI, TSETUP, NMEM, NJ, IC, STORE, ILEVEL, iMinElec1, iMaxElec1) use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SystemData, only: nEl, G1, nBasis, nBasisMax IMPLICIT NONE INTEGER NI(NEL) INTEGER, pointer :: DSTORE(:) ! STORE contains lengths of various components of the excitation generator INTEGER STORE(6) ! STORE will contain the addesses of various components of the excitation generator, and is passed to SYMSETUPEXCITS2 INTEGER, target :: NMEM(*) INTEGER NJ(NEL), IC LOGICAL TSETUP INTEGER ILEVEL INTEGER iMinElec1, iMaxElec1 CALL GENSYMEXCITIT2Par(NI, NEL, G1, NBASIS, TSETUP, NMEM, NJ, IC, STORE, ILEVEL, iMinElec1, iMaxElec1) END !.. A modified version of GENSYMEXCITIT2. This has min and max electron 1 specifiers used for parallelization SUBROUTINE GENSYMEXCITIT2Par(NI, NEL, G1, NBASIS, TSETUP, NMEM, NJ, IC, STORE, ILEVEL, iMinElec1, iMaxElec1) use SystemData, only: basisfn use SymExcit2, only: gensymexcitit2par_worker integer :: nel, nI(nel), nbasis, nmem(*), nJ(nel), ic, store(6) integer :: ilevel, iMinElec1, iMaxElec1 type(basisfn) :: g1(nbasis) logical :: tsetup call gensymexcitit2par_worker(nI, nel, g1, nbasis, tSetup, nmem, nJ, ic, store, ilevel, iminelec1, imaxelec1) end subroutine SUBROUTINE RESETEXIT2(NMEM) IMPLICIT NONE INTEGER NMEM(*) ! NMEM(1:22)=0 NMEM(11) = -1 ! Set I=-1 (i.e. start from the first electron again) NMEM(7) = 0 !set iExcit=0 (i.e. start from the first excit class again END ! CALL RESETEXIT(IPATH(1,LOCTAB(3,IVLEVEL)),NEL,G1, ! & NBASIS,NBASISMAX,CURGEN,IFRZ2) SUBROUTINE SYMGENEXCITIT(NI, NEL, EXCITTYPES, NEXCITTYPES, CLASSES, & SYMPRODIND, ILUT, ORBPAIRS, IEXCIT, ISPN, IFROM, ITO, & I, J, K, L, ICC, LS, NK, IC, iMinElec1, iMaxElec1) use SystemData, only: TSTOREASEXCITATIONS use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds use constants, only: maxExcit, stdout use util_mod, only: stop_all use excit_mod, only: FindExcitDet IMPLICIT NONE INTEGER NEXCITTYPES INTEGER NEL, NI(NEL), EXCITTYPES(5, NEXCITTYPES) INTEGER I, J, K, L INTEGER NK(NEL) TYPE(SymClass) CLASSES(*) INTEGER IEXCIT INTEGER IFROM, ITO, ISPN INTEGER IFROMSL, ITOSL TYPE(Symmetry) SPP LOGICAL L1, L2 INTEGER ICC(4) !.. 1,1= 1B, 1,2=1A; 2,1=2B, 2,2=2A. LOGICAL LS(2, 2), TParity INTEGER ORBPAIRS(2, *) INTEGER ILUT(0:*) INTEGER SYMPRODIND(2, 3, 1:*) INTEGER IC, ExcitMat(2, maxExcit) LOGICAL tDebugPrint INTEGER iMinElec1, iMaxElec1 character(*), parameter :: this_routine = 'SYMGENEXCITIT' tDebugPrint = .false. DO WHILE (.TRUE.) !.. see if we need a new EXCIT ! WRITE(stdout,*) I,iExcit,nExcitTypes IF (I < 0) THEN !.. move to the next excitation IEXCIT = IEXCIT + 1 IF (IEXCIT > NEXCITTYPES) THEN !.. We're done NK(1) = 0 RETURN END IF IF (EXCITTYPES(1, IEXCIT) == 1) THEN !.. a single ISPN = EXCITTYPES(2, IEXCIT) - 2 IFROM = CLASSES(EXCITTYPES(3, IEXCIT))%SymLab ITO = EXCITTYPES(4, IEXCIT) L = 0 K = SYMLABELCOUNTS(2, ITO) ! J will run along symblabels J = 0 ! I will run along the determinant I = 0 ! Take into account the we may only be doing a subset of the electrons DO WHILE (I < NEL) IF (NI(I + 1) >= iMinElec1) EXIT I = I + 1 END DO ! I now is the index of the first electron allowed in our subset IF (tDebugPrint) WRITE(stdout, *) "EXC", IEXCIT, ISPN, IFROM, ITO, SYMPRODIND(2, ISPN, IFROM) ELSE !.. a double ISPN = EXCITTYPES(2, IEXCIT) IFROM = EXCITTYPES(3, IEXCIT) ITO = EXCITTYPES(4, IEXCIT) I = 0 L = 5 K = -2 IF (tDebugPrint) WRITE(stdout, *) "EXC", IEXCIT, ISPN, IFROM, ITO, SYMPRODIND(2, ISPN, IFROM) END IF END IF IF (EXCITTYPES(1, IEXCIT) == 1) THEN !.. singles !.. We always need a new K. K and L run in parallel K = K + 1 !.. We've stored IFROMSL in ICC1 IFROMSL = ICC(1) !.. For each K, we check to see if it's valid IF (K >= SYMLABELCOUNTS(2, ITO)) THEN !.. no more possible K, so we get a new I K = -1 L = 0 !.. I and J run in parallel, and for each J, we check whether it's in !.. the det. If it is, then we carry on. !.. SYMLABELLIST holds a list of states grouped under symmlabel, and ordered within that symlabel !.. SYMLABELCOUNTS(1,J) is the index within SYMLABELLIST of the first state of symlabel J !.. SYMLABELCOUNTS(2,J) is the number of states with symlabel J !.. J runs along the symlabel looking for states of that symmetry !.. I runs along the determinant comparing against electrons of that symmetry. !.. We're looking for electrons in the det which are also in the SYMLABELLIST, and we run I and J !.. in parallel along each to keep the search efficient. ! instead of NEL, we have iMaxElec1 L2 = I < iMaxElec1 L1 = .TRUE. ! This loop, dependent on L2 gets a new I DO WHILE (L2) I = I + 1 L1 = J < SYMLABELCOUNTS(2, IFROM) ! This loop dependent on L1 gets a new J DO WHILE (L1) IFROMSL = (SYMLABELLIST(SYMLABELCOUNTS(1, IFROM) + J) * 2 + ISPN) ICC(1) = IFROMSL ! WRITE(stdout,*) I,NI(I),J,IFROM,IFROMSL ! If J points to an electron lower than the current in the det, inc J IF (IFROMSL < NI(I)) J = J + 1 ! If J was a lower elec, and there are more J to get, then carry on in this loop L1 = IFROMSL < NI(I) .AND. J < SYMLABELCOUNTS(2, IFROM) END DO !.. see if we need a new I because NI(I)<IFROMSL which is the current electron corresponging to J. ! Instead of NEL we have iMaxElec1 L2 = IFROMSL /= NI(I) .AND. I < iMaxElec1 ! If I.EQ.NEL, then we're run out of electrons, because the next electron we get will be in pos NEL+1 END DO !.. If we've gone too far, signal a new excit ! If L1 is true then we never made it into the get new J loop because L2 was FALSE because there were no more electrons to get in the det. Alternatively we've hit the last electron in the det, and not found a correspondence in the sym excit list. Either way we signal to give up on this set of excitations, as we cannot find a valid I. ! Instead of NEL we use iMaxElec1 IF (L1 .OR. (I == iMaxElec1 .AND. IFROMSL /= NI(I))) I = -1 ! Cycle back to the beginning with our new valid I (or invalid I signalling find a new excit type), and look for a K CYCLE END IF !.. it's a valid K, but is it in the det already? !.. ITOSL is the orb it corresponds to ITOSL = 2 * SYMLABELLIST(SYMLABELCOUNTS(1, ITO) + K) + ISPN !.. Check if it's in the det L2 = .TRUE. ! WRITE(stdout,*) SYMLABELCOUNTS(2,ITO),ITOSL DO WHILE (L2) L = L + 1 L2 = L <= NEL .AND. NI(L) < ITOSL END DO IF (L <= NEL .AND. NI(L) == ITOSL) THEN !.. We've found an L in the det which is the same as ITOSL. !.. we go round again, getting another K CYCLE END IF L = L - 1 !.. hoorah! We've got an I in the det, and a K not in the det. Create an excitation IF (tStoreAsExcitations) THEN !The excitation storage starts with -1. The next number is the excitation level,L . Next is the parity of the permutation required to lineup occupied->excited. Then follows a list of the indexes of the L occupied orbitals within the HFDET, and then L virtual spinorbitals. NK(1) = -1 NK(2) = 1 NK(3) = 0 NK(4) = NI(I) NK(5) = ITOSL call stop_all(this_routine, 'tStoreAsExcitations not tested for singles.') ELSE ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) IF (tDebugPrint) WRITE(stdout, *) "[", NK(I), "->", ITOSL, "]" ExcitMat(1, 1) = I ExcitMat(2, 1) = ITOSL CALL FindExcitDet(ExcitMat, NK, 1, TParity) ! NK(I)=ITOSL ! CALL NECI_SORTI(NEL,NK) IC = 1 END IF !.. quit the do loop EXIT ELSE !.. doubles SPP = SymPairProds(ITO)%Sym !.. See if we need a new K. L is the spin label, and goes from 1..4. IF (L > 4) THEN L = 1 K = K + 1 IF (K < 0 .OR. K >= SymPairProds(ITO)%nIndex + SymPairProds(ITO)%nPairs) THEN !.. K is invalid. Get a new I K = 1 I = I + 1 IF (I > SYMPRODIND(2, ISPN, IFROM)) THEN !.. I is now invalid I = -1 CYCLE ELSE !.. reset K K = SymPairProds(ITO)%nIndex END IF END IF !.. We've got a new K, so we need to reset some variables ICC(1) = SymStatePairs(1, K) * 2 - 1 ICC(2) = ICC(1) + 1 ICC(3) = SymStatePairs(2, K) * 2 - 1 ICC(4) = ICC(3) + 1 ! WRITE(stdout,*) ORBPAIRS(1,SYMPRODIND(1,ISPN,IFROM)+I), ! & ORBPAIRS(2,SYMPRODIND(1,ISPN,IFROM)+I) ! WRITE(stdout,*) ISPN,ICC(1),ICC(3) LS(1, 1) = BTEST(ILUT((ICC(1) - 1) / 32), MOD(ICC(1) - 1, 32)) LS(1, 2) = BTEST(ILUT((ICC(2) - 1) / 32), MOD(ICC(2) - 1, 32)) LS(2, 1) = BTEST(ILUT((ICC(3) - 1) / 32), MOD(ICC(3) - 1, 32)) LS(2, 2) = BTEST(ILUT((ICC(4) - 1) / 32), MOD(ICC(4) - 1, 32)) END IF !.. Now check for an excitation IF (L == 1) THEN L = 2 IF (ISPN == 1 .AND. ICC(1) /= ICC(3) .AND. .NOT.(LS(1, 1) .OR. LS(2, 1))) THEN IF (tStoreAsExcitations) THEN !The excitation storage starts with -1. The next number is the excitation level,L . Next is the parity of the permutation required to lineup occupied->excited. Then follows a list of the indexes of the L occupied orbitals within the HFDET, and then L virtual spinorbitals. NK(1) = -1 NK(2) = 2 NK(3) = 1 NK(4) = ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I) NK(5) = ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I) NK(6) = ICC(1) NK(7) = ICC(3) ELSE ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, "(A,I3,A,I3,A)", advance='no') "[", NK(J), "->", ICC(1), "," ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC(1) ! NK(J)=ICC(1) END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, *) NK(J), "->", ICC(3), "]" ! NK(J)=ICC(3) ExcitMat(1, 2) = J ExcitMat(2, 2) = ICC(3) END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) ! CALL NECI_SORTI(NEL,NK) CALL FindExcitDet(ExcitMat, NK, 2, TParity) END IF IC = 2 EXIT END IF END IF IF (L == 2) THEN L = 3 IF (ISPN == 2) THEN !.. If neither virtuals are in NI, then allow IF (.NOT.(LS(1, 1) .OR. LS(2, 2))) THEN IF (tStoreAsExcitations) THEN !The excitation storage starts with -1. The next number is the excitation level,L . Next is the parity of the permutation required to lineup occupied->excited. Then follows a list of the indexes of the L occupied orbitals within the HFDET, and then L virtual spinorbitals. NK(1) = -1 NK(2) = 2 NK(3) = 1 NK(4) = ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I) NK(5) = ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I) NK(6) = ICC(1) NK(7) = ICC(4) ELSE ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, "(A,I3,A,I3,A)", advance='no') "[", NK(J), "->", ICC(1), "," ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC(1) ! NK(J)=ICC(1) END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, *) NK(J), "->", ICC(4), "]" ExcitMat(1, 2) = J ExcitMat(2, 2) = ICC(4) ! NK(J)=ICC(4) END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) CALL FindExcitDet(ExcitMat, NK, 2, TParity) ! CALL NECI_SORTI(NEL,NK) END IF IC = 2 EXIT END IF END IF END IF IF (L == 3) THEN L = 4 IF (ISPN == 2) THEN !.. If neither virtuals are in NI, and they're not the same(which would give !.. us the same excitation as previously), then allow IF (.NOT.(LS(1, 2) .OR. LS(2, 1)) .AND. ICC(1) /= ICC(3)) THEN IF (tStoreAsExcitations) THEN !The excitation storage starts with -1. The next number is the excitation level,L . Next is the parity of the permutation required to lineup occupied->excited. Then follows a list of the indexes of the L occupied orbitals within the HFDET, and then L virtual spinorbitals. NK(1) = -1 NK(2) = 2 NK(3) = 1 NK(4) = ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I) NK(5) = ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I) NK(6) = ICC(2) NK(7) = ICC(3) ELSE ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, "(A,I3,A,I3,A)", advance='no') "[", NK(J), "->", ICC(2), "," ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC(2) ! NK(J)=ICC(2) END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, *) NK(J), "->", ICC(3), "]" ! NK(J)=ICC(3) ExcitMat(1, 2) = J ExcitMat(2, 2) = ICC(3) END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) ! CALL NECI_SORTI(NEL,NK) CALL FindExcitDet(ExcitMat, NK, 2, TParity) END IF IC = 2 EXIT END IF END IF END IF IF (L == 4) THEN L = 5 IF (ISPN == 3) THEN !.. If both virtuals aren't the samem and neither are in NI, then allow IF (ICC(1) /= ICC(3) .AND. .NOT.(LS(1, 2) .OR. LS(2, 2))) THEN IF (tStoreAsExcitations) THEN !The excitation storage starts with -1. The next number is the excitation level,L . Next is the parity of the permutation required to lineup occupied->excited. Then follows a list of the indexes of the L occupied orbitals within the HFDET, and then L virtual spinorbitals. NK(1) = -1 NK(2) = 2 NK(3) = 1 NK(4) = ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I) NK(5) = ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I) NK(6) = ICC(2) NK(7) = ICC(4) ELSE ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, "(A,I3,A,I3,A)", advance='no') "[", NK(J), "->", ICC(2), "," ExcitMat(1, 1) = J ExcitMat(2, 1) = ICC(2) ! NK(J)=ICC(2) END IF IF (NI(J) == ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I)) THEN IF (tDebugPrint) WRITE(stdout, *) NK(J), "->", ICC(4), "]" ! NK(J)=ICC(4) ExcitMat(1, 2) = J ExcitMat(2, 2) = ICC(4) END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) ! CALL NECI_SORTI(NEL,NK) CALL FindExcitDet(ExcitMat, NK, 2, TParity) END IF IC = 2 EXIT END IF END IF END IF END IF END DO END Subroutine SymGenExcitIt2(nI, nEl, ExcitTypes, nExcitTypes, & Classes, SymProdInd, iLUT, OrbPairs, iExcit, iSpn, & iFrom, iTo, I, J, K, L, iCC, LS, nK, iC, iMinElec1, iMaxElec1) use SystemData, only: TSTOREASEXCITATIONS use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds use constants, only: stdout IMPLICIT NONE INTEGER NEXCITTYPES INTEGER NEL, NI(NEL), EXCITTYPES(5, NEXCITTYPES) INTEGER I, J, K, L INTEGER NK(NEL) TYPE(SymClass) CLASSES(*) INTEGER IEXCIT INTEGER IFROM, ITO, ISPN TYPE(Symmetry) SPP INTEGER ICC(4) !.. 1,1= 1B, 1,2=1A; 2,1=2B, 2,2=2A. LOGICAL LS(2, 2) INTEGER ORBPAIRS(2, *) INTEGER ILUT(0:*) INTEGER SYMPRODIND(2, 3, 1:*) INTEGER IC LOGICAL tDebugPrint INTEGER iMinElec1, iMaxElec1 INTEGER iRet tDebugPrint = .false. if (tDebugPrint) write(stdout, *) "Entering SymGenExcitIt2" DO WHILE (.TRUE.) ! Indicate that we need to keep on cycling. If it is changed ! by the later routines we stop the loop iRet = 0 !.. see if we need a new EXCIT if (tDebugPrint) WRITE(stdout, *) "I,iExcit,nExcitTypes", I, iExcit, nExcitTypes IF (I < 0) THEN !.. move to the next excitation IEXCIT = IEXCIT + 1 IF (IEXCIT > NEXCITTYPES) THEN !.. We're done NK(1) = 0 RETURN END IF IF (EXCITTYPES(1, IEXCIT) == 1) THEN Call SymGenExcitIt_SetupSingle( & iSpn, iFrom, iTo, iExcit, ExcitTypes, Classes, SymProdInd, & I, J, K, L, nI, nEl, iMinElec1, tDebugPrint) ELSE Call SymGenExcitIt_SetupDouble( & iSpn, iFrom, iTo, iExcit, ExcitTypes, SymProdInd, I, K, L, tDebugPrint) END IF END IF IF (EXCITTYPES(1, IEXCIT) == 1) THEN Call SymGenExcitIt_GenSingle(iRet, iSpn, iFrom, iTo, iCC, I, J, K, L, tDebugPrint, iMaxElec1, iC, nI, nK, nEl) ELSE Call SymGenExcitIt_GenDouble( & iRet, SPP, I, K, L, iTo, iSpn, iFrom, iCC, & iLUT, LS, OrbPairs, SymProdInd, nI, nK, nEl, iC, tDebugPrint) END IF if (iRet == 1) cycle if (iRet == 2) return END DO End Subroutine SymGenExcitIt2 Subroutine SymGenExcitIt_SetupSingle(iSpn, iFrom, iTo, iExcit, ExcitTypes, Classes, SymProdInd, I, J, K, L, nI, nEl, iMinElec1, tDebugPrint) use SystemData, only: TSTOREASEXCITATIONS use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds use constants, only: stdout IMPLICIT NONE INTEGER nEl, nI(nEl) INTEGER ExcitTypes(5, *) INTEGER I, J, K, L TYPE(SymClass) Classes(*) INTEGER iExcit INTEGER iFrom, iTo, iSpn INTEGER SymProdInd(2, 3, 1:*) LOGICAL tDebugPrint INTEGER iMinElec1 !.. a single ISPN = EXCITTYPES(2, IEXCIT) - 2 IFROM = CLASSES(EXCITTYPES(3, IEXCIT))%SymLab ITO = EXCITTYPES(4, IEXCIT) L = 0 K = SYMLABELCOUNTS(2, ITO) ! J will run along symblabels J = 0 ! I will run along the determinant I = 0 ! Take into account the we may only be doing a subset of the electrons DO WHILE (I < NEL) IF (NI(I + 1) >= iMinElec1) EXIT I = I + 1 END DO ! I now is the index of the first electron allowed in our subset IF (tDebugPrint) WRITE(stdout, *) "EXC", IEXCIT, ISPN, IFROM, ITO, SYMPRODIND(2, ISPN, IFROM) End Subroutine SymGenExcitIt_SetupSingle Subroutine SymGenExcitIt_SetupDouble(iSpn, iFrom, iTo, iExcit, ExcitTypes, SymProdInd, I, K, L, tDebugPrint) use SystemData, only: TSTOREASEXCITATIONS use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds use constants, only: stdout IMPLICIT NONE INTEGER ExcitTypes(5, *) INTEGER I, K, L INTEGER iExcit INTEGER iFrom, iTo, iSpn INTEGER SymProdInd(2, 3, 1:*) LOGICAL tDebugPrint !.. a double ISPN = EXCITTYPES(2, IEXCIT) IFROM = EXCITTYPES(3, IEXCIT) ITO = EXCITTYPES(4, IEXCIT) I = 0 L = 5 !An invalid spin K = -2 !When we +1 this is still invalid so it resets the pair index IF (tDebugPrint) WRITE(stdout, *) "EXC", IEXCIT, ISPN, IFROM, ITO, SYMPRODIND(2, ISPN, IFROM) End Subroutine SymGenExcitIt_SetupDouble Subroutine SymGenExcitIt_GenSingle(iRet, iSpn, iFrom, iTo, iCC, I, J, K, L, tDebugPrint, iMaxElec1, iC, nI, nK, nEl) use SystemData, only: TSTOREASEXCITATIONS use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds use constants, only: maxExcit, stdout use util_mod, only: stop_all use excit_mod, only: FindExcitDet IMPLICIT NONE INTEGER nEl, nI(nEl) INTEGER I, J, K, L INTEGER nK(nEl) INTEGER iFrom, iTo, iSpn INTEGER ICC(4) INTEGER IFROMSL, ITOSL LOGICAL L1, L2, TParity !.. 1,1= 1B, 1,2=1A; 2,1=2B, 2,2=2A. INTEGER iC, ExcitMat(2, maxExcit) LOGICAL tDebugPrint INTEGER iMaxElec1 INTEGER iRet character(*), parameter:: this_routine = 'SymGenExcitIt_GenSingle' !.. singles !.. We always need a new K. K and L run in parallel K = K + 1 !.. We've stored IFROMSL in ICC1 IFROMSL = ICC(1) !.. For each K, we check to see if it's valid IF (K >= SYMLABELCOUNTS(2, ITO)) THEN !.. no more possible K, so we get a new I K = -1 L = 0 !.. I and J run in parallel, and for each J, we check whether it's in !.. the det. If it is, then we carry on. !.. SYMLABELLIST holds a list of states grouped under symmlabel, and ordered within that symlabel !.. SYMLABELCOUNTS(1,J) is the index within SYMLABELLIST of the first state of symlabel J !.. SYMLABELCOUNTS(2,J) is the number of states with symlabel J !.. J runs along the symlabel looking for states of that symmetry !.. I runs along the determinant comparing against electrons of that symmetry. !.. We're looking for electrons in the det which are also in the SYMLABELLIST, and we run I and J !.. in parallel along each to keep the search efficient. ! instead of NEL, we have iMaxElec1 L2 = I < iMaxElec1 L1 = .TRUE. ! This loop, dependent on L2 gets a new I DO WHILE (L2) I = I + 1 L1 = J < SYMLABELCOUNTS(2, IFROM) ! This loop dependent on L1 gets a new J DO WHILE (L1) IFROMSL = (SYMLABELLIST(SYMLABELCOUNTS(1, IFROM) + J) * 2 + ISPN) ICC(1) = IFROMSL ! WRITE(stdout,*) I,NI(I),J,IFROM,IFROMSL ! If J points to an electron lower than the current in the det, inc J IF (IFROMSL < NI(I)) J = J + 1 ! If J was a lower elec, and there are more J to get, then carry on in this loop L1 = IFROMSL < NI(I) .AND. J < SYMLABELCOUNTS(2, IFROM) END DO !.. see if we need a new I because NI(I)<IFROMSL which is the current electron corresponging to J. ! Instead of NEL we have iMaxElec1 L2 = IFROMSL /= NI(I) .AND. I < iMaxElec1 ! If I.EQ.NEL, then we're run out of electrons, because the next electron we get will be in pos NEL+1 END DO !.. If we've gone too far, signal a new excit ! If L1 is true then we never made it into the get new J loop because L2 was FALSE because there were no more electrons to get in the det. Alternatively we've hit the last electron in the det, and not found a correspondence in the sym excit list. Either way we signal to give up on this set of excitations, as we cannot find a valid I. ! Instead of NEL we use iMaxElec1 IF (L1 .OR. (I == iMaxElec1 .AND. IFROMSL /= NI(I))) I = -1 ! Cycle back to the beginning with our new valid I (or invalid I signalling find a new excit type), and look for a K iRet = 1 RETURN END IF !.. it's a valid K, but is it in the det already? !.. ITOSL is the orb it corresponds to ITOSL = 2 * SYMLABELLIST(SYMLABELCOUNTS(1, ITO) + K) + ISPN !.. Check if it's in the det L2 = .TRUE. ! WRITE(stdout,*) SYMLABELCOUNTS(2,ITO),ITOSL DO WHILE (L2) L = L + 1 L2 = .false. if (L <= nel) then if (nI(L) < iToSL) L2 = .true. end if END DO IF (L <= NEL) then if (NI(L) == ITOSL) THEN !.. We've found an L in the det which is the same as ITOSL. !.. we go round again, getting another K iRet = 1 RETURN end if END IF L = L - 1 !.. hoorah! We've got an I in the det, and a K not in the det. Create an excitation IF (tStoreAsExcitations) THEN !The excitation storage starts with -1. The next number is the excitation level,L . Next is the parity of the permutation required to lineup occupied->excited. Then follows a list of the indexes of the L occupied orbitals within the HFDET, and then L virtual spinorbitals. NK(1) = -1 NK(2) = 1 NK(3) = 0 NK(4) = NI(I) NK(5) = ITOSL call stop_all(this_routine, 'tStoreAsExcitations not tested for singles.') ELSE ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) IF (tDebugPrint) WRITE(stdout, *) "[", NK(I), "->", ITOSL, "]" ExcitMat(1, 1) = I ExcitMat(2, 1) = ITOSL ! NK(I)=ITOSL ! CALL NECI_SORTI(NEL,NK) CALL FindExcitDet(ExcitMat, NK, 1, TParity) IC = 1 END IF !.. quit the do loop iRet = 2 RETURN End Subroutine SymGenExcitIt_GenSingle !Because the fast abelian excitation generators don't keep a stored list of virtual pairs, they need a different excitation generator routine. We generate the list on the fly. Subroutine SymGenExcitItOld_GenDouble(iRet, SPP, I, K, L, iTo, iSpn, iFrom, iCC, & iLUT, LS, OrbPairs, SymProdInd, nI, nK, nEl, iC, tDebugPrint) use SystemData, only: TSTOREASEXCITATIONS use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds IMPLICIT NONE INTEGER NEL, NI(NEL) INTEGER I, K, L INTEGER NK(NEL) INTEGER IFROM, ITO, ISPN TYPE(Symmetry) SPP INTEGER ICC(4) !.. 1,1= 1B, 1,2=1A; 2,1=2B, 2,2=2A. LOGICAL LS(2, 2) INTEGER ORBPAIRS(2, *) INTEGER ILUT(0:*) INTEGER SYMPRODIND(2, 3, 1:*) INTEGER IC LOGICAL tDebugPrint INTEGER iRet iRet = 0 !.. doubles SPP = SymPairProds(ITO)%Sym !.. See if we need a new K. L is the spin label, and goes from 1..4. IF (L > 4) THEN L = 1 K = K + 1 IF (K < 0 .OR. K >= SymPairProds(ITO)%nIndex + SymPairProds(ITO)%nPairs) THEN !.. K is invalid. Get a new I K = 1 I = I + 1 IF (I > SYMPRODIND(2, ISPN, IFROM)) THEN !.. I is now invalid I = -1 iRet = 1 RETURN ELSE !.. reset K K = SymPairProds(ITO)%nIndex END IF END IF !.. We've got a new K, so we need to reset some variables ICC(1) = SymStatePairs(1, K) * 2 - 1 ICC(2) = ICC(1) + 1 ICC(3) = SymStatePairs(2, K) * 2 - 1 ICC(4) = ICC(3) + 1 ! WRITE(stdout,*) ORBPAIRS(1,SYMPRODIND(1,ISPN,IFROM)+I), ! & ORBPAIRS(2,SYMPRODIND(1,ISPN,IFROM)+I) ! WRITE(stdout,*) ISPN,ICC(1),ICC(3) LS(1, 1) = BTEST(ILUT((ICC(1) - 1) / 32), MOD(ICC(1) - 1, 32)) LS(1, 2) = BTEST(ILUT((ICC(2) - 1) / 32), MOD(ICC(2) - 1, 32)) LS(2, 1) = BTEST(ILUT((ICC(3) - 1) / 32), MOD(ICC(3) - 1, 32)) LS(2, 2) = BTEST(ILUT((ICC(4) - 1) / 32), MOD(ICC(4) - 1, 32)) END IF !.. Now check for an excitation IF (L == 1) THEN L = 2 IF (ISPN == 1 .AND. ICC(1) /= ICC(3) .AND. .NOT.(LS(1, 1) .OR. LS(2, 1))) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(1), ICC(3), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF IF (L == 2) THEN L = 3 IF (ISPN == 2) THEN !.. If neither virtuals are in NI, then allow IF (.NOT.(LS(1, 1) .OR. LS(2, 2))) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(1), ICC(4), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF END IF IF (L == 3) THEN L = 4 IF (ISPN == 2) THEN !.. If neither virtuals are in NI, and they're not the same(which would give !.. us the same excitation as previously), then allow IF (.NOT.(LS(1, 2) .OR. LS(2, 1)) .AND. ICC(1) /= ICC(3)) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(2), ICC(3), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF END IF IF (L == 4) THEN L = 5 IF (ISPN == 3) THEN !.. If both virtuals aren't the same and neither are in NI, then allow IF (ICC(1) /= ICC(3) .AND. .NOT.(LS(1, 2) .OR. LS(2, 2))) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(2), ICC(4), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF END IF End Subroutine SymGenExcitItOld_GenDouble !Get a new pair from the global list (if there is one) or generate one afresh. All according to the pair type iTo which is the index into SymPairProds. ! iLooped will be set to 1 by this if we've run out of pairs and had to go back to the beginning. ! The pair is retured in iTo1 and iTo2. ! K is a counter for us to keep track of where we are. If K<-1 on entry, we ! start afresh and set iLooped to -1. Subroutine SymGenExcitIt_GetNextPair(K, iTo, iLooped, iTo1, iTo2, tDebugPrint) use SymData, only: tStoreStateList use SymData, only: SymLabelCounts, SymStatePairs use SymData, only: SymLabelList, SymPairProds use SymData, only: SymClasses use constants, only: stdout IMPLICIT NONE INTEGER K, iTo INTEGER iLooped INTEGER iTo1, iTo2 INTEGER iLabelPairIndexOff INTEGER iLabelPairBase INTEGER iLabel1Index, iLabel2Index INTEGER iLabel1, iLabel2 LOGICAL tDebugPrint iLooped = 0 if (.not. tStoreStateList) then ! We must generate the pair as we don't have a stored list ! SymStatePairs holds a list of SymLabels. ! SymPairProds(iTo) tells is which set of pairs we're using ! iTo is the symmetry of the 'to' spin-orb pair ! we split K into 3 integers as we need to store 3 variables rather than 1 ! (LabelPairIndexOff, Label1Index, Label2Index) !bits 30-24 23-12 11-0 !The index of the current state of the 1st symmetry of the pair (Label1Index) !The index of the current state of the 2nd symmetry of the pair (Label2Index) !we loop over these with Label2Index changing fastest, then Label1Index, then iLabelPairIndexOff ! LabelPairIndexOff: Which pair of symmetries (in SymStatePairs) ! This is the index for a given iTo. The base is iLabelPairBase ! Label1Index: The index of the current first state within its symmetry class ! Label2Index: The index of the current second state within it symmetry class ! the symmetries of the states are determined by the LAbelPairIndexOff. ! We iterate through all possible [LabelPair,(state1,state2)], in order state2, state1, LabelPair. if (K < 0) then iLabelPairIndexOff = 0 iLabel1Index = 0 iLabel2Index = -1 iLooped = -1 !indicate we've reset from nothing else iLabelPairIndexOff = ishft(iand(K, 2130706432), -24) iLabel1Index = ishft(iand(K, 16773120), -12) iLabel2Index = iand(K, 4095) end if iLabelPairBase = SymPairProds(iTo)%nIndex iLabel1 = SymStatePairs(1, iLabelPairBase + iLabelPairIndexOff) iLabel2 = SymStatePairs(2, iLabelPairBase + iLabelPairIndexOff) ! We cycle through these with Label2Index fastest iLabel2Index = iLabel2Index + 1 ! This is a do rather than an if because if iLabel1==iLabel2, it's possible ! that there are no valid combinations after an increment, so we have to go round again. if (iLabel2Index >= SymLabelCounts(2, iLabel2)) then ! Increment label 1 iLabel1Index = iLabel1Index + 1 if (iLabel1Index >= SymLabelCounts(2, iLabel1)) then ! Increment the Pair Index iLabelPairIndexOff = iLabelPairIndexOff + 1 if (iLabelPairIndexOff >= SymPairProds(iTo)%nPairs) then iLooped = 1 ! indicate we're looping iLabelPairIndexOff = 0 end if iLabel1 = SymStatePairs(1, iLabelPairBase + iLabelPairIndexOff) iLabel2 = SymStatePairs(2, iLabelPairBase + iLabelPairIndexOff) iLabel1Index = 0 end if ! If the two are from the same symlabel, we enforce 2's index>1 if (iLabel1 == iLabel2) then iLabel2Index = iLabel1Index else iLabel2Index = 0 end if end if ! Now extract the states and turn them into orbitals. iTo1 = (SymLabelList(SymLabelCounts(1, iLabel1) + iLabel1Index)) * 2 - 1 iTo2 = (SymLabelList(SymLabelCounts(1, iLabel2) + iLabel2Index)) * 2 - 1 ! Put the K index back together K = IShft(iLabelPairIndexOff, 24) + IShft(iLabel1Index, 12) + iLabel2Index if (tDebugPrint) THEN Write(stdout, *) "To: ", iTo, "LabelPair:", iLabelPairBase, "+", iLabelPairIndexOff, "/", SymPairProds(iTo)%nPairs Write(stdout, "(A10,I4,A1,I4,A1,I4,I4)") "Label1: (", iLabel1, ")", iLabel1Index, "/", SymLabelCounts(2, iLabel1), iTo1 Write(stdout, "(A10,I4,A1,I4,A1,I4,I4)") "Label2: (", iLabel2, ")", iLabel2Index, "/", SymLabelCounts(2, iLabel2), iTo2 WRITE(stdout, "(A,Z10,A,I3)") "K:", K, " Looped:", iLooped end if else ! We have a stored list, so just get the next from there. K = K + 1 IF (K < 0 .or. K >= SymPairProds(ITO)%nIndex + SymPairProds(ITO)%nPairs) THEN iLooped = 1 !we've looped if (K < 0) iLooped = -1 ! we've reset K = SymPairProds(ITO)%nIndex END IF iTo1 = SymStatePairs(1, K) * 2 - 1 iTo2 = SymStatePairs(2, K) * 2 - 1 if (tDebugPrint) THEN Write(stdout, *) "To: ", iTo WRITE(stdout, "(A10,I4,A1,I4)") "Label1: (", SymClasses((iTo1 + 1) / 2), ")", iTo1 WRITE(stdout, "(A10,I4,A1,I4)") "Label2: (", SymClasses((iTo2 + 1) / 2), ")", iTo2 WRITE(stdout, "(A,I10,A,I3)") "K:", K, " Looped:", iLooped end if END IF RETURN End Subroutine SymGenExcitIt_GetNextPair Subroutine SymGenExcitIt_GenDouble(iRet, SPP, I, K, L, iTo, iSpn, iFrom, iCC, iLUT, LS, OrbPairs, SymProdInd, nI, nK, nEl, iC, tDebugPrint) use SystemData, only: TSTOREASEXCITATIONS use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB use SymData, only: SymLabelCounts, SymStatePairs, SymClass use SymData, only: SymLabelList, SymPairProds IMPLICIT NONE INTEGER NEL, NI(NEL) INTEGER I, K, L, iTo, iFrom, iSpn INTEGER NK(NEL) TYPE(Symmetry) SPP INTEGER ICC(4) !.. 1,1= 1B, 1,2=1A; 2,1=2B, 2,2=2A. LOGICAL LS(2, 2) INTEGER ORBPAIRS(2, *) INTEGER ILUT(0:*) INTEGER SYMPRODIND(2, 3, 1:*) INTEGER IC LOGICAL tDebugPrint INTEGER iRet INTEGER iLooped INTEGER iTo1, iTo2 iRet = 0 !.. doubles SPP = SymPairProds(ITO)%Sym !.. See if we need a new K. L is the spin label, and goes from 1..4. IF (L > 4) THEN L = 1 Call SymGenExcitIt_GetNextPair(K, iTo, iLooped, iTo1, iTo2, tDebugPrint) IF (iLooped /= 0) THEN !.. K is invalid. Get a new I I = I + 1 IF (I > SYMPRODIND(2, ISPN, IFROM)) THEN !.. I is now invalid I = -1 iRet = 1 RETURN END IF END IF !.. We've got a new K, so we need to reset some variables ICC(1) = iTo1 ICC(2) = iTo1 + 1 ICC(3) = iTo2 ICC(4) = iTo2 + 1 ! WRITE(stdout,*) ORBPAIRS(1,SYMPRODIND(1,ISPN,IFROM)+I), ! & ORBPAIRS(2,SYMPRODIND(1,ISPN,IFROM)+I) ! WRITE(stdout,*) ISPN,ICC(1),ICC(3) LS(1, 1) = BTEST(ILUT((ICC(1) - 1) / 32), MOD(ICC(1) - 1, 32)) LS(1, 2) = BTEST(ILUT((ICC(2) - 1) / 32), MOD(ICC(2) - 1, 32)) LS(2, 1) = BTEST(ILUT((ICC(3) - 1) / 32), MOD(ICC(3) - 1, 32)) LS(2, 2) = BTEST(ILUT((ICC(4) - 1) / 32), MOD(ICC(4) - 1, 32)) END IF !.. Now check for an excitation IF (L == 1) THEN L = 2 IF (ISPN == 1 .AND. ICC(1) /= ICC(3) .AND. .NOT.(LS(1, 1) .OR. LS(2, 1))) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(1), ICC(3), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF IF (L == 2) THEN L = 3 IF (ISPN == 2) THEN !.. If neither virtuals are in NI, then allow IF (.NOT.(LS(1, 1) .OR. LS(2, 2))) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(1), ICC(4), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF END IF IF (L == 3) THEN L = 4 IF (ISPN == 2) THEN !.. If neither virtuals are in NI, and they're not the same(which would give !.. us the same excitation as previously), then allow IF (.NOT.(LS(1, 2) .OR. LS(2, 1)) .AND. ICC(1) /= ICC(3)) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(2), ICC(3), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF END IF IF (L == 4) THEN L = 5 IF (ISPN == 3) THEN !.. If both virtuals aren't the samem and neither are in NI, then allow IF (ICC(1) /= ICC(3) .AND. .NOT.(LS(1, 2) .OR. LS(2, 2))) THEN Call SymGenExcitIt_MakeDouble( & ORBPAIRS(1, SYMPRODIND(1, ISPN, IFROM) + I), & ORBPAIRS(2, SYMPRODIND(1, ISPN, IFROM) + I), & ICC(2), ICC(4), nI, nK, nEl, tDebugPrint) IC = 2 iRet = 2 RETURN END IF END IF END IF End Subroutine SymGenExcitIt_GenDouble ! Actually go through and generate the excitation given a det and from and to. ! nI is the reference, nK has the new det returned in it and nEl is the # electrons. Subroutine SymGenExcitIt_MakeDouble(iFrom1, iFrom2, iTo1, iTo2, nI, nK, nEl, tDebugPrint) use SystemData, only: TSTOREASEXCITATIONS use constants, only: maxExcit, stdout use excit_mod, only: FindExcitDet IMPLICIT NONE INTEGER iFrom1, iFrom2 INTEGER iTo1, iTo2, ExcitMat(2, maxExcit) INTEGER nEl, nI(nEl), nK(nEl) LOGICAL tDebugPrint, TParity INTEGER J IF (tStoreAsExcitations) THEN !The excitation storage starts with -1. The next number is the excitation level,L . Next is the parity of the permutation required to lineup occupied->excited. Then follows a list of the indexes of the L occupied orbitals within the HFDET, and then L virtual spinorbitals. NK(1) = -1 NK(2) = 2 NK(3) = 1 NK(4) = iFrom1 NK(5) = iFrom2 NK(6) = iTo1 NK(7) = iTo2 ELSE ! CALL NECI_ICOPY(NEL,NI,1,NK,1) NK(1:NEL) = NI(1:NEL) DO J = 1, NEL IF (NI(J) == iFrom1) THEN IF (tDebugPrint) WRITE(stdout, "(A,I3,A,I3,A)", advance='no') "[", iFrom1, "->", iTo1, "," ExcitMat(1, 1) = J ExcitMat(2, 1) = iTo1 ! NK(J)=iTo1 END IF IF (NI(J) == iFrom2) THEN IF (tDebugPrint) WRITE(stdout, *) iFrom2, "->", iTo2, "]" ExcitMat(1, 2) = J ExcitMat(2, 2) = iTo2 ! NK(J)=iTo2 END IF END DO ! CALL WRITEDET(6,NK,NEL,.TRUE.) ! CALL NECI_SORTI(NEL,NK) CALL FindExcitDet(ExcitMat, NK, 2, TParity) END IF End Subroutine SymGenExcitIt_MakeDouble ! We are required to enshroud GenExcitProbInternal as F90 doesn't seem to want to allow any casting. SUBROUTINE IsConnectedDet2(nI, nJ, tIsConnected) use SystemData, only: nel use symexcit2 IMPLICIT NONE INTEGER nI(nEl), nJ(nEl) LOGICAL tIsConnected CALL IsConnectedDetInternal(nI, nJ, tIsConnected) END ! For reference below is the call and declaration of SYMGENRANDEXCITIT to extract the locations of teh variables. ! NMEM is nIExcitor ! CALL SYMGENRANDEXCITIT(NI,NEL,NMEM(NMEM(2)),NMEM(6),DSTORE(1), ! & NMEM(NMEM(5)),DSTORE(SymClassSize*NEL+1),NMEM(NMEM(4)), ! & NMEM(7),NMEM(8),NMEM(9),NMEM(10),NMEM(11),NMEM(12), ! & NMEM(13),NMEM(14),NMEM(15),NMEM(19),NMEM(23),ISEED,NJ,IC, ! & G1,NBASISMAX,UMAT,NBASIS,PGEN) ! IC=NMEM(23) ! END ! SymProds(0) = DSTORE(SymClassSize*NEL+1+NIfTot+1)) ! SUBROUTINE SYMGENRANDEXCITIT(NI,NEL,EXCITTYPES,NEXCITTYPES, & ! & CLASSES, & ! & SYMPRODIND,ILUT,ORBPAIRS,IEXCIT,ISPN,IFROM,ITO, & ! & I,J,K,L,ICC,LS,ITOTAL,ISEED, & ! & NK,IC,G1,NBASISMAX,UMAT,NBASIS,PGEN) ! We are required to enshroud GenExcitProbInternal as F90 doesn't seem to want to allow any casting. SUBROUTINE GenExcitProb2(nI, nJ, nEl, G1, nBasisMax, Arr, nBasis, OrbPairs, SymProdInd, iLUT, SymProds, ExcitTypes, iTotal, pGen) use constants, only: dp USE symexcit2 use SystemData, only: Symmetry, SymmetrySize, SymmetrySizeB use SystemData, only: BasisFN, BasisFNSize, BasisFNSizeB IMPLICIT NONE INTEGER nEl, nI(nEl), nJ(nEl), nBasis, nBasisMax(5, *) INTEGER ExcitTypes(5, *) TYPE(BasisFN) G1(nBasis) INTEGER iLUT(*), iTotal INTEGER OrbPairs(2, *) INTEGER SymProdInd(2, 3, 1:*) TYPE(Symmetry) SymProds(0:*) real(dp) pGen real(dp) Arr(nBasis, 2) CALL GenExcitProbInternal(nI, nJ, nEl, G1, nBasisMax, Arr, nBasis, OrbPairs, SymProdInd, iLUT, SymProds, ExcitTypes, iTotal, pGen) END