b2brepl.cc

Go to the documentation of this file.
00001 
00007 #define EXTERN
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <libqt/qt.h>
00011 #include <libciomr/libciomr.h>
00012 #include "structs.h"
00013 #include "globals.h"
00014 
00015 namespace psi { namespace detci {
00016 
00017 /* DEFINES */
00018 #define MAX_EL 30
00019 #define MIN0(a,b) (((a)<(b)) ? (a) : (b))
00020 #define MAX0(a,b) (((a)>(b)) ? (a) : (b))
00021 
00022 /* PROTOS */
00023 extern int subgr_lex_addr(struct level *head, int *occs, int nel, int norb);
00024 
00025 void b2brepl(unsigned char **occs, int *Jcnt, int **Jij, int **Joij, 
00026    int **Jridx, signed char **Jsgn, struct olsen_graph *Graph,
00027    int Ilist, int Jlist, int len);
00028 void b2bgen1(unsigned char **occs, int *Jcnt, int **Jij, int **Joij, 
00029    int **Jridx, signed char **Jsgn, struct level *subgr_head, 
00030    int len, int ijsym, int nel, int ras1_lvl, int ras3_lvl, int ras4_lvl);
00031 void b2bgen2(unsigned char **occs, int *Jcnt, int **Jij, int **Joij, 
00032    int **Jridx, signed char **Jsgn, struct level *subgr_head,
00033    int up, int down, int len, int ijsym, int nel, int ras1_lvl, int ras3_lvl,
00034    int ras4_lvl);
00035 
00036 
00037 /*
00038 ** b2brepl
00039 **
00040 ** Generate block to block single replacements on the fly.
00041 ** Generates replacements from strings I in list Ilist to strings J in
00042 **    list Jlist.
00043 **
00044 ** Parameters:
00045 **    occs     = array of occupied orbitals for each string I
00046 **    Jcnt     = array to hold number of replacements for each string I
00047 **    Jij      = matrix of ij's to all J's for each I (Jij[I][J])
00048 **    Joij     = matrix of olsen ij's to all J's for each I (Joij[I][J])
00049 **    Jridx    = matrix of relative indices of resultant strings J,
00050 **               i.e. J'[J] = Jridx[I][J] where J' is the proper address of J
00051 **    Jsgn     = matrix of signs as above
00052 **    Graph    = Olsen Graph for the relevant strings
00053 **    Ilist    = list number for I's
00054 **    Jlist    = list number for J's 
00055 **    len      = length of occs array (how many I strings)
00056 **
00057 ** David Sherrill
00058 ** August 1995
00059 */
00060 void b2brepl(unsigned char **occs, int *Jcnt, int **Jij, int **Joij, 
00061       int **Jridx, signed char **Jsgn, struct olsen_graph *Graph,
00062       int Ilist, int Jlist, int len)
00063 {
00064    int I_n1, I_n2, I_n3, I_n4;
00065    int J_n1, J_n2, J_n3, J_n4;
00066    int D_n1, D_n2, D_n3, D_n4;
00067    int Ilist_ir, Jlist_ir;
00068    int nel,Icode,Jcode,ijsym,up,down;
00069    struct level *subgr_head;
00070 
00071    /* zero out Jcnt so there's no mistake */
00072    zero_int_array(Jcnt, len);
00073 
00074    /* get pointer to subgraph */
00075    Icode = Ilist % Graph->subgr_per_irrep;
00076    Jcode = Jlist % Graph->subgr_per_irrep;
00077    Ilist_ir = Ilist / Graph->subgr_per_irrep;
00078    Jlist_ir = Jlist / Graph->subgr_per_irrep;
00079    subgr_head = Graph->sg[Jlist_ir][Jcode].lvl;
00080    /* first figure out how many electrons in RAS I, II, III, IV for
00081     * each of the blocks 
00082     */
00083    nel = Graph->num_el_expl;
00084    I_n1 = Graph->encode[0][Icode];
00085    I_n3 = Graph->encode[1][Icode];
00086    I_n4 = Graph->encode[2][Icode];
00087    I_n2 = nel - I_n1 - I_n3 - I_n4;
00088    J_n1 = Graph->encode[0][Jcode];
00089    J_n3 = Graph->encode[1][Jcode];
00090    J_n4 = Graph->encode[2][Jcode];
00091    J_n2 = nel - J_n1 - J_n3 - J_n4;
00092    if (I_n1 < 0 || I_n2 < 0 || I_n3 < 0 || J_n1 < 0 || J_n2 < 0 || J_n3 < 0
00093           || I_n4 < 0 || J_n4 < 0) {
00094       printf("b2brepl: got less than 1 electron in a partition\n");
00095       return;
00096       }
00097 
00098    /* now figure out the differences */
00099    D_n1 = J_n1 - I_n1;
00100    D_n2 = J_n2 - I_n2;
00101    D_n3 = J_n3 - I_n3;
00102    D_n4 = J_n4 - I_n4;
00103  
00104    /* are these ok? */
00105    if (abs(D_n1) + abs(D_n2) + abs(D_n3) + abs(D_n4) > 2) 
00106       return;
00107 
00108    /* get ijsym */
00109    ijsym = Ilist_ir ^ Jlist_ir;
00110 
00111    /* figure out the case */
00112    if (D_n1 == 0 && D_n2 == 0 && D_n3 == 0 && D_n4 == 0) {
00113       b2bgen1(occs,Jcnt,Jij,Joij,Jridx,Jsgn,subgr_head,len,ijsym,nel,
00114          Graph->ras1_lvl, Graph->ras3_lvl, Graph->ras4_lvl);
00115       }
00116    else { /* figure out which is 1 and which is -1 */
00117       if (D_n1 == 1) up = 0;
00118       else if (D_n2 == 1) up = 1;
00119       else if (D_n3 == 1) up = 2;
00120       else if (D_n4 == 1) up = 3;
00121       if (D_n1 == -1) down = 0;
00122       else if (D_n2 == -1) down = 1;
00123       else if (D_n3 == -1) down = 2;
00124       else if (D_n4 == -1) down = 3;
00125       b2bgen2(occs,Jcnt,Jij,Joij,Jridx,Jsgn,subgr_head,up,down,len,ijsym,nel,
00126          Graph->ras1_lvl, Graph->ras3_lvl, Graph->ras4_lvl);
00127       }         
00128 } 
00129 
00130 
00131 
00132 /*
00133 ** b2bgen1: Generate all single replacements going to another block
00134 **    in which the number of electrons in each RAS partition must
00135 **    remain constant (i.e. staying in same code, maybe irrep changes)
00136 **
00137 */
00138 void b2bgen1(unsigned char **occs, int *Jcnt, int **Jij, int **Joij, 
00139       int **Jridx, signed char **Jsgn, struct level *subgr_head, 
00140       int len, int ijsym, int nel, int ras1_lvl, int ras3_lvl, int ras4_lvl)
00141 {
00142    int I;
00143    int O[MAX_EL], T[MAX_EL], ras_occs[4][MAX_EL], ecnt[4];
00144    int i,j,k,l,m,ij,oij,orb,r1cnt,r2cnt,r3cnt,r4cnt;
00145    int isym,jsym;
00146    int cnt,ridx,norb;
00147    signed char sgn;
00148    int ras,hole,part,abshole,hops,iused;
00149    int **ras_orbs[4], **ras_opi;
00150 
00151    for (i=0; i<4; i++) ras_orbs[i] = CalcInfo.ras_orbs[i];
00152    ras_opi = CalcInfo.ras_opi;
00153    norb = CalcInfo.num_ci_orbs;
00154 
00155    /* loop over strings */
00156    for (I=0; I<len; I++) {
00157 
00158       cnt = 0;  /* how many singlerepls found for this string */
00159 
00160       /* divide up electrons into their subspaces */
00161       r1cnt = r2cnt = r3cnt = r4cnt = 0;
00162       for (i=0; i<nel; i++) {
00163          orb = (int) occs[I][i];
00164          O[i] = orb;
00165          if (orb <= ras1_lvl) ras_occs[0][r1cnt++] = orb;
00166          else if (orb >= ras3_lvl && orb < ras4_lvl) ras_occs[2][r3cnt++] = orb;
00167          else if (orb >= ras4_lvl) ras_occs[3][r4cnt++] = orb;
00168          else ras_occs[1][r2cnt++] = orb;
00169          }
00170 
00171       ecnt[0] = r1cnt;
00172       ecnt[1] = r2cnt;
00173       ecnt[2] = r3cnt;
00174       ecnt[3] = r4cnt;
00175 
00176       /* do diagonals first */
00177       if (ijsym == 0) {
00178          ridx = subgr_lex_addr(subgr_head, O, nel, norb);
00179          if (ridx < 0) {
00180             printf("b2bgen1: invalid string index = %d\n", ridx);
00181             continue;
00182             }
00183          for (k=0; k<nel; k++) {
00184             i = O[k];
00185             ij = ioff[i] + i;
00186             oij = i * norb + i;
00187             Jij[I][cnt] = ij;
00188             Joij[I][cnt] = oij;
00189             Jsgn[I][cnt] = 1;
00190             Jridx[I][cnt] = ridx; 
00191             cnt++;
00192             }
00193          }
00194 
00195       /* Done with diagonals.  Now loop over RAS subspaces */
00196       for (ras=0; ras<4; ras++) {
00197          /* loop over excited electrons/orbitals */
00198          for (hole=0; hole<ecnt[ras]; hole++) { 
00199 
00200             abshole = hole;
00201             for (k=0; k<ras; k++) abshole += ecnt[k];
00202  
00203             j = ras_occs[ras][hole];
00204             if (j < CalcInfo.num_cor_orbs) continue;
00205             jsym = CalcInfo.orbsym[j + CalcInfo.num_fzc_orbs];
00206             isym = ijsym ^ jsym;
00207             for (part=0; part<ras_opi[ras][isym]; part++) {
00208                i = ras_orbs[ras][isym][part]; 
00209                
00210                /* make sure i is not occupied already */
00211                for (k=0,l=0; k<ecnt[ras]; k++) {  
00212                   if (i == ras_occs[ras][k]) {l=1; break;}
00213                   }
00214                if (l==1) continue;
00215 
00216                /* arrange the occupied list in order */
00217                for (k=0,l=0; k<ras; k++) { 
00218                   for (m=0; m<ecnt[k]; m++) {
00219                      T[l++] = ras_occs[k][m];
00220                      }
00221                   }
00222                for (k=0,iused=0; k<ecnt[ras]; k++) {
00223                   if (!iused && i < ras_occs[ras][k]) {
00224                      iused=1; 
00225                      hops = l; 
00226                      T[l++] = i;
00227                      }
00228                   if (k != hole) {
00229                      T[l++] = ras_occs[ras][k];
00230                      }
00231                   } 
00232                if (!iused) {
00233                   hops = l;
00234                   T[l++] = i;
00235                   }
00236                for (k=ras+1; k<4; k++) {
00237                   for (m=0; m<ecnt[k]; m++) {
00238                      T[l++] = ras_occs[k][m];
00239                      }
00240                   }
00241                ridx = subgr_lex_addr(subgr_head, T, nel, norb);
00242                /* wouldn't be found if i is actually occupied */
00243                if (ridx < 0) {
00244                   printf("b2bgen1: invalid string index = %d\n", ridx);
00245                   continue;
00246                   }
00247 
00248                /* get the sign */
00249                sgn = ((abshole + hops) % 2) ? -1 : 1;
00250                ij = ioff[MAX0(i,j)] + MIN0(i,j);
00251                oij = i * norb + j;
00252 
00253                /* store these results and increment the counter */
00254                Jij[I][cnt] = ij;
00255                Joij[I][cnt] = oij;
00256                Jsgn[I][cnt] = sgn;
00257                Jridx[I][cnt] = ridx;
00258                cnt++;
00259 
00260                } /* end loop over particles */
00261             } /* end loop over holes */
00262          } /* end loop over RAS subspaces */
00263       Jcnt[I] = cnt;
00264       } /* end loop over strings I */
00265 
00266 }
00267 
00268 
00269 void b2bgen2(unsigned char **occs, int *Jcnt, int **Jij, int **Joij, 
00270       int **Jridx, signed char **Jsgn, struct level *subgr_head,
00271       int up, int down, int len, int ijsym, int nel, int ras1_lvl,
00272       int ras3_lvl, int ras4_lvl)
00273 {
00274    int I;
00275    int O[MAX_EL], T[MAX_EL], ras_occs[4][MAX_EL], ecnt[4];
00276    int i,j,k,l,ij,oij,orb,r1cnt,r2cnt,r3cnt,r4cnt;
00277    int isym,jsym;
00278    int cnt,ridx,norb;
00279    signed char sgn;
00280    int hole,part,abshole,hops,iused;
00281    int **ras_orbs, *ras_opi, *ras_occs_excite, *ras_occs_virt;
00282 
00283    norb = CalcInfo.num_ci_orbs;
00284 
00285    /* loop over strings */
00286    for (I=0; I<len; I++) {
00287 
00288       cnt = 0;  /* how many singlerepls found for this string */
00289 
00290       /* divide up electrons into their subspaces */
00291       r1cnt = r2cnt = r3cnt = r4cnt = 0;
00292       for (i=0; i<nel; i++) {
00293          orb = (int) occs[I][i];
00294          O[i] = orb;
00295          if (orb <= ras1_lvl) ras_occs[0][r1cnt++] = orb;
00296          else if (orb>=ras3_lvl && orb<ras4_lvl) ras_occs[2][r3cnt++] = orb;
00297          else if (orb >= ras4_lvl) ras_occs[3][r4cnt++] = orb;
00298          else ras_occs[1][r2cnt++] = orb;
00299          }
00300 
00301       ecnt[0] = r1cnt;
00302       ecnt[1] = r2cnt;
00303       ecnt[2] = r3cnt;
00304       ecnt[3] = r4cnt;
00305       ras_occs_excite = ras_occs[down]; 
00306       ras_occs_virt = ras_occs[up];
00307       ras_opi = CalcInfo.ras_opi[up];
00308       ras_orbs = CalcInfo.ras_orbs[up];
00309 
00310       for (hole=0; hole<ecnt[down]; hole++) {
00311 
00312          abshole = hole;
00313          for (k=0; k<down; k++) abshole += ecnt[k];
00314 
00315          j = ras_occs_excite[hole];
00316          if (j < CalcInfo.num_cor_orbs) continue;
00317          jsym = CalcInfo.orbsym[j + CalcInfo.num_fzc_orbs];
00318          isym = ijsym ^ jsym;
00319          for (part=0; part<ras_opi[isym]; part++) {
00320             i = ras_orbs[isym][part];
00321 
00322             /* make sure i is not occupied already */
00323             for (k=0,l=0; k<ecnt[up]; k++) {
00324                if (i == ras_occs_virt[k]) {l=1; break;}
00325                }
00326             if (l==1) continue;
00327 
00328             /* arrange the occupied list in order */
00329             for (k=0,iused=0,l=0; k<nel; k++) {
00330                if (!iused && i < O[k]) { iused=1; hops = l; T[l++] = i; }
00331                if (k != abshole) T[l++] = O[k];
00332                }
00333             if (!iused) { hops = l; T[l++] = i; }
00334 
00335             ridx = subgr_lex_addr(subgr_head, T, nel, norb);
00336             /* wouldn't be found if i is actually occupied */
00337             if (ridx < 0) {
00338                printf("b2bgen2: invalid string index = %d\n", ridx);
00339                continue;
00340                }
00341 
00342             /* get the sign */
00343             sgn = ((abshole + hops) % 2) ? -1 : 1;
00344 
00345             ij = ioff[MAX0(i,j)] + MIN0(i,j);
00346             oij = i * norb + j;
00347 
00348             /* store these results and increment the counter */
00349             Jij[I][cnt] = ij;
00350             Joij[I][cnt] = oij;
00351             Jsgn[I][cnt] = sgn;
00352             Jridx[I][cnt] = ridx;
00353             cnt++;
00354 
00355             } /* end loop over particles */
00356          } /* end loop over holes */
00357 
00358       Jcnt[I] = cnt;
00359       } /* end loop over strings I */
00360 
00361 }
00362 
00363 
00364 void b2brepl_test(unsigned char ***occs, int *Jcnt, int **Jij, int **Joij, 
00365       int **Jridx, signed char **Jsgn, struct olsen_graph *Graph)
00366 {
00367    int i, j, nirreps, ncodes;
00368    int Iirrep, Icode, Ilistnum;
00369    int Jirrep, Jcode, Jlistnum;
00370    struct stringgraph *Isubgraph, *Jsubgraph;
00371 
00372    nirreps = Graph->nirreps;
00373    ncodes = Graph->subgr_per_irrep;
00374 
00375    fprintf(outfile,"\nTesting block to block single-replacements b2brepl()\n"); 
00376    for (Iirrep=0,Ilistnum=0; Iirrep<nirreps; Iirrep++) {
00377       for (Icode=0; Icode<ncodes; Icode++,Ilistnum++) {
00378          Isubgraph = Graph->sg[Iirrep] + Icode;
00379          if (!Isubgraph->num_strings) continue;
00380          for (Jirrep=0,Jlistnum=0; Jirrep<nirreps; Jirrep++) {
00381             for (Jcode=0; Jcode<ncodes; Jcode++,Jlistnum++) {
00382                Jsubgraph = Graph->sg[Jirrep] + Jcode;
00383                if (!Jsubgraph->num_strings) continue;
00384 
00385                b2brepl(occs[Ilistnum], Jcnt, Jij, Joij, Jridx, Jsgn,
00386                   Graph, Ilistnum, Jlistnum, Isubgraph->num_strings);
00387 
00388                for (i=0; i<Isubgraph->num_strings; i++) {
00389                   fprintf(outfile, "\nString %4d (",i);
00390                      for (j=0; j<Graph->num_el_expl; j++) {
00391                         fprintf(outfile, "%2d ", (int) occs[Ilistnum][i][j]);
00392                         }
00393                   fprintf(outfile, ")\n   Links:\n") ;
00394                   for (j=0; j<Jcnt[i]; j++) {
00395                      fprintf(outfile, "   %3d [%3d] %c (%2d %3d)\n",
00396                         Jij[i][j], Joij[i][j], (Jsgn[i][j]==1) ? '+' : '-', 
00397                         Jlistnum, Jridx[i][j]);
00398                      }                     
00399                   }
00400 
00401                } /* end loop over Jcodes */
00402             } /* end loop over Jirrep */
00403          } /* end loop over Icodes */
00404       } /* end loop over Iirrep */
00405 }
00406 
00407 }} // namespace psi::detci
00408 

Generated on Wed Feb 13 16:35:39 2008 for PSI by  doxygen 1.5.4